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>