summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNagi5Yeq <nagi5yeq@github.com>2019-07-04 20:43:45 +0800
committerNagi5Yeq <nagi5yeq@github.com>2019-07-04 20:43:45 +0800
commitac411589296383ff0432118264b3a4bf24766ad4 (patch)
treef3186cdf6c1b81432765fd68223d54f1134896f0
init commit
-rw-r--r--.gitignore3
-rw-r--r--README.md7
-rw-r--r--defs.h14
-rw-r--r--fe448.c345
-rw-r--r--fe448.h62
-rw-r--r--sc448.c291
-rw-r--r--sc448.h57
7 files changed, 779 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6190b1a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.o
+*.py
+.vscode/ \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bbec377
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# fe448
+
+A naive implementation of ed448, may have many bugs...
+
+**Not finished yet.**
+
+Mainly modified from [SUPERCOP](https://bench.cr.yp.to/supercop.html) ed25519 ref implementation. \ No newline at end of file
diff --git a/defs.h b/defs.h
new file mode 100644
index 0000000..40c0b13
--- /dev/null
+++ b/defs.h
@@ -0,0 +1,14 @@
+#ifndef DEFS_H
+#define DEFS_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+typedef int8_t crypto_int8;
+typedef uint8_t crypto_uint8;
+typedef int16_t crypto_int16;
+typedef uint16_t crypto_uint16;
+typedef int32_t crypto_int32;
+typedef uint32_t crypto_uint32;
+
+#endif /* DEFS_H */
diff --git a/fe448.c b/fe448.c
new file mode 100644
index 0000000..961e944
--- /dev/null
+++ b/fe448.c
@@ -0,0 +1,345 @@
+#define WINDOWSIZE 1 /* Should be 1,2, or 4 */
+#define WINDOWMASK ((1 << WINDOWSIZE) - 1)
+
+#include "fe448.h"
+
+/* 2**448-2**224-1 */
+static const crypto_uint32 m[57] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
+
+/* 256**114//m */
+static const crypto_uint32 mu[59] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
+
+static crypto_uint32 equal(crypto_uint32 a, crypto_uint32 b) /* 16-bit inputs */
+{
+ crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */
+ x -= 1; /* 4294967295: yes; 0..65534: no */
+ x >>= 31; /* 1: yes; 0: no */
+ return x;
+}
+
+static crypto_uint32 lt(crypto_uint32 a, crypto_uint32 b) /* 16-bit inputs */
+{
+ unsigned int x = a;
+ x -= (unsigned int)b; /* 0..65535: no; 4294901761..4294967295: yes */
+ x >>= 31; /* 0: no; 1: yes */
+ return x;
+}
+
+static void reduce_add_sub(fe448 *r)
+{
+ crypto_uint32 t;
+ int i, rep;
+
+ for (rep = 0; rep < 4; rep++)
+ {
+ t = r->v[56];
+ r->v[56] = 0;
+ r->v[0] += t;
+ r->v[28] += t;
+ for (i = 0; i < 56; i++)
+ {
+ t = r->v[i] >> 8;
+ r->v[i + 1] += t;
+ r->v[i] &= 255;
+ }
+ }
+}
+
+/* copied from sc448.c, a bit of slowly on 2**448-2**224-1 */
+static void barrett_reduce(fe448 *r, const crypto_uint32 x[114])
+{
+ /* See HAC, Alg. 14.42 */
+ int i, j;
+ crypto_uint32 q2[116];
+ crypto_uint32 *q3 = q2 + 58;
+ crypto_uint32 r1[58];
+ crypto_uint32 r2[58];
+ crypto_uint32 carry;
+ crypto_uint32 pb = 0;
+ crypto_uint32 b;
+
+ for (i = 0; i < 116; ++i)
+ q2[i] = 0;
+ for (i = 0; i < 58; ++i)
+ r2[i] = 0;
+
+ for (i = 0; i < 59; i++)
+ for (j = 0; j < 58; j++)
+ if (i + j >= 56)
+ q2[i + j] += mu[i] * x[j + 56];
+ carry = q2[56] >> 8;
+ q2[57] += carry;
+ carry = q2[57] >> 8;
+ q2[58] += carry;
+
+ for (i = 0; i < 58; i++)
+ r1[i] = x[i];
+ for (i = 0; i < 57; i++)
+ for (j = 0; j < 58; j++)
+ if (i + j < 58)
+ r2[i + j] += m[i] * q3[j];
+
+ for (i = 0; i < 57; i++)
+ {
+ carry = r2[i] >> 8;
+ r2[i + 1] += carry;
+ r2[i] &= 0xff;
+ }
+
+ for (i = 0; i < 57; i++)
+ {
+ pb += r2[i];
+ b = lt(r1[i], pb);
+ r->v[i] = r1[i] - pb + (b << 8);
+ pb = b;
+ }
+
+ reduce_add_sub(r);
+ reduce_add_sub(r);
+ reduce_add_sub(r);
+ reduce_add_sub(r);
+}
+
+/* reduction modulo 2**448-2**224-1 */
+void fe448_freeze(fe448 *r)
+{
+ int i;
+ crypto_uint32 m0;
+ crypto_uint32 m1;
+ crypto_uint32 b = 0, t;
+ m0 = equal(r->v[56], 0);
+ for (i = 55; i > 28; i--)
+ m0 &= equal(r->v[i], 255);
+ m1 = m0;
+ m0 &= equal(r->v[28], 255);
+ m1 &= equal(r->v[28], 254);
+ for (i = 27; i >= 0; i--)
+ m1 &= equal(r->v[i], 255);
+
+ m0 |= m1;
+ m0 = -m0;
+
+ for (i = 0; i < 57; i++)
+ {
+ t = r->v[i] - m[i] - b;
+ r->v[i] -= (m[i] + b) & 255 & m0;
+ b = (t >> 8) & 1;
+ }
+}
+
+void fe448_unpack(fe448 *r, const unsigned char x[57])
+{
+ int i;
+ for (i = 0; i < 56; i++)
+ r->v[i] = x[i];
+ r->v[56] = 0;
+}
+
+/* Assumes input x being reduced below 2^448 */
+void fe448_pack(unsigned char r[57], const fe448 *x)
+{
+ int i;
+ fe448 y = *x;
+ fe448_freeze(&y);
+ for (i = 0; i < 57; i++)
+ r[i] = y.v[i];
+}
+
+int fe448_iszero(const fe448 *x)
+{
+ int i;
+ int r;
+ fe448 t = *x;
+ fe448_freeze(&t);
+ r = equal(t.v[0], 0);
+ for (i = 1; i < 57; i++)
+ r &= equal(t.v[i], 0);
+ return r;
+}
+
+int fe448_iseq_vartime(const fe448 *x, const fe448 *y)
+{
+ int i;
+ fe448 t1 = *x;
+ fe448 t2 = *y;
+ fe448_freeze(&t1);
+ fe448_freeze(&t2);
+ for (i = 0; i < 57; i++)
+ if (t1.v[i] != t2.v[i])
+ return 0;
+ return 1;
+}
+
+void fe448_cmov(fe448 *r, const fe448 *x, unsigned char b)
+{
+ int i;
+ crypto_uint32 mask = b;
+ mask = -mask;
+ for (i = 0; i < 57; i++)
+ r->v[i] ^= mask & (x->v[i] ^ r->v[i]);
+}
+
+unsigned char fe448_getparity(const fe448 *x)
+{
+ fe448 t = *x;
+ fe448_freeze(&t);
+ return t.v[0] & 1;
+}
+
+void fe448_setone(fe448 *r)
+{
+ int i;
+ r->v[0] = 1;
+ for (i = 1; i < 57; i++)
+ r->v[i] = 0;
+}
+
+void fe448_setzero(fe448 *r)
+{
+ int i;
+ for (i = 0; i < 57; i++)
+ r->v[i] = 0;
+}
+
+void fe448_neg(fe448 *r, const fe448 *x)
+{
+ fe448 t;
+ int i;
+ for (i = 0; i < 57; i++)
+ t.v[i] = x->v[i];
+ fe448_setzero(r);
+ fe448_sub(r, r, &t);
+}
+
+void fe448_add(fe448 *r, const fe448 *x, const fe448 *y)
+{
+ int i;
+ for (i = 0; i < 57; i++)
+ r->v[i] = x->v[i] + y->v[i];
+ reduce_add_sub(r);
+}
+
+void fe448_sub(fe448 *r, const fe448 *x, const fe448 *y)
+{
+ int i;
+ crypto_uint32 t[57];
+ for (i = 0; i < 28; i++) /* add x with p previously so that r>0 */
+ {
+ t[i] = x->v[i] + 0x1fe;
+ }
+ t[28] = x->v[28] + 0x1fc;
+ for (i = 29; i < 56; i++)
+ {
+ t[i] = x->v[i] + 0x1fe;
+ }
+ t[56] = 0;
+ for (i = 0; i < 57; i++)
+ r->v[i] = t[i] - y->v[i];
+ reduce_add_sub(r);
+}
+
+/* a slow version copied from sc448.c */
+void fe448_mul(fe448 *r, const fe448 *x, const fe448 *y)
+{
+ int i, j, carry;
+ crypto_uint32 t[114];
+ for (i = 0; i < 114; i++)
+ t[i] = 0;
+
+ for (i = 0; i < 57; i++)
+ for (j = 0; j < 57; j++)
+ t[i + j] += x->v[i] * y->v[j];
+
+ for (i = 0; i < 113; i++)
+ {
+ carry = t[i] >> 8;
+ t[i + 1] += carry;
+ t[i] &= 0xff;
+ }
+
+ barrett_reduce(r, t);
+}
+
+void fe448_square(fe448 *r, const fe448 *x)
+{
+ fe448_mul(r, x, x);
+}
+
+void fe448_invert(fe448 *r, const fe448 *x)
+{
+ fe448 t0;
+ fe448 t1;
+ fe448 t2;
+ int i;
+
+ fe448_square(&t0, x);
+ fe448_mul(&t0, &t0, x); /* 2^2 - 1 */
+ fe448_square(&t0, &t0); /* 2^3 - 2 */
+ fe448_mul(&t1, &t0, x); /* 2^3 - 1 */
+ fe448_square(&t0, &t1); /* 2^4 - 2^1 */
+ for (i = 0; i < 2; i++)
+ {
+ fe448_square(&t0, &t0);
+ } /* 2^6 - 2^3 */
+ fe448_mul(&t1, &t1, &t0); /* 2^6 - 1 */
+ fe448_square(&t0, &t1); /* 2^7 - 2^1 */
+ for (i = 0; i < 5; i++)
+ {
+ fe448_square(&t0, &t0);
+ } /* 2^12 - 2^6 */
+ fe448_mul(&t1, &t1, &t0); /* 2^12 - 1 */
+ fe448_square(&t1, &t1); /* 2^13 - 2^1 */
+ fe448_mul(&t1, &t1, x); /* 2^13 - 1 */
+ fe448_square(&t0, &t1); /* 2^14 - 2^1 */
+ for (i = 0; i < 12; i++)
+ {
+ fe448_square(&t0, &t0);
+ } /* 2^26 - 2^13 */
+ fe448_mul(&t1, &t1, &t0); /* 2^26 - 1 */
+ fe448_square(&t1, &t1); /* 2^26 - 2^1 */
+ fe448_mul(&t1, &t1, x); /* 2^27 - 1 */
+ fe448_square(&t0, &t1); /* 2^28 - 2^1 */
+ for (i = 0; i < 26; i++)
+ {
+ fe448_square(&t0, &t0);
+ } /* 2^54 - 2^27 */
+ fe448_mul(&t1, &t1, &t0); /* 2^54 - 1 */
+ fe448_square(&t1, &t1); /* 2^55 - 2^1 */
+ fe448_mul(&t1, &t1, x); /* 2^55 - 1 */
+ fe448_square(&t0, &t1); /* 2^56 - 2^1 */
+ for (i = 0; i < 54; i++)
+ {
+ fe448_square(&t0, &t0);
+ } /* 2^110 - 2^55 */
+ fe448_mul(&t1, &t1, &t0); /* 2^110 - 1 */
+ fe448_square(&t1, &t1); /* 2^111 - 2^1 */
+ fe448_mul(&t1, &t1, x); /* 2^111 - 1 */
+ fe448_square(&t0, &t1); /* 2^112 - 2^1 */
+ for (i = 0; i < 110; i++)
+ {
+ fe448_square(&t0, &t0);
+ } /* 2^222 - 2^111 */
+ fe448_mul(&t2, &t1, &t0); /* 2^222 - 1 */
+ fe448_square(&t1, &t2); /* 2^223 - 2^1 */
+ fe448_mul(&t1, &t1, x); /* 2^223 - 1 */
+ fe448_square(&t0, &t1); /* 2^224 - 2^1 */
+ for (i = 0; i < 222; i++)
+ {
+ fe448_square(&t0, &t0);
+ } /* 2^446 - 2^223 */
+ fe448_mul(&t0, &t2, &t0); /* 2^446 - 2^222 - 1 */
+ fe448_square(&t0, &t0); /* 2^447 - 2^223 - 2 */
+ fe448_square(&t0, &t0); /* 2^448 - 2^224 - 4 */
+ fe448_mul(r, &t0, x); /* 2^448 - 2^224 - 3 */
+}
+
+/* pow(2**446-2**222-1) */
+void fe448_pow446(fe448 *r, const fe448 *x)
+{
+}
diff --git a/fe448.h b/fe448.h
new file mode 100644
index 0000000..6eda9d1
--- /dev/null
+++ b/fe448.h
@@ -0,0 +1,62 @@
+#ifndef FE448_H
+#define FE448_H
+
+#include "defs.h"
+
+#define fe448 crypto_sign_ed448_ref_fe448
+#define fe448_freeze crypto_sign_ed448_ref_fe448_freeze
+#define fe448_unpack crypto_sign_ed448_ref_fe448_unpack
+#define fe448_pack crypto_sign_ed448_ref_fe448_pack
+#define fe448_iszero crypto_sign_ed448_ref_fe448_iszero
+#define fe448_iseq_vartime crypto_sign_ed448_ref_fe448_iseq_vartime
+#define fe448_cmov crypto_sign_ed448_ref_fe448_cmov
+#define fe448_setone crypto_sign_ed448_ref_fe448_setone
+#define fe448_setzero crypto_sign_ed448_ref_fe448_setzero
+#define fe448_neg crypto_sign_ed448_ref_fe448_neg
+#define fe448_getparity crypto_sign_ed448_ref_fe448_getparity
+#define fe448_add crypto_sign_ed448_ref_fe448_add
+#define fe448_sub crypto_sign_ed448_ref_fe448_sub
+#define fe448_mul crypto_sign_ed448_ref_fe448_mul
+#define fe448_square crypto_sign_ed448_ref_fe448_square
+#define fe448_invert crypto_sign_ed448_ref_fe448_invert
+#define fe448_pow2523 crypto_sign_ed448_ref_fe448_pow2523
+
+typedef struct
+{
+ crypto_uint32 v[57];
+}
+fe448;
+
+void fe448_freeze(fe448 *r);
+
+void fe448_unpack(fe448 *r, const unsigned char x[57]);
+
+void fe448_pack(unsigned char r[57], const fe448 *x);
+
+int fe448_iszero(const fe448 *x);
+
+int fe448_iseq_vartime(const fe448 *x, const fe448 *y);
+
+void fe448_cmov(fe448 *r, const fe448 *x, unsigned char b);
+
+void fe448_setone(fe448 *r);
+
+void fe448_setzero(fe448 *r);
+
+void fe448_neg(fe448 *r, const fe448 *x);
+
+unsigned char fe448_getparity(const fe448 *x);
+
+void fe448_add(fe448 *r, const fe448 *x, const fe448 *y);
+
+void fe448_sub(fe448 *r, const fe448 *x, const fe448 *y);
+
+void fe448_mul(fe448 *r, const fe448 *x, const fe448 *y);
+
+void fe448_square(fe448 *r, const fe448 *x);
+
+void fe448_invert(fe448 *r, const fe448 *x);
+
+void fe448_pow446(fe448 *r, const fe448 *x);
+
+#endif
diff --git a/sc448.c b/sc448.c
new file mode 100644
index 0000000..75ea623
--- /dev/null
+++ b/sc448.c
@@ -0,0 +1,291 @@
+#include "sc448.h"
+
+/* order of base point of Ed448-Goldilocks: 2**446-13818066809895115352007386748515426880336692474882178609894547503885 */
+
+static const crypto_uint32 m[57] = {0xF3, 0x44, 0x58, 0xAB, 0x92, 0xC2, 0x78, 0x23, 0x55, 0x8F, 0xC5, 0x8D, 0x72, 0xC2, 0x6C, 0x21,
+ 0x90, 0x36, 0xD6, 0xAE, 0x49, 0xDB, 0x4E, 0xC4, 0xE9, 0x23, 0xCA, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00};
+
+/* 256**114//m */
+static const crypto_uint32 mu[59] = {0x0A, 0xD0, 0xE0, 0xB0, 0x7B, 0x4A, 0xD5, 0xD6, 0x73, 0xC8, 0xAD, 0x0A, 0xA7, 0x23, 0xD7, 0xD8,
+ 0x33, 0xE9, 0xFD, 0x96, 0x9C, 0x12, 0x65, 0x4B, 0x12, 0xBB, 0x63, 0xC1, 0x5D, 0x33, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
+
+static crypto_uint32 lt(crypto_uint32 a, crypto_uint32 b) /* 16-bit inputs */
+{
+ unsigned int x = a;
+ x -= (unsigned int)b; /* 0..65535: no; 4294901761..4294967295: yes */
+ x >>= 31; /* 0: no; 1: yes */
+ return x;
+}
+
+/* Reduce coefficients of r before calling reduce_add_sub */
+static void reduce_add_sub(sc448 *r)
+{
+ crypto_uint32 pb = 0;
+ crypto_uint32 b;
+ crypto_uint32 mask;
+ int i;
+ unsigned char t[57];
+
+ for (i = 0; i < 57; i++)
+ {
+ pb += m[i];
+ b = lt(r->v[i], pb);
+ t[i] = r->v[i] - pb + (b << 8);
+ pb = b;
+ }
+ mask = b - 1;
+ for (i = 0; i < 57; i++)
+ r->v[i] ^= mask & (r->v[i] ^ t[i]);
+}
+
+/* Reduce coefficients of x before calling barrett_reduce */
+static void barrett_reduce(sc448 *r, const crypto_uint32 x[114])
+{
+ /* See HAC, Alg. 14.42 */
+ int i, j;
+ crypto_uint32 q2[116];
+ crypto_uint32 *q3 = q2 + 58;
+ crypto_uint32 r1[58];
+ crypto_uint32 r2[58];
+ crypto_uint32 carry;
+ crypto_uint32 pb = 0;
+ crypto_uint32 b;
+
+ for (i = 0; i < 116; ++i)
+ q2[i] = 0;
+ for (i = 0; i < 58; ++i)
+ r2[i] = 0;
+
+ for (i = 0; i < 59; i++)
+ for (j = 0; j < 58; j++)
+ if (i + j >= 56)
+ q2[i + j] += mu[i] * x[j + 56];
+ carry = q2[56] >> 8;
+ q2[57] += carry;
+ carry = q2[57] >> 8;
+ q2[58] += carry;
+
+ for (i = 0; i < 58; i++)
+ r1[i] = x[i];
+ for (i = 0; i < 57; i++)
+ for (j = 0; j < 58; j++)
+ if (i + j < 58)
+ r2[i + j] += m[i] * q3[j];
+
+ for (i = 0; i < 57; i++)
+ {
+ carry = r2[i] >> 8;
+ r2[i + 1] += carry;
+ r2[i] &= 0xff;
+ }
+
+ for (i = 0; i < 57; i++)
+ {
+ pb += r2[i];
+ b = lt(r1[i], pb);
+ r->v[i] = r1[i] - pb + (b << 8);
+ pb = b;
+ }
+
+ /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3
+ * If so: Handle it here!
+ */
+
+ reduce_add_sub(r);
+ reduce_add_sub(r);
+ reduce_add_sub(r);
+ reduce_add_sub(r);
+}
+
+void sc448_from57bytes(sc448 *r, const unsigned char x[57])
+{
+ int i;
+ crypto_uint32 t[114];
+ for (i = 0; i < 57; i++)
+ t[i] = x[i];
+ for (i = 57; i < 114; ++i)
+ t[i] = 0;
+ barrett_reduce(r, t);
+}
+
+void sc448_from114bytes(sc448 *r, const unsigned char x[114])
+{
+ int i;
+ crypto_uint32 t[114];
+ for (i = 0; i < 114; i++)
+ t[i] = x[i];
+ barrett_reduce(r, t);
+}
+
+void sc448_to57bytes(unsigned char r[57], const sc448 *x)
+{
+ int i;
+ for (i = 0; i < 57; i++)
+ r[i] = x->v[i];
+}
+
+int sc448_iszero_vartime(const sc448 *x)
+{
+ int i;
+ for (i = 0; i < 57; i++)
+ if (x->v[i] != 0)
+ return 0;
+ return 1;
+}
+
+int sc448_lt_vartime(const sc448 *x, const sc448 *y)
+{
+ int i;
+ for (i = 56; i >= 0; i--)
+ {
+ if (x->v[i] < y->v[i])
+ return 1;
+ if (x->v[i] > y->v[i])
+ return 0;
+ }
+ return 0;
+}
+
+void sc448_add(sc448 *r, const sc448 *x, const sc448 *y)
+{
+ int i, carry;
+ for (i = 0; i < 57; i++)
+ r->v[i] = x->v[i] + y->v[i];
+ for (i = 0; i < 56; i++)
+ {
+ carry = r->v[i] >> 8;
+ r->v[i + 1] += carry;
+ r->v[i] &= 0xff;
+ }
+ reduce_add_sub(r);
+}
+
+void sc448_sub_nored(sc448 *r, const sc448 *x, const sc448 *y)
+{
+ crypto_uint32 b = 0;
+ crypto_uint32 t;
+ int i;
+ for (i = 0; i < 57; i++)
+ {
+ t = x->v[i] - y->v[i] - b;
+ r->v[i] = t & 255;
+ b = (t >> 8) & 1;
+ }
+}
+
+void sc448_mul(sc448 *r, const sc448 *x, const sc448 *y)
+{
+ int i, j, carry;
+ crypto_uint32 t[114];
+ for (i = 0; i < 114; i++)
+ t[i] = 0;
+
+ for (i = 0; i < 57; i++)
+ for (j = 0; j < 57; j++)
+ t[i + j] += x->v[i] * y->v[j];
+
+ /* Reduce coefficients */
+ for (i = 0; i < 113; i++)
+ {
+ carry = t[i] >> 8;
+ t[i + 1] += carry;
+ t[i] &= 0xff;
+ }
+
+ barrett_reduce(r, t);
+}
+ /* not implemented yet */
+#if 0
+void sc25519_window3(signed char r[85], const sc25519 *s)
+{
+ char carry;
+ int i;
+ for (i = 0; i < 10; i++)
+ {
+ r[8 * i + 0] = s->v[3 * i + 0] & 7;
+ r[8 * i + 1] = (s->v[3 * i + 0] >> 3) & 7;
+ r[8 * i + 2] = (s->v[3 * i + 0] >> 6) & 7;
+ r[8 * i + 2] ^= (s->v[3 * i + 1] << 2) & 7;
+ r[8 * i + 3] = (s->v[3 * i + 1] >> 1) & 7;
+ r[8 * i + 4] = (s->v[3 * i + 1] >> 4) & 7;
+ r[8 * i + 5] = (s->v[3 * i + 1] >> 7) & 7;
+ r[8 * i + 5] ^= (s->v[3 * i + 2] << 1) & 7;
+ r[8 * i + 6] = (s->v[3 * i + 2] >> 2) & 7;
+ r[8 * i + 7] = (s->v[3 * i + 2] >> 5) & 7;
+ }
+ r[8 * i + 0] = s->v[3 * i + 0] & 7;
+ r[8 * i + 1] = (s->v[3 * i + 0] >> 3) & 7;
+ r[8 * i + 2] = (s->v[3 * i + 0] >> 6) & 7;
+ r[8 * i + 2] ^= (s->v[3 * i + 1] << 2) & 7;
+ r[8 * i + 3] = (s->v[3 * i + 1] >> 1) & 7;
+ r[8 * i + 4] = (s->v[3 * i + 1] >> 4) & 7;
+
+ /* Making it signed */
+ carry = 0;
+ for (i = 0; i < 84; i++)
+ {
+ r[i] += carry;
+ r[i + 1] += r[i] >> 3;
+ r[i] &= 7;
+ carry = r[i] >> 2;
+ r[i] -= carry << 3;
+ }
+ r[84] += carry;
+}
+
+void sc25519_window5(signed char r[51], const sc25519 *s)
+{
+ char carry;
+ int i;
+ for (i = 0; i < 6; i++)
+ {
+ r[8 * i + 0] = s->v[5 * i + 0] & 31;
+ r[8 * i + 1] = (s->v[5 * i + 0] >> 5) & 31;
+ r[8 * i + 1] ^= (s->v[5 * i + 1] << 3) & 31;
+ r[8 * i + 2] = (s->v[5 * i + 1] >> 2) & 31;
+ r[8 * i + 3] = (s->v[5 * i + 1] >> 7) & 31;
+ r[8 * i + 3] ^= (s->v[5 * i + 2] << 1) & 31;
+ r[8 * i + 4] = (s->v[5 * i + 2] >> 4) & 31;
+ r[8 * i + 4] ^= (s->v[5 * i + 3] << 4) & 31;
+ r[8 * i + 5] = (s->v[5 * i + 3] >> 1) & 31;
+ r[8 * i + 6] = (s->v[5 * i + 3] >> 6) & 31;
+ r[8 * i + 6] ^= (s->v[5 * i + 4] << 2) & 31;
+ r[8 * i + 7] = (s->v[5 * i + 4] >> 3) & 31;
+ }
+ r[8 * i + 0] = s->v[5 * i + 0] & 31;
+ r[8 * i + 1] = (s->v[5 * i + 0] >> 5) & 31;
+ r[8 * i + 1] ^= (s->v[5 * i + 1] << 3) & 31;
+ r[8 * i + 2] = (s->v[5 * i + 1] >> 2) & 31;
+
+ /* Making it signed */
+ carry = 0;
+ for (i = 0; i < 50; i++)
+ {
+ r[i] += carry;
+ r[i + 1] += r[i] >> 5;
+ r[i] &= 31;
+ carry = r[i] >> 4;
+ r[i] -= carry << 5;
+ }
+ r[50] += carry;
+}
+
+void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2)
+{
+ int i;
+ for (i = 0; i < 31; i++)
+ {
+ r[4 * i] = (s1->v[i] & 3) ^ ((s2->v[i] & 3) << 2);
+ r[4 * i + 1] = ((s1->v[i] >> 2) & 3) ^ (((s2->v[i] >> 2) & 3) << 2);
+ r[4 * i + 2] = ((s1->v[i] >> 4) & 3) ^ (((s2->v[i] >> 4) & 3) << 2);
+ r[4 * i + 3] = ((s1->v[i] >> 6) & 3) ^ (((s2->v[i] >> 6) & 3) << 2);
+ }
+ r[124] = (s1->v[31] & 3) ^ ((s2->v[31] & 3) << 2);
+ r[125] = ((s1->v[31] >> 2) & 3) ^ (((s2->v[31] >> 2) & 3) << 2);
+ r[126] = ((s1->v[31] >> 4) & 3) ^ (((s2->v[31] >> 4) & 3) << 2);
+}
+#endif
diff --git a/sc448.h b/sc448.h
new file mode 100644
index 0000000..86d1c31
--- /dev/null
+++ b/sc448.h
@@ -0,0 +1,57 @@
+#ifndef SC448_H
+#define SC448_H
+
+#include "defs.h"
+
+#define sc448 crypto_sign_ed448_ref_sc448
+#define sc448_from57bytes crypto_sign_ed448_ref_sc448_from57bytes
+#define sc448_from114bytes crypto_sign_ed448_ref_sc448_from114bytes
+#define sc448_to57bytes crypto_sign_ed448_ref_sc448_to57bytes
+#define sc448_iszero_vartime crypto_sign_ed448_ref_sc448_iszero_vartime
+#define sc448_isshort_vartime crypto_sign_ed448_ref_sc448_isshort_vartime
+#define sc448_lt_vartime crypto_sign_ed448_ref_sc448_lt_vartime
+#define sc448_add crypto_sign_ed448_ref_sc448_add
+#define sc448_sub_nored crypto_sign_ed448_ref_sc448_sub_nored
+#define sc448_mul crypto_sign_ed448_ref_sc448_mul
+#define sc448_window3 crypto_sign_ed448_ref_sc448_window3
+#define sc448_window5 crypto_sign_ed448_ref_sc448_window5
+#define sc448_2interleave2 crypto_sign_ed448_ref_sc448_2interleave2
+
+typedef struct
+{
+ crypto_uint32 v[57];
+}
+sc448;
+
+void sc448_from57bytes(sc448 *r, const unsigned char x[57]);
+
+void sc448_from114bytes(sc448 *r, const unsigned char x[114]);
+
+void sc448_to57bytes(unsigned char r[57], const sc448 *x);
+
+int sc448_iszero_vartime(const sc448 *x);
+
+int sc448_isshort_vartime(const sc448 *x);
+
+int sc448_lt_vartime(const sc448 *x, const sc448 *y);
+
+void sc448_add(sc448 *r, const sc448 *x, const sc448 *y);
+
+void sc448_sub_nored(sc448 *r, const sc448 *x, const sc448 *y);
+
+void sc448_mul(sc448 *r, const sc448 *x, const sc448 *y);
+
+#if 0
+/* Convert s into a representation of the form \sum_{i=0}^{84}r[i]2^3
+ * with r[i] in {-4,...,3}
+ */
+void sc448_window3(signed char r[85], const sc448 *s);
+
+/* Convert s into a representation of the form \sum_{i=0}^{50}r[i]2^5
+ * with r[i] in {-16,...,15}
+ */
+void sc448_window5(signed char r[51], const sc448 *s);
+
+void sc448_2interleave2(unsigned char r[127], const sc448 *s1, const sc448 *s2);
+#endif
+#endif