diff --git a/.gitignore b/.gitignore
index ab2bf5ab..de7d69ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -102,6 +102,7 @@ test/default/box_seed
test/default/chacha20
test/default/codecs
test/default/core_ed25519
+test/default/core_ristretto255
test/default/core1
test/default/core2
test/default/core3
@@ -129,6 +130,7 @@ test/default/pwhash_scrypt_ll
test/default/randombytes
test/default/scalarmult
test/default/scalarmult_ed25519
+test/default/scalarmult_ristretto255
test/default/scalarmult2
test/default/scalarmult5
test/default/scalarmult6
diff --git a/AUTHORS b/AUTHORS
index 39e55f62..f4a4b9d8 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -28,6 +28,13 @@ ed25519 Daniel J. Bernstein
poly1305 Daniel J. Bernstein
+ristretto Mike Hamburg
+ Henry de Valence
+ Jack Grigg
+ George Tankersley
+ Filippo Valsorda
+ Isis Lovecruft
+
salsa20 Daniel J. Bernstein
scrypt Colin Percival
@@ -56,6 +63,7 @@ crypto_box/curve25519xchacha20poly1305 Frank Denis
crypto_core/ed25519 Daniel J. Bernstein
Adam Langley
+ Frank Denis
crypto_core/hchacha20 Frank Denis
@@ -93,6 +101,8 @@ crypto_scalarmult/curve25519/sandy2x Tung Chou
crypto_scalarmult/ed25519 Frank Denis
+crypto_scalarmult/ristretto255 Frank Denis
+
crypto_secretbox/xsalsa20poly1305 Daniel J. Bernstein
crypto_secretbox/xchacha20poly1305 Frank Denis
diff --git a/builds/msvc/vs2010/libsodium/libsodium.vcxproj b/builds/msvc/vs2010/libsodium/libsodium.vcxproj
index 62fa4f36..031b18af 100644
--- a/builds/msvc/vs2010/libsodium/libsodium.vcxproj
+++ b/builds/msvc/vs2010/libsodium/libsodium.vcxproj
@@ -126,6 +126,7 @@
+
@@ -180,6 +181,7 @@
+
@@ -209,6 +211,7 @@
+
@@ -216,6 +219,7 @@
+
diff --git a/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters
index d4d97413..c2e167b3 100644
--- a/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters
+++ b/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters
@@ -171,6 +171,9 @@
crypto_scalarmult
+
+ crypto_scalarmult\ristretto255\ref10
+
crypto_scalarmult\ed25519\ref10
@@ -333,6 +336,9 @@
crypto_core\ed25519
+
+ crypto_core\ed25519
+
crypto_core\ed25519\ref10
@@ -416,6 +422,9 @@
include\sodium
+
+ include\sodium
+
include\sodium
@@ -437,6 +446,9 @@
include\sodium
+
+ include\sodium
+
include\sodium
@@ -874,6 +886,12 @@
{834d4827-81e4-3de3-baa1-a216763f11d6}
+
+ {52bf28eb-7ffd-399a-be35-0df3e8e99c15}
+
+
+ {39cc576f-4b54-3d71-b14c-27445bc4b138}
+
{b9b02bee-5c1f-36d2-b97d-983f865a4cc6}
diff --git a/builds/msvc/vs2012/libsodium/libsodium.vcxproj b/builds/msvc/vs2012/libsodium/libsodium.vcxproj
index 482284ec..832f0a41 100644
--- a/builds/msvc/vs2012/libsodium/libsodium.vcxproj
+++ b/builds/msvc/vs2012/libsodium/libsodium.vcxproj
@@ -126,6 +126,7 @@
+
@@ -180,6 +181,7 @@
+
@@ -209,6 +211,7 @@
+
@@ -216,6 +219,7 @@
+
diff --git a/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters
index d4d97413..c2e167b3 100644
--- a/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters
+++ b/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters
@@ -171,6 +171,9 @@
crypto_scalarmult
+
+ crypto_scalarmult\ristretto255\ref10
+
crypto_scalarmult\ed25519\ref10
@@ -333,6 +336,9 @@
crypto_core\ed25519
+
+ crypto_core\ed25519
+
crypto_core\ed25519\ref10
@@ -416,6 +422,9 @@
include\sodium
+
+ include\sodium
+
include\sodium
@@ -437,6 +446,9 @@
include\sodium
+
+ include\sodium
+
include\sodium
@@ -874,6 +886,12 @@
{834d4827-81e4-3de3-baa1-a216763f11d6}
+
+ {52bf28eb-7ffd-399a-be35-0df3e8e99c15}
+
+
+ {39cc576f-4b54-3d71-b14c-27445bc4b138}
+
{b9b02bee-5c1f-36d2-b97d-983f865a4cc6}
diff --git a/builds/msvc/vs2013/libsodium/libsodium.vcxproj b/builds/msvc/vs2013/libsodium/libsodium.vcxproj
index f41661f0..b7bb553f 100644
--- a/builds/msvc/vs2013/libsodium/libsodium.vcxproj
+++ b/builds/msvc/vs2013/libsodium/libsodium.vcxproj
@@ -126,6 +126,7 @@
+
@@ -180,6 +181,7 @@
+
@@ -209,6 +211,7 @@
+
@@ -216,6 +219,7 @@
+
diff --git a/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters
index d4d97413..c2e167b3 100644
--- a/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters
+++ b/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters
@@ -171,6 +171,9 @@
crypto_scalarmult
+
+ crypto_scalarmult\ristretto255\ref10
+
crypto_scalarmult\ed25519\ref10
@@ -333,6 +336,9 @@
crypto_core\ed25519
+
+ crypto_core\ed25519
+
crypto_core\ed25519\ref10
@@ -416,6 +422,9 @@
include\sodium
+
+ include\sodium
+
include\sodium
@@ -437,6 +446,9 @@
include\sodium
+
+ include\sodium
+
include\sodium
@@ -874,6 +886,12 @@
{834d4827-81e4-3de3-baa1-a216763f11d6}
+
+ {52bf28eb-7ffd-399a-be35-0df3e8e99c15}
+
+
+ {39cc576f-4b54-3d71-b14c-27445bc4b138}
+
{b9b02bee-5c1f-36d2-b97d-983f865a4cc6}
diff --git a/builds/msvc/vs2015/libsodium/libsodium.vcxproj b/builds/msvc/vs2015/libsodium/libsodium.vcxproj
index 13e08b85..a0b94c18 100644
--- a/builds/msvc/vs2015/libsodium/libsodium.vcxproj
+++ b/builds/msvc/vs2015/libsodium/libsodium.vcxproj
@@ -126,6 +126,7 @@
+
@@ -180,6 +181,7 @@
+
@@ -209,6 +211,7 @@
+
@@ -216,6 +219,7 @@
+
diff --git a/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters
index d4d97413..c2e167b3 100644
--- a/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters
+++ b/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters
@@ -171,6 +171,9 @@
crypto_scalarmult
+
+ crypto_scalarmult\ristretto255\ref10
+
crypto_scalarmult\ed25519\ref10
@@ -333,6 +336,9 @@
crypto_core\ed25519
+
+ crypto_core\ed25519
+
crypto_core\ed25519\ref10
@@ -416,6 +422,9 @@
include\sodium
+
+ include\sodium
+
include\sodium
@@ -437,6 +446,9 @@
include\sodium
+
+ include\sodium
+
include\sodium
@@ -874,6 +886,12 @@
{834d4827-81e4-3de3-baa1-a216763f11d6}
+
+ {52bf28eb-7ffd-399a-be35-0df3e8e99c15}
+
+
+ {39cc576f-4b54-3d71-b14c-27445bc4b138}
+
{b9b02bee-5c1f-36d2-b97d-983f865a4cc6}
diff --git a/builds/msvc/vs2017/libsodium/libsodium.vcxproj b/builds/msvc/vs2017/libsodium/libsodium.vcxproj
index 1c7b4a95..1e62541d 100644
--- a/builds/msvc/vs2017/libsodium/libsodium.vcxproj
+++ b/builds/msvc/vs2017/libsodium/libsodium.vcxproj
@@ -126,6 +126,7 @@
+
@@ -180,6 +181,7 @@
+
@@ -209,6 +211,7 @@
+
@@ -216,6 +219,7 @@
+
diff --git a/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters
index d4d97413..c2e167b3 100644
--- a/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters
+++ b/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters
@@ -171,6 +171,9 @@
crypto_scalarmult
+
+ crypto_scalarmult\ristretto255\ref10
+
crypto_scalarmult\ed25519\ref10
@@ -333,6 +336,9 @@
crypto_core\ed25519
+
+ crypto_core\ed25519
+
crypto_core\ed25519\ref10
@@ -416,6 +422,9 @@
include\sodium
+
+ include\sodium
+
include\sodium
@@ -437,6 +446,9 @@
include\sodium
+
+ include\sodium
+
include\sodium
@@ -874,6 +886,12 @@
{834d4827-81e4-3de3-baa1-a216763f11d6}
+
+ {52bf28eb-7ffd-399a-be35-0df3e8e99c15}
+
+
+ {39cc576f-4b54-3d71-b14c-27445bc4b138}
+
{b9b02bee-5c1f-36d2-b97d-983f865a4cc6}
diff --git a/libsodium.vcxproj b/libsodium.vcxproj
index 0828adaf..f438f89b 100644
--- a/libsodium.vcxproj
+++ b/libsodium.vcxproj
@@ -364,6 +364,7 @@
+
@@ -418,6 +419,7 @@
+
@@ -447,6 +449,7 @@
+
@@ -454,6 +457,7 @@
+
diff --git a/libsodium.vcxproj.filters b/libsodium.vcxproj.filters
index ecd8d01c..d31c96e3 100644
--- a/libsodium.vcxproj.filters
+++ b/libsodium.vcxproj.filters
@@ -162,6 +162,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -324,6 +327,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -407,6 +413,9 @@
Header Files
+
+ Header Files
+
Header Files
@@ -428,6 +437,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/src/libsodium/Makefile.am b/src/libsodium/Makefile.am
index 7649f27d..ad555055 100644
--- a/src/libsodium/Makefile.am
+++ b/src/libsodium/Makefile.am
@@ -152,6 +152,7 @@ libsodium_la_SOURCES += \
crypto_box/curve25519xchacha20poly1305/box_curve25519xchacha20poly1305.c \
crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c \
crypto_core/ed25519/core_ed25519.c \
+ crypto_core/ed25519/core_ristretto255.c \
crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c \
crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h \
crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c \
@@ -160,6 +161,7 @@ libsodium_la_SOURCES += \
crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c \
crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c \
crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c \
+ crypto_scalarmult/ristretto255/ref10/scalarmult_ristretto255_ref10.c \
crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305.c \
crypto_shorthash/siphash24/shorthash_siphashx24.c \
crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c \
diff --git a/src/libsodium/crypto_core/ed25519/core_ristretto255.c b/src/libsodium/crypto_core/ed25519/core_ristretto255.c
new file mode 100644
index 00000000..fbd5372c
--- /dev/null
+++ b/src/libsodium/crypto_core/ed25519/core_ristretto255.c
@@ -0,0 +1,140 @@
+
+#include
+
+#include "crypto_core_ed25519.h"
+#include "crypto_core_ristretto255.h"
+#include "private/common.h"
+#include "private/ed25519_ref10.h"
+#include "randombytes.h"
+#include "utils.h"
+
+int
+crypto_core_ristretto255_is_valid_point(const unsigned char *p)
+{
+ ge25519_p3 p_p3;
+
+ if (ristretto255_frombytes(&p_p3, p) != 0) {
+ return 0;
+ }
+ return 1;
+}
+
+int
+crypto_core_ristretto255_add(unsigned char *r,
+ const unsigned char *p, const unsigned char *q)
+{
+ ge25519_p3 p_p3, q_p3, r_p3;
+ ge25519_p1p1 r_p1p1;
+ ge25519_cached q_cached;
+
+ if (ristretto255_frombytes(&p_p3, p) != 0 ||
+ ristretto255_frombytes(&q_p3, q) != 0) {
+ return -1;
+ }
+ ge25519_p3_to_cached(&q_cached, &q_p3);
+ ge25519_add(&r_p1p1, &p_p3, &q_cached);
+ ge25519_p1p1_to_p3(&r_p3, &r_p1p1);
+ ristretto255_p3_tobytes(r, &r_p3);
+
+ return 0;
+}
+
+int
+crypto_core_ristretto255_sub(unsigned char *r,
+ const unsigned char *p, const unsigned char *q)
+{
+ ge25519_p3 p_p3, q_p3, r_p3;
+ ge25519_p1p1 r_p1p1;
+ ge25519_cached q_cached;
+
+ if (ristretto255_frombytes(&p_p3, p) != 0 ||
+ ristretto255_frombytes(&q_p3, q) != 0) {
+ return -1;
+ }
+ ge25519_p3_to_cached(&q_cached, &q_p3);
+ ge25519_sub(&r_p1p1, &p_p3, &q_cached);
+ ge25519_p1p1_to_p3(&r_p3, &r_p1p1);
+ ristretto255_p3_tobytes(r, &r_p3);
+
+ return 0;
+}
+
+int
+crypto_core_ristretto255_from_uniform(unsigned char *p, const unsigned char *r)
+{
+ ristretto255_from_uniform(p, r);
+
+ return 0;
+}
+
+void
+crypto_core_ristretto255_scalar_random(unsigned char *r)
+{
+ crypto_core_ed25519_scalar_random(r);
+}
+
+int
+crypto_core_ristretto255_scalar_invert(unsigned char *recip,
+ const unsigned char *s)
+{
+ return crypto_core_ed25519_scalar_invert(recip, s);
+}
+
+void
+crypto_core_ristretto255_scalar_negate(unsigned char *neg,
+ const unsigned char *s)
+{
+ crypto_core_ed25519_scalar_negate(neg, s);
+}
+
+void
+crypto_core_ristretto255_scalar_complement(unsigned char *comp,
+ const unsigned char *s)
+{
+ crypto_core_ed25519_scalar_complement(comp, s);
+}
+
+void
+crypto_core_ristretto255_scalar_add(unsigned char *z, const unsigned char *x,
+ const unsigned char *y)
+{
+ crypto_core_ed25519_scalar_add(z, x, y);
+}
+
+void
+crypto_core_ristretto255_scalar_sub(unsigned char *z, const unsigned char *x,
+ const unsigned char *y)
+{
+ crypto_core_ed25519_scalar_sub(z, x, y);
+}
+
+void
+crypto_core_ristretto255_scalar_reduce(unsigned char *r,
+ const unsigned char *s)
+{
+ crypto_core_ed25519_scalar_reduce(r, s);
+}
+
+size_t
+crypto_core_ristretto255_bytes(void)
+{
+ return crypto_core_ristretto255_BYTES;
+}
+
+size_t
+crypto_core_ristretto255_nonreducedscalarbytes(void)
+{
+ return crypto_core_ristretto255_NONREDUCEDSCALARBYTES;
+}
+
+size_t
+crypto_core_ristretto255_uniformbytes(void)
+{
+ return crypto_core_ristretto255_UNIFORMBYTES;
+}
+
+size_t
+crypto_core_ristretto255_scalarbytes(void)
+{
+ return crypto_core_ristretto255_SCALARBYTES;
+}
diff --git a/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c b/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
index 2aba8fa6..10531d48 100644
--- a/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
+++ b/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
@@ -163,6 +163,22 @@ fe25519_pow22523(fe25519 out, const fe25519 z)
fe25519_mul(out, t0, z);
}
+static inline void
+fe25519_cneg(fe25519 h, const fe25519 f, unsigned int b)
+{
+ fe25519 negf;
+
+ fe25519_neg(negf, f);
+ fe25519_copy(h, f);
+ fe25519_cmov(h, negf, b);
+}
+
+static inline void
+fe25519_abs(fe25519 h, const fe25519 f)
+{
+ fe25519_cneg(h, f, fe25519_isnegative(f));
+}
+
/*
r = p + q
*/
@@ -2583,3 +2599,237 @@ ge25519_from_uniform(unsigned char s[32], const unsigned char r[32])
ge25519_p3_tobytes(s, &p3);
}
+
+/* Ristretto group */
+
+static int
+ristretto255_sqrt_ratio_m1(fe25519 x, const fe25519 u, const fe25519 v)
+{
+ fe25519 v3;
+ fe25519 vxx;
+ fe25519 m_root_check, p_root_check, f_root_check;
+ fe25519 negx;
+ fe25519 x_sqrtm1;
+ int has_m_root, has_p_root, has_f_root;
+
+ fe25519_sq(v3, v);
+ fe25519_mul(v3, v3, v); /* v3 = v^3 */
+ fe25519_sq(x, v3);
+ fe25519_mul(x, x, v);
+ fe25519_mul(x, x, u); /* x = uv^7 */
+
+ fe25519_pow22523(x, x); /* x = (uv^7)^((q-5)/8) */
+ fe25519_mul(x, x, v3);
+ fe25519_mul(x, x, u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+ fe25519_sq(vxx, x);
+ fe25519_mul(vxx, vxx, v); /* vx^2 */
+ fe25519_sub(m_root_check, vxx, u); /* vx^2-u */
+ fe25519_add(p_root_check, vxx, u); /* vx^2+u */
+ fe25519_mul(f_root_check, u, sqrtm1); /* u*sqrt(-1) */
+ fe25519_add(f_root_check, vxx, f_root_check); /* vx^2+u*sqrt(-1) */
+ has_m_root = fe25519_iszero(m_root_check);
+ has_p_root = fe25519_iszero(p_root_check);
+ has_f_root = fe25519_iszero(f_root_check);
+ fe25519_mul(x_sqrtm1, x, sqrtm1); /* x*sqrt(-1) */
+
+ fe25519_cmov(x, x_sqrtm1, has_p_root | has_f_root);
+ fe25519_abs(x, x);
+
+ return has_m_root | has_p_root;
+}
+
+static int
+ristretto255_is_canonical(const unsigned char *s)
+{
+ unsigned char c;
+ unsigned char d;
+ unsigned int i;
+
+ c = (s[31] & 0x7f) ^ 0x7f;
+ for (i = 30; i > 0; i--) {
+ c |= s[i] ^ 0xff;
+ }
+ c = (((unsigned int) c) - 1U) >> 8;
+ d = (0xed - 1U - (unsigned int) s[0]) >> 8;
+
+ return 1 - (((c & d) | s[0]) & 1);
+}
+
+int
+ristretto255_frombytes(ge25519_p3 *h, const unsigned char *s)
+{
+ fe25519 inv_sqrt;
+ fe25519 one;
+ fe25519 s_;
+ fe25519 ss;
+ fe25519 u1, u2;
+ fe25519 u1u1, u2u2;
+ fe25519 v;
+ fe25519 v_u2u2;
+ int was_square;
+
+ if (ristretto255_is_canonical(s) == 0) {
+ return -1;
+ }
+ fe25519_frombytes(s_, s);
+ fe25519_sq(ss, s_); /* ss = s^2 */
+
+ fe25519_1(u1);
+ fe25519_sub(u1, u1, ss); /* u1 = 1-ss */
+ fe25519_sq(u1u1, u1); /* u1u1 = u1^2 */
+
+ fe25519_1(u2);
+ fe25519_add(u2, u2, ss); /* u2 = 1+ss */
+ fe25519_sq(u2u2, u2); /* u2u2 = u2^2 */
+
+ fe25519_mul(v, d, u1u1); /* v = d*u1^2 */
+ fe25519_neg(v, v); /* v = -d*u1^2 */
+ fe25519_sub(v, v, u2u2); /* v = -(d*u1^2)-u2^2 */
+
+ fe25519_1(one);
+ fe25519_mul(v_u2u2, v, u2u2); /* v_u2u2 = v*u2^2 */
+
+ was_square = ristretto255_sqrt_ratio_m1(inv_sqrt, one, v_u2u2);
+ fe25519_mul(h->X, inv_sqrt, u2);
+ fe25519_mul(h->Y, inv_sqrt, h->X);
+ fe25519_mul(h->Y, h->Y, v);
+
+ fe25519_mul(h->X, h->X, s_);
+ fe25519_add(h->X, h->X, h->X);
+ fe25519_abs(h->X, h->X);
+ fe25519_mul(h->Y, u1, h->Y);
+ fe25519_1(h->Z);
+ fe25519_mul(h->T, h->X, h->Y);
+
+ return - ((1 - was_square) |
+ fe25519_isnegative(h->T) | fe25519_iszero(h->Y));
+}
+
+void
+ristretto255_p3_tobytes(unsigned char *s, const ge25519_p3 *h)
+{
+ fe25519 den1, den2;
+ fe25519 den_inv;
+ fe25519 eden;
+ fe25519 inv_sqrt;
+ fe25519 ix, iy;
+ fe25519 one;
+ fe25519 s_;
+ fe25519 t_z_inv;
+ fe25519 u1, u2;
+ fe25519 u1_u2u2;
+ fe25519 x_, y_;
+ fe25519 x_z_inv;
+ fe25519 z_inv;
+ fe25519 zmy;
+ int rotate;
+
+ fe25519_add(u1, h->Z, h->Y); /* u1 = Z+Y */
+ fe25519_sub(zmy, h->Z, h->Y); /* zmy = Z-Y */
+ fe25519_mul(u1, u1, zmy); /* u1 = (Z+Y)*(Z-Y) */
+ fe25519_mul(u2, h->X, h->Y); /* u2 = X*Y */
+
+ fe25519_1(one);
+ fe25519_sq(u1_u2u2, u2); /* u1_u2u2 = u2^2 */
+ fe25519_mul(u1_u2u2, u1, u1_u2u2); /* u1_u2u2 = u1*u2^2 */
+
+ (void) ristretto255_sqrt_ratio_m1(inv_sqrt, one, u1_u2u2);
+ fe25519_mul(den1, inv_sqrt, u1); /* den1 = inv_sqrt*u1 */
+ fe25519_mul(den2, inv_sqrt, u2); /* den2 = inv_sqrt*u2 */
+ fe25519_mul(z_inv, den1, den2); /* z_inv = den1*den2 */
+ fe25519_mul(z_inv, z_inv, h->T); /* z_inv = den1*den2*T */
+
+ fe25519_mul(ix, h->X, sqrtm1); /* ix = X*sqrt(-1) */
+ fe25519_mul(iy, h->Y, sqrtm1); /* iy = Y*sqrt(-1) */
+ fe25519_mul(eden, den1, invsqrtamd); /* eden = den1*sqrt(a-d) */
+
+ fe25519_mul(t_z_inv, h->T, z_inv); /* t_z_inv = T*z_inv */
+ rotate = fe25519_isnegative(t_z_inv);
+
+ fe25519_copy(x_, h->X);
+ fe25519_copy(y_, h->Y);
+ fe25519_copy(den_inv, den2) ;
+
+ fe25519_cmov(x_, iy, rotate);
+ fe25519_cmov(y_, ix, rotate);
+ fe25519_cmov(den_inv, eden, rotate);
+
+ fe25519_mul(x_z_inv, x_, z_inv);
+ fe25519_cneg(y_, y_, fe25519_isnegative(x_z_inv));
+
+ fe25519_sub(s_, h->Z, y_);
+ fe25519_mul(s_, den_inv, s_);
+ fe25519_abs(s_, s_);
+ fe25519_tobytes(s, s_);
+}
+
+static void
+ristretto255_elligator(ge25519_p3 *p, const fe25519 t)
+{
+ fe25519 c;
+ fe25519 n;
+ fe25519 one;
+ fe25519 r;
+ fe25519 rpd;
+ fe25519 s, s_prime;
+ fe25519 ss;
+ fe25519 u, v;
+ fe25519 w0, w1, w2, w3;
+ int wasnt_square;
+
+ fe25519_1(one);
+ fe25519_sq(r, t); /* r = t^2 */
+ fe25519_mul(r, sqrtm1, r); /* r = sqrt(-1)*t^2 */
+ fe25519_add(u, r, one); /* u = r+1 */
+ fe25519_mul(u, u, onemsqd); /* u = (r+1)*(1-d^2) */
+ fe25519_1(c);
+ fe25519_neg(c, c); /* c = -1 */
+ fe25519_add(rpd, r, d); /* rpd = r*d */
+ fe25519_mul(v, r, d); /* v = r*d */
+ fe25519_sub(v, c, v); /* v = c-r*d */
+ fe25519_mul(v, v, rpd); /* v = (c-r*d)*(r+d) */
+
+ wasnt_square = 1 - ristretto255_sqrt_ratio_m1(s, u, v);
+ fe25519_mul(s_prime, s, t);
+ fe25519_abs(s_prime, s_prime);
+ fe25519_neg(s_prime, s_prime); /* s_prime = -|s*t| */
+ fe25519_cmov(s, s_prime, wasnt_square);
+ fe25519_cmov(c, r, wasnt_square);
+
+ fe25519_sub(n, r, one); /* n = r-1 */
+ fe25519_mul(n, n, c); /* n = c*(r-1) */
+ fe25519_mul(n, n, sqdmone); /* n = c*(r-1)*(d-1)^2 */
+ fe25519_sub(n, n, v); /* n = c*(r-1)*(d-1)^2-v */
+
+ fe25519_add(w0, s, s); /* w0 = 2s */
+ fe25519_mul(w0, w0, v); /* w0 = 2s*v */
+ fe25519_mul(w1, n, sqrtadm1); /* w1 = n*sqrt(ad-1) */
+ fe25519_sq(ss, s); /* ss = s^2 */
+ fe25519_sub(w2, one, ss); /* w2 = 1-s^2 */
+ fe25519_add(w3, one, ss); /* w3 = 1+s^2 */
+
+ fe25519_mul(p->X, w0, w3);
+ fe25519_mul(p->Y, w2, w1);
+ fe25519_mul(p->Z, w1, w3);
+ fe25519_mul(p->T, w0, w2);
+}
+
+void
+ristretto255_from_uniform(unsigned char s[32], const unsigned char r[64])
+{
+ fe25519 r0, r1;
+ ge25519_cached p1_cached;
+ ge25519_p1p1 p_p1p1;
+ ge25519_p3 p0, p1;
+ ge25519_p3 p;
+
+ fe25519_frombytes(r0, r);
+ fe25519_frombytes(r1, r + 32);
+ ristretto255_elligator(&p0, r0);
+ ristretto255_elligator(&p1, r1);
+ ge25519_p3_to_cached(&p1_cached, &p1);
+ ge25519_add(&p_p1p1, &p0, &p1_cached);
+ ge25519_p1p1_to_p3(&p, &p_p1p1);
+ ristretto255_p3_tobytes(s, &p);
+}
diff --git a/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/constants.h b/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/constants.h
index 3dc9156a..dd6da1b8 100644
--- a/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/constants.h
+++ b/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/constants.h
@@ -18,3 +18,23 @@ static const fe25519 sqrtm1 = {
static const fe25519 curve25519_A = {
486662, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
+
+/* sqrt(ad - 1) with a = -1 (mod p) */
+static const fe25519 sqrtadm1 = {
+ 24849947, -153582, -23613485, 6347715, -21072328, -667138, -25271143, -15367704, -870347, 14525639
+};
+
+/* 1 / sqrt(a - d) */
+static const fe25519 invsqrtamd = {
+ 6111485, 4156064, -27798727, 12243468, -25904040, 120897, 20826367, -7060776, 6093568, -1986012
+};
+
+/* 1 - d ^ 2 */
+static const fe25519 onemsqd = {
+ 6275446, -16617371, -22938544, -3773710, 11667077, 7397348, -27922721, 1766195, -24433858, 672203
+};
+
+/* (d - 1) ^ 2 */
+static const fe25519 sqdmone = {
+ 15551795, -11097455, -13425098, -10125071, -11896535, 10178284, -26634327, 4729244, -5282110, -10116402
+};
diff --git a/src/libsodium/crypto_core/ed25519/ref10/fe_51/constants.h b/src/libsodium/crypto_core/ed25519/ref10/fe_51/constants.h
index 53b75c6b..24e5cb5e 100644
--- a/src/libsodium/crypto_core/ed25519/ref10/fe_51/constants.h
+++ b/src/libsodium/crypto_core/ed25519/ref10/fe_51/constants.h
@@ -19,3 +19,23 @@ static const fe25519 sqrtm1 = {
static const fe25519 curve25519_A = {
486662, 0, 0, 0, 0
};
+
+/* sqrt(ad - 1) with a = -1 (mod p) */
+static const fe25519 sqrtadm1 = {
+ 2241493124984347, 425987919032274, 2207028919301688, 1220490630685848, 974799131293748
+};
+
+/* 1 / sqrt(a - d) */
+static const fe25519 invsqrtamd = {
+ 278908739862762, 821645201101625, 8113234426968, 1777959178193151, 2118520810568447
+};
+
+/* 1 - d ^ 2 */
+static const fe25519 onemsqd = {
+ 1136626929484150, 1998550399581263, 496427632559748, 118527312129759, 45110755273534
+};
+
+/* (d - 1) ^ 2 */
+static const fe25519 sqdmone = {
+ 1507062230895904, 1572317787530805, 683053064812840, 317374165784489, 1572899562415810
+};
diff --git a/src/libsodium/crypto_scalarmult/ristretto255/ref10/scalarmult_ristretto255_ref10.c b/src/libsodium/crypto_scalarmult/ristretto255/ref10/scalarmult_ristretto255_ref10.c
new file mode 100644
index 00000000..09d87eba
--- /dev/null
+++ b/src/libsodium/crypto_scalarmult/ristretto255/ref10/scalarmult_ristretto255_ref10.c
@@ -0,0 +1,62 @@
+
+#include
+
+#include "crypto_scalarmult_ed25519.h"
+#include "crypto_scalarmult_ristretto255.h"
+#include "private/ed25519_ref10.h"
+#include "utils.h"
+
+int
+crypto_scalarmult_ristretto255(unsigned char *q, const unsigned char *n,
+ const unsigned char *p)
+{
+ unsigned char *t = q;
+ ge25519_p3 Q;
+ ge25519_p3 P;
+ unsigned int i;
+
+ if (ristretto255_frombytes(&P, p) != 0) {
+ return -1;
+ }
+ for (i = 0; i < 32; ++i) {
+ t[i] = n[i];
+ }
+ t[31] &= 127;
+ ge25519_scalarmult(&Q, t, &P);
+ ristretto255_p3_tobytes(q, &Q);
+ if (sodium_is_zero(q, 32)) {
+ return -1;
+ }
+ return 0;
+}
+
+int
+crypto_scalarmult_ristretto255_base(unsigned char *q,
+ const unsigned char *n)
+{
+ unsigned char *t = q;
+ ge25519_p3 Q;
+ unsigned int i;
+
+ for (i = 0; i < 32; ++i) {
+ t[i] = n[i];
+ }
+ t[31] &= 127;
+ ge25519_scalarmult_base(&Q, t);
+ ristretto255_p3_tobytes(q, &Q);
+ if (sodium_is_zero(q, 32)) {
+ return -1;
+ }
+ return 0;
+}
+size_t
+crypto_scalarmult_ristretto255_bytes(void)
+{
+ return crypto_scalarmult_ristretto255_BYTES;
+}
+
+size_t
+crypto_scalarmult_ristretto255_scalarbytes(void)
+{
+ return crypto_scalarmult_ristretto255_SCALARBYTES;
+}
diff --git a/src/libsodium/include/Makefile.am b/src/libsodium/include/Makefile.am
index c7d5121f..b78df193 100644
--- a/src/libsodium/include/Makefile.am
+++ b/src/libsodium/include/Makefile.am
@@ -13,6 +13,7 @@ SODIUM_EXPORT = \
sodium/crypto_box_curve25519xchacha20poly1305.h \
sodium/crypto_box_curve25519xsalsa20poly1305.h \
sodium/crypto_core_ed25519.h \
+ sodium/crypto_core_ristretto255.h \
sodium/crypto_core_hchacha20.h \
sodium/crypto_core_hsalsa20.h \
sodium/crypto_core_salsa20.h \
@@ -35,6 +36,7 @@ SODIUM_EXPORT = \
sodium/crypto_scalarmult.h \
sodium/crypto_scalarmult_curve25519.h \
sodium/crypto_scalarmult_ed25519.h \
+ sodium/crypto_scalarmult_ristretto255.h \
sodium/crypto_secretbox.h \
sodium/crypto_secretbox_xchacha20poly1305.h \
sodium/crypto_secretbox_xsalsa20poly1305.h \
diff --git a/src/libsodium/include/sodium.h b/src/libsodium/include/sodium.h
index ecc8f689..0fc1dbe2 100644
--- a/src/libsodium/include/sodium.h
+++ b/src/libsodium/include/sodium.h
@@ -56,7 +56,9 @@
#ifndef SODIUM_LIBRARY_MINIMAL
# include "sodium/crypto_box_curve25519xchacha20poly1305.h"
# include "sodium/crypto_core_ed25519.h"
+# include "sodium/crypto_core_ristretto255.h"
# include "sodium/crypto_scalarmult_ed25519.h"
+# include "sodium/crypto_scalarmult_ristretto255.h"
# include "sodium/crypto_secretbox_xchacha20poly1305.h"
# include "sodium/crypto_pwhash_scryptsalsa208sha256.h"
# include "sodium/crypto_stream_salsa2012.h"
diff --git a/src/libsodium/include/sodium/crypto_core_ristretto255.h b/src/libsodium/include/sodium/crypto_core_ristretto255.h
new file mode 100644
index 00000000..2f2c1f29
--- /dev/null
+++ b/src/libsodium/include/sodium/crypto_core_ristretto255.h
@@ -0,0 +1,90 @@
+#ifndef crypto_core_ristretto255_H
+#define crypto_core_ristretto255_H
+
+#include
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_core_ristretto255_BYTES 32
+SODIUM_EXPORT
+size_t crypto_core_ristretto255_bytes(void);
+
+#define crypto_core_ristretto255_UNIFORMBYTES 64
+SODIUM_EXPORT
+size_t crypto_core_ristretto255_uniformbytes(void);
+
+#define crypto_core_ristretto255_SCALARBYTES 32
+SODIUM_EXPORT
+size_t crypto_core_ristretto255_scalarbytes(void);
+
+#define crypto_core_ristretto255_NONREDUCEDSCALARBYTES 64
+SODIUM_EXPORT
+size_t crypto_core_ristretto255_nonreducedscalarbytes(void);
+
+SODIUM_EXPORT
+int crypto_core_ristretto255_is_valid_point(const unsigned char *p)
+ __attribute__ ((nonnull));
+
+SODIUM_EXPORT
+int crypto_core_ristretto255_add(unsigned char *r,
+ const unsigned char *p, const unsigned char *q)
+ __attribute__ ((nonnull));
+
+SODIUM_EXPORT
+int crypto_core_ristretto255_sub(unsigned char *r,
+ const unsigned char *p, const unsigned char *q)
+ __attribute__ ((nonnull));
+
+SODIUM_EXPORT
+int crypto_core_ristretto255_from_uniform(unsigned char *p,
+ const unsigned char *r)
+ __attribute__ ((nonnull));
+
+SODIUM_EXPORT
+void crypto_core_ristretto255_scalar_random(unsigned char *r)
+ __attribute__ ((nonnull));
+
+SODIUM_EXPORT
+int crypto_core_ristretto255_scalar_invert(unsigned char *recip,
+ const unsigned char *s)
+ __attribute__ ((nonnull));
+
+SODIUM_EXPORT
+void crypto_core_ristretto255_scalar_negate(unsigned char *neg,
+ const unsigned char *s)
+ __attribute__ ((nonnull));
+
+SODIUM_EXPORT
+void crypto_core_ristretto255_scalar_complement(unsigned char *comp,
+ const unsigned char *s)
+ __attribute__ ((nonnull));
+
+SODIUM_EXPORT
+void crypto_core_ristretto255_scalar_add(unsigned char *z,
+ const unsigned char *x,
+ const unsigned char *y)
+ __attribute__ ((nonnull));
+
+SODIUM_EXPORT
+void crypto_core_ristretto255_scalar_sub(unsigned char *z,
+ const unsigned char *x,
+ const unsigned char *y)
+ __attribute__ ((nonnull));
+
+/*
+ * The interval `s` is sampled from should be at least 317 bits to ensure almost
+ * uniformity of `r` over `L`.
+ */
+SODIUM_EXPORT
+void crypto_core_ristretto255_scalar_reduce(unsigned char *r,
+ const unsigned char *s)
+ __attribute__ ((nonnull));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libsodium/include/sodium/crypto_scalarmult.h b/src/libsodium/include/sodium/crypto_scalarmult.h
index 01a8e3ea..1c685853 100644
--- a/src/libsodium/include/sodium/crypto_scalarmult.h
+++ b/src/libsodium/include/sodium/crypto_scalarmult.h
@@ -27,7 +27,7 @@ int crypto_scalarmult_base(unsigned char *q, const unsigned char *n)
__attribute__ ((nonnull));
/*
- * NOTE: Do not use the result of this function directly.
+ * NOTE: Do not use the result of this function directly for key exchange.
*
* Hash the result with the public keys in order to compute a shared
* secret key: H(q || client_pk || server_pk)
diff --git a/src/libsodium/include/sodium/crypto_scalarmult_curve25519.h b/src/libsodium/include/sodium/crypto_scalarmult_curve25519.h
index e5605cb2..60e9d0c5 100644
--- a/src/libsodium/include/sodium/crypto_scalarmult_curve25519.h
+++ b/src/libsodium/include/sodium/crypto_scalarmult_curve25519.h
@@ -18,7 +18,7 @@ SODIUM_EXPORT
size_t crypto_scalarmult_curve25519_scalarbytes(void);
/*
- * NOTE: Do not use the result of this function directly.
+ * NOTE: Do not use the result of this function directly for key exchange.
*
* Hash the result with the public keys in order to compute a shared
* secret key: H(q || client_pk || server_pk)
diff --git a/src/libsodium/include/sodium/crypto_scalarmult_ed25519.h b/src/libsodium/include/sodium/crypto_scalarmult_ed25519.h
index 1958643c..2dfa4d70 100644
--- a/src/libsodium/include/sodium/crypto_scalarmult_ed25519.h
+++ b/src/libsodium/include/sodium/crypto_scalarmult_ed25519.h
@@ -19,7 +19,7 @@ SODIUM_EXPORT
size_t crypto_scalarmult_ed25519_scalarbytes(void);
/*
- * NOTE: Do not use the result of this function directly.
+ * NOTE: Do not use the result of this function directly for key exchange.
*
* Hash the result with the public keys in order to compute a shared
* secret key: H(q || client_pk || server_pk)
diff --git a/src/libsodium/include/sodium/crypto_scalarmult_ristretto255.h b/src/libsodium/include/sodium/crypto_scalarmult_ristretto255.h
new file mode 100644
index 00000000..40a45cce
--- /dev/null
+++ b/src/libsodium/include/sodium/crypto_scalarmult_ristretto255.h
@@ -0,0 +1,43 @@
+
+#ifndef crypto_scalarmult_ristretto255_H
+#define crypto_scalarmult_ristretto255_H
+
+#include
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define crypto_scalarmult_ristretto255_BYTES 32U
+SODIUM_EXPORT
+size_t crypto_scalarmult_ristretto255_bytes(void);
+
+#define crypto_scalarmult_ristretto255_SCALARBYTES 32U
+SODIUM_EXPORT
+size_t crypto_scalarmult_ristretto255_scalarbytes(void);
+
+/*
+ * NOTE: Do not use the result of this function directly for key exchange.
+ *
+ * Hash the result with the public keys in order to compute a shared
+ * secret key: H(q || client_pk || server_pk)
+ *
+ * Or unless this is not an option, use the crypto_kx() API instead.
+ */
+SODIUM_EXPORT
+int crypto_scalarmult_ristretto255(unsigned char *q, const unsigned char *n,
+ const unsigned char *p)
+ __attribute__ ((warn_unused_result)) __attribute__ ((nonnull));
+
+SODIUM_EXPORT
+int crypto_scalarmult_ristretto255_base(unsigned char *q,
+ const unsigned char *n)
+ __attribute__ ((nonnull));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libsodium/include/sodium/private/ed25519_ref10.h b/src/libsodium/include/sodium/private/ed25519_ref10.h
index 5af41591..d309e021 100644
--- a/src/libsodium/include/sodium/private/ed25519_ref10.h
+++ b/src/libsodium/include/sodium/private/ed25519_ref10.h
@@ -110,6 +110,16 @@ int ge25519_has_small_order(const unsigned char s[32]);
void ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]);
+/*
+ Ristretto group
+ */
+
+int ristretto255_frombytes(ge25519_p3 *h, const unsigned char *s);
+
+void ristretto255_p3_tobytes(unsigned char *s, const ge25519_p3 *h);
+
+void ristretto255_from_uniform(unsigned char s[32], const unsigned char r[64]);
+
/*
The set of scalars is \Z/l
where l = 2^252 + 27742317777372353535851937790883648493.
diff --git a/test/default/Makefile.am b/test/default/Makefile.am
index 5a95c123..9ccefe70 100644
--- a/test/default/Makefile.am
+++ b/test/default/Makefile.am
@@ -25,6 +25,7 @@ EXTRA_DIST = \
chacha20.exp \
codecs.exp \
core_ed25519.exp \
+ core_ristretto255.exp \
core1.exp \
core2.exp \
core3.exp \
@@ -53,6 +54,7 @@ EXTRA_DIST = \
randombytes.exp \
scalarmult.exp \
scalarmult_ed25519.exp \
+ scalarmult_ristretto255.exp \
scalarmult2.exp \
scalarmult5.exp \
scalarmult6.exp \
@@ -103,6 +105,7 @@ DISTCLEANFILES = \
chacha20.res \
codecs.res \
core_ed25519.res \
+ core_ristretto255.res \
core1.res \
core2.res \
core3.res \
@@ -131,6 +134,7 @@ DISTCLEANFILES = \
randombytes.res \
scalarmult.res \
scalarmult_ed25519.res \
+ scalarmult_ristretto255.res \
scalarmult2.res \
scalarmult5.res \
scalarmult6.res \
@@ -316,6 +320,9 @@ codecs_LDADD = $(TESTS_LDADD)
core_ed25519_SOURCE = cmptest.h core_ed25519.c
core_ed25519_LDADD = $(TESTS_LDADD)
+core_ristretto255_SOURCE = cmptest.h core_ristretto255.c
+core_ristretto255_LDADD = $(TESTS_LDADD)
+
core1_SOURCE = cmptest.h core1.c
core1_LDADD = $(TESTS_LDADD)
@@ -397,6 +404,9 @@ scalarmult_LDADD = $(TESTS_LDADD)
scalarmult_ed25519_SOURCE = cmptest.h scalarmult_ed25519.c
scalarmult_ed25519_LDADD = $(TESTS_LDADD)
+scalarmult_ristretto255_SOURCE = cmptest.h scalarmult_ristretto255.c
+scalarmult_ristretto255_LDADD = $(TESTS_LDADD)
+
scalarmult2_SOURCE = cmptest.h scalarmult2.c
scalarmult2_LDADD = $(TESTS_LDADD)
@@ -478,9 +488,11 @@ xchacha20_LDADD = $(TESTS_LDADD)
if !MINIMAL
TESTS_TARGETS += \
core_ed25519 \
+ core_ristretto255 \
pwhash_scrypt \
pwhash_scrypt_ll \
scalarmult_ed25519 \
+ scalarmult_ristretto255 \
siphashx24 \
xchacha20
endif
diff --git a/test/default/core_ristretto255.c b/test/default/core_ristretto255.c
new file mode 100644
index 00000000..8af208b3
--- /dev/null
+++ b/test/default/core_ristretto255.c
@@ -0,0 +1,117 @@
+#define TEST_NAME "core_ristretto255"
+#include "cmptest.h"
+
+static void
+tv1(void)
+{
+ static const char *bad_encodings_hex[] = {
+ /* Non-canonical field encodings */
+ "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+ "f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+ "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+
+ /* Negative field elements */
+ "0100000000000000000000000000000000000000000000000000000000000000",
+ "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+ "ed57ffd8c914fb201471d1c3d245ce3c746fcbe63a3679d51b6a516ebebe0e20",
+ "c34c4e1826e5d403b78e246e88aa051c36ccf0aafebffe137d148a2bf9104562",
+ "c940e5a4404157cfb1628b108db051a8d439e1a421394ec4ebccb9ec92a8ac78",
+ "47cfc5497c53dc8e61c91d17fd626ffb1c49e2bca94eed052281b510b1117a24",
+ "f1c6165d33367351b0da8f6e4511010c68174a03b6581212c71c0e1d026c3c72",
+ "87260f7a2f12495118360f02c26a470f450dadf34a413d21042b43b9d93e1309",
+
+ /* Non-square x^2 */
+ "26948d35ca62e643e26a83177332e6b6afeb9d08e4268b650f1f5bbd8d81d371",
+ "4eac077a713c57b4f4397629a4145982c661f48044dd3f96427d40b147d9742f",
+ "de6a7b00deadc788eb6b6c8d20c0ae96c2f2019078fa604fee5b87d6e989ad7b",
+ "bcab477be20861e01e4a0e295284146a510150d9817763caf1a6f4b422d67042",
+ "2a292df7e32cababbd9de088d1d1abec9fc0440f637ed2fba145094dc14bea08",
+ "f4a9e534fc0d216c44b218fa0c42d99635a0127ee2e53c712f70609649fdff22",
+ "8268436f8c4126196cf64b3c7ddbda90746a378625f9813dd9b8457077256731",
+ "2810e5cbc2cc4d4eece54f61c6f69758e289aa7ab440b3cbeaa21995c2f4232b",
+
+ /* Negative xy value */
+ "3eb858e78f5a7254d8c9731174a94f76755fd3941c0ac93735c07ba14579630e",
+ "a45fdc55c76448c049a1ab33f17023edfb2be3581e9c7aade8a6125215e04220",
+ "d483fe813c6ba647ebbfd3ec41adca1c6130c2beeee9d9bf065c8d151c5f396e",
+ "8a2e1d30050198c65a54483123960ccc38aef6848e1ec8f5f780e8523769ba32",
+ "32888462f8b486c68ad7dd9610be5192bbeaf3b443951ac1a8118419d9fa097b",
+ "227142501b9d4355ccba290404bde41575b037693cef1f438c47f8fbf35d1165",
+ "5c37cc491da847cfeb9281d407efc41e15144c876e0170b499a96a22ed31e01e",
+ "445425117cb8c90edcbc7c1cc0e74f747f2c1efa5630a967c64f287792a48a4b",
+
+ /* s = -1, which causes y = 0 */
+ "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f"
+ };
+ unsigned char *s;
+ size_t i;
+
+ s = (unsigned char *) sodium_malloc(crypto_core_ristretto255_BYTES);
+ for (i = 0; i < sizeof bad_encodings_hex / sizeof bad_encodings_hex[0]; i++) {
+ sodium_hex2bin(s, crypto_core_ristretto255_BYTES, bad_encodings_hex[i],
+ crypto_core_ristretto255_BYTES * 2 + 1,
+ NULL, NULL, NULL);
+ if (crypto_core_ristretto255_is_valid_point(s)) {
+ printf("[%s] was not rejected\n", bad_encodings_hex[i]);
+ }
+ }
+ sodium_free(s);
+};
+
+static void
+tv2(void)
+{
+ static const char *uniform_hex[] = {
+ "5d1be09e3d0c82fc538112490e35701979d99e06ca3e2b5b54bffe8b4dc772c1"
+ "4d98b696a1bbfb5ca32c436cc61c16563790306c79eaca7705668b47dffe5bb6",
+
+ "f116b34b8f17ceb56e8732a60d913dd10cce47a6d53bee9204be8b44f6678b27"
+ "0102a56902e2488c46120e9276cfe54638286b9e4b3cdb470b542d46c2068d38",
+
+ "8422e1bbdaab52938b81fd602effb6f89110e1e57208ad12d9ad767e2e25510c"
+ "27140775f9337088b982d83d7fcf0b2fa1edffe51952cbe7365e95c86eaf325c",
+
+ "ac22415129b61427bf464e17baee8db65940c233b98afce8d17c57beeb7876c2"
+ "150d15af1cb1fb824bbd14955f2b57d08d388aab431a391cfc33d5bafb5dbbaf",
+
+ "165d697a1ef3d5cf3c38565beefcf88c0f282b8e7dbd28544c483432f1cec767"
+ "5debea8ebb4e5fe7d6f6e5db15f15587ac4d4d4a1de7191e0c1ca6664abcc413",
+
+ "a836e6c9a9ca9f1e8d486273ad56a78c70cf18f0ce10abb1c7172ddd605d7fd2"
+ "979854f47ae1ccf204a33102095b4200e5befc0465accc263175485f0e17ea5c",
+
+ "2cdc11eaeb95daf01189417cdddbf95952993aa9cb9c640eb5058d09702c7462"
+ "2c9965a697a3b345ec24ee56335b556e677b30e6f90ac77d781064f866a3c982"
+ };
+ unsigned char *s;
+ unsigned char *u;
+ char *hex;
+ size_t i;
+
+ s = (unsigned char *) sodium_malloc(crypto_core_ristretto255_BYTES);
+ u = (unsigned char *) sodium_malloc(crypto_core_ristretto255_UNIFORMBYTES);
+ hex = (char *) sodium_malloc(crypto_core_ristretto255_BYTES * 2 + 1);
+ for (i = 0; i < sizeof uniform_hex / sizeof uniform_hex[0]; i++) {
+ sodium_hex2bin(u, crypto_core_ristretto255_UNIFORMBYTES, uniform_hex[i],
+ crypto_core_ristretto255_UNIFORMBYTES * 2 + 1,
+ NULL, NULL, NULL);
+ crypto_core_ristretto255_from_uniform(s, u);
+ sodium_bin2hex(hex, crypto_core_ristretto255_BYTES * 2 + 1,
+ s, crypto_core_ristretto255_BYTES);
+ printf("%s\n", hex);
+ }
+ sodium_free(hex);
+ sodium_free(u);
+ sodium_free(s);
+}
+
+int
+main(void)
+{
+ tv1();
+ tv2();
+ printf("OK\n");
+
+ return 0;
+}
diff --git a/test/default/core_ristretto255.exp b/test/default/core_ristretto255.exp
new file mode 100644
index 00000000..8618d892
--- /dev/null
+++ b/test/default/core_ristretto255.exp
@@ -0,0 +1,8 @@
+3066f82a1a747d45120d1740f14358531a8f04bbffe6a819f86dfe50f44a0a46
+f26e5b6f7d362d2d2a94c5d0e7602cb4773c95a2e5c31a64f133189fa76ed61b
+006ccd2a9e6867e6a2c5cea83d3302cc9de128dd2a9a57dd8ee7b9d7ffe02826
+f8f0c87cf237953c5890aec3998169005dae3eca1fbb04548c635953c817f92a
+ae81e7dedf20a497e10c304a765c1767a42d6e06029758d2d7e8ef7cc4c41179
+e2705652ff9f5e44d3e841bf1c251cf7dddb77d140870d1ab2ed64f1a9ce8628
+80bd07262511cdde4863f8a7434cef696750681cb9510eea557088f76d9e5065
+OK
diff --git a/test/default/scalarmult_ristretto255.c b/test/default/scalarmult_ristretto255.c
new file mode 100644
index 00000000..96a813cb
--- /dev/null
+++ b/test/default/scalarmult_ristretto255.c
@@ -0,0 +1,47 @@
+#define TEST_NAME "scalarmult_ristretto255"
+#include "cmptest.h"
+
+#define B_HEX "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76"
+
+int
+main(void)
+{
+ unsigned char *b =
+ (unsigned char *) sodium_malloc(crypto_scalarmult_ristretto255_BYTES);
+ unsigned char *n =
+ (unsigned char *) sodium_malloc(crypto_scalarmult_ristretto255_SCALARBYTES);
+ unsigned char *p =
+ (unsigned char *) sodium_malloc(crypto_scalarmult_ristretto255_BYTES);
+ unsigned char *p2 =
+ (unsigned char *) sodium_malloc(crypto_scalarmult_ristretto255_BYTES);
+ char *hex =
+ (char *) sodium_malloc(2 * crypto_scalarmult_ristretto255_BYTES + 1);
+ int i;
+
+ sodium_hex2bin(b, crypto_scalarmult_ristretto255_BYTES,
+ B_HEX, sizeof B_HEX - (size_t) 1U, NULL, NULL, NULL);
+ memset(n, 0, crypto_scalarmult_ristretto255_SCALARBYTES);
+ for (i = 0; i < 16; i++) {
+ crypto_scalarmult_ristretto255_base(p, n);
+ if (crypto_scalarmult_ristretto255(p2, n, b) != 0) {
+ printf("crypto_scalarmult_ristretto255(%d) != 0\n", i);
+ }
+ sodium_bin2hex(hex, 2 * crypto_scalarmult_ristretto255_BYTES + 1,
+ p, crypto_scalarmult_ristretto255_BYTES);
+ printf("%s\n", hex);
+ assert(memcmp(p, p2, crypto_scalarmult_ristretto255_BYTES) == 0);
+ sodium_increment(n, crypto_scalarmult_ristretto255_SCALARBYTES);
+ }
+ sodium_free(hex);
+ sodium_free(p2);
+ sodium_free(p);
+ sodium_free(n);
+ sodium_free(b);
+
+ assert(crypto_scalarmult_ristretto255_BYTES == crypto_scalarmult_ristretto255_bytes());
+ assert(crypto_scalarmult_ristretto255_SCALARBYTES == crypto_scalarmult_ristretto255_scalarbytes());
+
+ printf("OK\n");
+
+ return 0;
+}
diff --git a/test/default/scalarmult_ristretto255.exp b/test/default/scalarmult_ristretto255.exp
new file mode 100644
index 00000000..919a7621
--- /dev/null
+++ b/test/default/scalarmult_ristretto255.exp
@@ -0,0 +1,18 @@
+crypto_scalarmult_ristretto255(0) != 0
+0000000000000000000000000000000000000000000000000000000000000000
+e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76
+6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919
+94741f5d5d52755ece4f23f044ee27d5d1ea1e2bd196b462166b16152a9d0259
+da80862773358b466ffadfe0b3293ab3d9fd53c5ea6c955358f568322daf6a57
+e882b131016b52c1d3337080187cf768423efccbb517bb495ab812c4160ff44e
+f64746d3c92b13050ed8d80236a7f0007c3b3f962f5ba793d19a601ebb1df403
+44f53520926ec81fbd5a387845beb7df85a96a24ece18738bdcfa6a7822a176d
+903293d8f2287ebe10e2374dc1a53e0bc887e592699f02d077d5263cdd55601c
+02622ace8f7303a31cafc63f8fc48fdc16e1c8c8d234b2f0d6685282a9076031
+20706fd788b2720a1ed2a5dad4952b01f413bcf0e7564de8cdc816689e2db95f
+bce83f8ba5dd2fa572864c24ba1810f9522bc6004afe95877ac73241cafdab42
+e4549ee16b9aa03099ca208c67adafcafa4c3f3e4e5303de6026e3ca8ff84460
+aa52e000df2e16f55fb1032fc33bc42742dad6bd5a8fc0be0167436c5948501f
+46376b80f409b29dc2b5f6f0c52591990896e5716f41477cd30085ab7f10301e
+e0c418f7c8d9c4cdd7395b93ea124f3ad99021bb681dfc3302a9d99a2e53e64e
+OK