@@ -3,7 +3,6 @@ | |||||
* @brief Example Decaf crypto routines | * @brief Example Decaf crypto routines | ||||
*/ | */ | ||||
#include "f_field.h" /* for SER_BYTES; FUTURE: find a better way to do this? */ | |||||
#include <decaf/crypto.h> | #include <decaf/crypto.h> | ||||
#include <string.h> | #include <string.h> | ||||
@@ -11,6 +10,7 @@ | |||||
#define API_NS(_id) $(c_ns)_##_id | #define API_NS(_id) $(c_ns)_##_id | ||||
#define SCALAR_BITS $(C_NS)_SCALAR_BITS | #define SCALAR_BITS $(C_NS)_SCALAR_BITS | ||||
#define SCALAR_BYTES ((SCALAR_BITS + 7)/8) | #define SCALAR_BYTES ((SCALAR_BITS + 7)/8) | ||||
#define SER_BYTES $(C_NS)_SER_BYTES | |||||
/* TODO: canonicalize and freeze the STROBE constants in this file | /* TODO: canonicalize and freeze the STROBE constants in this file | ||||
* (and STROBE itself for that matter) | * (and STROBE itself for that matter) | ||||
@@ -1076,7 +1076,7 @@ void API_NS(point_encode_like_eddsa) ( | |||||
gf_add( u, x, t ); // x^2 + y^2 | gf_add( u, x, t ); // x^2 + y^2 | ||||
gf_add( z, q->y, q->x ); | gf_add( z, q->y, q->x ); | ||||
gf_sqr ( y, z); | gf_sqr ( y, z); | ||||
gf_sub ( y, y, u ); // 2xy | |||||
gf_sub ( y, u, y ); // -2xy | |||||
gf_sub ( z, t, x ); // y^2 - x^2 | gf_sub ( z, t, x ); // y^2 - x^2 | ||||
gf_sqr ( x, q->z ); | gf_sqr ( x, q->z ); | ||||
gf_add ( t, x, x); | gf_add ( t, x, x); | ||||
@@ -1093,7 +1093,7 @@ void API_NS(point_encode_like_eddsa) ( | |||||
{ | { | ||||
API_NS(point_double)(q,q); | API_NS(point_double)(q,q); | ||||
API_NS(point_double)(q,q); | API_NS(point_double)(q,q); | ||||
gf_div_qnr(x, q->x); | |||||
gf_mul_qnr(x, q->x); | |||||
gf_copy(y, q->y); | gf_copy(y, q->y); | ||||
gf_copy(z, q->z); | gf_copy(z, q->z); | ||||
} | } | ||||
@@ -1106,7 +1106,7 @@ void API_NS(point_encode_like_eddsa) ( | |||||
gf_add( u, x, t ); | gf_add( u, x, t ); | ||||
gf_add( z, q->y, q->x ); | gf_add( z, q->y, q->x ); | ||||
gf_sqr ( y, z); | gf_sqr ( y, z); | ||||
gf_sub ( y, y, u ); | |||||
gf_sub ( y, u, y ); | |||||
gf_sub ( z, t, x ); | gf_sub ( z, t, x ); | ||||
gf_sqr ( x, q->z ); | gf_sqr ( x, q->z ); | ||||
gf_add ( t, x, x); | gf_add ( t, x, x); | ||||
@@ -1167,7 +1167,7 @@ decaf_error_t API_NS(point_decode_like_eddsa) ( | |||||
succ &= gf_isr(p->t,p->x); /* 1/sqrt(num * denom) */ | succ &= gf_isr(p->t,p->x); /* 1/sqrt(num * denom) */ | ||||
gf_mul(p->x,p->t,p->z); /* sqrt(num / denom) */ | gf_mul(p->x,p->t,p->z); /* sqrt(num / denom) */ | ||||
gf_cond_neg(p->x,gf_lobit(p->x)^low); | |||||
gf_cond_neg(p->x,~gf_lobit(p->x)^low); | |||||
gf_copy(p->z,ONE); | gf_copy(p->z,ONE); | ||||
#if EDDSA_USE_SIGMA_ISOGENY | #if EDDSA_USE_SIGMA_ISOGENY | ||||
@@ -679,7 +679,6 @@ void $(c_ns)_scalar_destroy ( | |||||
/** | /** | ||||
* @brief Overwrite point with zeros. | * @brief Overwrite point with zeros. | ||||
* @todo Use this internally. | |||||
*/ | */ | ||||
void $(c_ns)_point_destroy ( | void $(c_ns)_point_destroy ( | ||||
$(c_ns)_point_t point | $(c_ns)_point_t point | ||||
@@ -23,7 +23,7 @@ | |||||
#define EDDSA_USE_SIGMA_ISOGENY $(eddsa_sigma_iso) | #define EDDSA_USE_SIGMA_ISOGENY $(eddsa_sigma_iso) | ||||
#define COFACTOR $(cofactor) | #define COFACTOR $(cofactor) | ||||
static void clamp( | |||||
static void clamp ( | |||||
uint8_t secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES] | uint8_t secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES] | ||||
) { | ) { | ||||
/* Blarg */ | /* Blarg */ | ||||
@@ -78,9 +78,8 @@ void API_NS(eddsa_derive_public_key) ( | |||||
API_NS(scalar_t) secret_scalar; | API_NS(scalar_t) secret_scalar; | ||||
API_NS(scalar_decode_long)(secret_scalar, secret_scalar_ser, sizeof(secret_scalar_ser)); | API_NS(scalar_decode_long)(secret_scalar, secret_scalar_ser, sizeof(secret_scalar_ser)); | ||||
/* TODO: write documentation for why (due to isogenies) this needs to be quartered */ | |||||
API_NS(scalar_sub)(secret_scalar,API_NS(scalar_zero),secret_scalar); | |||||
/* TODO: write documentation for why (due to isogenies) this needs to be quartered/eighthed */ | |||||
for (unsigned int c = 1; c < COFACTOR/(1+EDDSA_USE_SIGMA_ISOGENY); c <<= 1) { | for (unsigned int c = 1; c < COFACTOR/(1+EDDSA_USE_SIGMA_ISOGENY); c <<= 1) { | ||||
API_NS(scalar_halve)(secret_scalar,secret_scalar); | API_NS(scalar_halve)(secret_scalar,secret_scalar); | ||||
} | } | ||||
@@ -149,9 +148,8 @@ void API_NS(eddsa_sign) ( | |||||
{ | { | ||||
/* Scalarmul to create the nonce-point */ | /* Scalarmul to create the nonce-point */ | ||||
API_NS(scalar_t) nonce_scalar_2; | API_NS(scalar_t) nonce_scalar_2; | ||||
API_NS(scalar_sub)(nonce_scalar_2,API_NS(scalar_zero),nonce_scalar); | |||||
for (unsigned int c = 1; c < COFACTOR/(1+EDDSA_USE_SIGMA_ISOGENY); c <<= 1) { | |||||
API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar); | |||||
for (unsigned int c = 2; c < COFACTOR/(1+EDDSA_USE_SIGMA_ISOGENY); c <<= 1) { | |||||
API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); | API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); | ||||
} | } | ||||
@@ -233,7 +231,6 @@ decaf_error_t API_NS(eddsa_verify) ( | |||||
&signature[$(C_NS)_EDDSA_PUBLIC_BYTES], | &signature[$(C_NS)_EDDSA_PUBLIC_BYTES], | ||||
$(C_NS)_EDDSA_PRIVATE_BYTES | $(C_NS)_EDDSA_PRIVATE_BYTES | ||||
); | ); | ||||
API_NS(scalar_sub)(response_scalar, API_NS(scalar_zero), response_scalar); /* TODO because nega-base point */ | |||||
#if EDDSA_USE_SIGMA_ISOGENY | #if EDDSA_USE_SIGMA_ISOGENY | ||||
API_NS(scalar_add)(response_scalar,response_scalar,response_scalar); | API_NS(scalar_add)(response_scalar,response_scalar,response_scalar); | ||||
#endif | #endif | ||||
@@ -68,8 +68,10 @@ void decaf_sha3_update ( | |||||
* @param [inout] sponge The context. | * @param [inout] sponge The context. | ||||
* @param [out] out The output data. | * @param [out] out The output data. | ||||
* @param [in] len The requested output data length in bytes. | * @param [in] len The requested output data length in bytes. | ||||
* @return DECAF_FAILURE if the sponge has exhausted its output capacity. | |||||
* @return DECAF_SUCCESS otherwise. | |||||
*/ | */ | ||||
void decaf_sha3_output ( | |||||
decaf_error_t decaf_sha3_output ( | |||||
decaf_keccak_sponge_t sponge, | decaf_keccak_sponge_t sponge, | ||||
uint8_t * __restrict__ out, | uint8_t * __restrict__ out, | ||||
size_t len | size_t len | ||||
@@ -83,7 +85,7 @@ void decaf_sha3_output ( | |||||
* @param [out] out The output data. | * @param [out] out The output data. | ||||
* @param [in] len The requested output data length in bytes. | * @param [in] len The requested output data length in bytes. | ||||
*/ | */ | ||||
void decaf_sha3_final ( | |||||
decaf_error_t decaf_sha3_final ( | |||||
decaf_keccak_sponge_t sponge, | decaf_keccak_sponge_t sponge, | ||||
uint8_t * __restrict__ out, | uint8_t * __restrict__ out, | ||||
size_t len | size_t len | ||||
@@ -58,7 +58,9 @@ public: | |||||
inline SecureBuffer output(size_t len) throw(std::bad_alloc, LengthException) { | inline SecureBuffer output(size_t len) throw(std::bad_alloc, LengthException) { | ||||
if (len > max_output_size()) throw LengthException(); | if (len > max_output_size()) throw LengthException(); | ||||
SecureBuffer buffer(len); | SecureBuffer buffer(len); | ||||
decaf_sha3_output(sp,buffer.data(),len); | |||||
if (DECAF_SUCCESS != decaf_sha3_output(sp,buffer.data(),len)) { | |||||
throw LengthException(); | |||||
} | |||||
return buffer; | return buffer; | ||||
} | } | ||||
@@ -66,21 +68,28 @@ public: | |||||
inline SecureBuffer final(size_t len) throw(std::bad_alloc, LengthException) { | inline SecureBuffer final(size_t len) throw(std::bad_alloc, LengthException) { | ||||
if (len > max_output_size()) throw LengthException(); | if (len > max_output_size()) throw LengthException(); | ||||
SecureBuffer buffer(len); | SecureBuffer buffer(len); | ||||
decaf_sha3_final(sp,buffer.data(),len); | |||||
if (DECAF_SUCCESS != decaf_sha3_final(sp,buffer.data(),len)) { | |||||
throw LengthException(); | |||||
} | |||||
return buffer; | return buffer; | ||||
} | } | ||||
/** | |||||
* @brief Output bytes from the sponge. | |||||
* @todo make this throw exceptions. | |||||
/** @brief Output bytes from the sponge. Throw LengthException if you've | |||||
* output too many bytes from a SHA-3 instance. | |||||
*/ | */ | ||||
inline void output(Buffer b) throw(LengthException) { | inline void output(Buffer b) throw(LengthException) { | ||||
decaf_sha3_output(sp,b.data(),b.size()); | |||||
if (DECAF_SUCCESS != decaf_sha3_output(sp,b.data(),b.size())) { | |||||
throw LengthException(); | |||||
} | |||||
} | } | ||||
/** @brief Output bytes from the sponge and reinitialize it. */ | |||||
/** @brief Output bytes from the sponge and reinitialize it. Throw | |||||
* LengthException if you've output too many bytes from a SHA3 instance. | |||||
*/ | |||||
inline void final(Buffer b) throw(LengthException) { | inline void final(Buffer b) throw(LengthException) { | ||||
decaf_sha3_final(sp,b.data(),b.size()); | |||||
if (DECAF_SUCCESS != decaf_sha3_final(sp,b.data(),b.size())) { | |||||
throw LengthException(); | |||||
} | |||||
} | } | ||||
/** @brief Return the sponge's default output size. */ | /** @brief Return the sponge's default output size. */ | ||||
@@ -94,12 +103,12 @@ public: | |||||
} | } | ||||
/** Output the default number of bytes. */ | /** Output the default number of bytes. */ | ||||
inline SecureBuffer output() throw(std::bad_alloc) { | |||||
inline SecureBuffer output() throw(std::bad_alloc,LengthException) { | |||||
return output(default_output_size()); | return output(default_output_size()); | ||||
} | } | ||||
/** Output the default number of bytes, and reset hash. */ | /** Output the default number of bytes, and reset hash. */ | ||||
inline SecureBuffer final() throw(std::bad_alloc) { | |||||
inline SecureBuffer final() throw(std::bad_alloc,LengthException) { | |||||
return final(default_output_size()); | return final(default_output_size()); | ||||
} | } | ||||
@@ -165,17 +165,22 @@ void decaf_sha3_update ( | |||||
} | } | ||||
} | } | ||||
void decaf_sha3_output ( | |||||
decaf_error_t decaf_sha3_output ( | |||||
decaf_keccak_sponge_t decaf_sponge, | decaf_keccak_sponge_t decaf_sponge, | ||||
uint8_t * __restrict__ out, | uint8_t * __restrict__ out, | ||||
size_t len | size_t len | ||||
) { | ) { | ||||
decaf_error_t ret = DECAF_SUCCESS; | |||||
assert(decaf_sponge->params->position < decaf_sponge->params->rate); | assert(decaf_sponge->params->position < decaf_sponge->params->rate); | ||||
assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state)); | assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state)); | ||||
if (decaf_sponge->params->max_out != 0xFF) { | if (decaf_sponge->params->max_out != 0xFF) { | ||||
assert(decaf_sponge->params->client >= len); | |||||
decaf_sponge->params->client -= len; | |||||
if (decaf_sponge->params->client >= len) { | |||||
decaf_sponge->params->client -= len; | |||||
} else { | |||||
decaf_sponge->params->client = 0; | |||||
ret = DECAF_FAILURE; | |||||
} | |||||
} | } | ||||
switch (decaf_sponge->params->flags) { | switch (decaf_sponge->params->flags) { | ||||
@@ -198,7 +203,7 @@ void decaf_sha3_output ( | |||||
if (cando > len) { | if (cando > len) { | ||||
memcpy(out, state, len); | memcpy(out, state, len); | ||||
decaf_sponge->params->position += len; | decaf_sponge->params->position += len; | ||||
return; | |||||
return ret; | |||||
} else { | } else { | ||||
memcpy(out, state, cando); | memcpy(out, state, cando); | ||||
dokeccak(decaf_sponge); | dokeccak(decaf_sponge); | ||||
@@ -206,15 +211,17 @@ void decaf_sha3_output ( | |||||
out += cando; | out += cando; | ||||
} | } | ||||
} | } | ||||
return ret; | |||||
} | } | ||||
void decaf_sha3_final ( | |||||
decaf_error_t decaf_sha3_final ( | |||||
decaf_keccak_sponge_t decaf_sponge, | decaf_keccak_sponge_t decaf_sponge, | ||||
uint8_t * __restrict__ out, | uint8_t * __restrict__ out, | ||||
size_t len | size_t len | ||||
) { | ) { | ||||
decaf_sha3_output(decaf_sponge,out,len); | |||||
decaf_error_t ret = decaf_sha3_output(decaf_sponge,out,len); | |||||
decaf_sha3_reset(decaf_sponge); | decaf_sha3_reset(decaf_sponge); | ||||
return ret; | |||||
} | } | ||||
void decaf_sha3_reset ( | void decaf_sha3_reset ( | ||||