Browse Source

rfc7748 implementation, but their names will probably change

master
Michael Hamburg 8 years ago
parent
commit
2eacff6ad6
10 changed files with 398 additions and 23 deletions
  1. +116
    -0
      src/decaf.c
  2. +14
    -0
      src/decaf_gen_tables.c
  3. +10
    -1
      src/gen_headers/curve_data.py
  4. +39
    -0
      src/gen_headers/decaf_h.py
  5. +61
    -3
      src/gen_headers/decaf_hxx.py
  6. +6
    -1
      src/gen_headers/f_field_h.py
  7. +10
    -4
      src/public_include/decaf/spongerng.hxx
  8. +17
    -7
      test/bench_decaf.cxx
  9. +4
    -0
      test/test_ct.cxx
  10. +121
    -7
      test/test_decaf.cxx

+ 116
- 0
src/decaf.c View File

@@ -1580,6 +1580,122 @@ decaf_error_t API_NS(direct_scalarmul) (
return succ;
}

decaf_error_t API_NS(x_direct_scalarmul) (
uint8_t out[X_PUBLIC_BYTES],
const uint8_t base[X_PUBLIC_BYTES],
const uint8_t scalar[X_PRIVATE_BYTES]
) {
gf x1, x2, z2, x3, z3, t1, t2;
ignore_result(gf_deserialize(x1,base));
gf_copy(x2,ONE);
gf_copy(z2,ZERO);
gf_copy(x3,x1);
gf_copy(z3,ONE);
int t;
mask_t swap = 0;
for (t = X_PRIVATE_BITS-1; t>=0; t--) {
uint8_t sb = scalar[t/8];
/* Scalar conditioning */
if (t/8==0) sb &= -(uint8_t)COFACTOR;
else if (t == X_PRIVATE_BITS-1) sb = -1;
mask_t k_t = (sb>>(t%8)) & 1;
k_t = -k_t; /* set to all 0s or all 1s */
swap ^= k_t;
cond_swap(x2,x3,swap);
cond_swap(z2,z3,swap);
swap = k_t;
gf_add(t1,x2,z2); /* A = x2 + z2 */
gf_sub(t2,x2,z2); /* B = x2 - z2 */
gf_sub(z2,x3,z3); /* D = x3 - z3 */
gf_mul(x2,t1,z2); /* DA */
gf_add(z2,z3,x3); /* C = x3 + z3 */
gf_mul(x3,t2,z2); /* CB */
gf_sub(z3,x2,x3); /* DA-CB */
gf_sqr(z2,z3); /* (DA-CB)^2 */
gf_mul(z3,x1,z2); /* z3 = x1(DA-CB)^2 */
gf_add(z2,x2,x3); /* (DA+CB) */
gf_sqr(x3,z2); /* x3 = (DA+CB)^2 */
gf_sqr(z2,t1); /* AA = A^2 */
gf_sqr(t1,t2); /* BB = B^2 */
gf_mul(x2,z2,t1); /* x2 = AA*BB */
gf_sub(t2,z2,t1); /* E = AA-BB */
gf_mulw_sgn(t1,t2,-EDWARDS_D); /* E*-d = a24*E */
gf_add(t1,t1,z2); /* AA + a24*E */
gf_mul(z2,t2,t1); /* z2 = E(AA+a24*E) */
}
/* Finish */
cond_swap(x2,x3,swap);
cond_swap(z2,z3,swap);
gf_invert(z2,z2);
gf_mul(x1,x2,z2);
gf_serialize(out,x1);
mask_t nz = ~gf_eq(x1,ZERO);
decaf_bzero(x1,sizeof(x1));
decaf_bzero(x2,sizeof(x2));
decaf_bzero(z2,sizeof(z2));
decaf_bzero(x3,sizeof(x3));
decaf_bzero(z3,sizeof(z3));
decaf_bzero(t1,sizeof(t1));
decaf_bzero(t2,sizeof(t2));
return decaf_succeed_if(mask_to_bool(nz));
}

void API_NS(x_base_scalarmul) (
uint8_t out[X_PUBLIC_BYTES],
const uint8_t scalar[X_PRIVATE_BYTES]
) {
/* Scalar conditioning */
uint8_t scalar2[X_PRIVATE_BYTES];
memcpy(scalar2,scalar,sizeof(scalar2));
scalar2[0] &= -(uint8_t)COFACTOR;
scalar2[X_PRIVATE_BYTES-1] &= ~(-1<<((X_PRIVATE_BITS+7)%8));
scalar2[X_PRIVATE_BYTES-1] |= 1<<((X_PRIVATE_BITS+7)%8);
scalar_t the_scalar;
API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2));
/* We're gonna isogenize by 2, so divide by 2.
*
* Why by 2, even though it's a 4-isogeny?
*
* The isogeny map looks like
* Montgomery <-2-> Jacobi <-2-> Edwards
*
* Since the Jacobi base point is the PREimage of the iso to
* the Montgomery curve, and we're going
* Jacobi -> Edwards -> Jacobi -> Montgomery,
* we pick up only a factor of 2 over Jacobi -> Montgomery.
*/
sc_halve(the_scalar,the_scalar,sc_p);
point_t p;
API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),the_scalar);
/* Isogenize to Montgomery curve */
gf_invert(p->t,p->x); /* 1/x */
gf_mul(p->z,p->t,p->y); /* y/x */
gf_sqr(p->y,p->z); /* (y/x)^2 */
#if IMAGINE_TWIST
gf_sub(p->y,ZERO,p->y);
#endif
gf_serialize(out,p->y);
decaf_bzero(scalar2,sizeof(scalar2));
API_NS(scalar_destroy)(the_scalar);
API_NS(point_destroy)(p);
}

/**
* @cond internal
* Control for variable-time scalar multiply algorithms.


+ 14
- 0
src/decaf_gen_tables.c View File

@@ -28,6 +28,7 @@ const API_NS(scalar_t) API_NS(sc_r2) = {{{0}}};
const decaf_word_t API_NS(MONTGOMERY_FACTOR) = 0;

const API_NS(point_t) API_NS(point_base);
const uint8_t API_NS(x_base_point)[X_PUBLIC_BYTES] = {0};

struct niels_s;
const gf_s *API_NS(precomputed_wnaf_as_fe);
@@ -170,6 +171,19 @@ int main(int argc, char **argv) {
w *= w*plo + 2;
}
printf("const decaf_word_t API_NS(MONTGOMERY_FACTOR) = (decaf_word_t)0x%016llxull;\n\n", w);

/* Generate the Montgomery ladder version of the base point */
gf base1,base2;
ret = gf_deserialize(base1,base_point_ser_for_pregen);
if (ret != DECAF_SUCCESS) return 1;
gf_sqr(base2,base1);
uint8_t x_ser[X_PUBLIC_BYTES] = {0};
gf_serialize(x_ser, base2);
printf("const uint8_t API_NS(x_base_point)[%d] = {", X_PUBLIC_BYTES);
for (i=0; i<X_PUBLIC_BYTES; i++) {
printf("%s%s%d",i?",":"",(i%32==0)?"\n ":"",x_ser[i]);
}
printf("\n};\n");
return 0;
}

+ 10
- 1
src/gen_headers/curve_data.py View File

@@ -49,6 +49,15 @@ def ceil_log2(x):
for field,data in field_data.iteritems():
if "gf_bits" not in data:
data["gf_bits"] = ceil_log2(data["modulus"])
if "x_pub_bytes" not in data:
data["x_pub_bytes"] = (data["gf_bits"]-1)//8 + 1
if "x_priv_bytes" not in data:
data["x_priv_bytes"] = (data["gf_bits"]-1)//8 + 1
if "x_priv_bits" not in data:
data["x_priv_bits"] = ceil_log2(data["modulus"]*0.99)

for curve,data in curve_data.iteritems():
for key in field_data[data["field"]]:
@@ -66,7 +75,7 @@ for curve,data in curve_data.iteritems():
data["bits"] = ceil_log2(data["modulus"])
if "ser_bytes" not in data:
data["ser_bytes"] = (data["bits"]-1)//8 + 1
data["ser_bytes"] = (data["bits"]-2)//8 + 1
if "scalar_ser_bytes" not in data:
data["scalar_ser_bytes"] = (data["scalar_bits"]-1)//8 + 1


+ 39
- 0
src/gen_headers/decaf_h.py View File

@@ -35,6 +35,12 @@ typedef struct gf_%(gf_shortname)s_s {
/** Number of bytes in a serialized scalar. */
#define %(C_NS)s_SCALAR_BYTES %(scalar_ser_bytes)d

/** Number of bytes in an x%(gf_shortname)s public key */
#define X%(gf_shortname)s_PUBLIC_BYTES %(x_pub_bytes)d

/** Number of bytes in an x%(gf_shortname)s private key */
#define X%(gf_shortname)s_PRIVATE_BYTES %(x_priv_bytes)d

/** Twisted Edwards extended homogeneous coordinates */
typedef struct %(c_ns)s_point_s {
/** @cond internal */
@@ -346,6 +352,39 @@ decaf_error_t %(c_ns)s_direct_scalarmul (
decaf_bool_t short_circuit
) API_VIS NONNULL3 WARN_UNUSED NOINLINE;

/**
* @brief RFC 7748 Diffie-Hellman scalarmul. This function uses a different
* (non-Decaf) encoding.
*
* @param [out] scaled The scaled point base*scalar
* @param [in] base The point to be scaled.
* @param [in] scalar The scalar to multiply by.
*
* @retval DECAF_SUCCESS The scalarmul succeeded.
* @retval DECAF_FAILURE The scalarmul didn't succeed, because the base
* point is in a small subgroup.
*/
decaf_error_t %(c_ns)s_x_direct_scalarmul ( /* TODO: rename? */
uint8_t out[X%(gf_shortname)s_PUBLIC_BYTES],
const uint8_t base[X%(gf_shortname)s_PUBLIC_BYTES],
const uint8_t scalar[X%(gf_shortname)s_PRIVATE_BYTES]
) API_VIS NONNULL3 WARN_UNUSED NOINLINE;

/** The base point for X%(gf_shortname)s Diffie-Hellman */
extern const uint8_t %(c_ns)s_x_base_point[X%(gf_shortname)s_PUBLIC_BYTES] API_VIS;

/**
* @brief RFC 7748 Diffie-Hellman base point scalarmul. This function uses
* a different (non-Decaf) encoding.
*
* @param [out] scaled The scaled point base*scalar
* @param [in] scalar The scalar to multiply by.
*/
void %(c_ns)s_x_base_scalarmul (
uint8_t out[X%(gf_shortname)s_PUBLIC_BYTES],
const uint8_t scalar[X%(gf_shortname)s_PRIVATE_BYTES]
) API_VIS NONNULL2 NOINLINE;

/**
* @brief Precompute a table for fast scalar multiplication.
* Some implementations do not include precomputed points; for


+ 61
- 3
src/gen_headers/decaf_hxx.py View File

@@ -136,7 +136,7 @@ public:
* Decode from correct-length little-endian byte sequence.
* @return DECAF_FAILURE if the scalar is greater than or equal to the group order q.
*/
static inline decaf_error_t __attribute__((warn_unused_result)) decode (
static inline decaf_error_t WARN_UNUSED decode (
Scalar &sc, const FixedBlock<SER_BYTES> buffer
) NOEXCEPT {
return %(c_ns)s_scalar_decode(sc.s,buffer.data());
@@ -175,7 +175,7 @@ public:

/** Invert with Fermat's Little Theorem (slow!). If *this == 0, set r=0
* and return DECAF_FAILURE. */
inline decaf_error_t __attribute__((warn_unused_result))
inline decaf_error_t WARN_UNUSED
inverse_noexcept(Scalar &r) const NOEXCEPT {
return %(c_ns)s_scalar_invert(r.s,s);
}
@@ -276,7 +276,7 @@ public:
* @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point,
* or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined.
*/
static inline decaf_error_t __attribute__((warn_unused_result)) decode (
static inline decaf_error_t WARN_UNUSED decode (
Point &p, const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE
) NOEXCEPT {
return %(c_ns)s_point_decode(p.p,buffer.data(),allow_identity);
@@ -565,6 +565,64 @@ public:
/** @endcond */
};

struct DhLadder {
public:
/** Bytes in an X%(gf_shortname)s public key. */
static const size_t PUBLIC_BYTES = X%(gf_shortname)s_PUBLIC_BYTES;

/** Bytes in an X%(gf_shortname)s private key. */
static const size_t PRIVATE_BYTES = X%(gf_shortname)s_PRIVATE_BYTES;

/** Base point for a scalar multiplication. */
static const FixedBlock<PUBLIC_BYTES> base_point() NOEXCEPT {
return FixedBlock<PUBLIC_BYTES>(%(c_ns)s_x_base_point);
}

/** Generate and return a shared secret with public key. */
static inline SecureBuffer shared_secret(
const FixedBlock<PUBLIC_BYTES> &pk,
const FixedBlock<PRIVATE_BYTES> &scalar
) throw(std::bad_alloc,CryptoException) {
SecureBuffer out(PUBLIC_BYTES);
if (DECAF_SUCCESS != %(c_ns)s_x_direct_scalarmul(out.data(), pk.data(), scalar.data())) {
throw CryptoException();
}
return out;
}

/** Generate and return a shared secret with public key, noexcept version. */
static inline decaf_error_t WARN_UNUSED
shared_secret_noexcept (
FixedBuffer<PUBLIC_BYTES> &out,
const FixedBlock<PUBLIC_BYTES> &pk,
const FixedBlock<PRIVATE_BYTES> &scalar
) NOEXCEPT {
return %(c_ns)s_x_direct_scalarmul(out.data(), pk.data(), scalar.data());
}

/** Generate and return a public key; equivalent to shared_secret(base_point(),scalar)
* but possibly faster.
*/
static inline SecureBuffer generate_key(
const FixedBlock<PRIVATE_BYTES> &scalar
) throw(std::bad_alloc) {
SecureBuffer out(PUBLIC_BYTES);
%(c_ns)s_x_base_scalarmul(out.data(), scalar.data());
return out;
}

/** Generate and return a public key into a fixed buffer;
* equivalent to shared_secret(base_point(),scalar) but possibly faster.
*/
static inline void
generate_key_noexcept (
FixedBuffer<PUBLIC_BYTES> &out,
const FixedBlock<PRIVATE_BYTES> &scalar
) NOEXCEPT {
%(c_ns)s_x_base_scalarmul(out.data(), scalar.data());
}
};

}; /* struct %(cxx_ns)s */

/** @cond internal */


+ 6
- 1
src/gen_headers/f_field_h.py View File

@@ -14,7 +14,7 @@ f_field_h = gen_file(

#define __DECAF_%(gf_shortname)s_GF_DEFINED__ 1
#define NLIMBS (%(gf_impl_bits)d/sizeof(word_t)/8)
#define SER_BYTES ((%(gf_bits)d-1)/8 + 1)
#define SER_BYTES ((%(gf_bits)d-1)/8 + 1) /* MAGIC: depends on if high bit known to be clear (eg p521) */
typedef struct gf_%(gf_shortname)s_s {
word_t limb[NLIMBS];
} __attribute__((aligned(32))) gf_%(gf_shortname)s_s, gf_%(gf_shortname)s_t[1];
@@ -42,6 +42,11 @@ typedef struct gf_%(gf_shortname)s_s {
#define gf_serialize gf_%(gf_shortname)s_serialize
#define gf_deserialize gf_%(gf_shortname)s_deserialize

/* RFC 7748 support */
#define X_PUBLIC_BYTES %(x_pub_bytes)d
#define X_PRIVATE_BYTES %(x_priv_bytes)d
#define X_PRIVATE_BITS %(x_priv_bits)d

#define SQRT_MINUS_ONE P%(gf_shortname)s_SQRT_MINUS_ONE /* might not be defined */

#define INLINE_UNUSED __inline__ __attribute__((unused,always_inline))


+ 10
- 4
src/public_include/decaf/spongerng.hxx View File

@@ -41,6 +41,12 @@ private:
keccak_prng_t sp;
public:
/** Deterministic flag.
* The idea is that DETERMINISTIC is used for testing or for lockstep computations,
* and NONDETERMINISTIC is used in production.
*/
enum Deterministic { RANDOM = 0, DETERMINISTIC = 1 };
/** Exception thrown when The RNG fails (to seed itself) */
class RngException : public std::exception {
private:
@@ -54,14 +60,14 @@ public:
};
/** Initialize, deterministically by default, from block */
inline SpongeRng( const Block &in, bool deterministic = true ) {
spongerng_init_from_buffer(sp,in.data(),in.size(),deterministic);
inline SpongeRng( const Block &in, Deterministic det ) {
spongerng_init_from_buffer(sp,in.data(),in.size(),(int)det);
}
/** Initialize, non-deterministically by default, from C/C++ filename */
inline SpongeRng( const std::string &in = "/dev/urandom", size_t len = 32, bool deterministic = false )
inline SpongeRng( const std::string &in = "/dev/urandom", size_t len = 32, Deterministic det = RANDOM )
throw(RngException) {
decaf_error_t ret = spongerng_init_from_file(sp,in.c_str(),len,deterministic);
decaf_error_t ret = spongerng_init_from_file(sp,in.c_str(),len,det);
if (!decaf_successful(ret)) {
throw RngException(errno, "Couldn't load from file");
}


+ 17
- 7
test/bench_decaf.cxx View File

@@ -288,10 +288,21 @@ static void spake2ee(
server.respec(STROBE_KEYED_128);
}

static void cfrg() {
SpongeRng rng(Block("bench_cfrg_crypto"),SpongeRng::DETERMINISTIC);
FixedArrayBuffer<Group::DhLadder::PUBLIC_BYTES> base(rng);
FixedArrayBuffer<Group::DhLadder::PRIVATE_BYTES> s1(rng);
for (Benchmark b("RFC 7748 keygen"); b.iter(); ) { Group::DhLadder::generate_key(s1); }
for (Benchmark b("RFC 7748 shared secret"); b.iter(); ) { Group::DhLadder::shared_secret(base,s1); }
}

static void macro() {
printf("\nMacro-benchmarks for %s:\n", Group::name());
printf("Crypto benchmarks:\n");
SpongeRng rng(Block("macro rng seed"));
printf("CFRG crypto benchmarks:\n");
cfrg();
printf("\nSample crypto benchmarks:\n");
SpongeRng rng(Block("macro rng seed"),SpongeRng::DETERMINISTIC);
PrivateKey<Group> s1((NOINIT())), s2(rng);
PublicKey<Group> p1((NOINIT())), p2(s2);

@@ -317,8 +328,8 @@ static void macro() {
}
printf("\nProtocol benchmarks:\n");
SpongeRng clientRng(Block("client rng seed"));
SpongeRng serverRng(Block("server rng seed"));
SpongeRng clientRng(Block("client rng seed"),SpongeRng::DETERMINISTIC);
SpongeRng serverRng(Block("server rng seed"),SpongeRng::DETERMINISTIC);
SecureBuffer hashedPassword(Block("hello world"));
for (Benchmark b("Spake2ee c+s",0.1); b.iter(); ) {
spake2ee(clientRng, serverRng, hashedPassword,false);
@@ -343,7 +354,7 @@ static void macro() {
}

static void micro() {
SpongeRng rng(Block("per-curve-benchmarks"));
SpongeRng rng(Block("per-curve-benchmarks"),SpongeRng::DETERMINISTIC);
Precomputed pBase;
Point p,q;
Scalar s(1),t(2);
@@ -382,7 +393,7 @@ int main(int argc, char **argv) {
if (argc >= 2 && !strcmp(argv[1], "--micro"))
micro = true;

SpongeRng rng(Block("micro-benchmarks"));
SpongeRng rng(Block("micro-benchmarks"),SpongeRng::DETERMINISTIC);
if (micro) {
printf("\nMicro-benchmarks:\n");
SHAKE<128> shake1;
@@ -415,7 +426,6 @@ int main(int argc, char **argv) {
Benches<Ed448Goldilocks>::micro();
}


Benches<IsoEd25519>::macro();
Benches<Ed448Goldilocks>::macro();



+ 4
- 0
test/test_ct.cxx View File

@@ -92,6 +92,10 @@ static void test_ec() {
}
}

/* TODO: test x25519/x448 */

/* FUTURE: test ed25519/ed448 */

/* Specify the same value as you did when compiling decaf_crypto.c */
#ifndef DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT
#define DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT DECAF_FALSE


+ 121
- 7
test/test_decaf.cxx View File

@@ -47,6 +47,7 @@ template<typename Group> struct Tests {

typedef typename Group::Scalar Scalar;
typedef typename Group::Point Point;
typedef typename Group::DhLadder DhLadder;
typedef typename Group::Precomputed Precomputed;

static void print(const char *name, const Scalar &x) {
@@ -128,7 +129,7 @@ static bool point_check(
}

static void test_arithmetic() {
SpongeRng rng(Block("test_arithmetic"));
SpongeRng rng(Block("test_arithmetic"),SpongeRng::DETERMINISTIC);
Test test("Arithmetic");
Scalar x(0),y(0),z(0);
@@ -169,7 +170,7 @@ static void test_arithmetic() {
}

static void test_elligator() {
SpongeRng rng(Block("test_elligator"));
SpongeRng rng(Block("test_elligator"),SpongeRng::DETERMINISTIC);
Test test("Elligator");
const int NHINTS = Group::REMOVED_COFACTOR * 2;
@@ -265,7 +266,7 @@ static void test_elligator() {
}

static void test_ec() {
SpongeRng rng(Block("test_ec"));
SpongeRng rng(Block("test_ec"),SpongeRng::DETERMINISTIC);
Test test("EC");

@@ -327,7 +328,7 @@ static void test_ec() {

static void test_crypto() {
Test test("Sample crypto");
SpongeRng rng(Block("test_decaf_crypto"));
SpongeRng rng(Block("test_decaf_crypto"),SpongeRng::DETERMINISTIC);

for (int i=0; i<NTESTS && test.passing_now; i++) {
PrivateKey<Group> priv1(rng), priv2(rng);
@@ -340,14 +341,123 @@ static void test_crypto() {
SecureBuffer s1(priv1.sharedSecret(pub2,32,true));
SecureBuffer s2(priv2.sharedSecret(pub1,32,false));
if (memcmp(s1.data(),s2.data(),s1.size())) {
if (!memeq(s1,s2)) {
test.fail();
printf(" Shared secrets disagree.");
printf(" Shared secrets disagree on iteration %d.\n",i);
}
}
}

}; /* template<GroupId GROUP> */
static const uint8_t rfc7748_1[DhLadder::PUBLIC_BYTES];
static const uint8_t rfc7748_1000[DhLadder::PUBLIC_BYTES];
static const uint8_t rfc7748_1000000[DhLadder::PUBLIC_BYTES];

static void test_cfrg_crypto() {
Test test("CFRG crypto");
SpongeRng rng(Block("test_cfrg_crypto"),SpongeRng::DETERMINISTIC);
for (int i=0; i<NTESTS && test.passing_now; i++) {
FixedArrayBuffer<DhLadder::PUBLIC_BYTES> base(rng);
FixedArrayBuffer<DhLadder::PRIVATE_BYTES> s1(rng), s2(rng);
SecureBuffer p1 = DhLadder::shared_secret(base,s1);
SecureBuffer p2 = DhLadder::shared_secret(base,s2);
SecureBuffer ss1 = DhLadder::shared_secret(p2,s1);
SecureBuffer ss2 = DhLadder::shared_secret(p1,s2);

if (!memeq(ss1,ss2)) {
test.fail();
printf(" Shared secrets disagree on iteration %d.\n",i);
}
if (!memeq(
DhLadder::shared_secret(DhLadder::base_point(),s1),
DhLadder::generate_key(s1)
)) {
test.fail();
printf(" Generated keys disagree on iteration %d.\n",i);
}
}
}

static void test_cfrg_vectors() {
Test test("CFRG test vectors");
SecureBuffer k = DhLadder::base_point();
SecureBuffer u = DhLadder::base_point();
int the_ntests = (NTESTS < 1000000) ? 1000 : 1000000;
for (int i=0; i<the_ntests && test.passing_now; i++) {
SecureBuffer n = DhLadder::shared_secret(u,k);
u = k; k = n;
if (i==1-1) {
if (!memeq(k,SecureBuffer(FixedBlock<DhLadder::PUBLIC_BYTES>(rfc7748_1)))) {
test.fail();
printf(" Test vectors disagree at 1.");
}
} else if (i==1000-1) {
if (!memeq(k,SecureBuffer(FixedBlock<DhLadder::PUBLIC_BYTES>(rfc7748_1000)))) {
test.fail();
printf(" Test vectors disagree at 1000.");
}
} else if (i==1000000-1) {
if (!memeq(k,SecureBuffer(FixedBlock<DhLadder::PUBLIC_BYTES>(rfc7748_1000000)))) {
test.fail();
printf(" Test vectors disagree at 1000000.");
}
}
}
}

}; /* template<GroupId GROUP> struct Tests */

template<> const uint8_t Tests<IsoEd25519>::rfc7748_1[32] = {
0x42,0x2c,0x8e,0x7a,0x62,0x27,0xd7,0xbc,
0xa1,0x35,0x0b,0x3e,0x2b,0xb7,0x27,0x9f,
0x78,0x97,0xb8,0x7b,0xb6,0x85,0x4b,0x78,
0x3c,0x60,0xe8,0x03,0x11,0xae,0x30,0x79
};
template<> const uint8_t Tests<IsoEd25519>::rfc7748_1000[32] = {
0x68,0x4c,0xf5,0x9b,0xa8,0x33,0x09,0x55,
0x28,0x00,0xef,0x56,0x6f,0x2f,0x4d,0x3c,
0x1c,0x38,0x87,0xc4,0x93,0x60,0xe3,0x87,
0x5f,0x2e,0xb9,0x4d,0x99,0x53,0x2c,0x51
};
template<> const uint8_t Tests<IsoEd25519>::rfc7748_1000000[32] = {
0x7c,0x39,0x11,0xe0,0xab,0x25,0x86,0xfd,
0x86,0x44,0x97,0x29,0x7e,0x57,0x5e,0x6f,
0x3b,0xc6,0x01,0xc0,0x88,0x3c,0x30,0xdf,
0x5f,0x4d,0xd2,0xd2,0x4f,0x66,0x54,0x24
};
template<> const uint8_t Tests<Ed448Goldilocks>::rfc7748_1[56] = {
0x3f,0x48,0x2c,0x8a,0x9f,0x19,0xb0,0x1e,
0x6c,0x46,0xee,0x97,0x11,0xd9,0xdc,0x14,
0xfd,0x4b,0xf6,0x7a,0xf3,0x07,0x65,0xc2,
0xae,0x2b,0x84,0x6a,0x4d,0x23,0xa8,0xcd,
0x0d,0xb8,0x97,0x08,0x62,0x39,0x49,0x2c,
0xaf,0x35,0x0b,0x51,0xf8,0x33,0x86,0x8b,
0x9b,0xc2,0xb3,0xbc,0xa9,0xcf,0x41,0x13
};
template<> const uint8_t Tests<Ed448Goldilocks>::rfc7748_1000[56] = {
0xaa,0x3b,0x47,0x49,0xd5,0x5b,0x9d,0xaf,
0x1e,0x5b,0x00,0x28,0x88,0x26,0xc4,0x67,
0x27,0x4c,0xe3,0xeb,0xbd,0xd5,0xc1,0x7b,
0x97,0x5e,0x09,0xd4,0xaf,0x6c,0x67,0xcf,
0x10,0xd0,0x87,0x20,0x2d,0xb8,0x82,0x86,
0xe2,0xb7,0x9f,0xce,0xea,0x3e,0xc3,0x53,
0xef,0x54,0xfa,0xa2,0x6e,0x21,0x9f,0x38
};
template<> const uint8_t Tests<Ed448Goldilocks>::rfc7748_1000000[56] = {
0x07,0x7f,0x45,0x36,0x81,0xca,0xca,0x36,
0x93,0x19,0x84,0x20,0xbb,0xe5,0x15,0xca,
0xe0,0x00,0x24,0x72,0x51,0x9b,0x3e,0x67,
0x66,0x1a,0x7e,0x89,0xca,0xb9,0x46,0x95,
0xc8,0xf4,0xbc,0xd6,0x6e,0x61,0xb9,0xb9,
0xc9,0x46,0xda,0x8d,0x52,0x4d,0xe3,0xd6,
0x9b,0xd9,0xd9,0xd6,0x6b,0x99,0x7e,0x37
};

int main(int argc, char **argv) {
(void) argc; (void) argv;
@@ -356,6 +466,8 @@ int main(int argc, char **argv) {
Tests<IsoEd25519>::test_arithmetic();
Tests<IsoEd25519>::test_elligator();
Tests<IsoEd25519>::test_ec();
Tests<IsoEd25519>::test_cfrg_crypto();
Tests<IsoEd25519>::test_cfrg_vectors();
Tests<IsoEd25519>::test_crypto();
printf("\n");
@@ -363,6 +475,8 @@ int main(int argc, char **argv) {
Tests<Ed448Goldilocks>::test_arithmetic();
Tests<Ed448Goldilocks>::test_elligator();
Tests<Ed448Goldilocks>::test_ec();
Tests<Ed448Goldilocks>::test_cfrg_crypto();
Tests<Ed448Goldilocks>::test_cfrg_vectors();
Tests<Ed448Goldilocks>::test_crypto();
if (passing) printf("Passed all tests.\n");


Loading…
Cancel
Save