/* * 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 . * * 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; }