diff options
Diffstat (limited to 'src/protocols/ec25519_fhmqvc')
-rw-r--r-- | src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c | 3 | ||||
-rw-r--r-- | src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h | 23 | ||||
-rw-r--r-- | src/protocols/ec25519_fhmqvc/handshake.c | 14 | ||||
-rw-r--r-- | src/protocols/ec25519_fhmqvc/state.c | 13 |
4 files changed, 47 insertions, 6 deletions
diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c index 17f8268..97cdb3d 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c @@ -71,6 +71,9 @@ static fastd_protocol_config_t * protocol_init(void) { ecc_25519_scalarmult_base(&work, &protocol_config->key.secret); ecc_25519_store_packed(&protocol_config->key.public.int256, &work); + if (!divide_key(&protocol_config->key.secret)) + exit_error("invalid secret key"); + return protocol_config; } diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h index 8dd8456..e2034bd 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h @@ -138,3 +138,26 @@ static inline void hexdump(char out[65], const unsigned char d[32]) { static inline bool is_session_valid(const protocol_session_t *session) { return (session->method && session->method->provider->session_is_valid(session->method_state)); } + + +/** Devides a secret key by 8 (for some optimizations) */ +static inline bool divide_key(ecc_int256_t *key) { + uint8_t c = 0, c2; + ssize_t i; + + for (i = 31; i >= 0; i--) { + c2 = key->p[i] << 5; + key->p[i] = (key->p[i] >> 3) | c; + c = c2; + } + + return (c == 0); +} + +/** Multiplies a point by 8 */ +static inline void octuple_point(ecc_25519_work_t *p) { + ecc_25519_work_t work; + ecc_25519_double(&work, p); + ecc_25519_double(&work, &work); + ecc_25519_double(p, &work); +} diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c index ee93e7a..b1c6242 100644 --- a/src/protocols/ec25519_fhmqvc/handshake.c +++ b/src/protocols/ec25519_fhmqvc/handshake.c @@ -192,7 +192,7 @@ static bool make_shared_handshake_key(bool initiator, const keypair_t *handshake if (!ecc_25519_load_packed(&workXY, &peer_handshake_key->int256)) return false; - if (!fastd_protocol_ec25519_fhmqvc_check_key(&workXY)) + if (ecc_25519_is_identity(&workXY)) return false; if (initiator) { @@ -235,6 +235,18 @@ static bool make_shared_handshake_key(bool initiator, const keypair_t *handshake } ecc_25519_add(&work, &workXY, &work); + + /* + Both our secret keys have been divided by 8 before, so we multiply + the point with 8 here to compensate. + + By multiplying with 8, we prevent small-subgroup attacks (8 is the order + of the curves twist, see djb's Curve25519 paper). While the factor 8 should + be in the private keys anyways, the reduction modulo the subgroup order (in ecc_25519_gf_*) + will only preserve it if the point actually lies on our subgroup. + */ + octuple_point(&work); + ecc_25519_scalarmult(&work, &s, &work); if (ecc_25519_is_identity(&work)) diff --git a/src/protocols/ec25519_fhmqvc/state.c b/src/protocols/ec25519_fhmqvc/state.c index 79bb6e2..cfb9028 100644 --- a/src/protocols/ec25519_fhmqvc/state.c +++ b/src/protocols/ec25519_fhmqvc/state.c @@ -46,12 +46,15 @@ static void init_protocol_state(void) { /** Generates a new ephemeral keypair */ static void new_handshake_key(keypair_t *key) { - fastd_random_bytes(key->secret.p, SECRETKEYBYTES, false); - ecc_25519_gf_sanitize_secret(&key->secret, &key->secret); + fastd_random_bytes(key->secret.p, SECRETKEYBYTES, false); + ecc_25519_gf_sanitize_secret(&key->secret, &key->secret); - ecc_25519_work_t work; - ecc_25519_scalarmult_base(&work, &key->secret); - ecc_25519_store_packed(&key->public.int256, &work); + ecc_25519_work_t work; + ecc_25519_scalarmult_base(&work, &key->secret); + ecc_25519_store_packed(&key->public.int256, &work); + + if (!divide_key(&key->secret)) + exit_bug("generated invalid ephemeral key"); } /** |