Annotation of embedaddon/strongswan/src/libstrongswan/plugins/ntru/ntru_poly.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2014-2016 Andreas Steffen
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * Copyright (C) 2009-2013 Security Innovation
6: *
7: * This program is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2 of the License, or (at your
10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11: *
12: * This program is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15: * for more details.
16: */
17:
18: #include "ntru_poly.h"
19:
20: #include <crypto/xofs/xof_bitspender.h>
21: #include <utils/debug.h>
22: #include <utils/test.h>
23:
24: typedef struct private_ntru_poly_t private_ntru_poly_t;
25: typedef struct indices_len_t indices_len_t;
26:
27: /**
28: * Stores number of +1 and -1 coefficients
29: */
30: struct indices_len_t {
31: int p;
32: int m;
33: };
34:
35: /**
36: * Private data of an ntru_poly_t object.
37: */
38: struct private_ntru_poly_t {
39:
40: /**
41: * Public ntru_poly_t interface.
42: */
43: ntru_poly_t public;
44:
45: /**
46: * Ring dimension equal to the number of polynomial coefficients
47: */
48: uint16_t N;
49:
50: /**
51: * Large modulus
52: */
53: uint16_t q;
54:
55: /**
56: * Array containing the indices of the non-zero coefficients
57: */
58: uint16_t *indices;
59:
60: /**
61: * Number of indices of the non-zero coefficients
62: */
63: size_t num_indices;
64:
65: /**
66: * Number of sparse polynomials
67: */
68: int num_polynomials;
69:
70: /**
71: * Number of nonzero coefficients for up to 3 sparse polynomials
72: */
73: indices_len_t indices_len[3];
74:
75: };
76:
77: METHOD(ntru_poly_t, get_size, size_t,
78: private_ntru_poly_t *this)
79: {
80: return this->num_indices;
81: }
82:
83: METHOD(ntru_poly_t, get_indices, uint16_t*,
84: private_ntru_poly_t *this)
85: {
86: return this->indices;
87: }
88:
89: /**
90: * Multiplication of polynomial a with a sparse polynomial b given by
91: * the indices of its +1 and -1 coefficients results in polynomial c.
92: * This is a convolution operation
93: */
94: static void ring_mult_i(uint16_t *a, indices_len_t len, uint16_t *indices,
95: uint16_t N, uint16_t mod_q_mask, uint16_t *t,
96: uint16_t *c)
97: {
98: int i, j, k;
99:
100: /* initialize temporary array t */
101: for (k = 0; k < N; k++)
102: {
103: t[k] = 0;
104: }
105:
106: /* t[(i+k)%N] = sum i=0 through N-1 of a[i], for b[k] = -1 */
107: for (j = len.p; j < len.p + len.m; j++)
108: {
109: k = indices[j];
110: for (i = 0; k < N; ++i, ++k)
111: {
112: t[k] += a[i];
113: }
114: for (k = 0; i < N; ++i, ++k)
115: {
116: t[k] += a[i];
117: }
118: }
119:
120: /* t[(i+k)%N] = -(sum i=0 through N-1 of a[i] for b[k] = -1) */
121: for (k = 0; k < N; k++)
122: {
123: t[k] = -t[k];
124: }
125:
126: /* t[(i+k)%N] += sum i=0 through N-1 of a[i] for b[k] = +1 */
127: for (j = 0; j < len.p; j++)
128: {
129: k = indices[j];
130: for (i = 0; k < N; ++i, ++k)
131: {
132: t[k] += a[i];
133: }
134: for (k = 0; i < N; ++i, ++k)
135: {
136: t[k] += a[i];
137: }
138: }
139:
140: /* c = (a * b) mod q */
141: for (k = 0; k < N; k++)
142: {
143: c[k] = t[k] & mod_q_mask;
144: }
145: }
146:
147: METHOD(ntru_poly_t, get_array, void,
148: private_ntru_poly_t *this, uint16_t *array)
149: {
150: uint16_t *t, *bi;
151: uint16_t mod_q_mask = this->q - 1;
152: indices_len_t len;
153: int i;
154:
155: /* form polynomial F or F1 */
156: memset(array, 0x00, this->N * sizeof(uint16_t));
157: bi = this->indices;
158: len = this->indices_len[0];
159: for (i = 0; i < len.p + len.m; i++)
160: {
161: array[bi[i]] = (i < len.p) ? 1 : mod_q_mask;
162: }
163:
164: if (this->num_polynomials == 3)
165: {
166: /* allocate temporary array t */
167: t = malloc(this->N * sizeof(uint16_t));
168:
169: /* form F1 * F2 */
170: bi += len.p + len.m;
171: len = this->indices_len[1];
172: ring_mult_i(array, len, bi, this->N, mod_q_mask, t, array);
173:
174: /* form (F1 * F2) + F3 */
175: bi += len.p + len.m;
176: len = this->indices_len[2];
177: for (i = 0; i < len.p + len.m; i++)
178: {
179: if (i < len.p)
180: {
181: array[bi[i]] += 1;
182: }
183: else
184: {
185: array[bi[i]] -= 1;
186: }
187: array[bi[i]] &= mod_q_mask;
188: }
189: free(t);
190: }
191: }
192:
193: METHOD(ntru_poly_t, ring_mult, void,
194: private_ntru_poly_t *this, uint16_t *a, uint16_t *c)
195: {
196: uint16_t *t1, *t2;
197: uint16_t *bi = this->indices;
198: uint16_t mod_q_mask = this->q - 1;
199: int i;
200:
201: /* allocate temporary array t1 */
202: t1 = malloc(this->N * sizeof(uint16_t));
203:
204: if (this->num_polynomials == 1)
205: {
206: ring_mult_i(a, this->indices_len[0], bi, this->N, mod_q_mask, t1, c);
207: }
208: else
209: {
210: /* allocate temporary array t2 */
211: t2 = malloc(this->N * sizeof(uint16_t));
212:
213: /* t1 = a * b1 */
214: ring_mult_i(a, this->indices_len[0], bi, this->N, mod_q_mask, t1, t1);
215:
216: /* t1 = (a * b1) * b2 */
217: bi += this->indices_len[0].p + this->indices_len[0].m;
218: ring_mult_i(t1, this->indices_len[1], bi, this->N, mod_q_mask, t2, t1);
219:
220: /* t2 = a * b3 */
221: bi += this->indices_len[1].p + this->indices_len[1].m;
222: ring_mult_i(a, this->indices_len[2], bi, this->N, mod_q_mask, t2, t2);
223:
224: /* c = (a * b1 * b2) + (a * b3) */
225: for (i = 0; i < this->N; i++)
226: {
227: c[i] = (t1[i] + t2[i]) & mod_q_mask;
228: }
229: free(t2);
230: }
231: free(t1);
232: }
233:
234: METHOD(ntru_poly_t, destroy, void,
235: private_ntru_poly_t *this)
236: {
237: memwipe(this->indices, sizeof(uint16_t) * get_size(this));
238: free(this->indices);
239: free(this);
240: }
241:
242: /**
243: * Creates an empty ntru_poly_t object with space allocated for indices
244: */
245: static private_ntru_poly_t* ntru_poly_create(uint16_t N, uint16_t q,
246: uint32_t indices_len_p,
247: uint32_t indices_len_m,
248: bool is_product_form)
249: {
250: private_ntru_poly_t *this;
251: int n;
252:
253: INIT(this,
254: .public = {
255: .get_size = _get_size,
256: .get_indices = _get_indices,
257: .get_array = _get_array,
258: .ring_mult = _ring_mult,
259: .destroy = _destroy,
260: },
261: .N = N,
262: .q = q,
263: );
264:
265: if (is_product_form)
266: {
267: this->num_polynomials = 3;
268: for (n = 0; n < 3; n++)
269: {
270: this->indices_len[n].p = 0xff & indices_len_p;
271: this->indices_len[n].m = 0xff & indices_len_m;
272: this->num_indices += this->indices_len[n].p +
273: this->indices_len[n].m;
274: indices_len_p >>= 8;
275: indices_len_m >>= 8;
276: }
277: }
278: else
279: {
280: this->num_polynomials = 1;
281: this->indices_len[0].p = indices_len_p;
282: this->indices_len[0].m = indices_len_m;
283: this->num_indices = indices_len_p + indices_len_m;
284: }
285: this->indices = malloc(sizeof(uint16_t) * this->num_indices);
286:
287: return this;
288: }
289:
290: /*
291: * Described in header.
292: */
293: ntru_poly_t *ntru_poly_create_from_seed(ext_out_function_t mgf1_type,
294: chunk_t seed, uint8_t c_bits,
295: uint16_t N, uint16_t q,
296: uint32_t indices_len_p,
297: uint32_t indices_len_m,
298: bool is_product_form)
299: {
300: private_ntru_poly_t *this;
301: int n, num_indices, index_i = 0;
302: uint32_t index, limit;
303: uint8_t *used;
304: xof_bitspender_t *bitspender;
305:
306: bitspender = xof_bitspender_create(mgf1_type, seed, TRUE);
307: if (!bitspender)
308: {
309: return NULL;
310: }
311: this = ntru_poly_create(N, q, indices_len_p, indices_len_m, is_product_form);
312: used = malloc(N);
313: limit = N * ((1 << c_bits) / N);
314:
315: /* generate indices for all polynomials */
316: for (n = 0; n < this->num_polynomials; n++)
317: {
318: memset(used, 0, N);
319: num_indices = this->indices_len[n].p + this->indices_len[n].m;
320:
321: /* generate indices for a single polynomial */
322: while (num_indices)
323: {
324: /* generate a random candidate index with a size of c_bits */
325: do
326: {
327: if (!bitspender->get_bits(bitspender, c_bits, &index))
328: {
329: bitspender->destroy(bitspender);
330: destroy(this);
331: free(used);
332: return NULL;
333: }
334: }
335: while (index >= limit);
336:
337: /* form index and check if unique */
338: index %= N;
339: if (!used[index])
340: {
341: used[index] = 1;
342: this->indices[index_i++] = index;
343: num_indices--;
344: }
345: }
346: }
347:
348: bitspender->destroy(bitspender);
349: free(used);
350:
351: return &this->public;
352: }
353:
354: /*
355: * Described in header.
356: */
357: ntru_poly_t *ntru_poly_create_from_data(uint16_t *data, uint16_t N, uint16_t q,
358: uint32_t indices_len_p,
359: uint32_t indices_len_m,
360: bool is_product_form)
361: {
362: private_ntru_poly_t *this;
363: int i;
364:
365: this = ntru_poly_create(N, q, indices_len_p, indices_len_m, is_product_form);
366:
367: for (i = 0; i < this->num_indices; i++)
368: {
369: this->indices[i] = data[i];
370: }
371:
372: return &this->public;
373: }
374:
375: EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_poly_create_from_seed);
376:
377: EXPORT_FUNCTION_FOR_TESTS(ntru, ntru_poly_create_from_data);
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>