]> git.codecow.com Git - Monocypher.git/commitdiff
Add tinyssh speed tests
authorLoup Vaillant <loup@loup-vaillant.fr>
Sun, 19 Mar 2023 21:54:48 +0000 (22:54 +0100)
committerLoup Vaillant <loup@loup-vaillant.fr>
Sun, 19 Mar 2023 21:56:15 +0000 (22:56 +0100)
36 files changed:
tests/externals/tinyssh/LICENCE [new file with mode: 0644]
tests/externals/tinyssh/cleanup.c [new file with mode: 0644]
tests/externals/tinyssh/cleanup.h [new file with mode: 0644]
tests/externals/tinyssh/crypto_hash_sha512.c [new file with mode: 0644]
tests/externals/tinyssh/crypto_hash_sha512.h [new file with mode: 0644]
tests/externals/tinyssh/crypto_int64.h [new file with mode: 0644]
tests/externals/tinyssh/crypto_onetimeauth_poly1305.c [new file with mode: 0644]
tests/externals/tinyssh/crypto_onetimeauth_poly1305.h [new file with mode: 0644]
tests/externals/tinyssh/crypto_scalarmult_curve25519.c [new file with mode: 0644]
tests/externals/tinyssh/crypto_scalarmult_curve25519.h [new file with mode: 0644]
tests/externals/tinyssh/crypto_sign_ed25519.c [new file with mode: 0644]
tests/externals/tinyssh/crypto_sign_ed25519.h [new file with mode: 0644]
tests/externals/tinyssh/crypto_stream_chacha20.c [new file with mode: 0644]
tests/externals/tinyssh/crypto_stream_chacha20.h [new file with mode: 0644]
tests/externals/tinyssh/crypto_uint32.h [new file with mode: 0644]
tests/externals/tinyssh/crypto_uint64.h [new file with mode: 0644]
tests/externals/tinyssh/crypto_verify_32.c [new file with mode: 0644]
tests/externals/tinyssh/crypto_verify_32.h [new file with mode: 0644]
tests/externals/tinyssh/fe.c [new file with mode: 0644]
tests/externals/tinyssh/fe.h [new file with mode: 0644]
tests/externals/tinyssh/fe25519.c [new file with mode: 0644]
tests/externals/tinyssh/fe25519.h [new file with mode: 0644]
tests/externals/tinyssh/ge25519.c [new file with mode: 0644]
tests/externals/tinyssh/ge25519.h [new file with mode: 0644]
tests/externals/tinyssh/randombytes.c [new file with mode: 0644]
tests/externals/tinyssh/randombytes.h [new file with mode: 0644]
tests/externals/tinyssh/sc25519.c [new file with mode: 0644]
tests/externals/tinyssh/sc25519.h [new file with mode: 0644]
tests/externals/tinyssh/uint32_pack.c [new file with mode: 0644]
tests/externals/tinyssh/uint32_pack.h [new file with mode: 0644]
tests/externals/tinyssh/uint32_unpack.c [new file with mode: 0644]
tests/externals/tinyssh/uint32_unpack.h [new file with mode: 0644]
tests/externals/tinyssh/verify.c [new file with mode: 0644]
tests/externals/tinyssh/verify.h [new file with mode: 0644]
tests/speed/makefile
tests/speed/speed-tinyssh.c [new file with mode: 0644]

diff --git a/tests/externals/tinyssh/LICENCE b/tests/externals/tinyssh/LICENCE
new file mode 100644 (file)
index 0000000..0e259d4
--- /dev/null
@@ -0,0 +1,121 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+    HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+  i. the right to reproduce, adapt, distribute, perform, display,
+     communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+     likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+     subject to the limitations in paragraph 4(a), below;
+  v. rights protecting the extraction, dissemination, use and reuse of data
+     in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+     European Parliament and of the Council of 11 March 1996 on the legal
+     protection of databases, and under any national implementation
+     thereof, including any amended or successor version of such
+     directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+     world based on applicable law or treaty, and any national
+     implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+    surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+    warranties of any kind concerning the Work, express, implied,
+    statutory or otherwise, including without limitation warranties of
+    title, merchantability, fitness for a particular purpose, non
+    infringement, or the absence of latent or other defects, accuracy, or
+    the present or absence of errors, whether or not discoverable, all to
+    the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+    that may apply to the Work or any use thereof, including without
+    limitation any person's Copyright and Related Rights in the Work.
+    Further, Affirmer disclaims responsibility for obtaining any necessary
+    consents, permissions or other rights required for any use of the
+    Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+    party to this document and has no duty or obligation with respect to
+    this CC0 or use of the Work.
diff --git a/tests/externals/tinyssh/cleanup.c b/tests/externals/tinyssh/cleanup.c
new file mode 100644 (file)
index 0000000..e126d36
--- /dev/null
@@ -0,0 +1,9 @@
+#include "cleanup.h"
+
+void cleanup_(void *yv, long long ylen) {
+    volatile char *y = (volatile char *)yv;
+    while (ylen > 0) { *y++ = 0; --ylen; }
+#ifdef HASASMVOLATILEMEMORY
+    __asm__ __volatile__("" : : "r"(yv) : "memory");
+#endif
+}
diff --git a/tests/externals/tinyssh/cleanup.h b/tests/externals/tinyssh/cleanup.h
new file mode 100644 (file)
index 0000000..a42fcb3
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _CLEANUP_H____
+#define _CLEANUP_H____
+
+extern void cleanup_(void *, long long);
+#define cleanup(x) cleanup_((x), sizeof(x))
+
+#endif
diff --git a/tests/externals/tinyssh/crypto_hash_sha512.c b/tests/externals/tinyssh/crypto_hash_sha512.c
new file mode 100644 (file)
index 0000000..06a2d9e
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+20180104
+*/
+/*
+- based on tweetnacl 20140427 (http://tweetnacl.cr.yp.to/software.html)
+- slightly modified
+*/
+
+#include "crypto_hash_sha512.h"
+
+static void store64_bigendian(unsigned char *y, unsigned long long x) {
+
+    long long i;
+
+    for (i = 7; i >= 0; --i) { y[i] = x; x >>= 8; }
+}
+
+static unsigned long long load64_bigendian(const unsigned char *x) {
+
+    unsigned long long y = 0;
+    long long i;
+
+    for (i = 0; i < 8; ++i) y = (y << 8) | x[i];
+    return y;
+}
+
+static unsigned long long R(unsigned long long x,int c) { return (x >> c) | ((x & 0xffffffffffffffffULL) << (64 - c)); }
+static unsigned long long Ch(unsigned long long x, unsigned long long y, unsigned long long z) { return (x & y) ^ (~x & z); }
+static unsigned long long Maj(unsigned long long x, unsigned long long y, unsigned long long z) { return (x & y) ^ (x & z) ^ (y & z); }
+static unsigned long long Sigma0(unsigned long long x) { return R(x, 28) ^ R(x, 34) ^ R(x, 39); }
+static unsigned long long Sigma1(unsigned long long x) { return R(x, 14) ^ R(x, 18) ^ R(x, 41); }
+static unsigned long long sigma0(unsigned long long x) { return R(x,  1) ^ R(x,  8) ^ (x >> 7); }
+static unsigned long long sigma1(unsigned long long x) { return R(x, 19) ^ R(x, 61) ^ (x >> 6); }
+
+static const unsigned long long K[80] = {
+    0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+    0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+    0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+    0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+    0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+    0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+    0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+    0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+    0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+    0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+    0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+    0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+    0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+    0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+    0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+    0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+    0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+    0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+    0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+    0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+static void blocks(unsigned long long *z, const unsigned char *m, unsigned long long n) {
+
+    unsigned long long b[8], a[8], w[80], t;
+    long long i, j;
+
+    for (i = 0; i < 8; ++i) a[i] = z[i];
+  
+    while (n >= 128) { 
+        for (i =  0; i < 16; ++i) w[i] = load64_bigendian(m + 8 * i);
+        for (i = 16; i < 80; ++i) w[i] = (sigma1(w[i - 2]) + w[i - 7] + sigma0(w[i - 15]) + w[i - 16]) & 0xffffffffffffffffULL;
+
+        for (i = 0; i < 80; ++i) {
+            for (j = 0; j < 8; ++j) b[j] = a[j];
+            t = a[7] + Sigma1(a[4]) + Ch(a[4], a[5], a[6]) + K[i] + w[i];
+            b[7] = t + Sigma0(a[0]) + Maj(a[0], a[1], a[2]);
+            b[3] += t;
+            for (j = 0; j < 8; ++j) a[(j + 1) % 8] = b[j] & 0xffffffffffffffffULL;
+        }
+    
+        for (i = 0; i < 8; ++i) { a[i] += z[i]; a[i] &= 0xffffffffffffffffULL; z[i] = a[i]; }
+    
+        m += 128;
+        n -= 128;
+    }
+}
+
+int crypto_hash_sha512_tinyssh(unsigned char *o,const unsigned char *m, unsigned long long n) {
+
+    long long i;
+    unsigned char x[256];
+    unsigned long long b = n;
+    unsigned long long h[8] = {
+        0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+        0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+    };
+
+    blocks(h, m, n);
+    m += n;
+    n &= 127;
+    m -= n;
+
+    for (i = 0; i < sizeof x; ++i) x[i] = 0;
+    for (i = 0; i < n; ++i) x[i] = m[i];
+    x[n] = 128;
+
+    n = 256 - 128 * (n < 112);
+    x[n - 9] = b >> 61;
+    store64_bigendian(x + n - 8, b << 3);
+    blocks(h, x, n);
+
+    for (i = 0; i < 8; ++i) store64_bigendian(o + 8 * i, h[i]);
+    return 0;
+}
diff --git a/tests/externals/tinyssh/crypto_hash_sha512.h b/tests/externals/tinyssh/crypto_hash_sha512.h
new file mode 100644 (file)
index 0000000..7b1d1ac
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef crypto_hash_sha512_H
+#define crypto_hash_sha512_H
+
+#define crypto_hash_sha512_tinyssh_BYTES 64
+extern int crypto_hash_sha512_tinyssh(unsigned char *, const unsigned char *, unsigned long long);
+
+#define crypto_hash_sha512 crypto_hash_sha512_tinyssh
+#define crypto_hash_sha512_BYTES crypto_hash_sha512_tinyssh_BYTES
+#define crypto_hash_sha512_IMPLEMENTATION "tinyssh"
+#define crypto_hash_sha512_VERSION "-"
+
+#endif
diff --git a/tests/externals/tinyssh/crypto_int64.h b/tests/externals/tinyssh/crypto_int64.h
new file mode 100644 (file)
index 0000000..acfd192
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef crypto_int64_h
+#define crypto_int64_h
+
+#include <stdint.h>
+
+typedef int64_t crypto_int64;
+
+#endif
diff --git a/tests/externals/tinyssh/crypto_onetimeauth_poly1305.c b/tests/externals/tinyssh/crypto_onetimeauth_poly1305.c
new file mode 100644 (file)
index 0000000..631e733
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+20200202
+*/
+/*
+Based on poly1305-donna (https://github.com/floodyberry/poly1305-opt/blob/master/extensions/poly1305_ref-32.c)
+- modified for NaCl API
+*/
+
+#include "crypto_onetimeauth_poly1305.h"
+
+/* clang-format off */
+static inline unsigned long unpack32(const unsigned char *x) {
+    return
+        (unsigned long) (x[0])                  \
+    | (((unsigned long) (x[1])) << 8)           \
+    | (((unsigned long) (x[2])) << 16)          \
+    | (((unsigned long) (x[3])) << 24);
+}
+static inline void pack32(unsigned char *x, unsigned long u) {
+    x[0] = u; u >>= 8;
+    x[1] = u; u >>= 8;
+    x[2] = u; u >>= 8;
+    x[3] = u;
+}
+
+int crypto_onetimeauth_poly1305_tinyssh(unsigned char *o, const unsigned char *m, unsigned long long n, const unsigned char *k) {
+
+    unsigned long h0, h1, h2, h3, h4;
+    unsigned long r0, r1, r2, r3, r4;
+    unsigned long     s1, s2, s3, s4;
+    unsigned long long d0, d1, d2, d3, d4;
+    unsigned long c, mask;
+    unsigned long long f;
+    long long i;
+
+
+    /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+    r0 = (unpack32(k +  0)     ) & 0x3ffffff;
+    r1 = (unpack32(k +  3) >> 2) & 0x3ffff03;
+    r2 = (unpack32(k +  6) >> 4) & 0x3ffc0ff;
+    r3 = (unpack32(k +  9) >> 6) & 0x3f03fff;
+    r4 = (unpack32(k + 12) >> 8) & 0x00fffff;
+
+    s1 = r1 * 5;
+    s2 = r2 * 5;
+    s3 = r3 * 5;
+    s4 = r4 * 5;
+
+    /* h = 0 */
+    h0 = h1 = h2 = h3 = h4 = 0;
+
+    while (n > 0) {
+        /* h += m[i] */
+        if (n >= 16) {
+            h0 += (unpack32(m     )     ) & 0x3ffffff;
+            h1 += (unpack32(m +  3) >> 2) & 0x3ffffff;
+            h2 += (unpack32(m +  6) >> 4) & 0x3ffffff;
+            h3 += (unpack32(m +  9) >> 6) & 0x3ffffff;
+            h4 += (unpack32(m + 12) >> 8) | 16777216;
+            m += 16;
+            n -= 16;
+        }
+        else {
+            unsigned char mm[16];
+            for (i = 0; i < 16; ++i) mm[i] = 0;
+            for (i = 0; i <  n; ++i) mm[i] = m[i];
+            mm[i] = 1;
+            h0 += (unpack32(mm     )     ) & 0x3ffffff;
+            h1 += (unpack32(mm +  3) >> 2) & 0x3ffffff;
+            h2 += (unpack32(mm +  6) >> 4) & 0x3ffffff;
+            h3 += (unpack32(mm +  9) >> 6) & 0x3ffffff;
+            h4 += (unpack32(mm + 12) >> 8);
+            n = 0;
+        }
+
+        /* h *= r */
+        d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1);
+        d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2);
+        d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3);
+        d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4);
+        d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0);
+
+        /* (partial) h %= p */
+                      c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff;
+        d1 += c;      c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff;
+        d2 += c;      c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff;
+        d3 += c;      c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff;
+        d4 += c;      c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff;
+        h0 += c * 5;  c =                (h0 >> 26); h0 =                h0 & 0x3ffffff;
+        h1 += c;
+    }
+
+
+    /* fully carry h */
+                 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;
+
+    /* compute h + -p */
+    r0 = h0 + 5; c = r0 >> 26; r0 &= 0x3ffffff;
+    r1 = h1 + c; c = r1 >> 26; r1 &= 0x3ffffff;
+    r2 = h2 + c; c = r2 >> 26; r2 &= 0x3ffffff;
+    r3 = h3 + c; c = r3 >> 26; r3 &= 0x3ffffff;
+    r4 = h4 + c - (1 << 26);
+
+    /* select h if h < p, or h + -p if h >= p */
+    mask = (r4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
+    r0 &= mask;
+    r1 &= mask;
+    r2 &= mask;
+    r3 &= mask;
+    r4 &= mask;
+    mask = ~mask;
+    h0 = (h0 & mask) | r0;
+    h1 = (h1 & mask) | r1;
+    h2 = (h2 & mask) | r2;
+    h3 = (h3 & mask) | r3;
+    h4 = (h4 & mask) | r4;
+
+    /* 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;
+
+    /* mac = (h + pad) % (2^128) */
+    f = (unsigned long long)h0 + unpack32(k + 16)            ; h0 = (unsigned long)f;
+    f = (unsigned long long)h1 + unpack32(k + 20) + (f >> 32); h1 = (unsigned long)f;
+    f = (unsigned long long)h2 + unpack32(k + 24) + (f >> 32); h2 = (unsigned long)f;
+    f = (unsigned long long)h3 + unpack32(k + 28) + (f >> 32); h3 = (unsigned long)f;
+
+    pack32(o +  0, h0);
+    pack32(o +  4, h1);
+    pack32(o +  8, h2);
+    pack32(o + 12, h3);
+
+    return 0;
+}
+
+int crypto_onetimeauth_poly1305_tinyssh_verify(const unsigned char *h, const unsigned char *in, unsigned long long l, const unsigned char *k) {
+
+    unsigned char correct[16];
+    unsigned int d = 0;
+    long long i;
+
+    crypto_onetimeauth_poly1305(correct, in, l, k);
+
+    for (i = 0; i < 16; ++i) d |= correct[i] ^ h[i];
+    return (1 & ((d - 1) >> 8)) - 1;
+}
+/* clang-format on */
diff --git a/tests/externals/tinyssh/crypto_onetimeauth_poly1305.h b/tests/externals/tinyssh/crypto_onetimeauth_poly1305.h
new file mode 100644 (file)
index 0000000..3d9f9ea
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef crypto_onetimeauth_poly1305_H
+#define crypto_onetimeauth_poly1305_H
+
+#define crypto_onetimeauth_poly1305_tinyssh_BYTES 16
+#define crypto_onetimeauth_poly1305_tinyssh_KEYBYTES 32
+extern int crypto_onetimeauth_poly1305_tinyssh(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
+extern int crypto_onetimeauth_poly1305_tinyssh_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
+
+#define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tinyssh
+#define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tinyssh_verify
+#define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tinyssh_BYTES
+#define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tinyssh_KEYBYTES
+#define crypto_onetimeauth_poly1305_IMPLEMENTATION "tinyssh"
+#define crypto_onetimeauth_poly1305_VERSION "-"
+
+#endif
diff --git a/tests/externals/tinyssh/crypto_scalarmult_curve25519.c b/tests/externals/tinyssh/crypto_scalarmult_curve25519.c
new file mode 100644 (file)
index 0000000..6681128
--- /dev/null
@@ -0,0 +1,73 @@
+#include "cleanup.h"
+#include "fe25519.h"
+#include "crypto_scalarmult_curve25519.h"
+
+int crypto_scalarmult_curve25519_tinyssh(unsigned char *q, const unsigned char *n, const unsigned char *p) {
+
+    unsigned char e[32];
+    fe x1, x2, z2, x3, z3, tmp0, tmp1;
+    long long i;
+    unsigned int d = 0;
+    int pos;
+    crypto_uint32 swap, b;
+
+    for (i = 0; i < 32; ++i) e[i] = n[i];
+    e[0] &= 248;
+    e[31] &= 127;
+    e[31] |= 64;
+    fe25519_frombytes(x1, p);
+    fe_1(x2);
+    fe_0(z2);
+    fe_copy(x3, x1);
+    fe_1(z3);
+
+    swap = 0;
+    for (pos = 254; pos >= 0; --pos) {
+        b = e[pos / 8] >> (pos & 7);
+        b &= 1;
+        swap ^= b;
+        fe_cswap(x2, x3, swap);
+        fe_cswap(z2, z3, swap);
+        swap = b;
+
+        fe25519_sub(tmp0, x3, z3);
+        fe25519_sub(tmp1, x2, z2);
+        fe25519_add(x2, x2, z2);
+        fe25519_add(z2, x3, z3);
+        fe25519_mul(z3, tmp0, x2);
+        fe25519_mul(z2, z2, tmp1);
+        fe25519_sq(tmp0, tmp1);
+        fe25519_sq(tmp1, x2);
+        fe25519_add(x3, z3, z2);
+        fe25519_sub(z2, z3, z2);
+        fe25519_mul(x2, tmp1, tmp0);
+        fe25519_sub(tmp1, tmp1, tmp0);
+        fe25519_sq(z2, z2);
+        fe25519_mul121666(z3, tmp1);
+        fe25519_sq(x3, x3);
+        fe25519_add(tmp0, tmp0, z3);
+        fe25519_mul(z3, x1, z2);
+        fe25519_mul(z2, tmp1, tmp0);
+    }
+
+    fe_cswap(x2, x3, swap);
+    fe_cswap(z2, z3, swap);
+
+    fe25519_inv(z2, z2);
+    fe25519_mul(x2, x2, z2);
+    fe25519_tobytes(q, x2);
+
+    cleanup(e);
+    cleanup(tmp0); cleanup(tmp1);
+    cleanup(x1); cleanup(x2); cleanup(x3);
+    cleanup(z2); cleanup(z3);
+
+    for (i = 0; i < 32; ++i) d |= q[i];
+    return -(1 & ((d - 1) >> 8));
+}
+
+static const unsigned char basepoint[32] = {9};
+
+int crypto_scalarmult_curve25519_tinyssh_base(unsigned char *q, const unsigned char *n) {
+    return crypto_scalarmult_curve25519_tinyssh(q, n, basepoint);
+}
diff --git a/tests/externals/tinyssh/crypto_scalarmult_curve25519.h b/tests/externals/tinyssh/crypto_scalarmult_curve25519.h
new file mode 100644 (file)
index 0000000..98a3ccf
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef crypto_scalarmult_curve25519_H
+#define crypto_scalarmult_curve25519_H
+
+#define crypto_scalarmult_curve25519_tinyssh_BYTES 32
+#define crypto_scalarmult_curve25519_tinyssh_SCALARBYTES 32
+extern int crypto_scalarmult_curve25519_tinyssh(unsigned char *,const unsigned char *,const unsigned char *);
+extern int crypto_scalarmult_curve25519_tinyssh_base(unsigned char *,const unsigned char *);
+
+#define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tinyssh
+#define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tinyssh_base
+#define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tinyssh_BYTES
+#define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tinyssh_SCALARBYTES
+#define crypto_scalarmult_curve25519_IMPLEMENTATION "tinyssh"
+#define crypto_scalarmult_curve25519_VERSION "-"
+
+#endif
diff --git a/tests/externals/tinyssh/crypto_sign_ed25519.c b/tests/externals/tinyssh/crypto_sign_ed25519.c
new file mode 100644 (file)
index 0000000..d16164c
--- /dev/null
@@ -0,0 +1,121 @@
+#include "randombytes.h"
+#include "cleanup.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_verify_32.h"
+#include "ge25519.h"
+#include "sc25519.h"
+#include "crypto_sign_ed25519.h"
+
+int crypto_sign_ed25519_tinyssh(unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long n, const unsigned char *skorig) {
+
+    long long i;
+    unsigned char nonce[64], hram[64], sk[64], pk[32];
+    ge25519 R;
+
+    /* compute secret key from seed sk = H(skorig), H = sha512 */
+    crypto_hash_sha512(sk, skorig, 32);
+    sk[0] &= 248;
+    sk[31] &= 63;
+    sk[31] |= 64;
+
+    /* copy m to sm, copy secret key and public key */
+    *smlen = n + 64;
+    for (i = 31; i >= 0; --i) pk[i     ] = skorig[i + 32];
+    for (i = n - 1; i >= 0; --i) sm[i + 64] = m[i];
+    for (i = 31; i >= 0; --i) sm[i + 32] = sk[i + 32];
+
+    /* get pseudorandom nonce = H(sk2, m) */
+    crypto_hash_sha512(nonce, sm + 32, n + 32);
+    sc25519_reduce(nonce);
+
+    /* copy pk to sm */
+    for (i = 31; i >= 0; --i) sm[i + 32] = pk[i];
+
+    /* compute R */
+    ge25519_scalarmult_base(R, nonce);
+    ge25519_tobytes(sm, R);
+
+    /* calculate hram = H(r, a, m) */
+    crypto_hash_sha512(hram, sm, n + 64);
+    sc25519_reduce(hram);
+
+    /* compute S */
+    sc25519_muladd(sm + 32, hram, sk, nonce);
+
+    /* cleanup */
+    cleanup(nonce); cleanup(hram); cleanup(sk); cleanup(pk); cleanup(R);
+    return 0;
+}
+
+int crypto_sign_ed25519_tinyssh_open(unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long n, const unsigned char *pk) {
+
+    long long i;
+    unsigned char pkcopy[32], rcopy[32], scopy[32], hram[64], rcheck[32];
+    ge25519 R, S, A;
+    int ret = -1;
+
+    /* check input */
+    if (n < 64) goto fail;
+    if (sm[63] & 224) goto fail;
+
+    /* unpack pk */
+    if (ge25519_frombytes_negate_vartime(A, pk) != 0) goto fail;
+
+    /* copy pk, r, s */
+    for (i = 0; i < 32; ++i) pkcopy[i] = pk[i];
+    for (i = 0; i < 32; ++i) rcopy[i]  = sm[i];
+    for (i = 0; i < 32; ++i) scopy[i]  = sm[i + 32];
+
+    /* copy sm to m and copy pk to m */
+    for (i = n - 1; i >= 0; --i) m[i] = sm[i];
+    for (i = 0; i < 32; ++i) m[i + 32] = pkcopy[i];
+
+    /* calculate hram = H(r, a, m) */
+    crypto_hash_sha512(hram, m, n);
+    sc25519_reduce(hram);
+
+    /* compute R */
+    ge25519_scalarmult(A, A, hram);
+    ge25519_scalarmult_base(S, scopy);
+    ge25519_add(R, S, A);
+
+    /* check R */
+    ge25519_tobytes(rcheck, R);
+    if (crypto_verify_32(rcheck, rcopy) != 0) goto fail;
+
+    /* copy message */
+    n -= 64; *mlen = n;
+    for (i = 0; i <  n; ++i) m[i] = m[i + 64];
+    for (i = 0; i < 64; ++i) m[i + n] = 0;
+    ret = 0;
+    goto cleanup;
+
+fail:
+    for (i = 0; i < n; ++i) m[i] = 0;
+
+cleanup:
+    cleanup(pkcopy); cleanup(rcopy); cleanup(scopy);
+    cleanup(hram); cleanup(rcheck);
+    cleanup(R); cleanup(S); cleanup(A);
+    return ret;
+}
+
+int crypto_sign_ed25519_tinyssh_keypair(unsigned char *pk, unsigned char *sk) {
+
+    unsigned char h[64];
+    ge25519 A;
+    long long i;
+
+    randombytes(sk, 32);
+    crypto_hash_sha512(h, sk, 32);
+    h[0] &= 248;
+    h[31] &= 63;
+    h[31] |= 64;
+
+    ge25519_scalarmult_base(A, h);
+    ge25519_tobytes(pk, A);
+
+    for (i = 31; i >= 0; --i) sk[i + 32] = pk[i];
+    cleanup(h); cleanup(A);
+    return 0;
+}
diff --git a/tests/externals/tinyssh/crypto_sign_ed25519.h b/tests/externals/tinyssh/crypto_sign_ed25519.h
new file mode 100644 (file)
index 0000000..e777efa
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef crypto_sign_ed25519_H
+#define crypto_sign_ed25519_H
+
+#define crypto_sign_ed25519_tinyssh_SECRETKEYBYTES 64
+#define crypto_sign_ed25519_tinyssh_PUBLICKEYBYTES 32
+#define crypto_sign_ed25519_tinyssh_BYTES 64
+extern int crypto_sign_ed25519_tinyssh(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
+extern int crypto_sign_ed25519_tinyssh_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
+extern int crypto_sign_ed25519_tinyssh_keypair(unsigned char *,unsigned char *);
+
+#define crypto_sign_ed25519 crypto_sign_ed25519_tinyssh
+#define crypto_sign_ed25519_open crypto_sign_ed25519_tinyssh_open
+#define crypto_sign_ed25519_keypair crypto_sign_ed25519_tinyssh_keypair
+#define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tinyssh_BYTES
+#define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_tinyssh_PUBLICKEYBYTES
+#define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_tinyssh_SECRETKEYBYTES
+#define crypto_sign_ed25519_IMPLEMENTATION "tinyssh"
+#define crypto_sign_ed25519_VERSION "-"
+
+#endif
diff --git a/tests/externals/tinyssh/crypto_stream_chacha20.c b/tests/externals/tinyssh/crypto_stream_chacha20.c
new file mode 100644 (file)
index 0000000..6104a4c
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+20210508
+Jan Mojzis
+Public domain.
+*/
+
+#include <stdint.h>
+#include "crypto_stream_chacha20.h"
+
+/* clang-format off */
+static inline uint32_t unpack32(const unsigned char *x) {
+    return
+        (uint32_t) (x[0])                  \
+    | (((uint32_t) (x[1])) << 8)           \
+    | (((uint32_t) (x[2])) << 16)          \
+    | (((uint32_t) (x[3])) << 24);
+}
+static inline void pack32(unsigned char *x, uint32_t u) {
+    x[0] = u; u >>= 8;
+    x[1] = u; u >>= 8;
+    x[2] = u; u >>= 8;
+    x[3] = u;
+}
+
+#define ROTATE(x, c) ((x) << (c)) ^ ((x) >> (32 - (c)))
+
+#define QUARTERROUND(a, b, c, d)                    \
+    a += b; d = ROTATE(d ^ a, 16);                  \
+    c += d; b = ROTATE(b ^ c, 12);                  \
+    a += b; d = ROTATE(d ^ a,  8);                  \
+    c += d; b = ROTATE(b ^ c,  7);
+
+#define TWOROUNDS                                   \
+    QUARTERROUND( x0, x4,  x8, x12)                 \
+    QUARTERROUND( x1, x5,  x9, x13)                 \
+    QUARTERROUND( x2, x6, x10, x14)                 \
+    QUARTERROUND( x3, x7, x11, x15)                 \
+    QUARTERROUND( x0, x5, x10, x15)                 \
+    QUARTERROUND( x1, x6, x11, x12)                 \
+    QUARTERROUND( x2, x7,  x8, x13)                 \
+    QUARTERROUND( x3, x4,  x9, x14)
+
+#define XORBLOCK(o, i)                              \
+    x0  = s0;                                       \
+    x1  = s1;                                       \
+    x2  = s2;                                       \
+    x3  = s3;                                       \
+    x4  = k0;                                       \
+    x5  = k1;                                       \
+    x6  = k2;                                       \
+    x7  = k3;                                       \
+    x8  = k4;                                       \
+    x9  = k5;                                       \
+    x10 = k6;                                       \
+    x11 = k7;                                       \
+    x12 = n0;                                       \
+    x13 = n1;                                       \
+    x14 = n2;                                       \
+    x15 = n3;                                       \
+                                                    \
+    TWOROUNDS /* round  1,  2 */                    \
+    TWOROUNDS /* round  3,  4 */                    \
+    TWOROUNDS /* round  5,  6 */                    \
+    TWOROUNDS /* round  7,  8 */                    \
+    TWOROUNDS /* round  9, 10 */                    \
+    TWOROUNDS /* round 11, 12 */                    \
+    TWOROUNDS /* round 13, 14 */                    \
+    TWOROUNDS /* round 15, 16 */                    \
+    TWOROUNDS /* round 17, 18 */                    \
+    TWOROUNDS /* round 19, 20 */                    \
+                                                    \
+    pack32(o     ,  (x0 + s0) ^ unpack32(i     ));  \
+    pack32(o +  4,  (x1 + s1) ^ unpack32(i +  4));  \
+    pack32(o +  8,  (x2 + s2) ^ unpack32(i +  8));  \
+    pack32(o + 12,  (x3 + s3) ^ unpack32(i + 12));  \
+    pack32(o + 16,  (x4 + k0) ^ unpack32(i + 16));  \
+    pack32(o + 20,  (x5 + k1) ^ unpack32(i + 20));  \
+    pack32(o + 24,  (x6 + k2) ^ unpack32(i + 24));  \
+    pack32(o + 28,  (x7 + k3) ^ unpack32(i + 28));  \
+    pack32(o + 32,  (x8 + k4) ^ unpack32(i + 32));  \
+    pack32(o + 36,  (x9 + k5) ^ unpack32(i + 36));  \
+    pack32(o + 40, (x10 + k6) ^ unpack32(i + 40));  \
+    pack32(o + 44, (x11 + k7) ^ unpack32(i + 44));  \
+    pack32(o + 48, (x12 + n0) ^ unpack32(i + 48));  \
+    pack32(o + 52, (x13 + n1) ^ unpack32(i + 52));  \
+    pack32(o + 56, (x14 + n2) ^ unpack32(i + 56));  \
+    pack32(o + 60, (x15 + n3) ^ unpack32(i + 60));
+
+int crypto_stream_chacha20_tinyssh_xor(unsigned char *c, const unsigned char *m, unsigned long long l, const unsigned char *n, const unsigned char *k) {
+
+    register uint32_t x0, x1, x2, x3, x4, x5, x6, x7;
+    register uint32_t x8, x9, x10, x11, x12, x13, x14, x15;
+    uint32_t k0 = unpack32(k     );
+    uint32_t k1 = unpack32(k +  4);
+    uint32_t k2 = unpack32(k +  8);
+    uint32_t k3 = unpack32(k + 12);
+    uint32_t k4 = unpack32(k + 16);
+    uint32_t k5 = unpack32(k + 20);
+    uint32_t k6 = unpack32(k + 24);
+    uint32_t k7 = unpack32(k + 28);
+    uint32_t n0 = 0;
+    uint32_t n1 = 0;
+    uint32_t n2 = unpack32(n    );
+    uint32_t n3 = unpack32(n + 4);
+    uint32_t s0 = 0x61707865;
+    uint32_t s1 = 0x3320646E;
+    uint32_t s2 = 0x79622D32;
+    uint32_t s3 = 0x6B206574;
+    uint64_t u = 0;
+
+    if (!l) return 0;
+
+    while (l >= 64) {
+        XORBLOCK(c, m);
+
+        if (!++u) return -1;
+        n0 = u;
+        n1 = u >> 32;
+
+        l -= 64;
+        c += 64;
+        m += 64;
+    }
+    if (l) {
+        unsigned char b[64] = {0};
+        unsigned long long j;
+
+        for (j = 0; j < l; ++j) b[j] = m[j];
+        XORBLOCK(b, b);
+        for (j = 0; j < l; ++j) c[j] = b[j];
+    }
+    return 0;
+}
+
+int crypto_stream_chacha20_tinyssh(unsigned char *c, unsigned long long l, const unsigned char *n, const unsigned char *k) {
+
+    unsigned long long j;
+    unsigned char ncopy[8], kcopy[32];
+
+    for (j = 0; j < 32; ++j) kcopy[j] = k[j];
+    for (j = 0; j <  8; ++j) ncopy[j] = n[j];
+    for (j = 0; j <  l; ++j) c[j] = 0;
+    return crypto_stream_chacha20_tinyssh_xor(c, c, l, ncopy, kcopy);
+}
+/* clang-format on */
diff --git a/tests/externals/tinyssh/crypto_stream_chacha20.h b/tests/externals/tinyssh/crypto_stream_chacha20.h
new file mode 100644 (file)
index 0000000..1451757
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef crypto_stream_chacha20_H
+#define crypto_stream_chacha20_H
+
+#define crypto_stream_chacha20_tinyssh_KEYBYTES 32
+#define crypto_stream_chacha20_tinyssh_NONCEBYTES 8
+extern int crypto_stream_chacha20_tinyssh(unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
+extern int crypto_stream_chacha20_tinyssh_xor(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
+
+#define crypto_stream_chacha20 crypto_stream_chacha20_tinyssh
+#define crypto_stream_chacha20_xor crypto_stream_chacha20_tinyssh_xor
+#define crypto_stream_chacha20_KEYBYTES crypto_stream_chacha20_tinyssh_KEYBYTES
+#define crypto_stream_chacha20_NONCEBYTES crypto_stream_chacha20_tinyssh_NONCEBYTES
+#define crypto_stream_chacha20_IMPLEMENTATION "tinyssh"
+#define crypto_stream_chacha20_VERSION "-"
+
+#endif
diff --git a/tests/externals/tinyssh/crypto_uint32.h b/tests/externals/tinyssh/crypto_uint32.h
new file mode 100644 (file)
index 0000000..73f22b1
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef crypto_uint32_h
+#define crypto_uint32_h
+
+#include <stdint.h>
+
+typedef uint32_t crypto_uint32;
+
+#endif
diff --git a/tests/externals/tinyssh/crypto_uint64.h b/tests/externals/tinyssh/crypto_uint64.h
new file mode 100644 (file)
index 0000000..b1b47a9
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef crypto_uint64_h
+#define crypto_uint64_h
+
+#include <stdint.h>
+
+typedef uint64_t crypto_uint64;
+
+#endif
diff --git a/tests/externals/tinyssh/crypto_verify_32.c b/tests/externals/tinyssh/crypto_verify_32.c
new file mode 100644 (file)
index 0000000..a7b5bec
--- /dev/null
@@ -0,0 +1,6 @@
+#include "verify.h"
+#include "crypto_verify_32.h"
+
+int crypto_verify_32_tinyssh(const unsigned char *x, const unsigned char *y) {
+    return verify(x, y, 32);
+}
diff --git a/tests/externals/tinyssh/crypto_verify_32.h b/tests/externals/tinyssh/crypto_verify_32.h
new file mode 100644 (file)
index 0000000..87767b9
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef crypto_verify_32_H
+#define crypto_verify_32_H
+
+#define crypto_verify_32_tinyssh_BYTES 32
+extern int crypto_verify_32_tinyssh(const unsigned char *, const unsigned char *);
+
+#define crypto_verify_32 crypto_verify_32_tinyssh
+#define crypto_verify_32_BYTES crypto_verify_32_tinyssh_BYTES
+#define crypto_verify_32_IMPLEMENTATION "tinyssh"
+#define crypto_verify_32_VERSION "-"
+
+#endif
diff --git a/tests/externals/tinyssh/fe.c b/tests/externals/tinyssh/fe.c
new file mode 100644 (file)
index 0000000..cf66d8d
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+20140918
+Jan Mojzis
+Public domain.
+*/
+
+#include "fe.h"
+
+/*
+o = 0
+*/
+void fe_0(fe o) {
+
+    long long i;
+    for (i = 0; i < 8; ++i) o[i] = 0;
+}
+
+/*
+o = 1
+*/
+void fe_1(fe o) {
+
+    fe_0(o);
+    o[0] = 1;
+}
+
+/*
+o = x
+*/
+void fe_copy(fe o, const fe x) {
+
+    long long i;
+    for (i = 0; i < 8; ++i) o[i] = x[i];
+}
+
+/*
+if (b) swap(f, g)
+*/
+void fe_cswap(fe f, fe g, crypto_uint32 b) {
+
+    long long i;
+    fe t;
+
+    b = -b;
+
+    for (i = 0; i < 8; ++i) t[i] = b & (f[i] ^ g[i]);
+    for (i = 0; i < 8; ++i) f[i] ^= t[i];
+    for (i = 0; i < 8; ++i) g[i] ^= t[i];
+    fe_0(t);
+}
+
+/*
+if (b) f = g
+*/
+void fe_cmov(fe f, const fe g, crypto_uint32 b) {
+
+    long long i;
+    fe t;
+
+    b = -b;
+
+    for (i = 0; i < 8; ++i) t[i] = b & (f[i] ^ g[i]);
+    for (i = 0; i < 8; ++i) f[i] ^= t[i];
+    fe_0(t);
+}
+
+
+/* 
+o = a * b
+*/
+/*
+Implementation note: fe_mul_() is unrolled version of:
+void fe_mul_(fel o, const fe a, const fe b) {
+
+    crypto_uint64 u;
+    long long i, j;
+
+    for (i = 0; i < 16; ++i) o[i] = 0;
+    for (i = 0; i <  8; ++i) for (j = 0; j < 8; ++j) {
+        u = (crypto_uint64)a[i] * (crypto_uint64)b[j];
+        o[i + j    ] += u & 0xffffffff;
+        o[i + j + 1] += u >> 32;
+    }
+}
+*/
+#define M(i, j) u = (crypto_uint64)a[i] * (crypto_uint64)b[j]; \
+                o[i + j    ] += u & 0xffffffff; \
+                o[i + j + 1] += u >> 32;
+void fe_mul_(fel o, const fe a, const fe b) {
+
+    crypto_uint64 u;
+    long long i;
+
+    for (i = 0; i < 16; ++i) o[i] = 0;
+
+    M(0, 0); M(0, 1); M(0, 2); M(0, 3); M(0, 4); M(0, 5); M(0, 6); M(0, 7); 
+    M(1, 0); M(1, 1); M(1, 2); M(1, 3); M(1, 4); M(1, 5); M(1, 6); M(1, 7); 
+    M(2, 0); M(2, 1); M(2, 2); M(2, 3); M(2, 4); M(2, 5); M(2, 6); M(2, 7); 
+    M(3, 0); M(3, 1); M(3, 2); M(3, 3); M(3, 4); M(3, 5); M(3, 6); M(3, 7); 
+    M(4, 0); M(4, 1); M(4, 2); M(4, 3); M(4, 4); M(4, 5); M(4, 6); M(4, 7); 
+    M(5, 0); M(5, 1); M(5, 2); M(5, 3); M(5, 4); M(5, 5); M(5, 6); M(5, 7); 
+    M(6, 0); M(6, 1); M(6, 2); M(6, 3); M(6, 4); M(6, 5); M(6, 6); M(6, 7); 
+    M(7, 0); M(7, 1); M(7, 2); M(7, 3); M(7, 4); M(7, 5); M(7, 6); M(7, 7);
+}
+
+/* 
+o = x ^ 2 
+*/
+/*
+Implementation note: fe_sq_() is unrolled version of:
+void fe_sq_(fel o, const fe a) {
+
+    crypto_uint64 u;
+    long long i, j;
+
+    for (i = 0; i < 16; ++i) o[i] = 0;
+    for (i = 0; i <  8; ++i) for (j = i + 1; j < 8; ++j) {
+        u = (crypto_uint64)a[i] * (crypto_uint64)a[j];
+        o[i + j    ] += 2 * (u & 0xffffffff);
+        o[i + j + 1] += 2 * (u >> 32);
+    }
+    for (i = 0; i <  8; ++i) {
+        u = (crypto_uint64)a[i] * (crypto_uint64)a[i];
+        o[2 * i    ] +=     (u & 0xffffffff);
+        o[2 * i + 1] +=     (u >> 32);
+    }
+}
+*/
+#define M2(i, j) u = (crypto_uint64)a[i] * (crypto_uint64)a[j]; \
+                 o[i + j    ] += 2 * (u & 0xffffffff); \
+                 o[i + j + 1] += 2 * (u >> 32);
+#define SQ(i)    u = (crypto_uint64)a[i] * (crypto_uint64)a[i]; \
+                 o[2 * i    ] +=     (u & 0xffffffff); \
+                 o[2 * i + 1] +=     (u >> 32)
+void fe_sq_(fel o, const fe a) {
+
+    crypto_uint64 u;
+    long long i;
+
+    for (i = 0; i < 16; ++i) o[i] = 0;
+
+    M2(0, 1); M2(0, 2); M2(0, 3); M2(0, 4); M2(0, 5); M2(0, 6); M2(0, 7); 
+    M2(1, 2); M2(1, 3); M2(1, 4); M2(1, 5); M2(1, 6); M2(1, 7); 
+    M2(2, 3); M2(2, 4); M2(2, 5); M2(2, 6); M2(2, 7); 
+    M2(3, 4); M2(3, 5); M2(3, 6); M2(3, 7); 
+    M2(4, 5); M2(4, 6); M2(4, 7); 
+    M2(5, 6); M2(5, 7); 
+    M2(6, 7); 
+    SQ(0); SQ(1); SQ(2); SQ(3); SQ(4); SQ(5); SQ(6); SQ(7); 
+}
+
+/*
+if (p < r) r -= p
+*/
+void fe_reducesmall(fe r, const fe p, const crypto_uint64 carry) {
+
+    crypto_uint64 pb = 0, b;
+    long long i;
+    fe t;
+
+    for (i = 0; i < 8; ++i) {
+        pb += (crypto_uint64)p[i];
+        b = (crypto_uint64)r[i] - pb; b >>= 63;
+        t[i] = (crypto_uint64)r[i] - pb + (b << 32);
+        pb = b;
+    }
+    b = carry - pb; b >>= 63;
+    b -= 1;
+    for (i = 0; i < 8; ++i) r[i] ^= b & (r[i] ^ t[i]);
+    fe_0(t);
+}
diff --git a/tests/externals/tinyssh/fe.h b/tests/externals/tinyssh/fe.h
new file mode 100644 (file)
index 0000000..5eeb93d
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _FE_H____
+#define _FE_H____
+
+#include "crypto_uint32.h"
+#include "crypto_uint64.h"
+
+typedef crypto_uint32 fe[8];
+typedef crypto_uint64 fel[16];
+
+extern void fe_0(fe);
+extern void fe_1(fe);
+extern void fe_copy(fe, const fe);
+extern void fe_cswap(fe, fe, crypto_uint32);
+extern void fe_cmov(fe, const fe, crypto_uint32);
+
+extern void fe_mul_(fel, const fe, const fe);
+extern void fe_sq_(fel, const fe);
+
+extern void fe_reducesmall(fe, const fe, const crypto_uint64);
+
+#endif
diff --git a/tests/externals/tinyssh/fe25519.c b/tests/externals/tinyssh/fe25519.c
new file mode 100644 (file)
index 0000000..fb6e08e
--- /dev/null
@@ -0,0 +1,236 @@
+#include "uint32_pack.h"
+#include "uint32_unpack.h"
+#include "crypto_verify_32.h"
+#include "cleanup.h"
+#include "fe.h"
+#include "fe25519.h"
+
+/*
+p = 2^255 - 19
+*/
+static const fe p = { 
+    0xffffffed, 0xffffffff, 0xffffffff, 0xffffffff,
+    0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff
+};
+
+/*
+p3 = 3 * p
+*/
+static const crypto_uint64 p3[8] = { 
+    0x2ffffffc7ULL, 0x2fffffffdULL, 0x2fffffffdULL, 0x2fffffffdULL,
+    0x2fffffffdULL, 0x2fffffffdULL, 0x2fffffffdULL, 0x17ffffffdULL
+};
+
+/*
+reduction modulo p: 16 limbs -> 8 limbs
+*/
+static void fe25519_reducebig(fe o, fel t) {
+
+    crypto_uint64 u = 0;
+    long long i;
+
+    for (i = 0; i < 7; ++i) { u += t[i] + 38ULL * t[i + 8]; t[i] = u & 0xffffffff; u >>= 32; }
+    u += t[i] + 38ULL * t[i + 8]; t[i] = u & 0x7fffffff; u >>= 31;
+    u *= 19ULL;
+    for (i = 0; i < 8; ++i) { u += t[i]; o[i] = u & 0xffffffff; u >>= 32; }
+}
+
+/*
+o = (a * b) % p
+*/
+void fe25519_mul(fe o, const fe a, const fe b) {
+
+    fel t;
+
+    fe_mul_(t, a, b);
+    fe25519_reducebig(o, t);
+
+    cleanup(t);
+}
+
+/*
+o = (a ^ 2) % p
+*/
+void fe25519_sq(fe o, const fe a) {
+
+    fel t;
+
+    fe_sq_(t, a);
+    fe25519_reducebig(o, t);
+
+    cleanup(t);
+}
+
+/* 
+o = (121666 * f) % p; 
+*/
+void fe25519_mul121666(fe o, const fe f) {
+
+    crypto_uint64 u = 0;
+    long long i;
+
+    for (i = 0; i < 7; ++i) { u += (crypto_uint64)121666 * (crypto_uint64)f[i]; o[i] = u & 0xffffffff; u >>= 32; }
+    u += (crypto_uint64)121666 * (crypto_uint64)f[i]; o[i] = u & 0x7fffffff; u >>= 31;
+    u *= 19ULL;
+    for (i = 0; i < 8; ++i) { u += o[i]; o[i] = u & 0xffffffff; u >>= 32; }
+}
+
+/*
+o = (x + y) % p
+*/
+void fe25519_add(fe o, const fe x, const fe y) {
+
+    crypto_uint64 u = 0;
+    long long i;
+
+    for (i = 0; i < 7; ++i) { u += (crypto_uint64)x[i] + (crypto_uint64)y[i]; o[i] = u & 0xffffffff; u >>= 32; }
+    u += (crypto_uint64)x[i] + (crypto_uint64)y[i]; o[i] = u & 0x7fffffff; u >>= 31;
+    u *= 19ULL;
+    for (i = 0; i < 8; ++i) { u += o[i]; o[i] = u & 0xffffffff; u >>= 32; }
+}
+
+/*
+o = (x - y) % p
+*/
+void fe25519_sub(fe o, const fe x, const fe y) {
+
+    crypto_uint64 u = 0;
+    long long i;
+
+    for (i = 0; i < 7; ++i) { u += p3[i] - (crypto_uint64)y[i] + (crypto_uint64)x[i]; o[i] = u & 0xffffffff; u >>= 32; }
+    u += p3[i] - (crypto_uint64)y[i] + (crypto_uint64)x[i]; o[i] = u & 0x7fffffff; u >>= 31;
+    u *= 19ULL;
+    for (i = 0; i < 8; ++i) { u += o[i]; o[i] = u & 0xffffffff; u >>= 32; }
+}
+
+/*
+o = -x % p
+*/
+void fe25519_neg(fe o, const fe x) {
+
+    fe t;
+
+    fe_0(t);
+    fe25519_sub(o, t, x);
+}
+
+
+/* 
+o = (1 / z) % p
+... using Fermat's Little Theorem
+*/
+void fe25519_inv(fe o, const fe z) {
+
+    fe t0, t1, t2, t3;
+    long long  i;
+
+    fe25519_sq(t0, z); for (i = 1; i < 1; ++i) fe25519_sq(t0, t0);
+    fe25519_sq(t1,t0); for (i = 1; i < 2; ++i) fe25519_sq(t1, t1);
+    fe25519_mul(t1, z, t1);
+    fe25519_mul(t0, t0, t1);
+    fe25519_sq(t2, t0); for (i = 1; i < 1; ++i) fe25519_sq(t2, t2);
+    fe25519_mul(t1, t1, t2);
+    fe25519_sq(t2, t1); for (i = 1; i < 5; ++i) fe25519_sq(t2, t2);
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t2, t1); for (i = 1; i < 10; ++i) fe25519_sq(t2, t2);
+    fe25519_mul(t2, t2, t1);
+    fe25519_sq(t3, t2); for (i = 1; i < 20; ++i) fe25519_sq(t3, t3);
+    fe25519_mul(t2, t3, t2);
+    fe25519_sq(t2, t2); for (i = 1; i < 10; ++i) fe25519_sq(t2, t2);
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t2, t1); for (i = 1; i < 50; ++i) fe25519_sq(t2, t2);
+    fe25519_mul(t2, t2, t1);
+    fe25519_sq(t3, t2); for (i = 1; i < 100; ++i) fe25519_sq(t3, t3);
+    fe25519_mul(t2, t3, t2);
+    fe25519_sq(t2, t2); for (i = 1; i < 50; ++i) fe25519_sq(t2, t2);
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t1, t1); for (i = 1; i < 5; ++i) fe25519_sq(t1, t1);
+    fe25519_mul(o, t1, t0);
+
+    cleanup(t0); cleanup(t1); cleanup(t2); cleanup(t3);
+}
+
+void fe25519_pow22523(fe out, const fe z) {
+
+    fe t0, t1, t2;
+    long long i;
+
+    fe25519_sq(t0, z); for (i = 1; i < 1; ++i) fe25519_sq(t0, t0);
+    fe25519_sq(t1, t0); for (i = 1; i < 2; ++i) fe25519_sq(t1, t1);
+    fe25519_mul(t1, z, t1);
+    fe25519_mul(t0, t0, t1);
+    fe25519_sq(t0, t0); for (i = 1; i < 1; ++i) fe25519_sq(t0, t0);
+    fe25519_mul(t0, t1, t0);
+    fe25519_sq(t1, t0); for (i = 1; i < 5; ++i) fe25519_sq(t1, t1);
+    fe25519_mul(t0, t1, t0);
+    fe25519_sq(t1, t0); for (i = 1; i < 10; ++i) fe25519_sq(t1, t1);
+    fe25519_mul(t1, t1, t0);
+    fe25519_sq(t2, t1); for (i = 1; i < 20; ++i) fe25519_sq(t2, t2);
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t1, t1); for (i = 1; i < 10; ++i) fe25519_sq(t1, t1);
+    fe25519_mul(t0, t1, t0);
+    fe25519_sq(t1, t0); for (i = 1; i < 50; ++i) fe25519_sq(t1, t1);
+    fe25519_mul(t1, t1, t0);
+    fe25519_sq(t2, t1); for (i = 1; i < 100; ++i) fe25519_sq(t2, t2);
+    fe25519_mul(t1, t2, t1);
+    fe25519_sq(t1, t1); for (i = 1; i < 50; ++i) fe25519_sq(t1, t1);
+    fe25519_mul(t0, t1, t0);
+    fe25519_sq(t0, t0); for (i = 1; i < 2; ++i) fe25519_sq(t0, t0);
+    fe25519_mul(out, t0, z);
+
+    cleanup(t0); cleanup(t1); cleanup(t2);
+}
+
+/*
+converts field-element into byte-array
+*/
+void fe25519_tobytes(unsigned char *out, const fe in) {
+
+    long long i;
+    fe x;
+
+    fe_copy(x, in);
+    fe_reducesmall(x, p, 0);
+    for (i = 0; i < 8; ++i) uint32_pack(out + 4 * i, x[i]);
+    cleanup(x);
+}
+
+/*
+converts byte-array into field-element
+*/
+void fe25519_frombytes(fe out, const unsigned char *in) {
+
+    long long i;
+
+    for (i = 0; i < 8; ++i) out[i] = uint32_unpack(in + 4 * i);
+    out[7] &= 0x7fffffff;
+}
+
+
+/*
+if (f == 0) return 0;
+else return -1;
+*/
+static const unsigned char zero[32] = {0};
+int fe25519_isnonzero(const fe f) {
+    unsigned char s[32];
+    int r;
+    fe25519_tobytes(s, f);
+    r = crypto_verify_32(s, zero);
+    cleanup(s);
+    return r;
+}
+
+
+/*
+if (f >= 0) return 0;
+else return -1;
+*/
+int fe25519_isnegative(const fe f) {
+    unsigned char s[32];
+    int r;
+    fe25519_tobytes(s,f);
+    r = s[0] & 1;
+    cleanup(s);
+    return r;
+}
diff --git a/tests/externals/tinyssh/fe25519.h b/tests/externals/tinyssh/fe25519.h
new file mode 100644 (file)
index 0000000..2722d26
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _FE25519_H____
+#define _FE25519_H____
+
+#include "fe.h"
+
+extern void fe25519_mul(fe, const fe, const fe);
+extern void fe25519_sq(fe, const fe);
+extern void fe25519_add(fe, const fe, const fe);
+extern void fe25519_mul121666(fe, const fe);
+extern void fe25519_sub(fe, const fe, const fe);
+extern void fe25519_neg(fe, const fe);
+extern void fe25519_inv(fe, const fe);
+extern void fe25519_pow22523(fe, const fe);
+
+extern void fe25519_tobytes(unsigned char *, const fe);
+extern void fe25519_frombytes(fe, const unsigned char *);
+
+extern int fe25519_isnonzero(const fe);
+extern int fe25519_isnegative(const fe);
+
+#endif
+
diff --git a/tests/externals/tinyssh/ge25519.c b/tests/externals/tinyssh/ge25519.c
new file mode 100644 (file)
index 0000000..31af206
--- /dev/null
@@ -0,0 +1,226 @@
+#include "fe25519.h"
+#include "cleanup.h"
+#include "ge25519.h"
+
+/* D = -121665/121666 */
+static fe D = { 
+    0x135978a3, 0x75eb4dca, 0x4141d8ab, 0x00700a4d,
+    0x7779e898, 0x8cc74079, 0x2b6ffe73, 0x52036cee
+};
+/* D2 = 2 * -121665/121666 */
+static fe D2 = { 
+    0x26b2f159, 0xebd69b94, 0x8283b156, 0x00e0149a,
+    0xeef3d130, 0x198e80f2, 0x56dffce7, 0x2406d9dc
+};
+
+static fe sqrtm1 = {
+    0x4a0ea0b0, 0xc4ee1b27, 0xad2fe478, 0x2f431806,
+    0x3dfbd7a7, 0x2b4d0099, 0x4fc1df0b, 0x2b832480,
+};
+
+static void neutral(ge25519 p) {
+    fe_0(p[0]);
+    fe_1(p[1]);
+    fe_1(p[2]);
+    fe_0(p[3]);
+}
+
+
+/*
+p = q
+*/
+static void copy(ge25519 p, ge25519 q) {
+
+    fe_copy(p[0], q[0]);
+    fe_copy(p[1], q[1]);
+    fe_copy(p[2], q[2]);
+    fe_copy(p[3], q[3]);
+}
+
+
+/*
+if (b) p = q;
+*/
+static void cmov(ge25519 p, ge25519 q, crypto_uint32 b) {
+
+    fe_cmov(p[0], q[0], b);
+    fe_cmov(p[1], q[1], b);
+    fe_cmov(p[2], q[2], b);
+    fe_cmov(p[3], q[3], b);
+}
+
+void ge25519_add(ge25519 o, ge25519 p, ge25519 q) {
+
+    fe a, b, c, d, t, e, f, g, h;
+
+    fe25519_sub(a, p[1], p[0]);
+    fe25519_sub(t, q[1], q[0]);
+    fe25519_mul(a, a, t);
+    fe25519_add(b, p[0], p[1]);
+    fe25519_add(t, q[0], q[1]);
+    fe25519_mul(b, b, t);
+    fe25519_mul(c, p[3], q[3]);
+    fe25519_mul(c, c, D2);
+    fe25519_mul(d, p[2], q[2]);
+    fe25519_add(d, d, d);
+    fe25519_sub(e, b, a);
+    fe25519_sub(f, d, c);
+    fe25519_add(g, d, c);
+    fe25519_add(h, b, a);
+
+    fe25519_mul(o[0], e, f);
+    fe25519_mul(o[1], h, g);
+    fe25519_mul(o[2], g, f);
+    fe25519_mul(o[3], e, h);
+
+    cleanup(a); cleanup(b); cleanup(c); cleanup(d); cleanup(t);
+    cleanup(e); cleanup(f); cleanup(g); cleanup(h);
+}
+
+
+/* https://hyperelliptic.org/EFD/g1p/auto-code/twisted/extended/doubling/dbl-2008-hwcd.op3 */
+static void dbl(ge25519 o, ge25519 p) {
+
+    fe a, b, c, d, e, f, g, h;
+
+    fe25519_sq(a, p[0]);        /* A  = X1^2  */
+    fe25519_sq(b, p[1]);        /* B  = Y1^2  */
+    fe25519_sq(c, p[2]);        /* t0 = Z1^2  */
+    fe25519_add(c, c, c);       /* C  = 2*t0  */
+    fe25519_neg(d, a);          /* D  = a*A   */
+    fe25519_add(e, p[0], p[1]); /* t1 = X1+Y1 */
+    fe25519_sq(e, e);           /* t2 = t1^2  */
+    fe25519_sub(e, e, a);       /* t3 = t2-A  */
+    fe25519_sub(e, e, b);       /* E  = t3-B  */
+    fe25519_add(g, d, b);       /* G  = D+B   */
+    fe25519_sub(f, g, c);       /* F  = G-C   */
+    fe25519_sub(h, d, b);       /* H  = D-B   */
+
+    fe25519_mul(o[0], e, f);    /* X3 = E*F   */
+    fe25519_mul(o[1], g, h);    /* Y3 = G*H   */
+    fe25519_mul(o[2], f, g);    /* Z3 = F*G   */
+    fe25519_mul(o[3], e, h);    /* T3 = E*H   */
+
+    cleanup(a); cleanup(b); cleanup(c); cleanup(d);
+    cleanup(e); cleanup(f); cleanup(g); cleanup(h);
+}
+
+
+void ge25519_tobytes(unsigned char *s, ge25519 h) {
+
+    fe x, y, z;
+
+    fe25519_inv(z, h[2]);
+    fe25519_mul(x, h[0], z);
+    fe25519_mul(y, h[1], z);
+    fe25519_tobytes(s, y);
+    s[31] ^= fe25519_isnegative(x) << 7;
+
+    cleanup(x); cleanup(y); cleanup(z);
+}
+
+int ge25519_frombytes_negate_vartime(ge25519 h, const unsigned char *s) {
+
+    fe u, v, v3, vxx, check;
+    int ret = -1;
+
+    fe25519_frombytes(h[1], s);
+    fe_1(h[2]);
+    fe25519_sq(u,h[1]);
+    fe25519_mul(v,u,D);
+    fe25519_sub(u,u,h[2]);       /* u = y^2-1 */
+    fe25519_add(v,v,h[2]);       /* v = dy^2+1 */
+
+    fe25519_sq(v3,v);
+    fe25519_mul(v3,v3,v);        /* v3 = v^3 */
+    fe25519_sq(h[0],v3);
+    fe25519_mul(h[0],h[0],v);
+    fe25519_mul(h[0],h[0],u);    /* x = uv^7 */
+
+    fe25519_pow22523(h[0],h[0]); /* x = (uv^7)^((q-5)/8) */
+    fe25519_mul(h[0],h[0],v3);
+    fe25519_mul(h[0],h[0],u);    /* x = uv^3(uv^7)^((q-5)/8) */
+
+    fe25519_sq(vxx,h[0]);
+    fe25519_mul(vxx,vxx,v);
+    fe25519_sub(check,vxx,u);    /* vx^2-u */
+    if (fe25519_isnonzero(check)) {
+        fe25519_add(check,vxx,u);  /* vx^2+u */
+        if (fe25519_isnonzero(check)) {
+            goto cleanup;
+        }
+        fe25519_mul(h[0],h[0],sqrtm1);
+    }
+
+    if (fe25519_isnegative(h[0]) == (s[31] >> 7))
+        fe25519_neg(h[0], h[0]);
+
+    fe25519_mul(h[3],h[0],h[1]);
+    ret = 0;
+
+cleanup:
+    cleanup(u); cleanup(v); cleanup(v3);
+    cleanup(vxx); cleanup(check);
+    return ret;
+}
+
+
+/*
+if (a == b) return 1;
+else return 0;
+*/
+static unsigned char equal(unsigned char a, unsigned char b) {
+
+    unsigned char x = a ^ b;
+    crypto_uint32 y = x;
+    y -= 1;
+    y >>= 31;
+    return y;
+}
+
+/*
+point multiplication using windowed method 
+*/
+void ge25519_scalarmult(ge25519 o, ge25519 q, const unsigned char *a) {
+
+    long long i, j;
+    ge25519 t[16], sp, p;
+    unsigned char e[64];
+
+    for (i = 0; i < 32; ++i) {
+        e[2 * i + 0] = (a[i] >> 0) & 0x0f;
+        e[2 * i + 1] = (a[i] >> 4) & 0x0f;
+    }
+
+    neutral(p);
+
+    /* precompute points */
+    copy(t[0], p);
+    copy(t[1], q);
+    for (i = 2; i < 16; ++i) {
+        if ((i & 1) == 0) dbl(t[i], t[i / 2]);
+        else ge25519_add(t[i], t[i - 1], q);
+    }
+
+    for (i = 63; i >= 0; --i) {
+        for (j = 0; j < 4; ++j) dbl(p, p);
+        for (j = 0; j < 16; ++j) cmov(sp, t[j], equal(e[i], j));
+        ge25519_add(p, p, sp);
+    }
+
+    copy(o, p);
+
+    cleanup(p); cleanup(t); cleanup(sp); cleanup(e);
+}
+
+static ge25519 baseq = {
+  { 0x8f25d51a,0xc9562d60,0x9525a7b2,0x692cc760,0xfdd6dc5c,0xc0a4e231,0xcd6e53fe,0x216936d3 },
+  { 0x66666658,0x66666666,0x66666666,0x66666666,0x66666666,0x66666666,0x66666666,0x66666666 },
+  { 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 },
+  { 0xa5b7dda3,0x6dde8ab3,0x775152f5,0x20f09f80,0x64abe37d,0x66ea4e8e,0xd78b7665,0x67875f0f },
+ };
+
+void ge25519_scalarmult_base(ge25519 p, const unsigned char *a) {
+
+    ge25519_scalarmult(p, baseq, a);
+}
diff --git a/tests/externals/tinyssh/ge25519.h b/tests/externals/tinyssh/ge25519.h
new file mode 100644 (file)
index 0000000..0428b73
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _GE25519_H____
+#define _GE25519_H____
+
+#include "fe.h"
+
+typedef fe ge25519[4];          /* X, Y, Z, T */
+
+extern void ge25519_tobytes(unsigned char *, ge25519);
+extern int ge25519_frombytes_negate_vartime(ge25519, const unsigned char *);
+extern void ge25519_add(ge25519, ge25519, ge25519);
+extern void ge25519_scalarmult(ge25519, ge25519, const unsigned char *);
+extern void ge25519_scalarmult_base(ge25519, const unsigned char *);
+
+#endif
diff --git a/tests/externals/tinyssh/randombytes.c b/tests/externals/tinyssh/randombytes.c
new file mode 100644 (file)
index 0000000..95645a9
--- /dev/null
@@ -0,0 +1,41 @@
+/* taken from nacl-20110221, from randombytes/devurandom.c, added close-on-exec */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "randombytes.h"
+
+/* it's really stupid that there isn't a syscall for this */
+
+static int fd = -1;
+
+void randombytes(unsigned char *x,unsigned long long xlen)
+{
+  int i;
+
+  if (fd == -1) {
+    for (;;) {
+#ifdef O_CLOEXEC
+      fd = open("/dev/urandom",O_RDONLY | O_CLOEXEC);
+#else
+      fd = open("/dev/urandom",O_RDONLY);
+      fcntl(fd,F_SETFD,1);
+#endif
+      if (fd != -1) break;
+      sleep(1);
+    }
+  }
+
+  while (xlen > 0) {
+    if (xlen < 1048576) i = xlen; else i = 1048576;
+
+    i = read(fd,x,i);
+    if (i < 1) {
+      sleep(1);
+      continue;
+    }
+
+    x += i;
+    xlen -= i;
+  }
+}
diff --git a/tests/externals/tinyssh/randombytes.h b/tests/externals/tinyssh/randombytes.h
new file mode 100644 (file)
index 0000000..724104f
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _RANDOMBYTES_H____
+#define _RANDOMBYTES_H____
+
+extern void randombytes(unsigned char *, unsigned long long);
+
+#ifndef randombytes_implementation
+#define randombytes_implementation "tinyssh"
+#endif
+
+#endif
diff --git a/tests/externals/tinyssh/sc25519.c b/tests/externals/tinyssh/sc25519.c
new file mode 100644 (file)
index 0000000..12610c3
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+- based on tweetnacl 20140427 (http://tweetnacl.cr.yp.to/software.html)
+*/
+
+#include "crypto_int64.h"
+#include "crypto_uint32.h"
+#include "crypto_uint64.h"
+#include "cleanup.h"
+#include "sc25519.h"
+
+#define FOR(i,n) for (i = 0;i < n;++i)
+
+static const crypto_uint64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10};
+
+static void modL(unsigned char *r,crypto_int64 x[64])
+{
+  crypto_int64 carry,i,j;
+  for (i = 63;i >= 32;--i) {
+    carry = 0;
+    for (j = i - 32;j < i - 12;++j) {
+      x[j] += carry - 16 * x[i] * L[j - (i - 32)];
+      carry = (x[j] + 128) >> 8;
+      x[j] -= carry << 8;
+    }
+    x[j] += carry;
+    x[i] = 0;
+  }
+  carry = 0;
+  FOR(j,32) {
+    x[j] += carry - (x[31] >> 4) * L[j];
+    carry = x[j] >> 8;
+    x[j] &= 255;
+  }
+  FOR(j,32) x[j] -= carry * L[j];
+  FOR(i,32) {
+    x[i+1] += x[i] >> 8;
+    r[i] = x[i] & 255;
+  }
+}
+
+void sc25519_reduce(unsigned char *s) {
+
+    crypto_int64 t[64], i;
+
+    for (i = 0; i < 64; ++i) t[i] = s[i];
+    for (i = 0; i < 64; ++i) s[i] = 0;
+    modL(s, t);
+
+    cleanup(t);
+}
+
+void sc25519_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) {
+
+    crypto_int64 t[64], i, j;
+
+
+    for (i = 0; i < 64; ++i) t[i] = 0;
+
+    for (i = 0; i < 32; ++i) for (j = 0; j < 32; ++j) {
+        t[i + j] += (crypto_int64)a[i] * (crypto_int64)b[j];
+    }
+
+    for (i = 0; i < 32; ++i) t[i] += c[i];
+    modL(s, t);
+
+    cleanup(t);
+}
diff --git a/tests/externals/tinyssh/sc25519.h b/tests/externals/tinyssh/sc25519.h
new file mode 100644 (file)
index 0000000..c08df70
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _SC25519_H____
+#define _SC25519_H____
+
+extern void sc25519_reduce(unsigned char *);
+extern void sc25519_muladd(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *);
+
+#endif
diff --git a/tests/externals/tinyssh/uint32_pack.c b/tests/externals/tinyssh/uint32_pack.c
new file mode 100644 (file)
index 0000000..8bf87fb
--- /dev/null
@@ -0,0 +1,11 @@
+#include "uint32_pack.h"
+
+/*
+The 'uint32_pack' function converts 32-bit unsigned
+integer into 4 bytes stored in little-endian format
+*/
+void uint32_pack(unsigned char *y, crypto_uint32 x) {
+
+    long long i;
+    for (i = 0; i < 4; ++i) { y[i] = x; x >>= 8; }
+}
diff --git a/tests/externals/tinyssh/uint32_pack.h b/tests/externals/tinyssh/uint32_pack.h
new file mode 100644 (file)
index 0000000..6f4f053
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _UINT32_PACK_H____
+#define _UINT32_PACK_H____
+
+#include "crypto_uint32.h"
+
+extern void uint32_pack(unsigned char *, crypto_uint32);
+
+#endif
diff --git a/tests/externals/tinyssh/uint32_unpack.c b/tests/externals/tinyssh/uint32_unpack.c
new file mode 100644 (file)
index 0000000..172c65d
--- /dev/null
@@ -0,0 +1,13 @@
+#include "uint32_unpack.h"
+
+/*
+The 'uint32_unpack' function converts 4 bytes
+in little-endian format into 32-bit unsigned integer.
+*/
+crypto_uint32 uint32_unpack(const unsigned char *x) {
+
+    crypto_uint32 y = 0;
+    long long i;
+    for (i = 3; i >= 0; --i) y = (y << 8) | x[i];
+    return y;
+}
diff --git a/tests/externals/tinyssh/uint32_unpack.h b/tests/externals/tinyssh/uint32_unpack.h
new file mode 100644 (file)
index 0000000..fb0588a
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _UINT32_UNPACK_H____
+#define _UINT32_UNPACK_H____
+
+#include "crypto_uint32.h"
+
+extern crypto_uint32 uint32_unpack(const unsigned char *);
+
+#endif
diff --git a/tests/externals/tinyssh/verify.c b/tests/externals/tinyssh/verify.c
new file mode 100644 (file)
index 0000000..9dcf121
--- /dev/null
@@ -0,0 +1,10 @@
+#include "verify.h"
+
+int verify(const unsigned char *x, const unsigned char *y, long long n) {
+
+    unsigned int d = 0;
+    long long i;
+
+    for (i = 0; i < n; ++i) d |= x[i] ^ y[i];
+    return (1 & ((d - 1) >> 8)) - 1;
+}
diff --git a/tests/externals/tinyssh/verify.h b/tests/externals/tinyssh/verify.h
new file mode 100644 (file)
index 0000000..718b831
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _VERIFY_H____
+#define _VERIFY_H____
+
+extern int verify(const unsigned char *, const unsigned char *, long long);
+
+#endif
index c3098653717d3ac0800512fc5979aca588f6814f..5eecac6f31ebd09167fa067889af705afc711ac7 100644 (file)
@@ -63,12 +63,18 @@ CFLAGS= -pedantic -Wall -Wextra -O3 -march=native
 all: speed
 
 speed          : speed.out
+       ./$<
 speed-sodium   : speed-sodium.out
+       ./$<
 speed-hydrogen : speed-hydrogen.out
+       ./$<
 speed-tweetnacl: speed-tweetnacl.out
+       ./$<
 speed-c25519   : speed-c25519.out
+       ./$<
 speed-donna    : speed-donna.out
-speed speed-sodium speed-hydrogen speed-tweetnacl speed-c25519 speed-donna:
+       ./$<
+speed-tinyssh  : speed-tinyssh.out
        ./$<
 
 clean:
@@ -127,6 +133,40 @@ donna.o: ../externals/ed25519-donna/ed25519.c $(DONNA_HEADERS)
            -DED25519_NO_INLINE_ASM \
            -DED25519_FORCE_32BIT
 
+# Tinyssh
+TSSH=../externals/tinyssh
+TSSH_O= \
+       cleanup.o crypto_hash_sha512.o crypto_onetimeauth_poly1305.o         \
+       crypto_scalarmult_curve25519.o crypto_sign_ed25519.o                 \
+       crypto_stream_chacha20.o crypto_verify_32.o fe25519.o fe.o ge25519.o \
+       randombytes.o sc25519.o uint32_pack.o uint32_unpack.o verify.o
+TSSH_H= \
+       $(TSSH)/cleanup.h $(TSSH)/crypto_hash_sha512.h $(TSSH)/crypto_int64.h  \
+       $(TSSH)/crypto_onetimeauth_poly1305.h                                  \
+       $(TSSH)/crypto_scalarmult_curve25519.h $(TSSH)/crypto_sign_ed25519.h   \
+       $(TSSH)/crypto_stream_chacha20.h $(TSSH)/crypto_uint32.h               \
+       $(TSSH)/crypto_uint64.h $(TSSH)/crypto_verify_32.h $(TSSH)/fe25519.h   \
+       $(TSSH)/fe.h $(TSSH)/ge25519.h $(TSSH)/sc25519.h $(TSSH)/uint32_pack.h \
+       $(TSSH)/uint32_unpack.h $(TSSH)/verify.h
+
+cleanup.o                     : $(TSSH)/cleanup.c                      $(TSSH_H)
+crypto_hash_sha512.o          : $(TSSH)/crypto_hash_sha512.c           $(TSSH_H)
+crypto_onetimeauth_poly1305.o : $(TSSH)/crypto_onetimeauth_poly1305.c  $(TSSH_H)
+crypto_scalarmult_curve25519.o: $(TSSH)/crypto_scalarmult_curve25519.c $(TSSH_H)
+crypto_sign_ed25519.o         : $(TSSH)/crypto_sign_ed25519.c          $(TSSH_H)
+crypto_stream_chacha20.o      : $(TSSH)/crypto_stream_chacha20.c       $(TSSH_H)
+crypto_verify_32.o            : $(TSSH)/crypto_verify_32.c             $(TSSH_H)
+fe25519.o                     : $(TSSH)/fe25519.c                      $(TSSH_H)
+fe.o                          : $(TSSH)/fe.c                           $(TSSH_H)
+ge25519.o                     : $(TSSH)/ge25519.c                      $(TSSH_H)
+randombytes.o                 : $(TSSH)/randombytes.c                  $(TSSH_H)
+sc25519.o                     : $(TSSH)/sc25519.c                      $(TSSH_H)
+uint32_pack.o                 : $(TSSH)/uint32_pack.c                  $(TSSH_H)
+uint32_unpack.o               : $(TSSH)/uint32_unpack.c                $(TSSH_H)
+verify.o                      : $(TSSH)/verify.c                       $(TSSH_H)
+$(TSSH_O):
+       $(CC) -c $(CFLAGS) -I ../externals/tinyssh/ -o $@ $<
+
 
 ######################
 ## Speed benchmarks ##
@@ -143,6 +183,8 @@ speed-c25519.o    : speed-c25519.c    speed.h ../utils.h $(C25519_HEADERS)
        $(CC) -c $(CFLAGS) $< -o $@ -I .. -I ../externals/c25519
 speed-donna.o     : speed-donna.c     speed.h ../utils.h $(DONNA_HEADERS)
        $(CC) -c $(CFLAGS) $< -o $@ -I .. -I ../externals/ed25519-donna
+speed-tinyssh.o   : speed-tinyssh.c   speed.h ../utils.h $(TSSH_H)
+       $(CC) -c $(CFLAGS) $< -o $@ -I .. -I $(TSSH)
 
 speed.out: speed.o utils.o monocypher.o monocypher-ed25519.o
        $(CC) $(CFLAGS) -o $@ $^
@@ -162,3 +204,5 @@ speed-tweetnacl.out: speed-tweetnacl.o tweetnacl.o utils.o
        $(CC) $(CFLAGS) -o $@ $^
 speed-c25519.out   : speed-c25519.o $(C25519_OBJECTS) utils.o
        $(CC) $(CFLAGS) -o $@ $^
+speed-tinyssh.out : speed-tinyssh.o $(TSSH_O) utils.o
+       $(CC) $(CFLAGS) -o $@ $^
diff --git a/tests/speed/speed-tinyssh.c b/tests/speed/speed-tinyssh.c
new file mode 100644 (file)
index 0000000..9ac1a33
--- /dev/null
@@ -0,0 +1,159 @@
+// This file is dual-licensed.  Choose whichever licence you want from
+// the two licences listed below.
+//
+// The first licence is a regular 2-clause BSD licence.  The second licence
+// is the CC-0 from Creative Commons. It is intended to release Monocypher
+// to the public domain.  The BSD licence serves as a fallback option.
+//
+// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
+//
+// ------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2019, Loup Vaillant
+// All rights reserved.
+//
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the
+//    distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ------------------------------------------------------------------------
+//
+// Written in 2017-2019 by Loup Vaillant
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related 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
+// <https://creativecommons.org/publicdomain/zero/1.0/>
+
+#include "speed.h"
+#include "utils.h"
+
+int crypto_stream_chacha20_tinyssh(unsigned char *,
+                                   unsigned long long,
+                                   const unsigned char *,
+                                   const unsigned char *);
+
+int crypto_stream_chacha20_tinyssh_xor(unsigned char *,
+                                       const unsigned char *,
+                                       unsigned long long,
+                                       const unsigned char *,
+                                       const unsigned char *);
+
+static u64 chacha20(void)
+{
+       u8 out[SIZE];
+       RANDOM_INPUT(in   , SIZE);
+       RANDOM_INPUT(key  ,   32);
+       RANDOM_INPUT(nonce,    8);
+
+       TIMING_START {
+               crypto_stream_chacha20_tinyssh_xor(out, in, SIZE, nonce, key);
+       }
+       TIMING_END;
+}
+
+static u64 poly1305(void)
+{
+       u8 out[16];
+       RANDOM_INPUT(in , SIZE);
+       RANDOM_INPUT(key,   32);
+
+       TIMING_START {
+               crypto_onetimeauth_poly1305_tinyssh(out, in, SIZE, key);
+       }
+       TIMING_END;
+}
+
+static u64 sha512(void)
+{
+       u8 hash[64];
+       RANDOM_INPUT(in, SIZE);
+
+       TIMING_START {
+               crypto_hash_sha512_tinyssh(hash, in, SIZE);
+       }
+       TIMING_END;
+}
+
+static u64 x25519(void)
+{
+       u8 in [32] = {9};
+       u8 out[32] = {9};
+
+       TIMING_START {
+               crypto_scalarmult_curve25519_tinyssh(out, out, in);
+       }
+       TIMING_END;
+}
+
+static u64 edDSA_sign(void)
+{
+       u8 sk        [ 64];
+       u8 pk        [ 32];
+       u8 signed_msg[128];
+       unsigned long long sig_size;
+       RANDOM_INPUT(message, 64);
+       crypto_sign_ed25519_tinyssh_keypair(pk, sk);
+
+       TIMING_START {
+               crypto_sign_ed25519_tinyssh(signed_msg, &sig_size, message, 64, sk);
+       }
+       TIMING_END;
+}
+
+static u64 edDSA_check(void)
+{
+       u8 sk        [ 64];
+       u8 pk        [ 32];
+       u8 signed_msg[128];
+       u8 out_msg   [128];
+       unsigned long long sig_size;
+       unsigned long long msg_size;
+       RANDOM_INPUT(message, 64);
+       crypto_sign_ed25519_tinyssh_keypair(pk, sk);
+       crypto_sign_ed25519_tinyssh(signed_msg, &sig_size, message, 64, sk);
+
+       TIMING_START {
+               if (crypto_sign_ed25519_tinyssh_open(out_msg, &msg_size,
+                                                    signed_msg, sig_size, pk)) {
+                       printf("TweetNaCl verification failed\n");
+               }
+       }
+       TIMING_END;
+}
+
+int main()
+{
+       print("Chacha20    ",chacha20()     *MUL ,"megabytes  per second");
+       print("Poly1305    ",poly1305()     *MUL ,"megabytes  per second");
+       print("SHA-512     ",sha512()       *MUL ,"megabytes  per second");
+       print("x25519      ",x25519()            ,"exchanges  per second");
+       print("EdDSA(sign) ",edDSA_sign()        ,"signatures per second");
+       print("EdDSA(check)",edDSA_check()       ,"checks     per second");
+       printf("\n");
+       return 0;
+}