From: Loup Vaillant Date: Sun, 19 Mar 2023 21:54:48 +0000 (+0100) Subject: Add tinyssh speed tests X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=ea79193643274dbf75c09ca8ec2d60231d0d21b3;p=Monocypher.git Add tinyssh speed tests --- diff --git a/tests/externals/tinyssh/LICENCE b/tests/externals/tinyssh/LICENCE new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/tests/externals/tinyssh/LICENCE @@ -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 index 0000000..e126d36 --- /dev/null +++ b/tests/externals/tinyssh/cleanup.c @@ -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 index 0000000..a42fcb3 --- /dev/null +++ b/tests/externals/tinyssh/cleanup.h @@ -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 index 0000000..06a2d9e --- /dev/null +++ b/tests/externals/tinyssh/crypto_hash_sha512.c @@ -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 index 0000000..7b1d1ac --- /dev/null +++ b/tests/externals/tinyssh/crypto_hash_sha512.h @@ -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 index 0000000..acfd192 --- /dev/null +++ b/tests/externals/tinyssh/crypto_int64.h @@ -0,0 +1,8 @@ +#ifndef crypto_int64_h +#define crypto_int64_h + +#include + +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 index 0000000..631e733 --- /dev/null +++ b/tests/externals/tinyssh/crypto_onetimeauth_poly1305.c @@ -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 index 0000000..3d9f9ea --- /dev/null +++ b/tests/externals/tinyssh/crypto_onetimeauth_poly1305.h @@ -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 index 0000000..6681128 --- /dev/null +++ b/tests/externals/tinyssh/crypto_scalarmult_curve25519.c @@ -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 index 0000000..98a3ccf --- /dev/null +++ b/tests/externals/tinyssh/crypto_scalarmult_curve25519.h @@ -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 index 0000000..d16164c --- /dev/null +++ b/tests/externals/tinyssh/crypto_sign_ed25519.c @@ -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 index 0000000..e777efa --- /dev/null +++ b/tests/externals/tinyssh/crypto_sign_ed25519.h @@ -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 index 0000000..6104a4c --- /dev/null +++ b/tests/externals/tinyssh/crypto_stream_chacha20.c @@ -0,0 +1,145 @@ +/* +20210508 +Jan Mojzis +Public domain. +*/ + +#include +#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 index 0000000..1451757 --- /dev/null +++ b/tests/externals/tinyssh/crypto_stream_chacha20.h @@ -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 index 0000000..73f22b1 --- /dev/null +++ b/tests/externals/tinyssh/crypto_uint32.h @@ -0,0 +1,8 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include + +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 index 0000000..b1b47a9 --- /dev/null +++ b/tests/externals/tinyssh/crypto_uint64.h @@ -0,0 +1,8 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include + +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 index 0000000..a7b5bec --- /dev/null +++ b/tests/externals/tinyssh/crypto_verify_32.c @@ -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 index 0000000..87767b9 --- /dev/null +++ b/tests/externals/tinyssh/crypto_verify_32.h @@ -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 index 0000000..cf66d8d --- /dev/null +++ b/tests/externals/tinyssh/fe.c @@ -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 index 0000000..5eeb93d --- /dev/null +++ b/tests/externals/tinyssh/fe.h @@ -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 index 0000000..fb6e08e --- /dev/null +++ b/tests/externals/tinyssh/fe25519.c @@ -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 index 0000000..2722d26 --- /dev/null +++ b/tests/externals/tinyssh/fe25519.h @@ -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 index 0000000..31af206 --- /dev/null +++ b/tests/externals/tinyssh/ge25519.c @@ -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 index 0000000..0428b73 --- /dev/null +++ b/tests/externals/tinyssh/ge25519.h @@ -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 index 0000000..95645a9 --- /dev/null +++ b/tests/externals/tinyssh/randombytes.c @@ -0,0 +1,41 @@ +/* taken from nacl-20110221, from randombytes/devurandom.c, added close-on-exec */ +#include +#include +#include +#include +#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 index 0000000..724104f --- /dev/null +++ b/tests/externals/tinyssh/randombytes.h @@ -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 index 0000000..12610c3 --- /dev/null +++ b/tests/externals/tinyssh/sc25519.c @@ -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 index 0000000..c08df70 --- /dev/null +++ b/tests/externals/tinyssh/sc25519.h @@ -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 index 0000000..8bf87fb --- /dev/null +++ b/tests/externals/tinyssh/uint32_pack.c @@ -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 index 0000000..6f4f053 --- /dev/null +++ b/tests/externals/tinyssh/uint32_pack.h @@ -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 index 0000000..172c65d --- /dev/null +++ b/tests/externals/tinyssh/uint32_unpack.c @@ -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 index 0000000..fb0588a --- /dev/null +++ b/tests/externals/tinyssh/uint32_unpack.h @@ -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 index 0000000..9dcf121 --- /dev/null +++ b/tests/externals/tinyssh/verify.c @@ -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 index 0000000..718b831 --- /dev/null +++ b/tests/externals/tinyssh/verify.h @@ -0,0 +1,6 @@ +#ifndef _VERIFY_H____ +#define _VERIFY_H____ + +extern int verify(const unsigned char *, const unsigned char *, long long); + +#endif diff --git a/tests/speed/makefile b/tests/speed/makefile index c309865..5eecac6 100644 --- a/tests/speed/makefile +++ b/tests/speed/makefile @@ -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 index 0000000..9ac1a33 --- /dev/null +++ b/tests/speed/speed-tinyssh.c @@ -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 +// + +#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; +}