--- /dev/null
+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.
--- /dev/null
+#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
+}
--- /dev/null
+#ifndef _CLEANUP_H____
+#define _CLEANUP_H____
+
+extern void cleanup_(void *, long long);
+#define cleanup(x) cleanup_((x), sizeof(x))
+
+#endif
--- /dev/null
+/*
+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;
+}
--- /dev/null
+#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
--- /dev/null
+#ifndef crypto_int64_h
+#define crypto_int64_h
+
+#include <stdint.h>
+
+typedef int64_t crypto_int64;
+
+#endif
--- /dev/null
+/*
+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 */
--- /dev/null
+#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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+/*
+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 */
--- /dev/null
+#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
--- /dev/null
+#ifndef crypto_uint32_h
+#define crypto_uint32_h
+
+#include <stdint.h>
+
+typedef uint32_t crypto_uint32;
+
+#endif
--- /dev/null
+#ifndef crypto_uint64_h
+#define crypto_uint64_h
+
+#include <stdint.h>
+
+typedef uint64_t crypto_uint64;
+
+#endif
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+/*
+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);
+}
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
+
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+/* 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;
+ }
+}
--- /dev/null
+#ifndef _RANDOMBYTES_H____
+#define _RANDOMBYTES_H____
+
+extern void randombytes(unsigned char *, unsigned long long);
+
+#ifndef randombytes_implementation
+#define randombytes_implementation "tinyssh"
+#endif
+
+#endif
--- /dev/null
+/*
+- 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);
+}
--- /dev/null
+#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
--- /dev/null
+#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; }
+}
--- /dev/null
+#ifndef _UINT32_PACK_H____
+#define _UINT32_PACK_H____
+
+#include "crypto_uint32.h"
+
+extern void uint32_pack(unsigned char *, crypto_uint32);
+
+#endif
--- /dev/null
+#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;
+}
--- /dev/null
+#ifndef _UINT32_UNPACK_H____
+#define _UINT32_UNPACK_H____
+
+#include "crypto_uint32.h"
+
+extern crypto_uint32 uint32_unpack(const unsigned char *);
+
+#endif
--- /dev/null
+#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;
+}
--- /dev/null
+#ifndef _VERIFY_H____
+#define _VERIFY_H____
+
+extern int verify(const unsigned char *, const unsigned char *, long long);
+
+#endif
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:
-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 ##
$(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 $@ $^
$(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 $@ $^
--- /dev/null
+// 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;
+}