Created newhope plugin implementing the New Hope key exchange algorithm
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* Based on public domain code by Erdem Alkim, Léo Ducas, Thomas Pöppelmann,
|
||||
* and Peter Schwabe.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "newhope_reconciliation.h"
|
||||
|
||||
typedef struct private_newhope_reconciliation_t private_newhope_reconciliation_t;
|
||||
|
||||
/**
|
||||
* Private data of an newhope_reconciliation_t object.
|
||||
*/
|
||||
struct private_newhope_reconciliation_t {
|
||||
|
||||
/**
|
||||
* Public newhope_reconciliation_t interface.
|
||||
*/
|
||||
newhope_reconciliation_t public;
|
||||
|
||||
/**
|
||||
* Array sizes
|
||||
*/
|
||||
int n, n4;
|
||||
|
||||
/**
|
||||
* Multiples of modulus q
|
||||
*/
|
||||
int32_t q, q2, q4, q8, q16;
|
||||
};
|
||||
|
||||
|
||||
static inline int32_t rec_abs(int32_t v)
|
||||
{
|
||||
int32_t mask = v >> 31;
|
||||
|
||||
return (v ^ mask) - mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auxiliary function used by help_reconcile() method
|
||||
*/
|
||||
static int32_t rec_f(private_newhope_reconciliation_t *this,
|
||||
int32_t v, uint8_t r, int32_t *v0, int32_t *v1)
|
||||
{
|
||||
int32_t x, xit, t, b;
|
||||
|
||||
x = 8 * v + 2 * r;
|
||||
|
||||
/* compute t = x/q */
|
||||
b = x * 2730;
|
||||
t = b >> 25;
|
||||
b = x - t * this->q;
|
||||
b = this->q - 1 - b;
|
||||
b >>= 31;
|
||||
t -= b;
|
||||
|
||||
r = t & 0x01;
|
||||
xit = (t >> 1);
|
||||
*v0 = xit + r ; /* v0 = round(x/(2q)) */
|
||||
|
||||
t -= 1;
|
||||
r = t & 0x01;
|
||||
*v1 = ( t>> 1) + r;
|
||||
|
||||
return rec_abs(x - (*v0) * this->q2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Auxiliary function used by reconcile() method
|
||||
*/
|
||||
static int32_t rec_g(private_newhope_reconciliation_t *this, int32_t x)
|
||||
{
|
||||
int32_t t, r, b;
|
||||
|
||||
/* t = x/(4*q) */
|
||||
b = x * 2730;
|
||||
t = b >> 27;
|
||||
b = x - t * this->q4;
|
||||
b = this->q4 - 1 - b;
|
||||
b >>= 31;
|
||||
t -= b;
|
||||
|
||||
r = t & 0x01;
|
||||
t = (t >> 1) + r; /* t = round(x/(8q)) */
|
||||
t *= this->q8;
|
||||
|
||||
return abs(t - x);
|
||||
}
|
||||
|
||||
METHOD(newhope_reconciliation_t, help_reconcile, uint8_t*,
|
||||
private_newhope_reconciliation_t *this, uint32_t *v, uint8_t *rbits)
|
||||
{
|
||||
int32_t v0[4], v1[4], v_tmp[4], k;
|
||||
int i, i0, i1, i2, i3, j;
|
||||
uint8_t *r, rbit;
|
||||
|
||||
/* allocate output vector */
|
||||
r = (uint8_t*)malloc(this->n);
|
||||
|
||||
for (i = 0; i < this->n4/8; i++)
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
i0 = 8*i + j;
|
||||
i1 = i0 + this->n4;
|
||||
i2 = i1 + this->n4;
|
||||
i3 = i2 + this->n4;
|
||||
|
||||
/* iterate through all 256 random bits */
|
||||
rbit = (rbits[i] >> j) & 0x01;
|
||||
|
||||
k = rec_f(this, v[i0], rbit, &v0[0], &v1[0]);
|
||||
k += rec_f(this, v[i1], rbit, &v0[1], &v1[1]);
|
||||
k += rec_f(this, v[i2], rbit, &v0[2], &v1[2]);
|
||||
k += rec_f(this, v[i3], rbit, &v0[3], &v1[3]);
|
||||
|
||||
k = (this->q2 - 1 - k) >> 31;
|
||||
|
||||
v_tmp[0] = ((~k) & v0[0]) ^ (k & v1[0]);
|
||||
v_tmp[1] = ((~k) & v0[1]) ^ (k & v1[1]);
|
||||
v_tmp[2] = ((~k) & v0[2]) ^ (k & v1[2]);
|
||||
v_tmp[3] = ((~k) & v0[3]) ^ (k & v1[3]);
|
||||
|
||||
r[i0] = (v_tmp[0] - v_tmp[3]) & 0x03;
|
||||
r[i1] = (v_tmp[1] - v_tmp[3]) & 0x03;
|
||||
r[i2] = (v_tmp[2] - v_tmp[3]) & 0x03;
|
||||
r[i3] = (v_tmp[3] - k + v_tmp[3]) & 0x03;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
METHOD(newhope_reconciliation_t, reconcile, chunk_t,
|
||||
private_newhope_reconciliation_t *this, uint32_t *v, uint8_t *r)
|
||||
{
|
||||
size_t key_len;
|
||||
uint8_t *key;
|
||||
int32_t tmp[4], t;
|
||||
int i, i0, i1, i2, i3, j;
|
||||
|
||||
key_len = this->n4 / 8;
|
||||
key = (uint8_t*)malloc(key_len);
|
||||
memset(key, 0x00, key_len);
|
||||
|
||||
for (i = 0; i < key_len; i++)
|
||||
{
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
i0 = 8*i + j;
|
||||
i1 = i0 + this->n4;
|
||||
i2 = i1 + this->n4;
|
||||
i3 = i2 + this->n4;
|
||||
|
||||
tmp[0] = this->q16 + 8 * (int32_t)v[i0] -
|
||||
this->q * (2*r[i0] + r[i3]);
|
||||
tmp[1] = this->q16 + 8 * (int32_t)v[i1] -
|
||||
this->q * (2*r[i1] + r[i3]);
|
||||
tmp[2] = this->q16 + 8 * (int32_t)v[i2] -
|
||||
this->q * (2*r[i2] + r[i3]);
|
||||
tmp[3] = this->q16 + 8 * (int32_t)v[i3] -
|
||||
this->q * ( r[i3]);
|
||||
|
||||
t = rec_g(this, tmp[0]) + rec_g(this, tmp[1]) +
|
||||
rec_g(this, tmp[2]) + rec_g(this, tmp[3]) - this->q8;
|
||||
|
||||
key[i] |= ((t >> 31) & 0x01) << j;
|
||||
}
|
||||
}
|
||||
|
||||
return chunk_create(key, key_len);
|
||||
}
|
||||
|
||||
METHOD(newhope_reconciliation_t, destroy, void,
|
||||
private_newhope_reconciliation_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
newhope_reconciliation_t *newhope_reconciliation_create(int n, int32_t q)
|
||||
{
|
||||
private_newhope_reconciliation_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.help_reconcile = _help_reconcile,
|
||||
.reconcile = _reconcile,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.n = n,
|
||||
.n4 = n / 4,
|
||||
.q = q,
|
||||
.q2 = 2 * q,
|
||||
.q4 = 4 * q,
|
||||
.q8 = 8 * q,
|
||||
.q16 = 16 * q,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
Reference in New Issue
Block a user