Annotation of embedaddon/strongswan/src/libstrongswan/plugins/ntru/ntru_poly.c, revision 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>