Compare commits

..

2 Commits

Author SHA1 Message Date
Moxie Marlinspike
813bdffeb5 Reinstate dynamic memory allocation
// FREEBIE
2016-08-10 15:18:45 -07:00
Moxie Marlinspike
4c2a5e9343 Add VUF support
// FREEBIE
2016-08-09 16:03:21 -07:00
75 changed files with 1205 additions and 2706 deletions

View File

@ -1,10 +1,10 @@
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.android.tools.build:gradle:1.0.0'
}
}
@ -44,9 +44,7 @@ repositories {
dependencies {
compile project(':java')
androidTestCompile (project(":tests")) {
exclude module: 'junit'
}
androidTestCompile project(":tests")
}
signing {

View File

@ -10,11 +10,8 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcurve25519-ref10
LOCAL_SRC_FILES := $(wildcard ed25519/*.c) $(wildcard ed25519/additions/*.c) \
$(wildcard ed25519/additions/generalized/*.c) $(wildcard ed25519/nacl_sha512/*.c) \
ed25519/tests/internal_fast_tests.c
LOCAL_C_INCLUDES := ed25519/nacl_includes ed25519/additions ed25519/additions/generalized ed25519/tests ed25519/sha512 ed25519
LOCAL_SRC_FILES := $(wildcard ed25519/*.c) $(wildcard ed25519/additions/*.c) $(wildcard ed25519/nacl_sha512/*.c)
LOCAL_C_INCLUDES := ed25519/nacl_includes ed25519/additions ed25519/sha512 ed25519
include $(BUILD_STATIC_LIBRARY)
@ -22,7 +19,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE := libcurve25519
LOCAL_SRC_FILES := curve25519-jni.c
LOCAL_C_INCLUDES := ed25519/additions ed25519/additions/generalized ed25519/tests
LOCAL_C_INCLUDES := ed25519/additions
LOCAL_STATIC_LIBRARIES := libcurve25519-donna libcurve25519-ref10

View File

@ -1 +1 @@
APP_ABI := armeabi armeabi-v7a x86 mips arm64-v8a x86_64
APP_ABI := armeabi armeabi-v7a x86 mips

View File

@ -11,9 +11,8 @@
#include <jni.h>
#include "curve25519-donna.h"
#include "curve_sigs.h"
#include "xeddsa.h"
#include "internal_fast_tests.h"
#include "gen_x.h"
#include "xdsa.h"
#include "uxdsa.h"
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_generatePrivateKey
(JNIEnv *env, jobject obj, jbyteArray random)
@ -73,7 +72,7 @@ JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
jsize messageLength = (*env)->GetArrayLength(env, message);
int result = xed25519_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength, randomBytes);
int result = xdsa_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength, randomBytes);
(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
(*env)->ReleaseByteArrayElements(env, random, randomBytes, 0);
@ -101,7 +100,7 @@ JNIEXPORT jboolean JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Pr
return result;
}
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_calculateVrfSignature
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_calculateUniqueSignature
(JNIEnv *env, jobject obj, jbyteArray random, jbyteArray privateKey, jbyteArray message)
{
jbyteArray signature = (*env)->NewByteArray(env, 96);
@ -111,7 +110,7 @@ JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
jsize messageLength = (*env)->GetArrayLength(env, message);
int result = generalized_xveddsa_25519_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength, randomBytes, NULL, 0);
int result = uxdsa_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength, randomBytes);
(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
(*env)->ReleaseByteArrayElements(env, random, randomBytes, 0);
@ -122,7 +121,7 @@ JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519
else (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/AssertionError"), "Signature failed!");
}
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_verifyVrfSignature
JNIEXPORT jboolean JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Provider_verifyUniqueSignature
(JNIEnv *env, jobject obj, jbyteArray publicKey, jbyteArray message, jbyteArray signature)
{
uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 0);
@ -130,18 +129,13 @@ JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_curve25519_NativeCurve25519
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
jsize messageLength = (*env)->GetArrayLength(env, message);
jbyteArray vrf = (*env)->NewByteArray(env, 32);
uint8_t* vrfBytes = (uint8_t*)(*env)->GetByteArrayElements(env, vrf, 0);
int result = generalized_xveddsa_25519_verify(vrfBytes, signatureBytes, publicKeyBytes, messageBytes, messageLength, NULL, 0);
jboolean result = (uxdsa_verify(signatureBytes, publicKeyBytes, messageBytes, messageLength) == 0);
(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
(*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, message, messageBytes, 0);
(*env)->ReleaseByteArrayElements(env, vrf, vrfBytes, 0);
if (result == 0) return vrf;
else (*env)->ThrowNew(env, (*env)->FindClass(env, "org/whispersystems/curve25519/VrfSignatureVerificationFailedException"), "Invalid signature");
return result;
}
@ -150,10 +144,3 @@ JNIEXPORT jboolean JNICALL Java_org_whispersystems_curve25519_NativeCurve25519Pr
{
return 1;
}
JNIEXPORT jboolean JNICALL Java_org_whispersystems_curve25519_NativeCurve25519ProviderTest_internalTest
(JNIEnv *env)
{
jboolean result = (all_fast_tests(1) == 0);
return result;
}

View File

@ -8,24 +8,24 @@
#define MAX_MSG_LEN 256
void sc_neg(unsigned char *b, const unsigned char *a);
void sc_cmov(unsigned char* f, const unsigned char* g, unsigned char b);
/* aneg = -a */
void sc_neg(unsigned char *aneg, const unsigned char *a);
int fe_isequal(const fe f, const fe g);
int fe_isreduced(const unsigned char* s);
void fe_mont_rhs(fe v2, const fe u);
void fe_montx_to_edy(fe y, const fe u);
void fe_sqrt(fe b, const fe a);
void fe_montx_to_edy(fe edy, const fe montx);
void ge_p3_to_montx(fe montx, const ge_p3 *ed);
int ge_isneutral(const ge_p3* q);
void ge_neg(ge_p3* r, const ge_p3 *p);
void ge_montx_to_p3(ge_p3* p, const fe u, const unsigned char ed_sign_bit);
void ge_p3_to_montx(fe u, const ge_p3 *p);
void ge_scalarmult(ge_p3 *h, const unsigned char *a, const ge_p3 *A);
void ge_scalarmult_cofactor(ge_p3 *q, const ge_p3 *p);
void elligator(fe u, const fe r);
void hash_to_point(ge_p3* p, const unsigned char* msg, const unsigned long in_len);
void elligator(fe out, const fe in);
void hash_to_point(ge_p3* out, const unsigned char* in, const unsigned long in_len);
void calculate_Bu(ge_p3* Bu,
unsigned char* buf,
const unsigned char* msg, const unsigned long msg_len);
void calculate_Bu_and_U(ge_p3* Bu,
unsigned char* U,
unsigned char* buf,
const unsigned char* a,
const unsigned char* msg, const unsigned long msg_len);
int crypto_sign_modified(
unsigned char *sm,
@ -36,10 +36,24 @@ int crypto_sign_modified(
);
int crypto_sign_open_modified(
unsigned char *m,
unsigned char *m,unsigned long long *mlen,
const unsigned char *sm,unsigned long long smlen,
const unsigned char *pk
);
int crypto_usign_modified(
unsigned char *sm,
const unsigned char *M,unsigned long Mlen,
const unsigned char *a,
const unsigned char *A,
const unsigned char *random,
const ge_p3 *Bu,
const unsigned char *U);
int crypto_usign_open_modified(
unsigned char *m,unsigned long long *mlen,
const unsigned char *sm,unsigned long long smlen,
const unsigned char *pk, ge_p3* Bu);
#endif

View File

@ -1,4 +1,3 @@
#include <stdlib.h>
#include <string.h>
#include "ge.h"
#include "curve_sigs.h"
@ -42,10 +41,11 @@ int curve25519_verify(const unsigned char* signature,
const unsigned char* curve25519_pubkey,
const unsigned char* msg, const unsigned long msg_len)
{
fe u;
fe y;
fe mont_x;
fe ed_y;
unsigned char ed_pubkey[32];
unsigned char *verifybuf = NULL; /* working buffer */
unsigned long long some_retval;
unsigned char *verifybuf = NULL; /* working buffer */
unsigned char *verifybuf2 = NULL; /* working buffer #2 */
int result;
@ -59,19 +59,20 @@ int curve25519_verify(const unsigned char* signature,
goto err;
}
/* Convert the Curve25519 public key into an Ed25519 public key. In
particular, convert Curve25519's "montgomery" x-coordinate (u) into an
particular, convert Curve25519's "montgomery" x-coordinate into an
Ed25519 "edwards" y-coordinate:
y = (u - 1) / (u + 1)
ed_y = (mont_x - 1) / (mont_x + 1)
NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp
NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp
Then move the sign bit into the pubkey from the signature.
*/
fe_frombytes(u, curve25519_pubkey);
fe_montx_to_edy(y, u);
fe_tobytes(ed_pubkey, y);
fe_frombytes(mont_x, curve25519_pubkey);
fe_montx_to_edy(ed_y, mont_x);
fe_tobytes(ed_pubkey, ed_y);
/* Copy the sign bit, and remove it from signature */
ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */
@ -85,8 +86,9 @@ int curve25519_verify(const unsigned char* signature,
/* The below call has a strange API: */
/* verifybuf = R || S || message */
/* verifybuf2 = internal to next call gets a copy of verifybuf, S gets
replaced with pubkey for hashing */
result = crypto_sign_open_modified(verifybuf2, verifybuf, 64 + msg_len, ed_pubkey);
replaced with pubkey for hashing, then the whole thing gets zeroized
(if bad sig), or contains a copy of msg (good sig) */
result = crypto_sign_open_modified(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey);
err:

View File

@ -8,7 +8,6 @@
unsigned int legendre_is_nonsquare(fe in)
{
fe temp;
unsigned char bytes[32];
fe_pow22523(temp, in); /* temp = in^((q-5)/8) */
fe_sq(temp, temp); /* in^((q-5)/4) */
fe_sq(temp, temp); /* in^((q-5)/2) */
@ -20,61 +19,123 @@ unsigned int legendre_is_nonsquare(fe in)
* 0 = input is zero
* -1 = nonsquare
*/
unsigned char bytes[32];
fe_tobytes(bytes, temp);
return 1 & bytes[31];
}
void elligator(fe u, const fe r)
void elligator(fe mont_x, const fe in)
{
/* r = input
* x = -A/(1+2r^2) # 2 is nonsquare
* e = (x^3 + Ax^2 + x)^((q-1)/2) # legendre symbol
* if e == 1 (square) or e == 0 (because x == 0 and 2r^2 + 1 == 0)
* u = x
/* r = in
* v = -A/(1+2r^2)
* e = (v^3 + Av^2 + v)^((q-1)/2) # legendre symbol
* if e == 1 (square) or e == 0 (because v == 0 and 2r^2 + 1 == 0)
* out = v
* if e == -1 (nonsquare)
* u = -x - A
* out = -v - A
*/
fe A, one, twor2, twor2plus1, twor2plus1inv;
fe x, e, Atemp, uneg;
fe v, v2, v3, Av2, e, u, Atemp, uneg;
unsigned int nonsquare;
fe_1(one);
fe_0(one);
one[0] = 1; /* 1 */
fe_0(A);
A[0] = 486662; /* A = 486662 */
fe_sq2(twor2, r); /* 2r^2 */
fe_sq2(twor2, in); /* 2r^2 */
fe_add(twor2plus1, twor2, one); /* 1+2r^2 */
fe_invert(twor2plus1inv, twor2plus1); /* 1/(1+2r^2) */
fe_mul(x, twor2plus1inv, A); /* A/(1+2r^2) */
fe_neg(x, x); /* x = -A/(1+2r^2) */
fe_mul(v, twor2plus1inv, A); /* A/(1+2r^2) */
fe_neg(v, v); /* v = -A/(1+2r^2) */
fe_mont_rhs(e, x); /* e = x^3 + Ax^2 + x */
fe_sq(v2, v); /* v^2 */
fe_mul(v3, v2, v); /* v^3 */
fe_mul(Av2, v2, A); /* Av^2 */
fe_add(e, v3, Av2); /* v^3 + Av^2 */
fe_add(e, e, v); /* v^3 + Av^2 + v */
nonsquare = legendre_is_nonsquare(e);
fe_0(Atemp);
fe_cmov(Atemp, A, nonsquare); /* 0, or A if nonsquare */
fe_add(u, x, Atemp); /* x, or x+A if nonsquare */
fe_neg(uneg, u); /* -x, or -x-A if nonsquare */
fe_cmov(u, uneg, nonsquare); /* x, or -x-A if nonsquare */
fe_add(u, v, Atemp); /* v, or v+A if nonsquare */
fe_neg(uneg, u); /* -v, or -v-A if nonsquare */
fe_cmov(u, uneg, nonsquare); /* v, or -v-A if nonsquare */
fe_copy(mont_x, u);
}
void hash_to_point(ge_p3* p, const unsigned char* in, const unsigned long in_len)
void hash_to_point(ge_p3* out, const unsigned char* in, const unsigned long in_len)
{
unsigned char hash[64];
fe h, u;
fe h, mont_x;
unsigned char sign_bit;
ge_p3 p3;
/* hash and elligator */
crypto_hash_sha512(hash, in, in_len);
/* take the high bit as Edwards sign bit */
sign_bit = (hash[31] & 0x80) >> 7;
sign_bit = hash[31] & 0x80; /* take the high bit as Edwards sign bit */
hash[31] &= 0x7F;
fe_frombytes(h, hash);
elligator(u, h);
ge_montx_to_p3(&p3, u, sign_bit);
ge_scalarmult_cofactor(p, &p3);
elligator(mont_x, h);
fe ed_y;
unsigned char ed_pubkey[32];
fe_montx_to_edy(ed_y, mont_x);
fe_tobytes(ed_pubkey, ed_y);
ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */
ed_pubkey[31] |= sign_bit;
/* decompress full point */
/* WARNING - due to timing-variance, don't use with secret inputs! */
ge_frombytes_negate_vartime(out, ed_pubkey);
/* undo the negation */
fe_neg(out->X, out->X);
fe_neg(out->T, out->T);
/* multiply by 8 (cofactor) to map onto the main subgroup,
* or map small-order points to the neutral element
* (the latter prevents leaking r mod (2, 4, 8) via U) */
ge_p1p1 dbl_result;
ge_p3_dbl(&dbl_result, out);
ge_p1p1_to_p3(out, &dbl_result);
ge_p3_dbl(&dbl_result, out);
ge_p1p1_to_p3(out, &dbl_result);
ge_p3_dbl(&dbl_result, out);
ge_p1p1_to_p3(out, &dbl_result);
}
void calculate_Bu(ge_p3* Bu,
unsigned char* buf,
const unsigned char* msg, const unsigned long msg_len)
{
int count;
/* Calculate SHA512(label(2) || msg) */
buf[0] = 0xFD;
for (count = 1; count < 32; count++)
buf[count] = 0xFF;
memmove(buf+32, msg, msg_len);
hash_to_point(Bu, buf, 32 + msg_len);
}
void calculate_Bu_and_U(ge_p3* Bu,
unsigned char* U,
unsigned char* buf,
const unsigned char* a,
const unsigned char* msg, const unsigned long msg_len)
{
ge_p3 p3;
calculate_Bu(Bu, buf, msg, msg_len);
ge_scalarmult(&p3, a, Bu);
ge_p3_tobytes(U, &p3);
}

View File

@ -1,14 +0,0 @@
#include "fe.h"
#include "crypto_verify_32.h"
/*
return 1 if f == g
return 0 if f != g
*/
int fe_isequal(const fe f, const fe g)
{
fe h;
fe_sub(h, f, g);
return 1 ^ (1 & (fe_isnonzero(h) >> 8));
}

View File

@ -1,14 +0,0 @@
#include "fe.h"
#include "crypto_verify_32.h"
int fe_isreduced(const unsigned char* s)
{
fe f;
unsigned char strict[32];
fe_frombytes(f, s);
fe_tobytes(strict, f);
if (crypto_verify_32(strict, s) != 0)
return 0;
return 1;
}

View File

@ -1,17 +0,0 @@
#include "fe.h"
void fe_mont_rhs(fe v2, fe u) {
fe A, one;
fe u2, Au, inner;
fe_1(one);
fe_0(A);
A[0] = 486662; /* A = 486662 */
fe_sq(u2, u); /* u^2 */
fe_mul(Au, A, u); /* Au */
fe_add(inner, u2, Au); /* u^2 + Au */
fe_add(inner, inner, one); /* u^2 + Au + 1 */
fe_mul(v2, u, inner); /* u(u^2 + Au + 1) */
}

View File

@ -2,18 +2,18 @@
#include "fe.h"
#include "crypto_additions.h"
void fe_montx_to_edy(fe y, const fe u)
void fe_montx_to_edy(fe edy, const fe montx)
{
/*
y = (u - 1) / (u + 1)
ed_y = (mont_x - 1) / (mont_x + 1)
NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp
NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp
*/
fe one, um1, up1;
fe one, montx_minus_one, montx_plus_one, inv_montx_plus_one;
fe_1(one);
fe_sub(um1, u, one);
fe_add(up1, u, one);
fe_invert(up1, up1);
fe_mul(y, um1, up1);
fe_sub(montx_minus_one, montx, one);
fe_add(montx_plus_one, montx, one);
fe_invert(inv_montx_plus_one, montx_plus_one);
fe_mul(edy, montx_minus_one, inv_montx_plus_one);
}

View File

@ -1,51 +0,0 @@
#include <assert.h>
#include "fe.h"
#include "crypto_additions.h"
/* sqrt(-1) */
static unsigned char i_bytes[32] = {
0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4,
0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f,
0xa7, 0xd7, 0xfb, 0x3d, 0x99, 0x00, 0x4d, 0x2b,
0x0b, 0xdf, 0xc1, 0x4f, 0x80, 0x24, 0x83, 0x2b
};
/* Preconditions: a is square or zero */
void fe_sqrt(fe out, const fe a)
{
fe exp, b, b2, bi, i;
#ifndef NDEBUG
fe legendre, zero, one;
#endif
fe_frombytes(i, i_bytes);
fe_pow22523(exp, a); /* b = a^(q-5)/8 */
/* PRECONDITION: legendre symbol == 1 (square) or 0 (a == zero) */
#ifndef NDEBUG
fe_sq(legendre, exp); /* in^((q-5)/4) */
fe_sq(legendre, legendre); /* in^((q-5)/2) */
fe_mul(legendre, legendre, a); /* in^((q-3)/2) */
fe_mul(legendre, legendre, a); /* in^((q-1)/2) */
fe_0(zero);
fe_1(one);
assert(fe_isequal(legendre, zero) || fe_isequal(legendre, one));
#endif
fe_mul(b, a, exp); /* b = a * a^(q-5)/8 */
fe_sq(b2, b); /* b^2 = a * a^(q-1)/4 */
/* note b^4 == a^2, so b^2 == a or -a
* if b^2 != a, multiply it by sqrt(-1) */
fe_mul(bi, b, i);
fe_cmov(b, bi, 1 ^ fe_isequal(b2, a));
fe_copy(out, b);
/* PRECONDITION: out^2 == a */
#ifndef NDEBUG
fe_sq(b2, out);
assert(fe_isequal(a, b2));
#endif
}

View File

@ -1,16 +0,0 @@
#include "crypto_additions.h"
#include "ge.h"
/*
return 1 if p is the neutral point
return 0 otherwise
*/
int ge_isneutral(const ge_p3 *p)
{
fe zero;
fe_0(zero);
/* Check if p == neutral element == (0, 1) */
return (fe_isequal(p->X, zero) & fe_isequal(p->Y, p->Z));
}

View File

@ -1,70 +0,0 @@
#include "fe.h"
#include "ge.h"
#include "assert.h"
#include "crypto_additions.h"
#include "utility.h"
/* sqrt(-(A+2)) */
static unsigned char A_bytes[32] = {
0x06, 0x7e, 0x45, 0xff, 0xaa, 0x04, 0x6e, 0xcc,
0x82, 0x1a, 0x7d, 0x4b, 0xd1, 0xd3, 0xa1, 0xc5,
0x7e, 0x4f, 0xfc, 0x03, 0xdc, 0x08, 0x7b, 0xd2,
0xbb, 0x06, 0xa0, 0x60, 0xf4, 0xed, 0x26, 0x0f
};
void ge_montx_to_p3(ge_p3* p, const fe u, const unsigned char ed_sign_bit)
{
fe x, y, A, v, v2, iv, nx;
fe_frombytes(A, A_bytes);
/* given u, recover edwards y */
/* given u, recover v */
/* given u and v, recover edwards x */
fe_montx_to_edy(y, u); /* y = (u - 1) / (u + 1) */
fe_mont_rhs(v2, u); /* v^2 = u(u^2 + Au + 1) */
fe_sqrt(v, v2); /* v = sqrt(v^2) */
fe_mul(x, u, A); /* x = u * sqrt(-(A+2)) */
fe_invert(iv, v); /* 1/v */
fe_mul(x, x, iv); /* x = (u/v) * sqrt(-(A+2)) */
fe_neg(nx, x); /* negate x to match sign bit */
fe_cmov(x, nx, fe_isnegative(x) ^ ed_sign_bit);
fe_copy(p->X, x);
fe_copy(p->Y, y);
fe_1(p->Z);
fe_mul(p->T, p->X, p->Y);
/* POSTCONDITION: check that p->X and p->Y satisfy the Ed curve equation */
/* -x^2 + y^2 = 1 + dx^2y^2 */
#ifndef NDEBUG
{
fe one, d, x2, y2, x2y2, dx2y2;
unsigned char dbytes[32] = {
0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52
};
fe_frombytes(d, dbytes);
fe_1(one);
fe_sq(x2, p->X); /* x^2 */
fe_sq(y2, p->Y); /* y^2 */
fe_mul(dx2y2, x2, y2); /* x^2y^2 */
fe_mul(dx2y2, dx2y2, d); /* dx^2y^2 */
fe_add(dx2y2, dx2y2, one); /* dx^2y^2 + 1 */
fe_neg(x2y2, x2); /* -x^2 */
fe_add(x2y2, x2y2, y2); /* -x^2 + y^2 */
assert(fe_isequal(x2y2, dx2y2));
}
#endif
}

View File

@ -1,15 +0,0 @@
#include "crypto_additions.h"
#include "ge.h"
/*
return r = -p
*/
void ge_neg(ge_p3* r, const ge_p3 *p)
{
fe_neg(r->X, p->X);
fe_copy(r->Y, p->Y);
fe_copy(r->Z, p->Z);
fe_neg(r->T, p->T);
}

View File

@ -1,21 +1,22 @@
#include "fe.h"
#include "crypto_additions.h"
void ge_p3_to_montx(fe u, const ge_p3 *ed)
void ge_p3_to_montx(fe montx, const ge_p3 *ed)
{
/*
u = (y + 1) / (1 - y)
or
u = (y + z) / (z - y)
mont_x = (ed_y + 1) / (1 - ed_y)
NOTE: y=1 is converted to u=0 since fe_invert is mod-exp
mont_x = (ed_y + ed_z) / (ed_z - ed_y)
NOTE: ed_y=1 is converted to mont_x=0 since fe_invert is mod-exp
*/
fe y_plus_one, one_minus_y, inv_one_minus_y;
fe edy_plus_one, one_minus_edy, inv_one_minus_edy;
fe_add(y_plus_one, ed->Y, ed->Z);
fe_sub(one_minus_y, ed->Z, ed->Y);
fe_invert(inv_one_minus_y, one_minus_y);
fe_mul(u, y_plus_one, inv_one_minus_y);
fe_add(edy_plus_one, ed->Y, ed->Z);
fe_sub(one_minus_edy, ed->Z, ed->Y);
fe_invert(inv_one_minus_edy, one_minus_edy);
fe_mul(montx, edy_plus_one, inv_one_minus_edy);
}

View File

@ -1,21 +0,0 @@
#include "crypto_additions.h"
#include "ge.h"
/*
return 8 * p
*/
void ge_scalarmult_cofactor(ge_p3 *q, const ge_p3 *p)
{
ge_p1p1 p1p1;
ge_p2 p2;
ge_p3_dbl(&p1p1, p);
ge_p1p1_to_p2(&p2, &p1p1);
ge_p2_dbl(&p1p1, &p2);
ge_p1p1_to_p2(&p2, &p1p1);
ge_p2_dbl(&p1p1, &p2);
ge_p1p1_to_p3(q, &p1p1);
}

View File

@ -1,15 +0,0 @@
#include "ge.h"
/*
r = p + q
*/
void ge_p3_add(ge_p3 *r, const ge_p3 *p, const ge_p3 *q)
{
ge_cached p_cached;
ge_p1p1 r_p1p1;
ge_p3_to_cached(&p_cached, p);
ge_add(&r_p1p1, q, &p_cached);
ge_p1p1_to_p3(r, &r_p1p1);
}

View File

@ -1,19 +0,0 @@
#ifndef _GEN_CONSTANTS_H__
#define _GEN_CONSTANTS_H__
#define LABELSETMAXLEN 512
#define LABELMAXLEN 128
#define BUFLEN 1024
#define BLOCKLEN 128 /* SHA512 */
#define HASHLEN 64 /* SHA512 */
#define POINTLEN 32
#define SCALARLEN 32
#define RANDLEN 32
#define SIGNATURELEN 64
#define VRFSIGNATURELEN 96
#define VRFOUTPUTLEN 32
#define MSTART 2048
#define MSGMAXLEN 1048576
#endif

View File

@ -1,16 +0,0 @@
#ifndef __GEN_CRYPTO_ADDITIONS__
#define __GEN_CRYPTO_ADDITIONS__
#include "crypto_uint32.h"
#include "fe.h"
#include "ge.h"
int sc_isreduced(const unsigned char* s);
int point_isreduced(const unsigned char* p);
void ge_p3_add(ge_p3 *r, const ge_p3 *p, const ge_p3 *q);
#endif

View File

@ -1,349 +0,0 @@
#include <string.h>
#include "gen_eddsa.h"
#include "gen_labelset.h"
#include "gen_constants.h"
#include "gen_crypto_additions.h"
#include "crypto_hash_sha512.h"
#include "crypto_verify_32.h"
#include "zeroize.h"
#include "ge.h"
#include "sc.h"
#include "crypto_additions.h"
#include "utility.h"
/* B: base point
* R: commitment (point),
r: private nonce (scalar)
K: encoded public key
k: private key (scalar)
Z: 32-bytes random
M: buffer containing message, message starts at M_start, continues for M_len
r = hash(B || labelset || Z || pad1 || k || pad2 || labelset || K || extra || M) (mod q)
*/
int generalized_commit(unsigned char* R_bytes, unsigned char* r_scalar,
const unsigned char* labelset, const unsigned long labelset_len,
const unsigned char* extra, const unsigned long extra_len,
const unsigned char* K_bytes, const unsigned char* k_scalar,
const unsigned char* Z,
unsigned char* M_buf, const unsigned long M_start, const unsigned long M_len)
{
ge_p3 R_point;
unsigned char hash[HASHLEN];
unsigned char* bufstart = NULL;
unsigned char* bufptr = NULL;
unsigned char* bufend = NULL;
unsigned long prefix_len = 0;
if (labelset_validate(labelset, labelset_len) != 0)
goto err;
if (R_bytes == NULL || r_scalar == NULL ||
K_bytes == NULL || k_scalar == NULL ||
Z == NULL || M_buf == NULL)
goto err;
if (extra == NULL && extra_len != 0)
goto err;
if (extra != NULL && extra_len == 0)
goto err;
if (extra != NULL && labelset_is_empty(labelset, labelset_len))
goto err;
if (HASHLEN != 64)
goto err;
prefix_len = 0;
prefix_len += POINTLEN + labelset_len + RANDLEN;
prefix_len += ((BLOCKLEN - (prefix_len % BLOCKLEN)) % BLOCKLEN);
prefix_len += SCALARLEN;
prefix_len += ((BLOCKLEN - (prefix_len % BLOCKLEN)) % BLOCKLEN);
prefix_len += labelset_len + POINTLEN + extra_len;
if (prefix_len > M_start)
goto err;
bufstart = M_buf + M_start - prefix_len;
bufptr = bufstart;
bufend = M_buf + M_start;
bufptr = buffer_add(bufptr, bufend, B_bytes, POINTLEN);
bufptr = buffer_add(bufptr, bufend, labelset, labelset_len);
bufptr = buffer_add(bufptr, bufend, Z, RANDLEN);
bufptr = buffer_pad(bufstart, bufptr, bufend);
bufptr = buffer_add(bufptr, bufend, k_scalar, SCALARLEN);
bufptr = buffer_pad(bufstart, bufptr, bufend);
bufptr = buffer_add(bufptr, bufend, labelset, labelset_len);
bufptr = buffer_add(bufptr, bufend, K_bytes, POINTLEN);
bufptr = buffer_add(bufptr, bufend, extra, extra_len);
if (bufptr != bufend || bufptr != M_buf + M_start || bufptr - bufstart != prefix_len)
goto err;
crypto_hash_sha512(hash, M_buf + M_start - prefix_len, prefix_len + M_len);
sc_reduce(hash);
ge_scalarmult_base(&R_point, hash);
ge_p3_tobytes(R_bytes, &R_point);
memcpy(r_scalar, hash, SCALARLEN);
zeroize(hash, HASHLEN);
zeroize(bufstart, prefix_len);
return 0;
err:
zeroize(hash, HASHLEN);
zeroize(M_buf, M_start);
return -1;
}
/* if is_labelset_empty(labelset):
return hash(R || K || M) (mod q)
else:
return hash(B || labelset || R || labelset || K || extra || M) (mod q)
*/
int generalized_challenge(unsigned char* h_scalar,
const unsigned char* labelset, const unsigned long labelset_len,
const unsigned char* extra, const unsigned long extra_len,
const unsigned char* R_bytes,
const unsigned char* K_bytes,
unsigned char* M_buf, const unsigned long M_start, const unsigned long M_len)
{
unsigned char hash[HASHLEN];
unsigned char* bufstart = NULL;
unsigned char* bufptr = NULL;
unsigned char* bufend = NULL;
unsigned long prefix_len = 0;
if (h_scalar == NULL)
goto err;
memset(h_scalar, 0, SCALARLEN);
if (labelset_validate(labelset, labelset_len) != 0)
goto err;
if (R_bytes == NULL || K_bytes == NULL || M_buf == NULL)
goto err;
if (extra == NULL && extra_len != 0)
goto err;
if (extra != NULL && extra_len == 0)
goto err;
if (extra != NULL && labelset_is_empty(labelset, labelset_len))
goto err;
if (HASHLEN != 64)
goto err;
if (labelset_is_empty(labelset, labelset_len)) {
if (2*POINTLEN > M_start)
goto err;
if (extra != NULL || extra_len != 0)
goto err;
memcpy(M_buf + M_start - (2*POINTLEN), R_bytes, POINTLEN);
memcpy(M_buf + M_start - (1*POINTLEN), K_bytes, POINTLEN);
prefix_len = 2*POINTLEN;
} else {
prefix_len = 3*POINTLEN + 2*labelset_len + extra_len;
if (prefix_len > M_start)
goto err;
bufstart = M_buf + M_start - prefix_len;
bufptr = bufstart;
bufend = M_buf + M_start;
bufptr = buffer_add(bufptr, bufend, B_bytes, POINTLEN);
bufptr = buffer_add(bufptr, bufend, labelset, labelset_len);
bufptr = buffer_add(bufptr, bufend, R_bytes, POINTLEN);
bufptr = buffer_add(bufptr, bufend, labelset, labelset_len);
bufptr = buffer_add(bufptr, bufend, K_bytes, POINTLEN);
bufptr = buffer_add(bufptr, bufend, extra, extra_len);
if (bufptr == NULL)
goto err;
if (bufptr != bufend || bufptr != M_buf + M_start || bufptr - bufstart != prefix_len)
goto err;
}
crypto_hash_sha512(hash, M_buf + M_start - prefix_len, prefix_len + M_len);
sc_reduce(hash);
memcpy(h_scalar, hash, SCALARLEN);
return 0;
err:
return -1;
}
/* return r + kh (mod q) */
int generalized_prove(unsigned char* out_scalar,
const unsigned char* r_scalar, const unsigned char* k_scalar, const unsigned char* h_scalar)
{
sc_muladd(out_scalar, h_scalar, k_scalar, r_scalar);
zeroize_stack();
return 0;
}
/* R = s*B - h*K */
int generalized_solve_commitment(unsigned char* R_bytes_out, ge_p3* K_point_out,
const ge_p3* B_point, const unsigned char* s_scalar,
const unsigned char* K_bytes, const unsigned char* h_scalar)
{
ge_p3 Kneg_point;
ge_p2 R_calc_point_p2;
ge_p3 sB;
ge_p3 hK;
ge_p3 R_calc_point_p3;
if (ge_frombytes_negate_vartime(&Kneg_point, K_bytes) != 0)
return -1;
if (B_point == NULL) {
ge_double_scalarmult_vartime(&R_calc_point_p2, h_scalar, &Kneg_point, s_scalar);
ge_tobytes(R_bytes_out, &R_calc_point_p2);
}
else {
// s * Bv
ge_scalarmult(&sB, s_scalar, B_point);
// h * -K
ge_scalarmult(&hK, h_scalar, &Kneg_point);
// R = sB - hK
ge_p3_add(&R_calc_point_p3, &sB, &hK);
ge_p3_tobytes(R_bytes_out, &R_calc_point_p3);
}
if (K_point_out) {
ge_neg(K_point_out, &Kneg_point);
}
return 0;
}
int generalized_eddsa_25519_sign(
unsigned char* signature_out,
const unsigned char* eddsa_25519_pubkey_bytes,
const unsigned char* eddsa_25519_privkey_scalar,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* random,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char labelset[LABELSETMAXLEN];
unsigned long labelset_len = 0;
unsigned char R_bytes[POINTLEN];
unsigned char r_scalar[SCALARLEN];
unsigned char h_scalar[SCALARLEN];
unsigned char s_scalar[SCALARLEN];
unsigned char* M_buf = NULL;
if (signature_out == NULL)
goto err;
memset(signature_out, 0, SIGNATURELEN);
if (eddsa_25519_pubkey_bytes == NULL)
goto err;
if (eddsa_25519_privkey_scalar == NULL)
goto err;
if (msg == NULL)
goto err;
if (customization_label == NULL && customization_label_len != 0)
goto err;
if (customization_label_len > LABELMAXLEN)
goto err;
if (msg_len > MSGMAXLEN)
goto err;
if ((M_buf = malloc(msg_len + MSTART)) == 0)
goto err;
memcpy(M_buf + MSTART, msg, msg_len);
if (labelset_new(labelset, &labelset_len, LABELSETMAXLEN, NULL, 0,
customization_label, customization_label_len) != 0)
goto err;
if (generalized_commit(R_bytes, r_scalar, labelset, labelset_len, NULL, 0,
eddsa_25519_pubkey_bytes, eddsa_25519_privkey_scalar,
random, M_buf, MSTART, msg_len) != 0)
goto err;
if (generalized_challenge(h_scalar, labelset, labelset_len, NULL, 0,
R_bytes, eddsa_25519_pubkey_bytes, M_buf, MSTART, msg_len) != 0)
goto err;
if (generalized_prove(s_scalar, r_scalar, eddsa_25519_privkey_scalar, h_scalar) != 0)
goto err;
memcpy(signature_out, R_bytes, POINTLEN);
memcpy(signature_out + POINTLEN, s_scalar, SCALARLEN);
zeroize(r_scalar, SCALARLEN);
zeroize_stack();
free(M_buf);
return 0;
err:
zeroize(r_scalar, SCALARLEN);
zeroize_stack();
free(M_buf);
return -1;
}
int generalized_eddsa_25519_verify(
const unsigned char* signature,
const unsigned char* eddsa_25519_pubkey_bytes,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char labelset[LABELSETMAXLEN];
unsigned long labelset_len = 0;
const unsigned char* R_bytes = NULL;
const unsigned char* s_scalar = NULL;
unsigned char h_scalar[SCALARLEN];
unsigned char* M_buf = NULL;
unsigned char R_calc_bytes[POINTLEN];
if (signature == NULL)
goto err;
if (eddsa_25519_pubkey_bytes == NULL)
goto err;
if (msg == NULL)
goto err;
if (customization_label == NULL && customization_label_len != 0)
goto err;
if (customization_label_len > LABELMAXLEN)
goto err;
if (msg_len > MSGMAXLEN)
goto err;
if ((M_buf = malloc(msg_len + MSTART)) == 0)
goto err;
memcpy(M_buf + MSTART, msg, msg_len);
if (labelset_new(labelset, &labelset_len, LABELSETMAXLEN, NULL, 0,
customization_label, customization_label_len) != 0)
goto err;
R_bytes = signature;
s_scalar = signature + POINTLEN;
if (!point_isreduced(eddsa_25519_pubkey_bytes))
goto err;
if (!point_isreduced(R_bytes))
goto err;
if (!sc_isreduced(s_scalar))
goto err;
if (generalized_challenge(h_scalar, labelset, labelset_len,
NULL, 0, R_bytes, eddsa_25519_pubkey_bytes, M_buf, MSTART, msg_len) != 0)
goto err;
if (generalized_solve_commitment(R_calc_bytes, NULL, NULL,
s_scalar, eddsa_25519_pubkey_bytes, h_scalar) != 0)
goto err;
if (crypto_verify_32(R_bytes, R_calc_bytes) != 0)
goto err;
free(M_buf);
return 0;
err:
free(M_buf);
return -1;
}

View File

@ -1,65 +0,0 @@
#ifndef __GEN_EDDSA_H__
#define __GEN_EDDSA_H__
#include "ge.h"
/* B: base point
R: commitment (point),
r: private nonce (scalar)
K: encoded public key
k: private key (scalar)
Z: 32-bytes random
M: buffer containing message, message starts at M_start, continues for M_len
r = hash(B || labelset || Z || pad1 || k || pad2 || labelset || K || extra || M) (mod q)
*/
int generalized_commit(unsigned char* R_bytes, unsigned char* r_scalar,
const unsigned char* labelset, const unsigned long labelset_len,
const unsigned char* extra, const unsigned long extra_len,
const unsigned char* K_bytes, const unsigned char* k_scalar,
const unsigned char* Z,
unsigned char* M_buf, const unsigned long M_start, const unsigned long M_len);
/* if is_labelset_empty(labelset):
return hash(R || K || M) (mod q)
else:
return hash(B || labelset || R || labelset || K || extra || M) (mod q)
*/
int generalized_challenge(unsigned char* h_scalar,
const unsigned char* labelset, const unsigned long labelset_len,
const unsigned char* extra, const unsigned long extra_len,
const unsigned char* R_bytes,
const unsigned char* K_bytes,
unsigned char* M_buf, const unsigned long M_start, const unsigned long M_len);
/* return r + kh (mod q) */
int generalized_prove(unsigned char* out_scalar,
const unsigned char* r_scalar,
const unsigned char* k_scalar,
const unsigned char* h_scalar);
/* R = B^s / K^h */
int generalized_solve_commitment(unsigned char* R_bytes_out, ge_p3* K_point_out,
const ge_p3* B_point, const unsigned char* s_scalar,
const unsigned char* K_bytes, const unsigned char* h_scalar);
int generalized_eddsa_25519_sign(
unsigned char* signature_out,
const unsigned char* eddsa_25519_pubkey_bytes,
const unsigned char* eddsa_25519_privkey_scalar,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* random,
const unsigned char* customization_label,
const unsigned long customization_label_len);
int generalized_eddsa_25519_verify(
const unsigned char* signature,
const unsigned char* eddsa_25519_pubkey,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* customization_label,
const unsigned long customization_label_len);
#endif

View File

@ -1,157 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "gen_labelset.h"
#include "gen_constants.h"
const unsigned char B_bytes[] = {
0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
};
unsigned char* buffer_add(unsigned char* bufptr, const unsigned char* bufend,
const unsigned char* in, const unsigned long in_len)
{
unsigned long count = 0;
if (bufptr == NULL || bufend == NULL || bufptr > bufend)
return NULL;
if (in == NULL && in_len != 0)
return NULL;
if (bufend - bufptr < in_len)
return NULL;
for (count=0; count < in_len; count++) {
if (bufptr >= bufend)
return NULL;
*bufptr++ = *in++;
}
return bufptr;
}
unsigned char* buffer_pad(const unsigned char* buf, unsigned char* bufptr, const unsigned char* bufend)
{
unsigned long count = 0;
unsigned long pad_len = 0;
if (buf == NULL || bufptr == NULL || bufend == NULL || bufptr >= bufend || bufptr < buf)
return NULL;
pad_len = (BLOCKLEN - ((bufptr-buf) % BLOCKLEN)) % BLOCKLEN;
if (bufend - bufptr < pad_len)
return NULL;
for (count=0; count < pad_len; count++) {
if (bufptr >= bufend)
return NULL;
*bufptr++ = 0;
}
return bufptr;
}
int labelset_new(unsigned char* labelset, unsigned long* labelset_len, const unsigned long labelset_maxlen,
const unsigned char* protocol_name, const unsigned char protocol_name_len,
const unsigned char* customization_label, const unsigned char customization_label_len)
{
unsigned char* bufptr;
*labelset_len = 0;
if (labelset == NULL)
return -1;
if (labelset_len == NULL)
return -1;
if (labelset_maxlen > LABELSETMAXLEN)
return -1;
if (labelset_maxlen < 3 + protocol_name_len + customization_label_len)
return -1;
if (protocol_name == NULL && protocol_name_len != 0)
return -1;
if (customization_label == NULL && customization_label_len != 0)
return -1;
if (protocol_name_len > LABELMAXLEN)
return -1;
if (customization_label_len > LABELMAXLEN)
return -1;
bufptr = labelset;
*bufptr++ = 2;
*bufptr++ = protocol_name_len;
bufptr = buffer_add(bufptr, labelset + labelset_maxlen, protocol_name, protocol_name_len);
if (bufptr != NULL && bufptr < labelset + labelset_maxlen)
*bufptr++ = customization_label_len;
bufptr = buffer_add(bufptr, labelset + labelset_maxlen,
customization_label, customization_label_len);
if (bufptr != NULL && bufptr - labelset == 3 + protocol_name_len + customization_label_len) {
*labelset_len = bufptr - labelset;
return 0;
}
return -1;
}
int labelset_add(unsigned char* labelset, unsigned long* labelset_len, const unsigned long labelset_maxlen,
const unsigned char* label, const unsigned char label_len)
{
unsigned char* bufptr;
if (labelset_len == NULL)
return -1;
if (*labelset_len > LABELSETMAXLEN || labelset_maxlen > LABELSETMAXLEN)
return -1;
if (*labelset_len >= labelset_maxlen || *labelset_len + label_len + 1 > labelset_maxlen)
return -1;
if (*labelset_len < 3 || labelset_maxlen < 4)
return -1;
if (label_len > LABELMAXLEN)
return -1;
labelset[0]++;
labelset[*labelset_len] = label_len;
bufptr = labelset + *labelset_len + 1;
bufptr = buffer_add(bufptr, labelset + labelset_maxlen, label, label_len);
if (bufptr == NULL)
return -1;
if (bufptr - labelset >= labelset_maxlen)
return -1;
if (bufptr - labelset != *labelset_len + 1 + label_len)
return -1;
*labelset_len += (1 + label_len);
return 0;
}
int labelset_validate(const unsigned char* labelset, const unsigned long labelset_len)
{
unsigned char num_labels = 0;
unsigned char count = 0;
unsigned long offset = 0;
unsigned char label_len = 0;
if (labelset == NULL)
return -1;
if (labelset_len < 3 || labelset_len > LABELSETMAXLEN)
return -1;
num_labels = labelset[0];
offset = 1;
for (count = 0; count < num_labels; count++) {
label_len = labelset[offset];
if (label_len > LABELMAXLEN)
return -1;
offset += 1 + label_len;
if (offset > labelset_len)
return -1;
}
if (offset != labelset_len)
return -1;
return 0;
}
int labelset_is_empty(const unsigned char* labelset, const unsigned long labelset_len)
{
if (labelset_len != 3)
return 0;
return 1;
}

View File

@ -1,23 +0,0 @@
#ifndef __GEN_LABELSET_H__
#define __GEN_LABELSET_H__
extern const unsigned char B_bytes[];
unsigned char* buffer_add(unsigned char* bufptr, const unsigned char* bufend,
const unsigned char* in, const unsigned long in_len);
unsigned char* buffer_pad(const unsigned char* buf, unsigned char* bufptr, const unsigned char* bufend);
int labelset_new(unsigned char* labelset, unsigned long* labelset_len, const unsigned long labelset_maxlen,
const unsigned char* protocol_name, const unsigned char protocol_name_len,
const unsigned char* customization_label, const unsigned char customization_label_len);
int labelset_add(unsigned char* labelset, unsigned long* labelset_len, const unsigned long labelset_maxlen,
const unsigned char* label, const unsigned char label_len);
int labelset_validate(const unsigned char* labelset, const unsigned long labelset_len);
int labelset_is_empty(const unsigned char* labelset, const unsigned long labelset_len);
#endif

View File

@ -1,312 +0,0 @@
#include <string.h>
#include "gen_eddsa.h"
#include "gen_veddsa.h"
#include "gen_constants.h"
#include "gen_labelset.h"
#include "gen_crypto_additions.h"
#include "crypto_hash_sha512.h"
#include "crypto_verify_32.h"
#include "crypto_additions.h"
#include "zeroize.h"
#include "ge.h"
#include "sc.h"
#include "utility.h"
static int generalized_calculate_Bv(ge_p3* Bv_point,
const unsigned char* labelset, const unsigned long labelset_len,
const unsigned char* K_bytes,
unsigned char* M_buf, const unsigned long M_start, const unsigned long M_len)
{
unsigned char* bufptr;
unsigned long prefix_len = 0;
if (labelset_validate(labelset, labelset_len) != 0)
return -1;
if (Bv_point == NULL || K_bytes == NULL || M_buf == NULL)
return -1;
prefix_len = 2*POINTLEN + labelset_len;
if (prefix_len > M_start)
return -1;
bufptr = M_buf + M_start - prefix_len;
bufptr = buffer_add(bufptr, M_buf + M_start, B_bytes, POINTLEN);
bufptr = buffer_add(bufptr, M_buf + M_start, labelset, labelset_len);
bufptr = buffer_add(bufptr, M_buf + M_start, K_bytes, POINTLEN);
if (bufptr == NULL || bufptr != M_buf + M_start)
return -1;
hash_to_point(Bv_point, M_buf + M_start - prefix_len, prefix_len + M_len);
if (ge_isneutral(Bv_point))
return -1;
return 0;
}
static int generalized_calculate_vrf_output(unsigned char* vrf_output,
const unsigned char* labelset, const unsigned long labelset_len,
const ge_p3* cKv_point)
{
unsigned char buf[BUFLEN];
unsigned char* bufptr = buf;
unsigned char* bufend = buf + BUFLEN;
unsigned char cKv_bytes[POINTLEN];
unsigned char hash[HASHLEN];
if (vrf_output == NULL)
return -1;
memset(vrf_output, 0, VRFOUTPUTLEN);
if (labelset_len + 2*POINTLEN > BUFLEN)
return -1;
if (labelset_validate(labelset, labelset_len) != 0)
return -1;
if (cKv_point == NULL)
return -1;
if (VRFOUTPUTLEN > HASHLEN)
return -1;
ge_p3_tobytes(cKv_bytes, cKv_point);
bufptr = buffer_add(bufptr, bufend, B_bytes, POINTLEN);
bufptr = buffer_add(bufptr, bufend, labelset, labelset_len);
bufptr = buffer_add(bufptr, bufend, cKv_bytes, POINTLEN);
if (bufptr == NULL)
return -1;
if (bufptr - buf > BUFLEN)
return -1;
crypto_hash_sha512(hash, buf, bufptr - buf);
memcpy(vrf_output, hash, VRFOUTPUTLEN);
return 0;
}
int generalized_veddsa_25519_sign(
unsigned char* signature_out,
const unsigned char* eddsa_25519_pubkey_bytes,
const unsigned char* eddsa_25519_privkey_scalar,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* random,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char labelset[LABELSETMAXLEN];
unsigned long labelset_len = 0;
ge_p3 Bv_point;
ge_p3 Kv_point;
ge_p3 Rv_point;
unsigned char Bv_bytes[POINTLEN];
unsigned char Kv_bytes[POINTLEN];
unsigned char Rv_bytes[POINTLEN];
unsigned char R_bytes[POINTLEN];
unsigned char r_scalar[SCALARLEN];
unsigned char h_scalar[SCALARLEN];
unsigned char s_scalar[SCALARLEN];
unsigned char extra[3*POINTLEN];
unsigned char* M_buf = NULL;
char* protocol_name = "VEdDSA_25519_SHA512_Elligator2";
if (signature_out == NULL)
goto err;
memset(signature_out, 0, VRFSIGNATURELEN);
if (eddsa_25519_pubkey_bytes == NULL)
goto err;
if (eddsa_25519_privkey_scalar == NULL)
goto err;
if (msg == NULL)
goto err;
if (customization_label == NULL && customization_label_len != 0)
goto err;
if (customization_label_len > LABELMAXLEN)
goto err;
if (msg_len > MSGMAXLEN)
goto err;
if ((M_buf = malloc(msg_len + MSTART)) == 0) {
goto err;
}
memcpy(M_buf + MSTART, msg, msg_len);
// labelset = new_labelset(protocol_name, customization_label)
if (labelset_new(labelset, &labelset_len, LABELSETMAXLEN,
(unsigned char*)protocol_name, strlen(protocol_name),
customization_label, customization_label_len) != 0)
goto err;
// labelset1 = add_label(labels, "1")
// Bv = hash(hash(labelset1 || K) || M)
// Kv = k * Bv
labelset_add(labelset, &labelset_len, LABELSETMAXLEN, (unsigned char*)"1", 1);
if (generalized_calculate_Bv(&Bv_point, labelset, labelset_len,
eddsa_25519_pubkey_bytes, M_buf, MSTART, msg_len) != 0)
goto err;
ge_scalarmult(&Kv_point, eddsa_25519_privkey_scalar, &Bv_point);
ge_p3_tobytes(Bv_bytes, &Bv_point);
ge_p3_tobytes(Kv_bytes, &Kv_point);
// labelset2 = add_label(labels, "2")
// R, r = commit(labelset2, (Bv || Kv), (K,k), Z, M)
labelset[labelset_len-1] = (unsigned char)'2';
memcpy(extra, Bv_bytes, POINTLEN);
memcpy(extra + POINTLEN, Kv_bytes, POINTLEN);
if (generalized_commit(R_bytes, r_scalar,
labelset, labelset_len,
extra, 2*POINTLEN,
eddsa_25519_pubkey_bytes, eddsa_25519_privkey_scalar,
random, M_buf, MSTART, msg_len) != 0)
goto err;
// Rv = r * Bv
ge_scalarmult(&Rv_point, r_scalar, &Bv_point);
ge_p3_tobytes(Rv_bytes, &Rv_point);
// labelset3 = add_label(labels, "3")
// h = challenge(labelset3, (Bv || Kv || Rv), R, K, M)
labelset[labelset_len-1] = (unsigned char)'3';
memcpy(extra + 2*POINTLEN, Rv_bytes, POINTLEN);
if (generalized_challenge(h_scalar,
labelset, labelset_len,
extra, 3*POINTLEN,
R_bytes, eddsa_25519_pubkey_bytes,
M_buf, MSTART, msg_len) != 0)
goto err;
// s = prove(r, k, h)
if (generalized_prove(s_scalar, r_scalar, eddsa_25519_privkey_scalar, h_scalar) != 0)
goto err;
// return (Kv || h || s)
memcpy(signature_out, Kv_bytes, POINTLEN);
memcpy(signature_out + POINTLEN, h_scalar, SCALARLEN);
memcpy(signature_out + POINTLEN + SCALARLEN, s_scalar, SCALARLEN);
zeroize(r_scalar, SCALARLEN);
zeroize_stack();
free(M_buf);
return 0;
err:
zeroize(r_scalar, SCALARLEN);
zeroize_stack();
free(M_buf);
return -1;
}
int generalized_veddsa_25519_verify(
unsigned char* vrf_out,
const unsigned char* signature,
const unsigned char* eddsa_25519_pubkey_bytes,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char labelset[LABELSETMAXLEN];
unsigned long labelset_len = 0;
const unsigned char* Kv_bytes;
const unsigned char* h_scalar;
const unsigned char* s_scalar;
ge_p3 Bv_point, K_point, Kv_point, cK_point, cKv_point;
unsigned char Bv_bytes[POINTLEN];
unsigned char R_calc_bytes[POINTLEN];
unsigned char Rv_calc_bytes[POINTLEN];
unsigned char h_calc_scalar[SCALARLEN];
unsigned char extra[3*POINTLEN];
unsigned char* M_buf = NULL;
char* protocol_name = "VEdDSA_25519_SHA512_Elligator2";
if (vrf_out == NULL)
goto err;
memset(vrf_out, 0, VRFOUTPUTLEN);
if (signature == NULL)
goto err;
if (eddsa_25519_pubkey_bytes == NULL)
goto err;
if (msg == NULL)
goto err;
if (customization_label == NULL && customization_label_len != 0)
goto err;
if (customization_label_len > LABELMAXLEN)
goto err;
if (msg_len > MSGMAXLEN)
goto err;
if ((M_buf = malloc(msg_len + MSTART)) == 0) {
goto err;
}
memcpy(M_buf + MSTART, msg, msg_len);
Kv_bytes = signature;
h_scalar = signature + POINTLEN;
s_scalar = signature + POINTLEN + SCALARLEN;
if (!point_isreduced(eddsa_25519_pubkey_bytes))
goto err;
if (!point_isreduced(Kv_bytes))
goto err;
if (!sc_isreduced(h_scalar))
goto err;
if (!sc_isreduced(s_scalar))
goto err;
// labelset = new_labelset(protocol_name, customization_label)
if (labelset_new(labelset, &labelset_len, LABELSETMAXLEN,
(unsigned char*)protocol_name, strlen(protocol_name),
customization_label, customization_label_len) != 0)
goto err;
// labelset1 = add_label(labels, "1")
// Bv = hash(hash(labelset1 || K) || M)
labelset_add(labelset, &labelset_len, LABELSETMAXLEN, (unsigned char*)"1", 1);
if (generalized_calculate_Bv(&Bv_point, labelset, labelset_len,
eddsa_25519_pubkey_bytes, M_buf, MSTART, msg_len) != 0)
goto err;
ge_p3_tobytes(Bv_bytes, &Bv_point);
// R = solve_commitment(B, s, K, h)
if (generalized_solve_commitment(R_calc_bytes, &K_point, NULL,
s_scalar, eddsa_25519_pubkey_bytes, h_scalar) != 0)
goto err;
// Rv = solve_commitment(Bv, s, Kv, h)
if (generalized_solve_commitment(Rv_calc_bytes, &Kv_point, &Bv_point,
s_scalar, Kv_bytes, h_scalar) != 0)
goto err;
ge_scalarmult_cofactor(&cK_point, &K_point);
ge_scalarmult_cofactor(&cKv_point, &Kv_point);
if (ge_isneutral(&cK_point) || ge_isneutral(&cKv_point) || ge_isneutral(&Bv_point))
goto err;
// labelset3 = add_label(labels, "3")
// h = challenge(labelset3, (Bv || Kv || Rv), R, K, M)
labelset[labelset_len-1] = (unsigned char)'3';
memcpy(extra, Bv_bytes, POINTLEN);
memcpy(extra + POINTLEN, Kv_bytes, POINTLEN);
memcpy(extra + 2*POINTLEN, Rv_calc_bytes, POINTLEN);
if (generalized_challenge(h_calc_scalar,
labelset, labelset_len,
extra, 3*POINTLEN,
R_calc_bytes, eddsa_25519_pubkey_bytes,
M_buf, MSTART, msg_len) != 0)
goto err;
// if bytes_equal(h, h')
if (crypto_verify_32(h_scalar, h_calc_scalar) != 0)
goto err;
// labelset4 = add_label(labels, "4")
// v = hash(labelset4 || c*Kv)
labelset[labelset_len-1] = (unsigned char)'4';
if (generalized_calculate_vrf_output(vrf_out, labelset, labelset_len, &cKv_point) != 0)
goto err;
free(M_buf);
return 0;
err:
free(M_buf);
return -1;
}

View File

@ -1,23 +0,0 @@
#ifndef __GEN_VEDDSA_H__
#define __GEN_VEDDSA_H__
int generalized_veddsa_25519_sign(
unsigned char* signature_out,
const unsigned char* eddsa_25519_pubkey_bytes,
const unsigned char* eddsa_25519_privkey_scalar,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* random,
const unsigned char* customization_label,
const unsigned long customization_label_len);
int generalized_veddsa_25519_verify(
unsigned char* vrf_out,
const unsigned char* signature,
const unsigned char* eddsa_25519_pubkey_bytes,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* customization_label,
const unsigned long customization_label_len);
#endif

View File

@ -1,131 +0,0 @@
#include <string.h>
#include "crypto_additions.h"
#include "gen_x.h"
#include "gen_constants.h"
#include "gen_eddsa.h"
#include "gen_veddsa.h"
#include "gen_crypto_additions.h"
#include "zeroize.h"
static int convert_25519_pubkey(unsigned char* ed_pubkey_bytes, const unsigned char* x25519_pubkey_bytes) {
fe u;
fe y;
/* Convert the X25519 public key into an Ed25519 public key.
y = (u - 1) / (u + 1)
NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp
*/
if (!fe_isreduced(x25519_pubkey_bytes))
return -1;
fe_frombytes(u, x25519_pubkey_bytes);
fe_montx_to_edy(y, u);
fe_tobytes(ed_pubkey_bytes, y);
return 0;
}
static int calculate_25519_keypair(unsigned char* K_bytes, unsigned char* k_scalar,
const unsigned char* x25519_privkey_scalar)
{
unsigned char kneg[SCALARLEN];
ge_p3 ed_pubkey_point;
unsigned char sign_bit = 0;
if (SCALARLEN != 32)
return -1;
/* Convert the Curve25519 privkey to an Ed25519 public key */
ge_scalarmult_base(&ed_pubkey_point, x25519_privkey_scalar);
ge_p3_tobytes(K_bytes, &ed_pubkey_point);
/* Force Edwards sign bit to zero */
sign_bit = (K_bytes[31] & 0x80) >> 7;
memcpy(k_scalar, x25519_privkey_scalar, 32);
sc_neg(kneg, k_scalar);
sc_cmov(k_scalar, kneg, sign_bit);
K_bytes[31] &= 0x7F;
zeroize(kneg, SCALARLEN);
return 0;
}
int generalized_xeddsa_25519_sign(unsigned char* signature_out,
const unsigned char* x25519_privkey_scalar,
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* random,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char K_bytes[POINTLEN];
unsigned char k_scalar[SCALARLEN];
int retval = -1;
if (calculate_25519_keypair(K_bytes, k_scalar, x25519_privkey_scalar) != 0)
return -1;
retval = generalized_eddsa_25519_sign(signature_out,
K_bytes, k_scalar,
msg, msg_len, random,
customization_label, customization_label_len);
zeroize(k_scalar, SCALARLEN);
return retval;
}
int generalized_xveddsa_25519_sign(
unsigned char* signature_out,
const unsigned char* x25519_privkey_scalar,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* random,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char K_bytes[POINTLEN];
unsigned char k_scalar[SCALARLEN];
int retval = -1;
if (calculate_25519_keypair(K_bytes, k_scalar, x25519_privkey_scalar) != 0)
return -1;
retval = generalized_veddsa_25519_sign(signature_out, K_bytes, k_scalar,
msg, msg_len, random,
customization_label, customization_label_len);
zeroize(k_scalar, SCALARLEN);
return retval;
}
int generalized_xeddsa_25519_verify(
const unsigned char* signature,
const unsigned char* x25519_pubkey_bytes,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char K_bytes[POINTLEN];
if (convert_25519_pubkey(K_bytes, x25519_pubkey_bytes) != 0)
return -1;
return generalized_eddsa_25519_verify(signature, K_bytes, msg, msg_len,
customization_label, customization_label_len);
}
int generalized_xveddsa_25519_verify(
unsigned char* vrf_out,
const unsigned char* signature,
const unsigned char* x25519_pubkey_bytes,
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* customization_label,
const unsigned long customization_label_len)
{
unsigned char K_bytes[POINTLEN];
if (convert_25519_pubkey(K_bytes, x25519_pubkey_bytes) != 0)
return -1;
return generalized_veddsa_25519_verify(vrf_out, signature, K_bytes, msg, msg_len,
customization_label, customization_label_len);
}

View File

@ -1,37 +0,0 @@
#ifndef __GEN_X_H
#define __GEN_X_H
int generalized_xeddsa_25519_sign(unsigned char* signature_out, /* 64 bytes */
const unsigned char* x25519_privkey_scalar, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* random, /* 32 bytes */
const unsigned char* customization_label,
const unsigned long customization_label_len);
int generalized_xeddsa_25519_verify(
const unsigned char* signature, /* 64 bytes */
const unsigned char* x25519_pubkey_bytes, /* 32 bytes */
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* customization_label,
const unsigned long customization_label_len);
int generalized_xveddsa_25519_sign(
unsigned char* signature_out, /* 96 bytes */
const unsigned char* x25519_privkey_scalar, /* 32 bytes */
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* random, /* 32 bytes */
const unsigned char* customization_label,
const unsigned long customization_label_len);
int generalized_xveddsa_25519_verify(
unsigned char* vrf_out, /* 32 bytes */
const unsigned char* signature, /* 96 bytes */
const unsigned char* x25519_pubkey_bytes, /* 32 bytes */
const unsigned char* msg,
const unsigned long msg_len,
const unsigned char* customization_label,
const unsigned long customization_label_len);
#endif

View File

@ -1,12 +0,0 @@
#include<string.h>
#include "fe.h"
#include "crypto_additions.h"
int point_isreduced(const unsigned char* p)
{
unsigned char strict[32];
memmove(strict, p, 32);
strict[31] &= 0x7F; /* mask off sign bit */
return fe_isreduced(strict);
}

View File

@ -1,17 +0,0 @@
#include <string.h>
#include "fe.h"
#include "sc.h"
#include "crypto_additions.h"
#include "crypto_verify_32.h"
int sc_isreduced(const unsigned char* s)
{
unsigned char strict[64];
memset(strict, 0, 64);
memmove(strict, s, 32);
sc_reduce(strict);
if (crypto_verify_32(strict, s) != 0)
return 0;
return 1;
}

View File

@ -9,13 +9,13 @@ void curve25519_keygen(unsigned char* curve25519_pubkey_out,
(which is efficient due to precalculated tables), then convert
to the Curve25519 montgomery-format public key.
NOTE: y=1 is converted to u=0 since fe_invert is mod-exp
NOTE: ed_y=1 is converted to mont_x=0 since fe_invert is mod-exp
*/
ge_p3 ed; /* Ed25519 pubkey point */
fe u;
fe mont_x;
ge_scalarmult_base(&ed, curve25519_privkey_in);
ge_p3_to_montx(u, &ed);
fe_tobytes(curve25519_pubkey_out, u);
ge_p3_to_montx(mont_x, &ed);
fe_tobytes(curve25519_pubkey_out, mont_x);
}

View File

@ -7,7 +7,7 @@
#include "crypto_additions.h"
int crypto_sign_open_modified(
unsigned char *m,
unsigned char *m,unsigned long long *mlen,
const unsigned char *sm,unsigned long long smlen,
const unsigned char *pk
)
@ -37,9 +37,14 @@ int crypto_sign_open_modified(
ge_tobytes(rcheck,&R);
if (crypto_verify_32(rcheck,rcopy) == 0) {
memmove(m,m + 64,smlen - 64);
memset(m + smlen - 64,0,64);
*mlen = smlen - 64;
return 0;
}
badsig:
*mlen = -1;
memset(m,0,smlen);
return -1;
}

View File

@ -1,21 +0,0 @@
#include "crypto_additions.h"
/*
Replace (f,g) with (g,g) if b == 1;
replace (f,g) with (f,g) if b == 0.
Preconditions: b in {0,1}.
*/
void sc_cmov(unsigned char* f, const unsigned char* g, unsigned char b)
{
int count=32;
unsigned char x[32];
for (count=0; count < 32; count++)
x[count] = f[count] ^ g[count];
b = -b;
for (count=0; count < 32; count++)
x[count] &= b;
for (count=0; count < 32; count++)
f[count] = f[count] ^ x[count];
}

View File

@ -2,24 +2,24 @@
#include "crypto_additions.h"
#include "sc.h"
/* l = order of base point = 2^252 + 27742317777372353535851937790883648493 */
/* L = order of base point = 2^252 + 27742317777372353535851937790883648493 */
/*
static unsigned char l[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
static unsigned char L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x10};
*/
static unsigned char lminus1[32] = {0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
static unsigned char Lminus1[32] = {0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
/* b = -a (mod l) */
void sc_neg(unsigned char *b, const unsigned char *a)
/* aneg = -a (mod L) */
void sc_neg(unsigned char *aneg, const unsigned char *a)
{
unsigned char zero[32];
memset(zero, 0, 32);
sc_muladd(b, lminus1, a, zero); /* b = (-1)a + 0 (mod l) */
sc_muladd(aneg, Lminus1, a, zero); /* sneg = (-1)s + 0 (mod L) */
}

View File

@ -45,9 +45,5 @@ int crypto_sign_modified(
sc_reduce(hram);
sc_muladd(sm + 32,hram,sk,nonce); /* NEW: Use privkey directly */
/* Erase any traces of private scalar or
nonce left in the stack from sc_muladd */
zeroize_stack();
zeroize(nonce, 64);
return 0;
}

View File

@ -0,0 +1,96 @@
#include <string.h>
#include "sc.h"
#include "ge.h"
#include "crypto_hash_sha512.h"
#include "crypto_verify_32.h"
#include "crypto_additions.h"
#include "crypto_sign.h"
int crypto_usign_open_modified(
unsigned char *m,unsigned long long *mlen,
const unsigned char *sm,unsigned long long smlen,
const unsigned char *pk, ge_p3* Bu
)
{
ge_p3 U;
unsigned char h[64];
unsigned char s[64];
unsigned char strict[64];
ge_p3 A;
ge_p2 R;
unsigned char hcheck[64];
int count;
if (smlen < 96) goto badsig;
if (sm[63] & 224) goto badsig; /* strict parsing of h */
if (sm[95] & 224) goto badsig; /* strict parsing of s */
/* Load -A */
if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig;
/* Load -U, h, s */
ge_frombytes_negate_vartime(&U, sm);
memset(h, 0, 64);
memset(s, 0, 64);
memmove(h, sm + 32, 32);
memmove(s, sm + 64, 32);
/* Insist that s and h are reduced scalars (strict parsing) */
memcpy(strict, h, 64);
sc_reduce(strict);
if (memcmp(strict, h, 32) != 0)
goto badsig;
memcpy(strict, s, 64);
sc_reduce(strict);
if (memcmp(strict, s, 32) != 0)
goto badsig;
// R = sB + h(-A)
ge_double_scalarmult_vartime(&R,h,&A,s);
// Ru = sBu + h(-U)
ge_p3 sBu, hU;
// sBu
ge_scalarmult(&sBu, s, Bu);
// h(-U)
ge_scalarmult(&hU, h, &U);
// Ru = sBu + h(-U)
ge_p1p1 Rp1p1;
ge_p3 Ru;
ge_cached hUcached;
ge_p3_to_cached(&hUcached, &hU);
ge_add(&Rp1p1, &sBu, &hUcached);
ge_p1p1_to_p3(&Ru, &Rp1p1);
// Check h == SHA512(label(4) || A || U || R || Ru || M)
m[0] = 0xFB;
for (count = 1; count < 32; count++)
m[count] = 0xFF;
memmove(m+32, pk, 32);
/* undo the negation for U */
fe_neg(U.X, U.X);
fe_neg(U.T, U.T);
ge_p3_tobytes(m+64, &U);
ge_tobytes(m+96, &R);
ge_p3_tobytes(m+128, &Ru);
memmove(m+160, sm+96, smlen - 96);
crypto_hash_sha512(hcheck, m, smlen + 64);
sc_reduce(hcheck);
if (crypto_verify_32(hcheck, h) == 0) {
memmove(m,m + 64,smlen - 64);
memset(m + smlen - 64,0,64);
*mlen = smlen - 64;
return 0;
}
badsig:
*mlen = -1;
memset(m,0,smlen);
return -1;
}

View File

@ -0,0 +1,58 @@
#include <string.h>
#include "crypto_sign.h"
#include "crypto_hash_sha512.h"
#include "ge.h"
#include "sc.h"
#include "zeroize.h"
#include "crypto_additions.h"
/* NEW: Compare to pristine crypto_sign()
Uses explicit private key for nonce derivation and as scalar,
instead of deriving both from a master key.
*/
int crypto_usign_modified(
unsigned char *sm,
const unsigned char *M,unsigned long Mlen,
const unsigned char *a,
const unsigned char *A,
const unsigned char *random,
const ge_p3 *Bu,
const unsigned char *U
)
{
unsigned char r[64];
unsigned char h[64];
ge_p3 R, Ru;
int count=0;
/* r = SHA512(label(3) || a || U || random(64)) */
sm[0] = 0xFC;
for (count = 1; count < 32; count++)
sm[count] = 0xFF;
memmove(sm + 32, a, 32); /* Use privkey directly for nonce derivation */
memmove(sm + 64, U, 32);
memmove(sm + 96, random, 64); /* Add suffix of random data */
crypto_hash_sha512(r, sm, 160);
sc_reduce(r);
ge_scalarmult_base(&R, r);
ge_scalarmult(&Ru, r, Bu);
/* h = SHA512(label(4) || A || U || R || Ru || M) */
sm[0] = 0xFB;
memmove(sm + 32, A, 32);
memmove(sm + 64, U, 32);
ge_p3_tobytes(sm+96, &R);
ge_p3_tobytes(sm+128, &Ru);
memmove(sm + 160, M, Mlen);
crypto_hash_sha512(h, sm, Mlen + 160);
sc_reduce(h);
memmove(sm, h, 32); /* Write h */
sc_muladd(sm + 32, h, a, r); /* Write s */
return 0;
}

View File

@ -11,15 +11,6 @@ void print_vector(const char* name, const unsigned char* v)
printf("\n");
}
void print_bytes(const char* name, const unsigned char* v, int numbytes)
{
int count;
printf("%s = \n", name);
for (count = 0; count < numbytes; count++)
printf("%02x ", v[count]);
printf("\n");
}
void print_fe(const char* name, const fe in)
{
unsigned char bytes[32];
@ -27,3 +18,8 @@ void print_fe(const char* name, const fe in)
print_vector(name, bytes);
}
void print_error(const char* error)
{
printf("ERROR: %s\n", error);
abort();
}

View File

@ -5,7 +5,8 @@
#include "fe.h"
void print_vector(const char* name, const unsigned char* v);
void print_bytes(const char* name, const unsigned char* v, int numbytes);
void print_fe(const char* name, const fe in);
void print_error(const char* error);
#endif

View File

@ -0,0 +1,80 @@
#include <string.h>
#include <stdio.h>
#include "ge.h"
#include "crypto_additions.h"
int uxdsa_sign(unsigned char* signature_out,
const unsigned char* curve25519_privkey,
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* random)
{
unsigned char a[32];
unsigned char A[32];
ge_p3 Bu, ed_pubkey_point;
unsigned char sigbuf[MAX_MSG_LEN + 160]; /* working buffer */
unsigned char sign_bit = 0;
if (msg_len > MAX_MSG_LEN) {
memset(signature_out, 0, 96);
return -1;
}
/* Convert the Curve25519 privkey to an Ed25519 public key */
ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey);
ge_p3_tobytes(A, &ed_pubkey_point);
/* Force Edwards sign bit to zero */
sign_bit = A[31] & 0x80;
if (sign_bit) {
sc_neg(a, curve25519_privkey);
A[31] &= 0x7F;
}
else
memcpy(a, curve25519_privkey, 32);
calculate_Bu_and_U(&Bu, signature_out, sigbuf, a, msg, msg_len);
/* Perform an Ed25519 signature with explicit private key */
crypto_usign_modified(sigbuf, msg, msg_len, a, A, random, &Bu, signature_out /*U*/);
memmove(signature_out+32, sigbuf, 64);
return 0;
}
int uxdsa_verify(const unsigned char* signature,
const unsigned char* curve25519_pubkey,
const unsigned char* msg, const unsigned long msg_len)
{
fe mont_x;
fe ed_y;
unsigned char ed_pubkey[32];
unsigned long long some_retval;
unsigned char verifybuf[MAX_MSG_LEN + 160]; /* working buffer */
unsigned char verifybuf2[MAX_MSG_LEN + 160]; /* working buffer #2 ?? !!! */
ge_p3 Bu;
if (msg_len > MAX_MSG_LEN) {
return -1;
}
calculate_Bu(&Bu, verifybuf, msg, msg_len);
/* Convert the Curve25519 public key into an Ed25519 public key.
ed_y = (mont_x - 1) / (mont_x + 1)
NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp
*/
fe_frombytes(mont_x, curve25519_pubkey);
fe_montx_to_edy(ed_y, mont_x);
fe_tobytes(ed_pubkey, ed_y);
memmove(verifybuf, signature, 96);
memmove(verifybuf+96, msg, msg_len);
/* Then perform a signature verification, return 0 on success */
/* The below call has a strange API: */
/* verifybuf = U || h || s || message */
/* verifybuf2 = internal to next call gets a copy of verifybuf, S gets
replaced with pubkey for hashing, then the whole thing gets zeroized
(if bad sig), or contains a copy of msg (good sig) */
return crypto_usign_open_modified(verifybuf2, &some_retval, verifybuf, 96 + msg_len, ed_pubkey, &Bu);
}

View File

@ -0,0 +1,20 @@
#ifndef __UXDSA_H__
#define __UXDSA_H__
/* WARNING: signing is non-constant time, based on the message (not the private key) */
/* This should be fixed if signing messages with secret contents */
/* returns 0 on success */
int uxdsa_sign(unsigned char* signature_out, /* 96 bytes */
const unsigned char* curve25519_privkey, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len, /* <= 256 bytes */
const unsigned char* random); /* 64 bytes */
/* returns 0 on success */
int uxdsa_verify(const unsigned char* signature, /* 96 bytes */
const unsigned char* curve25519_pubkey, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len); /* <= 256 bytes */
#endif

View File

@ -0,0 +1,78 @@
#include <string.h>
#include "ge.h"
#include "curve_sigs.h"
#include "crypto_sign.h"
#include "crypto_additions.h"
int xdsa_sign(unsigned char* signature_out,
const unsigned char* curve25519_privkey,
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* random)
{
unsigned char a[32];
unsigned char A[32];
ge_p3 ed_pubkey_point;
unsigned char sigbuf[MAX_MSG_LEN + 128]; /* working buffer */
unsigned char sign_bit = 0;
if (msg_len > MAX_MSG_LEN) {
memset(signature_out, 0, 64);
return -1;
}
/* Convert the Curve25519 privkey to an Ed25519 public key */
ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey);
ge_p3_tobytes(A, &ed_pubkey_point);
/* Force Edwards sign bit to zero */
sign_bit = A[31] & 0x80;
if (sign_bit) {
sc_neg(a, curve25519_privkey);
A[31] &= 0x7F;
}
else
memcpy(a, curve25519_privkey, 32);
/* Perform an Ed25519 signature with explicit private key */
crypto_sign_modified(sigbuf, msg, msg_len, a, A, random);
memmove(signature_out, sigbuf, 64);
return 0;
}
int xdsa_verify(const unsigned char* signature,
const unsigned char* curve25519_pubkey,
const unsigned char* msg, const unsigned long msg_len)
{
fe mont_x;
fe ed_y;
unsigned char ed_pubkey[32];
unsigned long long some_retval;
unsigned char verifybuf[MAX_MSG_LEN + 64]; /* working buffer */
unsigned char verifybuf2[MAX_MSG_LEN + 64]; /* working buffer #2 */
if (msg_len > MAX_MSG_LEN) {
return -1;
}
/* Convert the Curve25519 public key into an Ed25519 public key.
ed_y = (mont_x - 1) / (mont_x + 1)
NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp
*/
fe_frombytes(mont_x, curve25519_pubkey);
fe_montx_to_edy(ed_y, mont_x);
fe_tobytes(ed_pubkey, ed_y);
memmove(verifybuf, signature, 64);
memmove(verifybuf+64, msg, msg_len);
/* Then perform a normal Ed25519 verification, return 0 on success */
/* The below call has a strange API: */
/* verifybuf = R || S || message */
/* verifybuf2 = internal to next call gets a copy of verifybuf, S gets
replaced with pubkey for hashing, then the whole thing gets zeroized
(if bad sig), or contains a copy of msg (good sig) */
return crypto_sign_open_modified(verifybuf2, &some_retval, verifybuf, 64 + msg_len, ed_pubkey);
}

View File

@ -0,0 +1,16 @@
#ifndef __XDSA_H__
#define __XDSA_H__
/* returns 0 on success */
int xdsa_sign(unsigned char* signature_out, /* 64 bytes */
const unsigned char* curve25519_privkey, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len, /* <= 256 bytes */
const unsigned char* random); /* 64 bytes */
/* returns 0 on success */
int xdsa_verify(const unsigned char* signature, /* 64 bytes */
const unsigned char* curve25519_pubkey, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len); /* <= 256 bytes */
#endif

View File

@ -1,80 +0,0 @@
#include <string.h>
#include "ge.h"
#include "crypto_additions.h"
#include "zeroize.h"
#include "xeddsa.h"
#include "crypto_verify_32.h"
int xed25519_sign(unsigned char* signature_out,
const unsigned char* curve25519_privkey,
const unsigned char* msg, const unsigned long msg_len,
const unsigned char* random)
{
unsigned char a[32], aneg[32];
unsigned char A[32];
ge_p3 ed_pubkey_point;
unsigned char *sigbuf; /* working buffer */
unsigned char sign_bit = 0;
if ((sigbuf = malloc(msg_len + 128)) == 0) {
memset(signature_out, 0, 64);
return -1;
}
/* Convert the Curve25519 privkey to an Ed25519 public key */
ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey);
ge_p3_tobytes(A, &ed_pubkey_point);
/* Force Edwards sign bit to zero */
sign_bit = (A[31] & 0x80) >> 7;
memcpy(a, curve25519_privkey, 32);
sc_neg(aneg, a);
sc_cmov(a, aneg, sign_bit);
A[31] &= 0x7F;
/* Perform an Ed25519 signature with explicit private key */
crypto_sign_modified(sigbuf, msg, msg_len, a, A, random);
memmove(signature_out, sigbuf, 64);
zeroize(a, 32);
zeroize(aneg, 32);
free(sigbuf);
return 0;
}
int xed25519_verify(const unsigned char* signature,
const unsigned char* curve25519_pubkey,
const unsigned char* msg, const unsigned long msg_len)
{
fe u;
fe y;
unsigned char ed_pubkey[32];
unsigned char verifybuf[MAX_MSG_LEN + 64]; /* working buffer */
unsigned char verifybuf2[MAX_MSG_LEN + 64]; /* working buffer #2 */
if (msg_len > MAX_MSG_LEN) {
return -1;
}
/* Convert the Curve25519 public key into an Ed25519 public key.
y = (u - 1) / (u + 1)
NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp
*/
if (!fe_isreduced(curve25519_pubkey))
return -1;
fe_frombytes(u, curve25519_pubkey);
fe_montx_to_edy(y, u);
fe_tobytes(ed_pubkey, y);
memmove(verifybuf, signature, 64);
memmove(verifybuf+64, msg, msg_len);
/* Then perform a normal Ed25519 verification, return 0 on success */
/* The below call has a strange API: */
/* verifybuf = R || S || message */
/* verifybuf2 = internal to next call gets a copy of verifybuf, S gets
replaced with pubkey for hashing */
return crypto_sign_open_modified(verifybuf2, verifybuf, 64 + msg_len, ed_pubkey);
}

View File

@ -1,16 +0,0 @@
#ifndef __XEDDSA_H__
#define __XEDDSA_H__
/* returns 0 on success */
int xed25519_sign(unsigned char* signature_out, /* 64 bytes */
const unsigned char* curve25519_privkey, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len, /* <= 256 bytes */
const unsigned char* random); /* 64 bytes */
/* returns 0 on success */
int xed25519_verify(const unsigned char* signature, /* 64 bytes */
const unsigned char* curve25519_pubkey, /* 32 bytes */
const unsigned char* msg, const unsigned long msg_len); /* <= 256 bytes */
#endif

View File

@ -12,5 +12,5 @@ void zeroize(unsigned char* b, size_t len)
void zeroize_stack()
{
unsigned char m[ZEROIZE_STACK_SIZE];
zeroize(m, ZEROIZE_STACK_SIZE);
zeroize(m, sizeof m);
}

View File

@ -3,7 +3,7 @@
#include <stdlib.h>
#define ZEROIZE_STACK_SIZE 1024
#define ZEROIZE_STACK_SIZE 2048
void zeroize(unsigned char* b, size_t len);

View File

@ -0,0 +1,4 @@
#define CRYPTO_SECRETKEYBYTES 64
#define CRYPTO_PUBLICKEYBYTES 32
#define CRYPTO_BYTES 64
#define CRYPTO_DETERMINISTIC 1

View File

@ -9,15 +9,6 @@ Preconditions:
|f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*/
/* TREVOR'S COMMENT
*
* I think the above comment is wrong. Instead:
*
* return 0 if f == 0
* return -1 if f != 0
*
* */
static const unsigned char zero[32];
int fe_isnonzero(const fe f)

View File

@ -0,0 +1,13 @@
#include "tests.h"
int main(int argc, char* argv[])
{
all_fast_tests(0);
curvesigs_slow_test(0, 10000);
xdsa_slow_test(0, 10000);
xdsa_to_curvesigs_slow_test(0, 10000);
uxdsa_slow_test(0, 10000);
return 0;
}

View File

@ -1,469 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "crypto_hash_sha512.h"
#include "keygen.h"
#include "curve_sigs.h"
#include "xeddsa.h"
#include "crypto_additions.h"
#include "ge.h"
#include "utility.h"
#include "gen_crypto_additions.h"
#include "gen_x.h"
#include "internal_fast_tests.h"
#include <assert.h>
#define ERROR(...) do {if (!silent) { printf(__VA_ARGS__); abort(); } else return -1; } while (0)
#define INFO(...) do {if (!silent) printf(__VA_ARGS__);} while (0)
#define TEST(msg, cond) \
do { \
if ((cond)) { \
INFO("%s good\n", msg); \
} \
else { \
ERROR("%s BAD!!!\n", msg); \
} \
} while (0)
int sha512_fast_test(int silent)
{
unsigned char sha512_input[112] =
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
unsigned char sha512_correct_output[64] =
{
0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09
};
unsigned char sha512_actual_output[64];
crypto_hash_sha512(sha512_actual_output, sha512_input, sizeof(sha512_input));
TEST("SHA512 #1", memcmp(sha512_actual_output, sha512_correct_output, 64) == 0);
sha512_input[111] ^= 1;
crypto_hash_sha512(sha512_actual_output, sha512_input, sizeof(sha512_input));
TEST("SHA512 #2", memcmp(sha512_actual_output, sha512_correct_output, 64) != 0);
return 0;
}
int strict_fast_test(int silent)
{
unsigned char unreduced1[32] = {
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, 0xFF, 0xFF, 0xFF, 0x7F,
};
unsigned char unreduced2[32] = {
0xED, 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, 0xFF, 0xFF, 0x7F,
};
unsigned char unreduced3[32] = {
0xEC, 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, 0xFF, 0xFF, 0x7F,
};
unsigned char q[32] = {
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
};
unsigned char qminus1[32] = {
0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
};
unsigned char qplus1[32] = {
0xee, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
};
TEST("fe_isreduced",
(fe_isreduced(unreduced1) == 0) &&
(fe_isreduced(unreduced2) == 0) &&
(fe_isreduced(unreduced3) == 1)
);
TEST("sc_isreduced",
(sc_isreduced(q) == 0) &&
(sc_isreduced(qminus1) == 1) &&
(sc_isreduced(qplus1) == 0)
);
return 0;
}
int ge_fast_test(int silent)
{
const unsigned char B_bytes[] = {
0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
};
const unsigned char misc_bytes[] = {
0x57, 0x17, 0xfa, 0xce, 0xca, 0xb9, 0xdf, 0x0e,
0x90, 0x67, 0xaa, 0x46, 0xba, 0x83, 0x2f, 0xeb,
0x1c, 0x49, 0xd0, 0x21, 0xb1, 0x33, 0xff, 0x11,
0xc9, 0x7a, 0xb8, 0xcf, 0xe3, 0x29, 0x46, 0x17,
};
unsigned char q_scalar[32] = {
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
};
unsigned char c_scalar[32] = {
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, 0x00, 0x00, 0x00, 0x00
};
unsigned char neutral_bytes[] = {
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, 0x00, 0x00, 0x00, 0x00
};
/* unsigned char one_scalar[32] = {
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, 0x00, 0x00, 0x00, 0x00,
};
const unsigned char B_bytes[] = {
0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
};
*/
ge_p3 point1, point2, B_point, misc_point, miscneg_point;
unsigned char output1[32], output2[32];
if (ge_frombytes_negate_vartime(&B_point, B_bytes) != 0)
TEST("Failure to parse point #1", 0);
if (ge_frombytes_negate_vartime(&miscneg_point, misc_bytes) != 0)
TEST("Failure to parse point #2", 0);
ge_neg(&B_point, &B_point);
ge_neg(&misc_point, &miscneg_point);
/* q*B == neutral */
ge_scalarmult_base(&point1, q_scalar);
ge_scalarmult(&point2, q_scalar, &B_point);
ge_p3_tobytes(output1, &point1);
ge_p3_tobytes(output2, &point2);
TEST("qB == qB", memcmp(output1, output2, 32) == 0 && memcmp(output1, neutral_bytes, 32) == 0);
TEST("qB isneutral", ge_isneutral(&point1 ) && ge_isneutral(&point2) && !ge_isneutral(&B_point));
/* cB == cB, cX == cX */
ge_scalarmult_cofactor(&point1, &B_point);
ge_scalarmult_base(&point2, c_scalar);
ge_p3_tobytes(output1, &point1);
ge_p3_tobytes(output2, &point2);
TEST("cB == cB", memcmp(output1, output2, 32) == 0);
ge_scalarmult_cofactor(&point1, &misc_point);
ge_scalarmult(&point2, c_scalar, &misc_point);
ge_p3_tobytes(output1, &point1);
ge_p3_tobytes(output2, &point2);
TEST("cX == cX", memcmp(output1, output2, 32) == 0);
/* */
ge_p3_add(&point1, &misc_point, &miscneg_point);
TEST("X + -X isneutral", ge_isneutral(&point1));
return 0;
}
int elligator_fast_test(int silent)
{
unsigned char elligator_correct_output[32] =
{
0x5f, 0x35, 0x20, 0x00, 0x1c, 0x6c, 0x99, 0x36,
0xa3, 0x12, 0x06, 0xaf, 0xe7, 0xc7, 0xac, 0x22,
0x4e, 0x88, 0x61, 0x61, 0x9b, 0xf9, 0x88, 0x72,
0x44, 0x49, 0x15, 0x89, 0x9d, 0x95, 0xf4, 0x6e
};
unsigned char hashtopoint_correct_output1[32] =
{
0xce, 0x89, 0x9f, 0xb2, 0x8f, 0xf7, 0x20, 0x91,
0x5e, 0x14, 0xf5, 0xb7, 0x99, 0x08, 0xab, 0x17,
0xaa, 0x2e, 0xe2, 0x45, 0xb4, 0xfc, 0x2b, 0xf6,
0x06, 0x36, 0x29, 0x40, 0xed, 0x7d, 0xe7, 0xed
};
unsigned char hashtopoint_correct_output2[32] =
{
0xa0, 0x35, 0xbb, 0xa9, 0x4d, 0x30, 0x55, 0x33,
0x0d, 0xce, 0xc2, 0x7f, 0x83, 0xde, 0x79, 0xd0,
0x89, 0x67, 0x72, 0x4c, 0x07, 0x8d, 0x68, 0x9d,
0x61, 0x52, 0x1d, 0xf9, 0x2c, 0x5c, 0xba, 0x77
};
int count;
fe in, out;
unsigned char bytes[32];
fe_0(in);
fe_0(out);
for (count = 0; count < 32; count++) {
bytes[count] = count;
}
fe_frombytes(in, bytes);
elligator(out, in);
fe_tobytes(bytes, out);
TEST("Elligator vector", memcmp(bytes, elligator_correct_output, 32) == 0);
/* Elligator(0) == 0 test */
fe_0(in);
elligator(out, in);
TEST("Elligator(0) == 0", memcmp(in, out, 32) == 0);
/* ge_montx_to_p3(0) -> order2 point test */
fe one, negone, zero;
fe_1(one);
fe_0(zero);
fe_sub(negone, zero, one);
ge_p3 p3;
ge_montx_to_p3(&p3, zero, 0);
TEST("ge_montx_to_p3(0) == order 2 point",
fe_isequal(p3.X, zero) &&
fe_isequal(p3.Y, negone) &&
fe_isequal(p3.Z, one) &&
fe_isequal(p3.T, zero));
/* Hash to point vector test */
unsigned char htp[32];
for (count=0; count < 32; count++) {
htp[count] = count;
}
hash_to_point(&p3, htp, 32);
ge_p3_tobytes(htp, &p3);
TEST("hash_to_point #1", memcmp(htp, hashtopoint_correct_output1, 32) == 0);
for (count=0; count < 32; count++) {
htp[count] = count+1;
}
hash_to_point(&p3, htp, 32);
ge_p3_tobytes(htp, &p3);
TEST("hash_to_point #2", memcmp(htp, hashtopoint_correct_output2, 32) == 0);
return 0;
}
int curvesigs_fast_test(int silent)
{
unsigned char signature_correct[64] = {
0xcf, 0x87, 0x3d, 0x03, 0x79, 0xac, 0x20, 0xe8,
0x89, 0x3e, 0x55, 0x67, 0xee, 0x0f, 0x89, 0x51,
0xf8, 0xdb, 0x84, 0x0d, 0x26, 0xb2, 0x43, 0xb4,
0x63, 0x52, 0x66, 0x89, 0xd0, 0x1c, 0xa7, 0x18,
0xac, 0x18, 0x9f, 0xb1, 0x67, 0x85, 0x74, 0xeb,
0xdd, 0xe5, 0x69, 0x33, 0x06, 0x59, 0x44, 0x8b,
0x0b, 0xd6, 0xc1, 0x97, 0x3f, 0x7d, 0x78, 0x0a,
0xb3, 0x95, 0x18, 0x62, 0x68, 0x03, 0xd7, 0x82,
};
const int MSG_LEN = 200;
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[64];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 0, 64);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
privkey[8] = 189; /* just so there's some bits set */
sc_clamp(privkey);
/* Signature vector test */
curve25519_keygen(pubkey, privkey);
curve25519_sign(signature, privkey, msg, MSG_LEN, random);
TEST("Curvesig sign", memcmp(signature, signature_correct, 64) == 0);
TEST("Curvesig verify #1", curve25519_verify(signature, pubkey, msg, MSG_LEN) == 0);
signature[0] ^= 1;
TEST("Curvesig verify #2", curve25519_verify(signature, pubkey, msg, MSG_LEN) != 0);
return 0;
}
int xeddsa_fast_test(int silent)
{
unsigned char signature_correct[64] = {
0x11, 0xc7, 0xf3, 0xe6, 0xc4, 0xdf, 0x9e, 0x8a,
0x51, 0x50, 0xe1, 0xdb, 0x3b, 0x30, 0xf9, 0x2d,
0xe3, 0xa3, 0xb3, 0xaa, 0x43, 0x86, 0x56, 0x54,
0x5f, 0xa7, 0x39, 0x0f, 0x4b, 0xcc, 0x7b, 0xb2,
0x6c, 0x43, 0x1d, 0x9e, 0x90, 0x64, 0x3e, 0x4f,
0x0e, 0xaa, 0x0e, 0x9c, 0x55, 0x77, 0x66, 0xfa,
0x69, 0xad, 0xa5, 0x76, 0xd6, 0x3d, 0xca, 0xf2,
0xac, 0x32, 0x6c, 0x11, 0xd0, 0xb9, 0x77, 0x02,
};
const int MSG_LEN = 200;
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[64];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 0, 64);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
privkey[8] = 189; /* just so there's some bits set */
sc_clamp(privkey);
/* Signature vector test */
curve25519_keygen(pubkey, privkey);
xed25519_sign(signature, privkey, msg, MSG_LEN, random);
TEST("XEdDSA sign", memcmp(signature, signature_correct, 64) == 0);
TEST("XEdDSA verify #1", xed25519_verify(signature, pubkey, msg, MSG_LEN) == 0);
signature[0] ^= 1;
TEST("XEdDSA verify #2", xed25519_verify(signature, pubkey, msg, MSG_LEN) != 0);
memset(pubkey, 0xFF, 32);
TEST("XEdDSA verify #3", xed25519_verify(signature, pubkey, msg, MSG_LEN) != 0);
return 0;
}
int generalized_xeddsa_fast_test(int silent)
{
unsigned char signature1[64];
unsigned char signature2[64];
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char msg1[1000];
unsigned char msg2[1000];
unsigned char random[64];
memset(signature1, 0, 64);
memset(signature2, 0, 64);
memset(privkey, 0xF0, 32);
memset(pubkey, 2, 32);
memset(msg1, 0x10, 1000);
memset(msg2, 0x20, 1000);
memset(random, 0xBC, 64);
sc_clamp(privkey);
curve25519_keygen(pubkey, privkey);
msg2[0] = 1;
TEST("generalized xeddsa sign #1", generalized_xeddsa_25519_sign(signature1, privkey, msg1, 100, random, NULL, 0) == 0);
TEST("generalized xeddsa sign #2", generalized_xeddsa_25519_sign(signature2, privkey, msg2, 100, random, NULL, 0) == 0);
TEST("generalized (old) xeddsa verify #1", xed25519_verify(signature1, pubkey, msg1, 100) == 0);
TEST("generalized (old) xeddsa verify #2", xed25519_verify(signature2, pubkey, msg2, 100) == 0);
TEST("generalized (old) xeddsa verify #3", xed25519_verify(signature1, pubkey, msg2, 100) != 0);
TEST("generalized (old) xeddsa verify #4", xed25519_verify(signature2, pubkey, msg1, 100) != 0);
TEST("generalized xeddsa verify #1", generalized_xeddsa_25519_verify(signature1, pubkey, msg1, 100, NULL, 0) == 0);
TEST("generalized xeddsa verify #2", generalized_xeddsa_25519_verify(signature2, pubkey, msg2, 100, NULL, 0) == 0);
TEST("generalized xeddsa verify #3", generalized_xeddsa_25519_verify(signature1, pubkey, msg2, 100, NULL, 0) != 0);
TEST("generalized xeddsa verify #4", generalized_xeddsa_25519_verify(signature2, pubkey, msg1, 100, NULL, 0) != 0);
return 0;
}
int generalized_xveddsa_fast_test(int silent)
{
unsigned char signature1[96];
unsigned char signature2[96];
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char msg1[1000];
unsigned char msg2[1000];
unsigned char random[64];
unsigned char vrf[32];
memset(signature1, 0, 64);
memset(signature2, 0, 64);
memset(privkey, 1, 32);
memset(pubkey, 2, 32);
memset(msg1, 0x11, 1000);
memset(msg2, 0x22, 1000);
memset(random, 0xAB, 64);
sc_clamp(privkey);
curve25519_keygen(pubkey, privkey);
msg2[0] ^= 1;
TEST("generalized xveddsa sign #1", generalized_xveddsa_25519_sign(signature1, privkey, msg1, 100, random, NULL, 0) == 0);
TEST("generalized xveddsa sign #2", generalized_xveddsa_25519_sign(signature2, privkey, msg2, 100, random, (unsigned char*)"abc", 3) == 0);
TEST("generalized xveddsa verify #1", generalized_xveddsa_25519_verify(vrf, signature1, pubkey, msg1, 100, NULL, 0) == 0);
TEST("generalized xveddsa verify #2", generalized_xveddsa_25519_verify(vrf, signature2, pubkey, msg2, 100, (unsigned char*)"abc", 3) == 0);
TEST("generalized xveddsa verify #3", generalized_xveddsa_25519_verify(vrf, signature1, pubkey, msg2, 100, NULL, 0) != 0);
TEST("generalized xveddsa verify #4", generalized_xveddsa_25519_verify(vrf, signature2, pubkey, msg1, 100, (unsigned char*)"abc", 3) != 0);
unsigned char signature3[96];
unsigned char vrf3[96];
random[0] ^= 1;
TEST("generalized xveddsa sign #3", generalized_xveddsa_25519_sign(signature3, privkey, msg1, 100, random, NULL, 0) == 0);
TEST("generalized xveddsa verify #5", generalized_xveddsa_25519_verify(vrf, signature1, pubkey, msg1, 100, NULL, 0) == 0);
TEST("generalized xveddsa verify #6", generalized_xveddsa_25519_verify(vrf3, signature3, pubkey, msg1, 100, NULL, 0) == 0);
TEST("generalized xveddsa VRFs equal", memcmp(vrf, vrf3, 32) == 0);
TEST("generalized xveddsa Kv equal", memcmp(signature1+0, signature3+0, 32) == 0);
TEST("generalized xveddsa h not equal", memcmp(signature1+32, signature3+32, 32) != 0);
TEST("generalized xveddsa s not equal", memcmp(signature1+64, signature3+64, 32) != 0);
return 0;
}
int all_fast_tests(int silent)
{
int result;
if ((result = sha512_fast_test(silent)) != 0)
return -1;
if ((result = strict_fast_test(silent)) != 0)
return -2;
if ((result = ge_fast_test(silent)) != 0)
return -3;
if ((result = elligator_fast_test(silent)) != 0)
return -3;
if ((result = curvesigs_fast_test(silent)) != 0)
return -4;
if ((result = xeddsa_fast_test(silent)) != 0)
return -5;
if ((result = generalized_xeddsa_fast_test(silent)) != 0)
return -6;
if ((result = generalized_xveddsa_fast_test(silent)) != 0)
return -7;
return 0;
}

View File

@ -1,19 +0,0 @@
#ifndef __INTERNAL_FAST_TESTS_H__
#define __INTERNAL_FAST_TESTS_H__
/* silent = 0 : prints info+error messages to stdout, abort() on test failure
* silent = 1 : returns 0 for success, anything else for failure
*/
int sha512_fast_test(int silent);
int strict_fast_test(int silent);
int elligator_fast_test(int silent);
int curvesigs_fast_test(int silent);
int xeddsa_fast_test(int silent);
int vxeddsa_fast_test(int silent);
int generalized_xeddsa_fast_test(int silent);
int generalized_xveddsa_fast_test(int silent);
int all_fast_tests(int silent);
#endif

View File

@ -1,371 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "crypto_hash_sha512.h"
#include "keygen.h"
#include "curve_sigs.h"
#include "xeddsa.h"
#include "crypto_additions.h"
#include "ge.h"
#include "utility.h"
#include "gen_x.h"
#include "internal_slow_tests.h"
#include <assert.h>
#define ERROR(...) do {if (!silent) { printf(__VA_ARGS__); abort(); } else return -1; } while (0)
#define INFO(...) do {if (!silent) printf(__VA_ARGS__);} while (0)
#define TEST(msg, cond) \
do { \
if ((cond)) { \
INFO("%s good\n", msg); \
} \
else { \
ERROR("%s BAD!!!\n", msg); \
} \
} while (0)
int curvesigs_slow_test(int silent, int iterations)
{
unsigned char signature_10k_correct[64] = {
0xfc, 0xba, 0x55, 0xc4, 0x85, 0x4a, 0x42, 0x25,
0x19, 0xab, 0x08, 0x8d, 0xfe, 0xb5, 0x13, 0xb6,
0x0d, 0x24, 0xbb, 0x16, 0x27, 0x55, 0x71, 0x48,
0xdd, 0x20, 0xb1, 0xcd, 0x2a, 0xd6, 0x7e, 0x35,
0xef, 0x33, 0x4c, 0x7b, 0x6d, 0x94, 0x6f, 0x52,
0xec, 0x43, 0xd7, 0xe6, 0x35, 0x24, 0xcd, 0x5b,
0x5d, 0xdc, 0xb2, 0x32, 0xc6, 0x22, 0x53, 0xf3,
0x38, 0x02, 0xf8, 0x28, 0x28, 0xc5, 0x65, 0x05,
};
int count;
const int MSG_LEN = 200;
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[64];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 0, 64);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
/* Signature random test */
INFO("Pseudorandom curvesigs...\n");
for (count = 1; count <= iterations; count++) {
unsigned char b[64];
crypto_hash_sha512(b, signature, 64);
memmove(privkey, b, 32);
crypto_hash_sha512(b, privkey, 32);
memmove(random, b, 64);
sc_clamp(privkey);
curve25519_keygen(pubkey, privkey);
curve25519_sign(signature, privkey, msg, MSG_LEN, random);
if (curve25519_verify(signature, pubkey, msg, MSG_LEN) != 0)
ERROR("Curvesig verify failure #1 %d\n", count);
if (b[63] & 1)
signature[count % 64] ^= 1;
else
msg[count % MSG_LEN] ^= 1;
if (curve25519_verify(signature, pubkey, msg, MSG_LEN) == 0)
ERROR("Curvesig verify failure #2 %d\n", count);
if (count == 10000) {
if (memcmp(signature, signature_10k_correct, 64) != 0)
ERROR("Curvesig signature 10K doesn't match %d\n", count);
}
if (count == 100000)
print_bytes("100K curvesigs", signature, 64);
if (count == 1000000)
print_bytes("1M curvesigs", signature, 64);
if (count == 10000000)
print_bytes("10M curvesigs", signature, 64);
}
INFO("good\n");
return 0;
}
int xeddsa_slow_test(int silent, int iterations)
{
unsigned char signature_10k_correct[64] = {
0x15, 0x29, 0x03, 0x38, 0x66, 0x16, 0xcd, 0x26,
0xbb, 0x3e, 0xec, 0xe2, 0x9f, 0x72, 0xa2, 0x5c,
0x7d, 0x05, 0xc9, 0xcb, 0x84, 0x3f, 0x92, 0x96,
0xb3, 0xfb, 0xb9, 0xdd, 0xd6, 0xed, 0x99, 0x04,
0xc1, 0xa8, 0x02, 0x16, 0xcf, 0x49, 0x3f, 0xf1,
0xbe, 0x69, 0xf9, 0xf1, 0xcc, 0x16, 0xd7, 0xdc,
0x6e, 0xd3, 0x78, 0xaa, 0x04, 0xeb, 0x71, 0x51,
0x9d, 0xe8, 0x7a, 0x5b, 0xd8, 0x49, 0x7b, 0x05,
};
int count;
const int MSG_LEN = 200;
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[96];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 1, 64);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
/* Signature random test */
INFO("Pseudorandom XEdDSA...\n");
for (count = 1; count <= iterations; count++) {
unsigned char b[64];
crypto_hash_sha512(b, signature, 64);
memmove(privkey, b, 32);
crypto_hash_sha512(b, privkey, 32);
memmove(random, b, 64);
sc_clamp(privkey);
curve25519_keygen(pubkey, privkey);
xed25519_sign(signature, privkey, msg, MSG_LEN, random);
if (xed25519_verify(signature, pubkey, msg, MSG_LEN) != 0)
ERROR("XEdDSA verify failure #1 %d\n", count);
if (b[63] & 1)
signature[count % 64] ^= 1;
else
msg[count % MSG_LEN] ^= 1;
if (xed25519_verify(signature, pubkey, msg, MSG_LEN) == 0)
ERROR("XEdDSA verify failure #2 %d\n", count);
if (count == 10000) {
if (memcmp(signature, signature_10k_correct, 64) != 0)
ERROR("XEDSA signature 10K doesn't match %d\n", count);
}
if (count == 100000)
print_bytes("100K XEdDSA", signature, 64);
if (count == 1000000)
print_bytes("1M XEdDSA", signature, 64);
if (count == 10000000)
print_bytes("10M XEdDSA", signature, 64);
}
INFO("good\n");
return 0;
}
int xeddsa_to_curvesigs_slow_test(int silent, int iterations)
{
unsigned char signature_10k_correct[64] = {
0x33, 0x50, 0xa8, 0x68, 0xcd, 0x9e, 0x74, 0x99,
0xa3, 0x5c, 0x33, 0x75, 0x2b, 0x22, 0x03, 0xf8,
0xb5, 0x0f, 0xea, 0x8c, 0x33, 0x1c, 0x68, 0x8b,
0xbb, 0xf3, 0x31, 0xcf, 0x7c, 0x42, 0x37, 0x35,
0xa0, 0x0e, 0x15, 0xb8, 0x5d, 0x2b, 0xe1, 0xa2,
0x03, 0x77, 0x94, 0x3d, 0x13, 0x5c, 0xd4, 0x9b,
0x6a, 0x31, 0xf4, 0xdc, 0xfe, 0x24, 0xad, 0x54,
0xeb, 0xd2, 0x98, 0x47, 0xf1, 0xcc, 0xbf, 0x0d
};
int count;
const int MSG_LEN = 200;
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[96];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 2, 64);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
/* Signature random test */
INFO("Pseudorandom XEdDSA/Curvesigs...\n");
for (count = 1; count <= iterations; count++) {
unsigned char b[64];
crypto_hash_sha512(b, signature, 64);
memmove(privkey, b, 32);
crypto_hash_sha512(b, privkey, 32);
memmove(random, b, 64);
sc_clamp(privkey);
curve25519_keygen(pubkey, privkey);
xed25519_sign(signature, privkey, msg, MSG_LEN, random);
if (curve25519_verify(signature, pubkey, msg, MSG_LEN) != 0)
ERROR("XEdDSA/Curvesigs verify failure #1 %d\n", count);
if (b[63] & 1)
signature[count % 64] ^= 1;
else
msg[count % MSG_LEN] ^= 1;
if (curve25519_verify(signature, pubkey, msg, MSG_LEN) == 0)
ERROR("XEdDSA/Curvesigs verify failure #2 %d\n", count);
if (count == 10000) {
if (memcmp(signature, signature_10k_correct, 64) != 0)
ERROR("XEdDSA/Curvesigs signature 10K doesn't match %d\n", count);
}
if (count == 100000)
print_bytes("100K XEdDSA/C", signature, 64);
if (count == 1000000)
print_bytes("1M XEdDSA/C", signature, 64);
if (count == 10000000)
print_bytes("10M XEdDSA/C", signature, 64);
}
INFO("good\n");
return 0;
}
int generalized_xveddsa_slow_test(int silent, int iterations)
{
unsigned char signature_10k_correct[96] = {
0x89, 0x21, 0xf5, 0x2f, 0x37, 0x72, 0x08, 0x55,
0x18, 0x9d, 0x24, 0xed, 0x86, 0xb1, 0x7a, 0x02,
0xbf, 0x29, 0x5e, 0xa7, 0x45, 0xdc, 0x80, 0x03,
0x7f, 0x4f, 0xca, 0x79, 0xe0, 0x95, 0xd0, 0xa1,
0xb5, 0x99, 0xbe, 0xbd, 0xef, 0xbe, 0xa4, 0xdc,
0x0c, 0x07, 0x6a, 0xf7, 0x7f, 0xe1, 0x1c, 0xb8,
0x18, 0x84, 0xb8, 0xb4, 0xcf, 0x38, 0x7d, 0x98,
0x37, 0xd8, 0x40, 0x23, 0x42, 0x12, 0x70, 0x06,
0xb0, 0xd1, 0x0c, 0xc0, 0x1c, 0xa6, 0x9a, 0x2f,
0xb4, 0x02, 0xd6, 0x37, 0x22, 0xe9, 0xfb, 0x00,
0x22, 0x02, 0x5a, 0xf4, 0x40, 0x43, 0xb8, 0xe9,
0xf4, 0x13, 0x44, 0x16, 0x19, 0x8d, 0x7e, 0x02,
};
unsigned char signature_100k_correct[96] = {
0xc4, 0x99, 0x64, 0x1f, 0x94, 0x95, 0xf4, 0x57,
0xa0, 0xb9, 0x3d, 0xc3, 0xb5, 0x2e, 0x1e, 0xdd,
0x92, 0xf2, 0x4c, 0xb2, 0x01, 0x36, 0x3d, 0xf2,
0xea, 0x2c, 0xdc, 0x32, 0x21, 0x5f, 0xc5, 0xd2,
0xff, 0x16, 0x41, 0x71, 0x3a, 0x77, 0x79, 0xeb,
0x67, 0x20, 0xc4, 0xec, 0x39, 0xe1, 0x54, 0x2d,
0x40, 0x10, 0xf9, 0xca, 0xc5, 0x21, 0x0a, 0x47,
0x63, 0x99, 0x23, 0x04, 0x9d, 0x03, 0x1a, 0x06,
0x00, 0xb9, 0x56, 0x7e, 0xef, 0xee, 0x0b, 0x40,
0x59, 0xc1, 0x86, 0xd9, 0xa7, 0x87, 0x70, 0xec,
0x05, 0x89, 0xbe, 0x71, 0x43, 0xd1, 0xf5, 0x61,
0x5e, 0x00, 0x41, 0xde, 0x1f, 0x41, 0x2d, 0x0e,
};
/*
unsigned char signature_1m_correct[96] = {
0xf8, 0xb1, 0x20, 0xf2, 0x1e, 0x5c, 0xbf, 0x5f,
0xea, 0x07, 0xcb, 0xb5, 0x77, 0xb8, 0x03, 0xbc,
0xcb, 0x6d, 0xf1, 0xc1, 0xa5, 0x03, 0x05, 0x7b,
0x01, 0x63, 0x9b, 0xf9, 0xed, 0x3e, 0x57, 0x47,
0xd2, 0x5b, 0xf4, 0x7e, 0x7c, 0x45, 0xce, 0xfc,
0x06, 0xb3, 0xf4, 0x05, 0x81, 0x9f, 0x53, 0xb0,
0x18, 0xe3, 0xfa, 0xcb, 0xb2, 0x52, 0x3e, 0x57,
0xcb, 0x34, 0xcc, 0x81, 0x60, 0xb9, 0x0b, 0x04,
0x07, 0x79, 0xc0, 0x53, 0xad, 0xc4, 0x4b, 0xd0,
0xb5, 0x7d, 0x95, 0x4e, 0xbe, 0xa5, 0x75, 0x0c,
0xd4, 0xbf, 0xa7, 0xc0, 0xcf, 0xba, 0xe7, 0x7c,
0xe2, 0x90, 0xef, 0x61, 0xa9, 0x29, 0x66, 0x0d,
};
unsigned char signature_10m_correct[96] = {
0xf5, 0xa4, 0xbc, 0xec, 0xc3, 0x3d, 0xd0, 0x43,
0xd2, 0x81, 0x27, 0x9e, 0xf0, 0x4c, 0xbe, 0xf3,
0x77, 0x01, 0x56, 0x41, 0x0e, 0xff, 0x0c, 0xb9,
0x66, 0xec, 0x4d, 0xe0, 0xb7, 0x25, 0x63, 0x6b,
0x5c, 0x08, 0x39, 0x80, 0x4e, 0x37, 0x1b, 0x2c,
0x46, 0x6f, 0x86, 0x99, 0x1c, 0x4e, 0x31, 0x60,
0xdb, 0x4c, 0xfe, 0xc5, 0xa2, 0x4d, 0x71, 0x2b,
0xd6, 0xd0, 0xc3, 0x98, 0x88, 0xdb, 0x0e, 0x0c,
0x68, 0x4a, 0xd3, 0xc7, 0x56, 0xac, 0x8d, 0x95,
0x7b, 0xbd, 0x99, 0x50, 0xe8, 0xd3, 0xea, 0xf3,
0x7b, 0x26, 0xf2, 0xa2, 0x2b, 0x02, 0x58, 0xca,
0xbd, 0x2c, 0x2b, 0xf7, 0x77, 0x58, 0xfe, 0x09,
};
*/
int count;
const int MSG_LEN = 200;
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[96];
unsigned char msg[MSG_LEN];
unsigned char random[64];
unsigned char vrf_out[32];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 3, 96);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
INFO("Pseudorandom XVEdDSA...\n");
for (count = 1; count <= iterations; count++) {
unsigned char b[64];
crypto_hash_sha512(b, signature, 96);
memmove(privkey, b, 32);
crypto_hash_sha512(b, privkey, 32);
memmove(random, b, 64);
sc_clamp(privkey);
curve25519_keygen(pubkey, privkey);
generalized_xveddsa_25519_sign(signature, privkey, msg, MSG_LEN, random, NULL, 0);
if (generalized_xveddsa_25519_verify(vrf_out, signature, pubkey, msg, MSG_LEN, NULL, 0) != 0)
ERROR("XVEdDSA verify failure #1 %d\n", count);
if (b[63] & 1)
signature[count % 96] ^= 1;
else
msg[count % MSG_LEN] ^= 1;
if (generalized_xveddsa_25519_verify(vrf_out, signature, pubkey, msg, MSG_LEN, NULL, 0) == 0)
ERROR("XVEdDSA verify failure #2 %d\n", count);
if (count == 10000)
print_bytes("10K XVEdDSA", signature, 96);
if (count == 100000)
print_bytes("100K XVEdDSA", signature, 96);
if (count == 1000000)
print_bytes("1M XVEdDSA", signature, 96);
if (count == 10000000)
print_bytes("10M XVEdDSA", signature, 96);
if (count == 100000000)
print_bytes("100M XVEdDSA", signature, 96);
if (count == 10000) {
if (memcmp(signature, signature_10k_correct, 96) != 0)
ERROR("XVEDDSA 10K doesn't match %d\n", count);
}
if (count == 100000) {
if (memcmp(signature, signature_100k_correct, 96) != 0)
ERROR("XVEDDSA 100K doesn't match %d\n", count);
}
/*
if (count == 1000000) {
if (memcmp(signature, signature_1m_correct, 96) != 0)
ERROR("XVEDDSA 1m doesn't match %d\n", count);
}
if (count == 10000000) {
if (memcmp(signature, signature_10m_correct, 96) != 0)
ERROR("XVEDDSA 10m doesn't match %d\n", count);
}
if (count == 100000000) {
if (memcmp(signature, signature_100m_correct, 96) != 0)
ERROR("XVEDDSA 100m doesn't match %d\n", count);
}
*/
}
INFO("good\n");
return 0;
}

View File

@ -1,15 +0,0 @@
#ifndef __INTERNAL_SLOW_TESTS_H__
#define __INTERNAL_SLOW_TESTS_H__
/* silent = 0 : prints info+error messages to stdout, abort() on test failure
* silent = 1 : returns 0 for success, anything else for failure
* iterations : hardcoded known-good values are at 10000, so run at least this many
*/
int curvesigs_slow_test(int silent, int iterations);
int xeddsa_slow_test(int silent, int iterations);
int xeddsa_to_curvesigs_slow_test(int silent, int iterations);
int generalized_xveddsa_slow_test(int silent, int iterations);
#endif

View File

@ -0,0 +1,587 @@
#include <stdio.h>
#include <string.h>
#include "crypto_hash_sha512.h"
#include "keygen.h"
#include "curve_sigs.h"
#include "xdsa.h"
#include "uxdsa.h"
#include "crypto_additions.h"
#include "ge.h"
#include "utility.h"
#include "tests.h"
#define MSG_LEN 200
#define ERROR(msg) {if (!silent) print_error(msg); else return -1; }
#define INFO(msg) {if (!silent) printf("%s\n", msg);}
int sha512_fast_test(int silent)
{
unsigned char sha512_input[112] =
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
unsigned char sha512_correct_output[64] =
{
0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09
};
unsigned char sha512_actual_output[64];
crypto_hash_sha512(sha512_actual_output, sha512_input, sizeof(sha512_input));
if (memcmp(sha512_actual_output, sha512_correct_output, 64) != 0)
ERROR("SHA512 #1 BAD")
else
INFO("SHA512 #1 good");
sha512_input[111] ^= 1;
crypto_hash_sha512(sha512_actual_output, sha512_input, sizeof(sha512_input));
if (memcmp(sha512_actual_output, sha512_correct_output, 64) != 0)
INFO("SHA512 #2 good")
else
ERROR("SHA512 #2 BAD");
return 0;
}
int elligator_fast_test(int silent)
{
unsigned char elligator_correct_output[32] =
{
0x5f, 0x35, 0x20, 0x00, 0x1c, 0x6c, 0x99, 0x36,
0xa3, 0x12, 0x06, 0xaf, 0xe7, 0xc7, 0xac, 0x22,
0x4e, 0x88, 0x61, 0x61, 0x9b, 0xf9, 0x88, 0x72,
0x44, 0x49, 0x15, 0x89, 0x9d, 0x95, 0xf4, 0x6e
};
unsigned char hashtopoint_correct_output[32] =
{
0xce, 0x89, 0x9f, 0xb2, 0x8f, 0xf7, 0x20, 0x91,
0x5e, 0x14, 0xf5, 0xb7, 0x99, 0x08, 0xab, 0x17,
0xaa, 0x2e, 0xe2, 0x45, 0xb4, 0xfc, 0x2b, 0xf6,
0x06, 0x36, 0x29, 0x40, 0xed, 0x7d, 0xe7, 0xed
};
unsigned char calculateu_correct_output[32] =
{
0xa8, 0x36, 0xb5, 0x30, 0xd3, 0xe7, 0x65, 0x54,
0x3e, 0x72, 0xc8, 0x87, 0x7d, 0xa4, 0x12, 0x6d,
0x77, 0xbf, 0x22, 0x0b, 0x72, 0xd5, 0xad, 0x6b,
0xb6, 0xc2, 0x16, 0xb2, 0x92, 0x5f, 0x0f, 0x2a
};
int count;
fe in, out;
unsigned char bytes[32];
fe_0(in);
fe_0(out);
for (count = 0; count < 32; count++) {
bytes[count] = count;
}
fe_frombytes(in, bytes);
elligator(out, in);
fe_tobytes(bytes, out);
if (memcmp(bytes, elligator_correct_output, 32) != 0)
ERROR("Elligator BAD!!!")
else
INFO("Elligator good");
/*
// Test whether Elligator can calculate Legendre == 0
// Answer appears to be yes, since 2r^2 + 1 == 0 has a solution
//
fe NEG1;
fe ONE;
fe TWO;
fe_1(ONE);
fe_add(TWO, ONE, ONE);
fe_neg(NEG1, ONE);
printf("NEG1\n");
legendre_is_nonsquare(out, NEG1);
printf("TWO\n");
legendre_is_nonsquare(out, TWO);
print_error("done");
*/
/* Hash to point vector test */
ge_p3 p3;
unsigned char htp[32];
for (count=0; count < 32; count++) {
htp[count] = count;
}
hash_to_point(&p3, htp, 32);
ge_p3_tobytes(htp, &p3);
if (memcmp(htp, hashtopoint_correct_output, 32) != 0)
ERROR("hash_to_point BAD!!!")
else
INFO("hash_to_point good");
/* calculate_U vector test */
ge_p3 Bu;
unsigned char U[32];
unsigned char Ubuf[200];
unsigned char a[32];
unsigned char Umsg[3];
Umsg[0] = 0;
Umsg[1] = 1;
Umsg[2] = 2;
for (count=0; count < 32; count++) {
a[count] = 8 + count;
}
sc_clamp(a);
calculate_Bu_and_U(&Bu, U, Ubuf, a, Umsg, 3);
if (memcmp(U, calculateu_correct_output, 32) != 0)
ERROR("calculate_U BAD!!!")
else
INFO("calculate_U good");
return 0;
}
int curvesigs_fast_test(int silent)
{
unsigned char signature_correct[64] = {
0xcf, 0x87, 0x3d, 0x03, 0x79, 0xac, 0x20, 0xe8,
0x89, 0x3e, 0x55, 0x67, 0xee, 0x0f, 0x89, 0x51,
0xf8, 0xdb, 0x84, 0x0d, 0x26, 0xb2, 0x43, 0xb4,
0x63, 0x52, 0x66, 0x89, 0xd0, 0x1c, 0xa7, 0x18,
0xac, 0x18, 0x9f, 0xb1, 0x67, 0x85, 0x74, 0xeb,
0xdd, 0xe5, 0x69, 0x33, 0x06, 0x59, 0x44, 0x8b,
0x0b, 0xd6, 0xc1, 0x97, 0x3f, 0x7d, 0x78, 0x0a,
0xb3, 0x95, 0x18, 0x62, 0x68, 0x03, 0xd7, 0x82,
};
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[64];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 0, 64);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
privkey[8] = 189; /* just so there's some bits set */
sc_clamp(privkey);
/* Signature vector test */
curve25519_keygen(pubkey, privkey);
curve25519_sign(signature, privkey, msg, MSG_LEN, random);
if (memcmp(signature, signature_correct, 64) != 0)
ERROR("Curvesig incorrect - BAD")
else
INFO("Curvesig correct - good");
if (curve25519_verify(signature, pubkey, msg, MSG_LEN) == 0)
INFO("Curvesig #1 verified - good")
else
ERROR("Curvesig #1 didn't verify - BAD");
signature[0] ^= 1;
if (curve25519_verify(signature, pubkey, msg, MSG_LEN) == 0)
ERROR("Curvesig #2 verified - BAD")
else
INFO("Curvesig #2 didn't verify - good");
return 0;
}
int xdsa_fast_test(int silent)
{
unsigned char signature_correct[64] = {
0x11, 0xc7, 0xf3, 0xe6, 0xc4, 0xdf, 0x9e, 0x8a,
0x51, 0x50, 0xe1, 0xdb, 0x3b, 0x30, 0xf9, 0x2d,
0xe3, 0xa3, 0xb3, 0xaa, 0x43, 0x86, 0x56, 0x54,
0x5f, 0xa7, 0x39, 0x0f, 0x4b, 0xcc, 0x7b, 0xb2,
0x6c, 0x43, 0x1d, 0x9e, 0x90, 0x64, 0x3e, 0x4f,
0x0e, 0xaa, 0x0e, 0x9c, 0x55, 0x77, 0x66, 0xfa,
0x69, 0xad, 0xa5, 0x76, 0xd6, 0x3d, 0xca, 0xf2,
0xac, 0x32, 0x6c, 0x11, 0xd0, 0xb9, 0x77, 0x02,
};
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[64];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 0, 64);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
privkey[8] = 189; /* just so there's some bits set */
sc_clamp(privkey);
/* Signature vector test */
curve25519_keygen(pubkey, privkey);
xdsa_sign(signature, privkey, msg, MSG_LEN, random);
if (memcmp(signature, signature_correct, 64) != 0)
ERROR("XDSA incorrect - BAD")
else
INFO("XDSA correct - good");
if (xdsa_verify(signature, pubkey, msg, MSG_LEN) == 0)
INFO("XDSA #1 verified - good")
else
ERROR("XDSA #1 didn't verify - BAD");
signature[0] ^= 1;
if (xdsa_verify(signature, pubkey, msg, MSG_LEN) == 0)
ERROR("XDSA #2 verified - BAD")
else
INFO("XDSA #2 didn't verify - good");
return 0;
}
int uxdsa_fast_test(int silent)
{
unsigned char signature_correct[96] = {
0x66, 0x51, 0x0b, 0x68, 0x9e, 0xb7, 0xd8, 0x55,
0x04, 0x62, 0xaf, 0x52, 0x0c, 0x89, 0x69, 0xe8,
0xa9, 0xa5, 0x3d, 0xf3, 0x8e, 0xd6, 0xe6, 0x0f,
0xe8, 0xfe, 0xd6, 0xa8, 0x95, 0x66, 0x9c, 0x19,
0x66, 0x4a, 0x65, 0x25, 0xff, 0xb7, 0x47, 0x74,
0x8e, 0x86, 0x40, 0x55, 0x0f, 0xb1, 0x4a, 0xd1,
0x6d, 0xe0, 0x3d, 0x51, 0xa2, 0xd3, 0x4d, 0xee,
0x64, 0x7e, 0x35, 0x98, 0x42, 0x25, 0x5a, 0x02,
0xf8, 0x8c, 0x1e, 0x23, 0x5b, 0xd5, 0x7f, 0xb9,
0x98, 0x60, 0x55, 0x63, 0xd6, 0xe0, 0x6d, 0xa1,
0x29, 0xd9, 0xfc, 0xee, 0x1c, 0x08, 0x6d, 0x5a,
0x28, 0xa1, 0x27, 0xf0, 0x06, 0xb9, 0x79, 0x03
};
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[96];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 0, 96);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
privkey[8] = 189; /* just so there's some bits set */
sc_clamp(privkey);
/* Signature vector test */
curve25519_keygen(pubkey, privkey);
uxdsa_sign(signature, privkey, msg, MSG_LEN, random);
if (memcmp(signature, signature_correct, 96) != 0)
ERROR("UXDSA incorrect - BAD")
else
INFO("UXDSA correct - good");
if (uxdsa_verify(signature, pubkey, msg, MSG_LEN) == 0)
INFO("UXDSA #1 verified - good")
else
ERROR("UXDSA #1 didn't verify - BAD");
signature[0] ^= 1;
if (uxdsa_verify(signature, pubkey, msg, MSG_LEN) == 0)
ERROR("UXDSA #2 verified - BAD")
else
INFO("UXDSA #2 didn't verify - good");
/* Test U */
unsigned char sigprev[96];
memcpy(sigprev, signature, 96);
sigprev[0] ^= 1; /* undo prev disturbance */
random[0] ^= 1;
uxdsa_sign(signature, privkey, msg, MSG_LEN, random);
if (memcmp(signature, sigprev, 32) != 0)
ERROR("UXDSA U value changed - BAD")
else
INFO("UXDSA U value constant - good");
if (memcmp(signature+32, sigprev+32, 64) == 0)
ERROR("UXDSA (h, s) values didn't change - BAD")
else
INFO("UXDSA (h, s) values changed - good");
return 0;
}
int curvesigs_slow_test(int silent, int iterations)
{
unsigned char signature_10k_correct[64] = {
0xfc, 0xba, 0x55, 0xc4, 0x85, 0x4a, 0x42, 0x25,
0x19, 0xab, 0x08, 0x8d, 0xfe, 0xb5, 0x13, 0xb6,
0x0d, 0x24, 0xbb, 0x16, 0x27, 0x55, 0x71, 0x48,
0xdd, 0x20, 0xb1, 0xcd, 0x2a, 0xd6, 0x7e, 0x35,
0xef, 0x33, 0x4c, 0x7b, 0x6d, 0x94, 0x6f, 0x52,
0xec, 0x43, 0xd7, 0xe6, 0x35, 0x24, 0xcd, 0x5b,
0x5d, 0xdc, 0xb2, 0x32, 0xc6, 0x22, 0x53, 0xf3,
0x38, 0x02, 0xf8, 0x28, 0x28, 0xc5, 0x65, 0x05,
};
int count;
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[64];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 0, 64);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
/* Signature random test */
INFO("Pseudorandom curvesigs...");
for (count = 1; count <= iterations; count++) {
unsigned char b[64];
crypto_hash_sha512(b, signature, 64);
memmove(privkey, b, 32);
crypto_hash_sha512(b, privkey, 32);
memmove(random, b, 64);
sc_clamp(privkey);
curve25519_keygen(pubkey, privkey);
curve25519_sign(signature, privkey, msg, MSG_LEN, random);
if (curve25519_verify(signature, pubkey, msg, MSG_LEN) != 0)
ERROR("Curvesig verify failure #1");
if (b[63] & 1)
signature[count % 64] ^= 1;
else
msg[count % MSG_LEN] ^= 1;
if (curve25519_verify(signature, pubkey, msg, MSG_LEN) == 0)
ERROR("Curvesig verify failure #2");
if (count == 10000) {
if (memcmp(signature, signature_10k_correct, 64) != 0)
ERROR("Curvesig signature 10K doesn't match");
}
}
INFO("good");
return 1;
}
int xdsa_slow_test(int silent, int iterations)
{
unsigned char signature_10k_correct[64] = {
0x15, 0x29, 0x03, 0x38, 0x66, 0x16, 0xcd, 0x26,
0xbb, 0x3e, 0xec, 0xe2, 0x9f, 0x72, 0xa2, 0x5c,
0x7d, 0x05, 0xc9, 0xcb, 0x84, 0x3f, 0x92, 0x96,
0xb3, 0xfb, 0xb9, 0xdd, 0xd6, 0xed, 0x99, 0x04,
0xc1, 0xa8, 0x02, 0x16, 0xcf, 0x49, 0x3f, 0xf1,
0xbe, 0x69, 0xf9, 0xf1, 0xcc, 0x16, 0xd7, 0xdc,
0x6e, 0xd3, 0x78, 0xaa, 0x04, 0xeb, 0x71, 0x51,
0x9d, 0xe8, 0x7a, 0x5b, 0xd8, 0x49, 0x7b, 0x05,
};
int count;
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[96];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 1, 64);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
/* Signature random test */
INFO("Pseudorandom XDSA...");
for (count = 1; count <= iterations; count++) {
unsigned char b[64];
crypto_hash_sha512(b, signature, 64);
memmove(privkey, b, 32);
crypto_hash_sha512(b, privkey, 32);
memmove(random, b, 64);
sc_clamp(privkey);
curve25519_keygen(pubkey, privkey);
xdsa_sign(signature, privkey, msg, MSG_LEN, random);
if (xdsa_verify(signature, pubkey, msg, MSG_LEN) != 0)
ERROR("XDSA verify failure #1");
if (b[63] & 1)
signature[count % 64] ^= 1;
else
msg[count % MSG_LEN] ^= 1;
if (xdsa_verify(signature, pubkey, msg, MSG_LEN) == 0)
ERROR("XDSA verify failure #2");
if (count == 10000) {
if (memcmp(signature, signature_10k_correct, 64) != 0)
ERROR("XDSA signature 10K doesn't match");
}
}
INFO("good");
return 1;
}
int xdsa_to_curvesigs_slow_test(int silent, int iterations)
{
unsigned char signature_10k_correct[64] = {
0x33, 0x50, 0xa8, 0x68, 0xcd, 0x9e, 0x74, 0x99,
0xa3, 0x5c, 0x33, 0x75, 0x2b, 0x22, 0x03, 0xf8,
0xb5, 0x0f, 0xea, 0x8c, 0x33, 0x1c, 0x68, 0x8b,
0xbb, 0xf3, 0x31, 0xcf, 0x7c, 0x42, 0x37, 0x35,
0xa0, 0x0e, 0x15, 0xb8, 0x5d, 0x2b, 0xe1, 0xa2,
0x03, 0x77, 0x94, 0x3d, 0x13, 0x5c, 0xd4, 0x9b,
0x6a, 0x31, 0xf4, 0xdc, 0xfe, 0x24, 0xad, 0x54,
0xeb, 0xd2, 0x98, 0x47, 0xf1, 0xcc, 0xbf, 0x0d
};
int count;
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[96];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 2, 64);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
/* Signature random test */
INFO("Pseudorandom XDSA/Curvesigs...");
for (count = 1; count <= iterations; count++) {
unsigned char b[64];
crypto_hash_sha512(b, signature, 64);
memmove(privkey, b, 32);
crypto_hash_sha512(b, privkey, 32);
memmove(random, b, 64);
sc_clamp(privkey);
curve25519_keygen(pubkey, privkey);
xdsa_sign(signature, privkey, msg, MSG_LEN, random);
if (curve25519_verify(signature, pubkey, msg, MSG_LEN) != 0)
ERROR("XDSA/Curvesigs verify failure #1");
if (b[63] & 1)
signature[count % 64] ^= 1;
else
msg[count % MSG_LEN] ^= 1;
if (curve25519_verify(signature, pubkey, msg, MSG_LEN) == 0)
ERROR("XDSA/Curvesigs verify failure #2");
if (count == 10000) {
if (memcmp(signature, signature_10k_correct, 64) != 0)
ERROR("XDSA/Curvesigs signature 10K doesn't match");
}
}
INFO("good");
return 1;
}
int uxdsa_slow_test(int silent, int iterations)
{
unsigned char signature_10k_correct[96] = {
0x2d, 0x2a, 0x69, 0x20, 0x0a, 0xe7, 0x76, 0xeb,
0x08, 0xc0, 0x3b, 0x4f, 0x26, 0x82, 0xd5, 0x3c,
0x97, 0xc6, 0xb7, 0x9c, 0x6a, 0xf6, 0x24, 0x91,
0xe1, 0xf9, 0x8f, 0x4f, 0x23, 0xc4, 0xba, 0x28,
0x4b, 0x60, 0x87, 0x07, 0xe5, 0x94, 0xcb, 0xda,
0x1b, 0x03, 0x5a, 0xd4, 0xd0, 0x6d, 0xd9, 0xa0,
0x6a, 0x07, 0xee, 0x7b, 0x98, 0x7c, 0xe1, 0xc4,
0x91, 0x52, 0x0d, 0x08, 0x32, 0xd7, 0x10, 0x03,
0xbd, 0x96, 0x34, 0x11, 0x0c, 0x44, 0x56, 0x95,
0x8b, 0x87, 0xdb, 0x12, 0x97, 0xa9, 0x5a, 0x62,
0x2a, 0x34, 0xb1, 0xb1, 0xe2, 0xb4, 0xf5, 0x3c,
0x34, 0xb6, 0x69, 0x0b, 0x77, 0x0e, 0x49, 0x07,
};
int count;
unsigned char privkey[32];
unsigned char pubkey[32];
unsigned char signature[96];
unsigned char msg[MSG_LEN];
unsigned char random[64];
memset(privkey, 0, 32);
memset(pubkey, 0, 32);
memset(signature, 3, 96);
memset(msg, 0, MSG_LEN);
memset(random, 0, 64);
INFO("Pseudorandom UXDSA...");
for (count = 1; count <= iterations; count++) {
unsigned char b[64];
crypto_hash_sha512(b, signature, 96);
memmove(privkey, b, 32);
crypto_hash_sha512(b, privkey, 32);
memmove(random, b, 64);
sc_clamp(privkey);
curve25519_keygen(pubkey, privkey);
uxdsa_sign(signature, privkey, msg, MSG_LEN, random);
if (uxdsa_verify(signature, pubkey, msg, MSG_LEN) != 0)
ERROR("UXDSA verify failure #1");
if (b[63] & 1)
signature[count % 96] ^= 1;
else
msg[count % MSG_LEN] ^= 1;
if (uxdsa_verify(signature, pubkey, msg, MSG_LEN) == 0)
ERROR("UXDSA verify failure #2");
if (count == 10000) {
if (memcmp(signature, signature_10k_correct, 96) != 0)
ERROR("UXDSA 10K doesn't match");
}
}
INFO("good");
return 1;
}
int all_fast_tests(int silent)
{
int result;
if ((result = sha512_fast_test(silent)) != 0)
return result;
if ((result = elligator_fast_test(silent)) != 0)
return result;
if ((result = curvesigs_fast_test(silent)) != 0)
return result;
if ((result = xdsa_fast_test(silent)) != 0)
return result;
if ((result = uxdsa_fast_test(silent)) != 0)
return result;
return 0;
}

View File

@ -0,0 +1,22 @@
#ifndef __TESTS_H__
#define __TESTS_H__
/* silent = 0 : prints info+error messages to stdout, abort() on test failure
* silent = 1 : returns 0 for success, anything else for failure
* iterations : hardcoded known-good values are at 10000, so run at least this many
*/
int sha512_fast_test(int silent);
int elligator_fast_test(int silent);
int curvesigs_fast_test(int silent);
int xdsa_fast_test(int silent);
int uxdsa_fast_test(int silent);
int curvesigs_slow_test(int silent, int iterations);
int xdsa_slow_test(int silent, int iterations);
int xdsa_to_curvesigs_slow_test(int silent, int iterations);
int uxdsa_slow_test(int silent, int iterations);
int all_fast_tests(int silent);
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -5,12 +5,4 @@ public class NativeCurve25519ProviderTest extends Curve25519ProviderTest {
protected Curve25519Provider createProvider() throws NoSuchProviderException {
return new NativeCurve25519Provider();
}
private native boolean internalTest();
public void testInternalTest() throws Exception {
assertTrue(internalTest());
}
}

View File

@ -1,16 +1,7 @@
package org.whispersystems.curve25519;
import java.util.Arrays;
import java.util.Random;
public class NativeCurve25519Test extends Curve25519Test {
private final byte[] PUBLIC_KEY = new byte[]{(byte) 0x21, (byte) 0xf7, (byte) 0x34, (byte) 0x5f, (byte) 0x56, (byte) 0xd9, (byte) 0x60, (byte) 0x2f, (byte) 0x15, (byte) 0x23, (byte) 0x29, (byte) 0x8f, (byte) 0x4f, (byte) 0x6f, (byte) 0xce, (byte) 0xcb, (byte) 0x14, (byte) 0xdd, (byte) 0xe2, (byte) 0xd5, (byte) 0xb9, (byte) 0xa9, (byte) 0xb4, (byte) 0x8b, (byte) 0xca, (byte) 0x82, (byte) 0x42, (byte) 0x68, (byte) 0x14, (byte) 0x92, (byte) 0xb9, (byte) 0x20};
private final byte[] PRIVATE_KEY = new byte[]{(byte) 0x38, (byte) 0x61, (byte) 0x1d, (byte) 0x25, (byte) 0x3b, (byte) 0xea, (byte) 0x85, (byte) 0xa2, (byte) 0x03, (byte) 0x80, (byte) 0x53, (byte) 0x43, (byte) 0xb7, (byte) 0x4a, (byte) 0x93, (byte) 0x6d, (byte) 0x3b, (byte) 0x13, (byte) 0xb9, (byte) 0xe3, (byte) 0x12, (byte) 0x14, (byte) 0x53, (byte) 0xe9, (byte) 0x74, (byte) 0x0b, (byte) 0x6b, (byte) 0x82, (byte) 0x7e, (byte) 0x33, (byte) 0x7e, (byte) 0x5d};
private final byte[] MESSAGE = new byte[]{(byte) 0x54, (byte) 0x68, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x75, (byte) 0x6e, (byte) 0x69, (byte) 0x71, (byte) 0x75, (byte) 0x65, (byte) 0x2e};
private final byte[] VRF = new byte[]{(byte) 0x45, (byte) 0xdc, (byte) 0x7b, (byte) 0x81, (byte) 0x6b, (byte) 0x01, (byte) 0xb3, (byte) 0x6c, (byte) 0xfa, (byte) 0x16, (byte) 0x45, (byte) 0xdc, (byte) 0xae, (byte) 0x8a, (byte) 0xc9, (byte) 0xbc, (byte) 0x8e, (byte) 0x52, (byte) 0x3c, (byte) 0xd8, (byte) 0x6d, (byte) 0x00, (byte) 0x7d, (byte) 0x19, (byte) 0x95, (byte) 0x3f, (byte) 0x03, (byte) 0xe7, (byte) 0xd5, (byte) 0x45, (byte) 0x54, (byte) 0xa0};
@Override
public void testCheckProvider() throws NoSuchProviderException {
assertTrue(Curve25519.getInstance(getProviderName()).isNative());
@ -21,37 +12,4 @@ public class NativeCurve25519Test extends Curve25519Test {
return "native";
}
public void testUniqueSignatures() throws Exception {
Curve25519KeyPair keys = getInstance().generateKeyPair();
Random random = new Random(System.currentTimeMillis());
for (int i=1;i<=256;i++) {
byte[] message = new byte[i];
random.nextBytes(message);
byte[] signature = getInstance().calculateVrfSignature(keys.getPrivateKey(), message);
byte[] vrf = getInstance().verifyVrfSignature(keys.getPublicKey(), message, signature);
assertFalse(getInstance().verifySignature(keys.getPublicKey(), message, signature));
message[Math.abs(random.nextInt()) % message.length] ^= 0x01;
try {
getInstance().verifyVrfSignature(keys.getPublicKey(), message, signature);
throw new AssertionError("Should have failed");
} catch (VrfSignatureVerificationFailedException e) {
// good
}
}
}
public void testUniqueSignatureVector() throws Exception {
Curve25519KeyPair keys = new Curve25519KeyPair(PUBLIC_KEY, PRIVATE_KEY);
byte[] signature = getInstance().calculateVrfSignature(keys.getPrivateKey(), MESSAGE);
byte[] vrf = getInstance().verifyVrfSignature(keys.getPublicKey(), MESSAGE, signature);
assertTrue(Arrays.equals(vrf, VRF));
}
}

View File

@ -1,4 +1,4 @@
subprojects {
ext.version_number = "0.5.0"
ext.version_number = "0.2.5-RC1"
ext.group_info = "org.whispersystems"
}

View File

@ -73,13 +73,11 @@ abstract class BaseJavaCurve25519Provider implements Curve25519Provider {
return curve_sigs.curve25519_verify(sha512provider, signature, publicKey, message, message.length) == 0;
}
public byte[] calculateVrfSignature(byte[] random, byte[] privateKey, byte[] message) {
public byte[] calculateUniqueSignature(byte[] random, byte[] privateKey, byte[] message) {
throw new AssertionError("NYI");
}
public byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature)
throws VrfSignatureVerificationFailedException
{
public boolean verifyUniqueSignature(byte[] publicKey, byte[] message, byte[] signature) {
throw new AssertionError("NYI");
}

View File

@ -70,14 +70,6 @@ public class Curve25519 {
* @return A 32-byte shared secret.
*/
public byte[] calculateAgreement(byte[] publicKey, byte[] privateKey) {
if (publicKey == null || privateKey == null) {
throw new IllegalArgumentException("Keys must not be null!");
}
if (publicKey.length != 32 || privateKey.length != 32) {
throw new IllegalArgumentException("Keys must be 32 bytes!");
}
return provider.calculateAgreement(privateKey, publicKey);
}
@ -89,10 +81,6 @@ public class Curve25519 {
* @return A 64-byte signature.
*/
public byte[] calculateSignature(byte[] privateKey, byte[] message) {
if (privateKey == null || privateKey.length != 32) {
throw new IllegalArgumentException("Invalid private key length!");
}
byte[] random = provider.getRandom(64);
return provider.calculateSignature(random, privateKey, message);
}
@ -106,56 +94,9 @@ public class Curve25519 {
* @return true if valid, false if not.
*/
public boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature) {
if (publicKey == null || publicKey.length != 32) {
throw new IllegalArgumentException("Invalid public key!");
}
if (message == null || signature == null || signature.length != 64) {
return false;
}
return provider.verifySignature(publicKey, message, signature);
}
/**
* Calculates a Unique Curve25519 signature.
*
* @param privateKey The private Curve25519 key to create the signature with.
* @param message The message to sign.
* @return A 96-byte signature.
*/
public byte[] calculateVrfSignature(byte[] privateKey, byte[] message) {
if (privateKey == null || privateKey.length != 32) {
throw new IllegalArgumentException("Invalid private key!");
}
byte[] random = provider.getRandom(64);
return provider.calculateVrfSignature(random, privateKey, message);
}
/**
* Verify a Unique Curve25519 signature.
*
* @param publicKey The Curve25519 public key the unique signature belongs to.
* @param message The message that was signed.
* @param signature The unique signature to verify.
*
* @return The vrf for this signature.
*/
public byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature)
throws VrfSignatureVerificationFailedException
{
if (publicKey == null || publicKey.length != 32) {
throw new IllegalArgumentException("Invalid public key!");
}
if (message == null || signature == null || signature.length != 96) {
throw new VrfSignatureVerificationFailedException("Invalid message or signature format");
}
return provider.verifyVrfSignature(publicKey, message, signature);
}
private static Curve25519Provider constructNativeProvider(SecureRandomProvider random) throws NoSuchProviderException {
return constructClass("NativeCurve25519Provider", random);
}

View File

@ -18,9 +18,8 @@ interface Curve25519Provider {
byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message);
boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature);
byte[] calculateVrfSignature(byte[] random, byte[] privateKey, byte[] message);
byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature)
throws VrfSignatureVerificationFailedException;
byte[] calculateUniqueSignature(byte[] random, byte[] privateKey, byte[] message);
boolean verifyUniqueSignature(byte[] publicKey, byte[] message, byte[] signature);
byte[] getRandom(int length);

View File

@ -1,16 +0,0 @@
package org.whispersystems.curve25519;
public class VrfSignatureVerificationFailedException extends Exception {
public VrfSignatureVerificationFailedException() {
super();
}
public VrfSignatureVerificationFailedException(String message) {
super(message);
}
public VrfSignatureVerificationFailedException(Exception exception) {
super(exception);
}
}

View File

@ -6,6 +6,7 @@ public class curve_sigs {
byte[] curve25519_privkey_in)
{
ge_p3 ed = new ge_p3(); /* Ed25519 pubkey point */
int[] ed_y = new int[10];
int[] ed_y_plus_one = new int[10];
int[] one_minus_ed_y = new int[10];
int[] inv_one_minus_ed_y = new int[10];

View File

@ -37,7 +37,7 @@ Can get away with 11 carries, but then data flow is much deeper.
With tighter constraints on inputs can squeeze carries into int32.
*/
public static long[] fe_mul1(int[] f,int[] g)
public static void fe_mul(int[] h,int[] f,int[] g)
{
int f0 = f[0];
int f1 = f[1];
@ -173,36 +173,16 @@ public static long[] fe_mul1(int[] f,int[] g)
long f9g7_38 = f9_2 * (long) g7_19;
long f9g8_19 = f9 * (long) g8_19;
long f9g9_38 = f9_2 * (long) g9_19;
long h[] = new long[10];
h[0] = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38;
h[1] = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19;
h[2] = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38;
h[3] = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19;
h[4] = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38;
h[5] = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19;
h[6] = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38;
h[7] = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19;
h[8] = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38;
h[9] = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ;
return h;
}
public static void fe_mul(int[] h,int[] f,int[] g)
{
long[] hr = fe_mul1(f, g);
long h0 = hr[0];
long h1 = hr[1];
long h2 = hr[2];
long h3 = hr[3];
long h4 = hr[4];
long h5 = hr[5];
long h6 = hr[6];
long h7 = hr[7];
long h8 = hr[8];
long h9 = hr[9];
long h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38;
long h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19;
long h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38;
long h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19;
long h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38;
long h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19;
long h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38;
long h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19;
long h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38;
long h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ;
long carry0;
long carry1;
long carry2;

View File

@ -1,6 +1,6 @@
#Mon Oct 17 15:10:52 PDT 2016
#Tue Jan 06 14:11:31 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

View File

@ -1,4 +1,4 @@
/*
/**
* Copyright (C) 2014-2016 Open Whisper Systems
*
* Licensed according to the LICENSE file in this repository.
@ -6,17 +6,28 @@
package org.whispersystems.curve25519;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class JCESecureRandomProvider implements SecureRandomProvider {
@Override
public void nextBytes(byte[] output) {
new SecureRandom().nextBytes(output);
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.nextBytes(output);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
@Override
public int nextInt(int maxValue) {
return new SecureRandom().nextInt(maxValue);
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
return secureRandom.nextInt(maxValue);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
}

View File

@ -73,11 +73,10 @@ class NativeCurve25519Provider implements Curve25519Provider {
public native boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature);
@Override
public native byte[] calculateVrfSignature(byte[] random, byte[] privateKey, byte[] message);
public native byte[] calculateUniqueSignature(byte[] random, byte[] privateKey, byte[] message);
@Override
public native byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature)
throws VrfSignatureVerificationFailedException;
public native boolean verifyUniqueSignature(byte[] publicKey, byte[] message, byte[] signature);
private native boolean smokeCheck(int dummy);

View File

@ -64,15 +64,13 @@ public class OpportunisticCurve25519Provider implements Curve25519Provider {
}
@Override
public byte[] calculateVrfSignature(byte[] random, byte[] privateKey, byte[] message) {
return delegate.calculateVrfSignature(random, privateKey, message);
public byte[] calculateUniqueSignature(byte[] random, byte[] privateKey, byte[] message) {
return delegate.calculateUniqueSignature(random, privateKey, message);
}
@Override
public byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature)
throws VrfSignatureVerificationFailedException
{
return delegate.verifyVrfSignature(publicKey, message, signature);
public boolean verifyUniqueSignature(byte[] publicKey, byte[] message, byte[] signature) {
return delegate.verifyUniqueSignature(publicKey, message, signature);
}
}