/
githubmirror
/
libgcrypt
Обзор
Документация
Войти
/
githubmirror
/
libgcrypt
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
cipher/dilithium-common.c
1 385 строк
43 KB
NIIBE Yutaka
cipher:dilithium: Don't include unused freeze function.
01 июл 2025, 03:20
Не верифицирован
01 июл 2025, 03:20
aeb775a
Код
Авторство
О чём код?
/* dilithium-common.c - the Dilithium (common part) * Copyright (C) 2025 g10 Code GmbH * * This file was modified for use by Libgcrypt. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This file 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see <https://www.gnu.org/licenses/>. * SPDX-License-Identifier: LGPL-2.1-or-later * * You can also use this file under the same licence of original code. * SPDX-License-Identifier: CC0 OR Apache-2.0 * */ /* Original code from: Repository: https://github.com/pq-crystals/dilithium.git Branch: master Commit: 444cdcc84eb36b66fe27b3a2529ee48f6d8150c2 Licence: Public Domain (https://creativecommons.org/share-your-work/public-domain/cc0/); or Apache 2.0 License (https://www.apache.org/licenses/LICENSE-2.0.html). Authors: Léo Ducas Eike Kiltz Tancrède Lepoint Vadim Lyubashevsky Gregor Seiler Peter Schwabe Damien Stehlé Dilithium Home: https://github.com/pq-crystals/dilithium.git */ /*************** dilithium/ref/ntt.h */ static void ntt(int32_t a[N]); static void invntt_tomont(int32_t a[N]); /*************** dilithium/ref/ntt.c */ static const int32_t zetas[N] = { 0, 25847, -2608894, -518909, 237124, -777960, -876248, 466468, 1826347, 2353451, -359251, -2091905, 3119733, -2884855, 3111497, 2680103, 2725464, 1024112, -1079900, 3585928, -549488, -1119584, 2619752, -2108549, -2118186, -3859737, -1399561, -3277672, 1757237, -19422, 4010497, 280005, 2706023, 95776, 3077325, 3530437, -1661693, -3592148, -2537516, 3915439, -3861115, -3043716, 3574422, -2867647, 3539968, -300467, 2348700, -539299, -1699267, -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596, 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892, -2797779, -3930395, -1528703, -3677745, -3041255, -1452451, 3475950, 2176455, -1585221, -1257611, 1939314, -4083598, -1000202, -3190144, -3157330, -3632928, 126922, 3412210, -983419, 2147896, 2715295, -2967645, -3693493, -411027, -2477047, -671102, -1228525, -22981, -1308169, -381987, 1349076, 1852771, -1430430, -3343383, 264944, 508951, 3097992, 44288, -1100098, 904516, 3958618, -3724342, -8578, 1653064, -3249728, 2389356, -210977, 759969, -1316856, 189548, -3553272, 3159746, -1851402, -2409325, -177440, 1315589, 1341330, 1285669, -1584928, -812732, -1439742, -3019102, -3881060, -3628969, 3839961, 2091667, 3407706, 2316500, 3817976, -3342478, 2244091, -2446433, -3562462, 266997, 2434439, -1235728, 3513181, -3520352, -3759364, -1197226, -3193378, 900702, 1859098, 909542, 819034, 495491, -1613174, -43260, -522500, -655327, -3122442, 2031748, 3207046, -3556995, -525098, -768622, -3595838, 342297, 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044, 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, 1595974, -3767016, 1250494, 2635921, -3548272, -2994039, 1869119, 1903435, -1050970, -1333058, 1237275, -3318210, -1430225, -451100, 1312455, 3306115, -1962642, -1279661, 1917081, -2546312, -1374803, 1500165, 777191, 2235880, 3406031, -542412, -2831860, -1671176, -1846953, -2584293, -3724270, 594136, -3776993, -2013608, 2432395, 2454455, -164721, 1957272, 3369112, 185531, -1207385, -3183426, 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, -3038916, 3523897, 3866901, 269760, 2213111, -975884, 1717735, 472078, -426683, 1723600, -1803090, 1910376, -1667432, -1104333, -260646, -3833893, -2939036, -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782 }; /************************************************* * Name: ntt * * Description: Forward NTT, in-place. No modular reduction is performed after * additions or subtractions. Output vector is in bitreversed order. * * Arguments: - uint32_t p[N]: input/output coefficient array **************************************************/ void ntt(int32_t a[N]) { unsigned int len, start, j, k; int32_t zeta, t; k = 0; for(len = 128; len > 0; len >>= 1) { for(start = 0; start < N; start = j + len) { zeta = zetas[++k]; for(j = start; j < start + len; ++j) { t = montgomery_reduce((int64_t)zeta * a[j + len]); a[j + len] = a[j] - t; a[j] = a[j] + t; } } } } /************************************************* * Name: invntt_tomont * * Description: Inverse NTT and multiplication by Montgomery factor 2^32. * In-place. No modular reductions after additions or * subtractions; input coefficients need to be smaller than * Q in absolute value. Output coefficient are smaller than Q in * absolute value. * * Arguments: - uint32_t p[N]: input/output coefficient array **************************************************/ void invntt_tomont(int32_t a[N]) { unsigned int start, len, j, k; int32_t t, zeta; const int32_t f = 41978; /* mont^2/256 */ k = 256; for(len = 1; len < N; len <<= 1) { for(start = 0; start < N; start = j + len) { zeta = -zetas[--k]; for(j = start; j < start + len; ++j) { t = a[j]; a[j] = t + a[j + len]; a[j + len] = t - a[j + len]; a[j + len] = montgomery_reduce((int64_t)zeta * a[j + len]); } } } for(j = 0; j < N; ++j) { a[j] = montgomery_reduce((int64_t)f * a[j]); } } /*************** dilithium/ref/rounding.h */ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 static int32_t decompose_88(int32_t *a0, int32_t a); #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 static int32_t decompose_32(int32_t *a0, int32_t a); #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 static unsigned int make_hint_88(int32_t a0, int32_t a1); #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 static unsigned int make_hint_32(int32_t a0, int32_t a1); #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 static int32_t use_hint_88(int32_t a, unsigned int hint); #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 static int32_t use_hint_32(int32_t a, unsigned int hint); #endif /*************** dilithium/ref/rounding.c */ /************************************************* * Name: power2round * * Description: For finite field element a, compute a0, a1 such that * a mod^+ Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}. * Assumes a to be standard representative. * * Arguments: - int32_t a: input element * - int32_t *a0: pointer to output element a0 * * Returns a1. **************************************************/ int32_t power2round(int32_t *a0, int32_t a) { int32_t a1; a1 = (a + (1 << (D-1)) - 1) >> D; *a0 = a - (a1 << D); return a1; } /************************************************* * Name: decompose * * Description: For finite field element a, compute high and low bits a0, a1 such * that a mod^+ Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except * if a1 = (Q-1)/ALPHA where we set a1 = 0 and * -ALPHA/2 <= a0 = a mod^+ Q - Q < 0. Assumes a to be standard * representative. * * Arguments: - int32_t a: input element * - int32_t *a0: pointer to output element a0 * * Returns a1. **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 int32_t decompose_88(int32_t *a0, int32_t a) { int32_t a1; a1 = (a + 127) >> 7; a1 = (a1*11275 + (1 << 23)) >> 24; a1 ^= ((43 - a1) >> 31) & a1; *a0 = a - a1*2*GAMMA2_88; *a0 -= (((Q-1)/2 - *a0) >> 31) & Q; return a1; } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 int32_t decompose_32(int32_t *a0, int32_t a) { int32_t a1; a1 = (a + 127) >> 7; a1 = (a1*1025 + (1 << 21)) >> 22; a1 &= 15; *a0 = a - a1*2*GAMMA2_32; *a0 -= (((Q-1)/2 - *a0) >> 31) & Q; return a1; } #endif /************************************************* * Name: make_hint * * Description: Compute hint bit indicating whether the low bits of the * input element overflow into the high bits. * * Arguments: - int32_t a0: low bits of input element * - int32_t a1: high bits of input element * * Returns 1 if overflow. **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 unsigned int make_hint_88(int32_t a0, int32_t a1) { if(a0 > GAMMA2_88 || a0 < -GAMMA2_88 || (a0 == -GAMMA2_88 && a1 != 0)) return 1; return 0; } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 unsigned int make_hint_32(int32_t a0, int32_t a1) { if(a0 > GAMMA2_32 || a0 < -GAMMA2_32 || (a0 == -GAMMA2_32 && a1 != 0)) return 1; return 0; } #endif /************************************************* * Name: use_hint * * Description: Correct high bits according to hint. * * Arguments: - int32_t a: input element * - unsigned int hint: hint bit * * Returns corrected high bits. **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 int32_t use_hint_88(int32_t a, unsigned int hint) { int32_t a0, a1; a1 = decompose_88(&a0, a); if(hint == 0) return a1; if(a0 > 0) return (a1 == 43) ? 0 : a1 + 1; else return (a1 == 0) ? 43 : a1 - 1; } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 int32_t use_hint_32(int32_t a, unsigned int hint) { int32_t a0, a1; a1 = decompose_32(&a0, a); if(hint == 0) return a1; if(a0 > 0) return (a1 + 1) & 15; else return (a1 - 1) & 15; } #endif /*************** dilithium/ref/poly.c */ #ifdef DBENCH extern const uint64_t timing_overhead; extern uint64_t *tred, *tadd, *tmul, *tround, *tsample, *tpack; #define DBENCH_START() uint64_t time = cpucycles() #define DBENCH_STOP(t) t += cpucycles() - time - timing_overhead #else #define DBENCH_START() #define DBENCH_STOP(t) #endif /************************************************* * Name: poly_reduce * * Description: Inplace reduction of all coefficients of polynomial to * representative in [-6283008,6283008]. * * Arguments: - poly *a: pointer to input/output polynomial **************************************************/ void poly_reduce(poly *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) a->coeffs[i] = reduce32(a->coeffs[i]); DBENCH_STOP(*tred); } /************************************************* * Name: poly_caddq * * Description: For all coefficients of in/out polynomial add Q if * coefficient is negative. * * Arguments: - poly *a: pointer to input/output polynomial **************************************************/ void poly_caddq(poly *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) a->coeffs[i] = caddq(a->coeffs[i]); DBENCH_STOP(*tred); } /************************************************* * Name: poly_add * * Description: Add polynomials. No modular reduction is performed. * * Arguments: - poly *c: pointer to output polynomial * - const poly *a: pointer to first summand * - const poly *b: pointer to second summand **************************************************/ void poly_add(poly *c, const poly *a, const poly *b) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; DBENCH_STOP(*tadd); } /************************************************* * Name: poly_sub * * Description: Subtract polynomials. No modular reduction is * performed. * * Arguments: - poly *c: pointer to output polynomial * - const poly *a: pointer to first input polynomial * - const poly *b: pointer to second input polynomial to be * subtraced from first input polynomial **************************************************/ void poly_sub(poly *c, const poly *a, const poly *b) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; DBENCH_STOP(*tadd); } /************************************************* * Name: poly_shiftl * * Description: Multiply polynomial by 2^D without modular reduction. Assumes * input coefficients to be less than 2^{31-D} in absolute value. * * Arguments: - poly *a: pointer to input/output polynomial **************************************************/ void poly_shiftl(poly *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) a->coeffs[i] <<= D; DBENCH_STOP(*tmul); } /************************************************* * Name: poly_ntt * * Description: Inplace forward NTT. Coefficients can grow by * 8*Q in absolute value. * * Arguments: - poly *a: pointer to input/output polynomial **************************************************/ void poly_ntt(poly *a) { DBENCH_START(); ntt(a->coeffs); DBENCH_STOP(*tmul); } /************************************************* * Name: poly_invntt_tomont * * Description: Inplace inverse NTT and multiplication by 2^{32}. * Input coefficients need to be less than Q in absolute * value and output coefficients are again bounded by Q. * * Arguments: - poly *a: pointer to input/output polynomial **************************************************/ void poly_invntt_tomont(poly *a) { DBENCH_START(); invntt_tomont(a->coeffs); DBENCH_STOP(*tmul); } /************************************************* * Name: poly_pointwise_montgomery * * Description: Pointwise multiplication of polynomials in NTT domain * representation and multiplication of resulting polynomial * by 2^{-32}. * * Arguments: - poly *c: pointer to output polynomial * - const poly *a: pointer to first input polynomial * - const poly *b: pointer to second input polynomial **************************************************/ void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); DBENCH_STOP(*tmul); } /************************************************* * Name: poly_power2round * * Description: For all coefficients c of the input polynomial, * compute c0, c1 such that c mod Q = c1*2^D + c0 * with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be * standard representatives. * * Arguments: - poly *a1: pointer to output polynomial with coefficients c1 * - poly *a0: pointer to output polynomial with coefficients c0 * - const poly *a: pointer to input polynomial **************************************************/ void poly_power2round(poly *a1, poly *a0, const poly *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) a1->coeffs[i] = power2round(&a0->coeffs[i], a->coeffs[i]); DBENCH_STOP(*tround); } /************************************************* * Name: poly_decompose * * Description: For all coefficients c of the input polynomial, * compute high and low bits c0, c1 such c mod Q = c1*ALPHA + c0 * with -ALPHA/2 < c0 <= ALPHA/2 except c1 = (Q-1)/ALPHA where we * set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0. * Assumes coefficients to be standard representatives. * * Arguments: - poly *a1: pointer to output polynomial with coefficients c1 * - poly *a0: pointer to output polynomial with coefficients c0 * - const poly *a: pointer to input polynomial **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 static void poly_decompose_88(poly *a1, poly *a0, const poly *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) a1->coeffs[i] = decompose_88(&a0->coeffs[i], a->coeffs[i]); DBENCH_STOP(*tround); } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 static void poly_decompose_32(poly *a1, poly *a0, const poly *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) a1->coeffs[i] = decompose_32(&a0->coeffs[i], a->coeffs[i]); DBENCH_STOP(*tround); } #endif /************************************************* * Name: poly_make_hint * * Description: Compute hint polynomial. The coefficients of which indicate * whether the low bits of the corresponding coefficient of * the input polynomial overflow into the high bits. * * Arguments: - poly *h: pointer to output hint polynomial * - const poly *a0: pointer to low part of input polynomial * - const poly *a1: pointer to high part of input polynomial * * Returns number of 1 bits. **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 static unsigned int poly_make_hint_88(poly *h, const poly *a0, const poly *a1) { unsigned int i, s = 0; DBENCH_START(); for(i = 0; i < N; ++i) { h->coeffs[i] = make_hint_88(a0->coeffs[i], a1->coeffs[i]); s += h->coeffs[i]; } DBENCH_STOP(*tround); return s; } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 static unsigned int poly_make_hint_32(poly *h, const poly *a0, const poly *a1) { unsigned int i, s = 0; DBENCH_START(); for(i = 0; i < N; ++i) { h->coeffs[i] = make_hint_32(a0->coeffs[i], a1->coeffs[i]); s += h->coeffs[i]; } DBENCH_STOP(*tround); return s; } #endif /************************************************* * Name: poly_use_hint * * Description: Use hint polynomial to correct the high bits of a polynomial. * * Arguments: - poly *b: pointer to output polynomial with corrected high bits * - const poly *a: pointer to input polynomial * - const poly *h: pointer to input hint polynomial **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 static void poly_use_hint_88(poly *b, const poly *a, const poly *h) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) b->coeffs[i] = use_hint_88(a->coeffs[i], h->coeffs[i]); DBENCH_STOP(*tround); } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 static void poly_use_hint_32(poly *b, const poly *a, const poly *h) { unsigned int i; DBENCH_START(); for(i = 0; i < N; ++i) b->coeffs[i] = use_hint_32(a->coeffs[i], h->coeffs[i]); DBENCH_STOP(*tround); } #endif /************************************************* * Name: poly_chknorm * * Description: Check infinity norm of polynomial against given bound. * Assumes input coefficients were reduced by reduce32(). * * Arguments: - const poly *a: pointer to polynomial * - int32_t B: norm bound * * Returns 0 if norm is strictly smaller than B <= (Q-1)/8 and 1 otherwise. **************************************************/ int poly_chknorm(const poly *a, int32_t B) { unsigned int i; int32_t t; DBENCH_START(); if(B > (Q-1)/8) return 1; /* It is ok to leak which coefficient violates the bound since the probability for each coefficient is independent of secret data but we must not leak the sign of the centralized representative. */ for(i = 0; i < N; ++i) { /* Absolute value */ t = a->coeffs[i] >> 31; t = a->coeffs[i] - (t & 2*a->coeffs[i]); if(t >= B) { DBENCH_STOP(*tsample); return 1; } } DBENCH_STOP(*tsample); return 0; } /************************************************* * Name: rej_uniform * * Description: Sample uniformly random coefficients in [0, Q-1] by * performing rejection sampling on array of random bytes. * * Arguments: - int32_t *a: pointer to output array (allocated) * - unsigned int len: number of coefficients to be sampled * - const uint8_t *buf: array of random bytes * - unsigned int buflen: length of array of random bytes * * Returns number of sampled coefficients. Can be smaller than len if not enough * random bytes were given. **************************************************/ static unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, unsigned int buflen) { unsigned int ctr, pos; uint32_t t; DBENCH_START(); ctr = pos = 0; while(ctr < len && pos + 3 <= buflen) { t = buf[pos++]; t |= (uint32_t)buf[pos++] << 8; t |= (uint32_t)buf[pos++] << 16; t &= 0x7FFFFF; if(t < Q) a[ctr++] = t; } DBENCH_STOP(*tsample); return ctr; } /************************************************* * Name: poly_uniform * * Description: Sample polynomial with uniformly random coefficients * in [0,Q-1] by performing rejection sampling on the * output stream of SHAKE128(seed|nonce) * * Arguments: - poly *a: pointer to output polynomial * - const uint8_t seed[]: byte array with seed of length SEEDBYTES * - uint16_t nonce: 2-byte nonce **************************************************/ #define POLY_UNIFORM_NBLOCKS ((768 + STREAM128_BLOCKBYTES - 1)/STREAM128_BLOCKBYTES) void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) { unsigned int i, ctr, off; unsigned int buflen = POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES; uint8_t buf[POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES + 2]; stream128_state state; stream128_init(&state, seed, nonce); stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); ctr = rej_uniform(a->coeffs, N, buf, buflen); while(ctr < N) { off = buflen % 3; for(i = 0; i < off; ++i) buf[i] = buf[buflen - off + i]; stream128_squeezeblocks(buf + off, 1, &state); buflen = STREAM128_BLOCKBYTES + off; ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen); } stream128_close(&state); } /************************************************* * Name: rej_eta * * Description: Sample uniformly random coefficients in [-ETA, ETA] by * performing rejection sampling on array of random bytes. * * Arguments: - int32_t *a: pointer to output array (allocated) * - unsigned int len: number of coefficients to be sampled * - const uint8_t *buf: array of random bytes * - unsigned int buflen: length of array of random bytes * * Returns number of sampled coefficients. Can be smaller than len if not enough * random bytes were given. **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 || DILITHIUM_MODE == 5 static unsigned int rej_eta_2(int32_t *a, unsigned int len, const uint8_t *buf, unsigned int buflen) { unsigned int ctr, pos; uint32_t t0, t1; DBENCH_START(); ctr = pos = 0; while(ctr < len && pos < buflen) { t0 = buf[pos] & 0x0F; t1 = buf[pos++] >> 4; if(t0 < 15) { t0 = t0 - (205*t0 >> 10)*5; a[ctr++] = 2 - t0; } if(t1 < 15 && ctr < len) { t1 = t1 - (205*t1 >> 10)*5; a[ctr++] = 2 - t1; } } DBENCH_STOP(*tsample); return ctr; } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 static unsigned int rej_eta_4(int32_t *a, unsigned int len, const uint8_t *buf, unsigned int buflen) { unsigned int ctr, pos; uint32_t t0, t1; DBENCH_START(); ctr = pos = 0; while(ctr < len && pos < buflen) { t0 = buf[pos] & 0x0F; t1 = buf[pos++] >> 4; if(t0 < 9) a[ctr++] = 4 - t0; if(t1 < 9 && ctr < len) a[ctr++] = 4 - t1; } DBENCH_STOP(*tsample); return ctr; } #endif /************************************************* * Name: poly_uniform_eta * * Description: Sample polynomial with uniformly random coefficients * in [-ETA,ETA] by performing rejection sampling on the * output stream from SHAKE256(seed|nonce) * * Arguments: - poly *a: pointer to output polynomial * - const uint8_t seed[]: byte array with seed of length CRHBYTES * - uint16_t nonce: 2-byte nonce **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 || DILITHIUM_MODE == 5 #define POLY_UNIFORM_ETA_NBLOCKS_2 ((136 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) static void poly_uniform_eta_2(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) { unsigned int ctr; unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS_2*STREAM256_BLOCKBYTES; uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS_2*STREAM256_BLOCKBYTES]; stream256_state state; stream256_init(&state, seed, nonce); stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS_2, &state); ctr = rej_eta_2(a->coeffs, N, buf, buflen); while(ctr < N) { stream256_squeezeblocks(buf, 1, &state); ctr += rej_eta_2(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); } stream256_close(&state); } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 #define POLY_UNIFORM_ETA_NBLOCKS_4 ((227 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) static void poly_uniform_eta_4(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) { unsigned int ctr; unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS_4*STREAM256_BLOCKBYTES; uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS_4*STREAM256_BLOCKBYTES]; stream256_state state; stream256_init(&state, seed, nonce); stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS_4, &state); ctr = rej_eta_4(a->coeffs, N, buf, buflen); while(ctr < N) { stream256_squeezeblocks(buf, 1, &state); ctr += rej_eta_4(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); } stream256_close(&state); } #endif /************************************************* * Name: poly_uniform_gamma1m1 * * Description: Sample polynomial with uniformly random coefficients * in [-(GAMMA1 - 1), GAMMA1] by unpacking output stream * of SHAKE256(seed|nonce) * * Arguments: - poly *a: pointer to output polynomial * - const uint8_t seed[]: byte array with seed of length CRHBYTES * - uint16_t nonce: 16-bit nonce **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 #define POLY_UNIFORM_GAMMA1_NBLOCKS_17 ((POLYZ_PACKEDBYTES_17 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) static void polyz_unpack_17(poly *r, const uint8_t *a);/* Forward declarations */ static void poly_uniform_gamma1_17(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) { uint8_t buf[POLY_UNIFORM_GAMMA1_NBLOCKS_17*STREAM256_BLOCKBYTES]; stream256_state state; stream256_init(&state, seed, nonce); stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1_NBLOCKS_17, &state); polyz_unpack_17(a, buf); stream256_close(&state); } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 #define POLY_UNIFORM_GAMMA1_NBLOCKS_19 ((POLYZ_PACKEDBYTES_19 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) static void polyz_unpack_19(poly *r, const uint8_t *a);/* Forward declarations */ static void poly_uniform_gamma1_19(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) { uint8_t buf[POLY_UNIFORM_GAMMA1_NBLOCKS_19*STREAM256_BLOCKBYTES]; stream256_state state; stream256_init(&state, seed, nonce); stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1_NBLOCKS_19, &state); polyz_unpack_19(a, buf); stream256_close(&state); } #endif /************************************************* * Name: polyeta_pack * * Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. * * Arguments: - uint8_t *r: pointer to output byte array with at least * POLYETA_PACKEDBYTES bytes * - const poly *a: pointer to input polynomial **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 || DILITHIUM_MODE == 5 static void polyeta_pack_2(uint8_t *r, const poly *a) { unsigned int i; uint8_t t[8]; DBENCH_START(); for(i = 0; i < N/8; ++i) { t[0] = ETA2 - a->coeffs[8*i+0]; t[1] = ETA2 - a->coeffs[8*i+1]; t[2] = ETA2 - a->coeffs[8*i+2]; t[3] = ETA2 - a->coeffs[8*i+3]; t[4] = ETA2 - a->coeffs[8*i+4]; t[5] = ETA2 - a->coeffs[8*i+5]; t[6] = ETA2 - a->coeffs[8*i+6]; t[7] = ETA2 - a->coeffs[8*i+7]; r[3*i+0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); r[3*i+1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); r[3*i+2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); } DBENCH_STOP(*tpack); } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 static void polyeta_pack_4(uint8_t *r, const poly *a) { unsigned int i; uint8_t t[8]; DBENCH_START(); for(i = 0; i < N/2; ++i) { t[0] = ETA4 - a->coeffs[2*i+0]; t[1] = ETA4 - a->coeffs[2*i+1]; r[i] = t[0] | (t[1] << 4); } DBENCH_STOP(*tpack); } #endif /************************************************* * Name: polyeta_unpack * * Description: Unpack polynomial with coefficients in [-ETA,ETA]. * * Arguments: - poly *r: pointer to output polynomial * - const uint8_t *a: byte array with bit-packed polynomial **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 || DILITHIUM_MODE == 5 static void polyeta_unpack_2(poly *r, const uint8_t *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N/8; ++i) { r->coeffs[8*i+0] = (a[3*i+0] >> 0) & 7; r->coeffs[8*i+1] = (a[3*i+0] >> 3) & 7; r->coeffs[8*i+2] = ((a[3*i+0] >> 6) | (a[3*i+1] << 2)) & 7; r->coeffs[8*i+3] = (a[3*i+1] >> 1) & 7; r->coeffs[8*i+4] = (a[3*i+1] >> 4) & 7; r->coeffs[8*i+5] = ((a[3*i+1] >> 7) | (a[3*i+2] << 1)) & 7; r->coeffs[8*i+6] = (a[3*i+2] >> 2) & 7; r->coeffs[8*i+7] = (a[3*i+2] >> 5) & 7; r->coeffs[8*i+0] = ETA2 - r->coeffs[8*i+0]; r->coeffs[8*i+1] = ETA2 - r->coeffs[8*i+1]; r->coeffs[8*i+2] = ETA2 - r->coeffs[8*i+2]; r->coeffs[8*i+3] = ETA2 - r->coeffs[8*i+3]; r->coeffs[8*i+4] = ETA2 - r->coeffs[8*i+4]; r->coeffs[8*i+5] = ETA2 - r->coeffs[8*i+5]; r->coeffs[8*i+6] = ETA2 - r->coeffs[8*i+6]; r->coeffs[8*i+7] = ETA2 - r->coeffs[8*i+7]; } DBENCH_STOP(*tpack); } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 static void polyeta_unpack_4(poly *r, const uint8_t *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N/2; ++i) { r->coeffs[2*i+0] = a[i] & 0x0F; r->coeffs[2*i+1] = a[i] >> 4; r->coeffs[2*i+0] = ETA4 - r->coeffs[2*i+0]; r->coeffs[2*i+1] = ETA4 - r->coeffs[2*i+1]; } DBENCH_STOP(*tpack); } #endif /************************************************* * Name: polyt1_pack * * Description: Bit-pack polynomial t1 with coefficients fitting in 10 bits. * Input coefficients are assumed to be standard representatives. * * Arguments: - uint8_t *r: pointer to output byte array with at least * POLYT1_PACKEDBYTES bytes * - const poly *a: pointer to input polynomial **************************************************/ void polyt1_pack(uint8_t *r, const poly *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N/4; ++i) { r[5*i+0] = (a->coeffs[4*i+0] >> 0); r[5*i+1] = (a->coeffs[4*i+0] >> 8) | (a->coeffs[4*i+1] << 2); r[5*i+2] = (a->coeffs[4*i+1] >> 6) | (a->coeffs[4*i+2] << 4); r[5*i+3] = (a->coeffs[4*i+2] >> 4) | (a->coeffs[4*i+3] << 6); r[5*i+4] = (a->coeffs[4*i+3] >> 2); } DBENCH_STOP(*tpack); } /************************************************* * Name: polyt1_unpack * * Description: Unpack polynomial t1 with 10-bit coefficients. * Output coefficients are standard representatives. * * Arguments: - poly *r: pointer to output polynomial * - const uint8_t *a: byte array with bit-packed polynomial **************************************************/ void polyt1_unpack(poly *r, const uint8_t *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N/4; ++i) { r->coeffs[4*i+0] = ((a[5*i+0] >> 0) | ((uint32_t)a[5*i+1] << 8)) & 0x3FF; r->coeffs[4*i+1] = ((a[5*i+1] >> 2) | ((uint32_t)a[5*i+2] << 6)) & 0x3FF; r->coeffs[4*i+2] = ((a[5*i+2] >> 4) | ((uint32_t)a[5*i+3] << 4)) & 0x3FF; r->coeffs[4*i+3] = ((a[5*i+3] >> 6) | ((uint32_t)a[5*i+4] << 2)) & 0x3FF; } DBENCH_STOP(*tpack); } /************************************************* * Name: polyt0_pack * * Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. * * Arguments: - uint8_t *r: pointer to output byte array with at least * POLYT0_PACKEDBYTES bytes * - const poly *a: pointer to input polynomial **************************************************/ void polyt0_pack(uint8_t *r, const poly *a) { unsigned int i; uint32_t t[8]; DBENCH_START(); for(i = 0; i < N/8; ++i) { t[0] = (1 << (D-1)) - a->coeffs[8*i+0]; t[1] = (1 << (D-1)) - a->coeffs[8*i+1]; t[2] = (1 << (D-1)) - a->coeffs[8*i+2]; t[3] = (1 << (D-1)) - a->coeffs[8*i+3]; t[4] = (1 << (D-1)) - a->coeffs[8*i+4]; t[5] = (1 << (D-1)) - a->coeffs[8*i+5]; t[6] = (1 << (D-1)) - a->coeffs[8*i+6]; t[7] = (1 << (D-1)) - a->coeffs[8*i+7]; r[13*i+ 0] = t[0]; r[13*i+ 1] = t[0] >> 8; r[13*i+ 1] |= t[1] << 5; r[13*i+ 2] = t[1] >> 3; r[13*i+ 3] = t[1] >> 11; r[13*i+ 3] |= t[2] << 2; r[13*i+ 4] = t[2] >> 6; r[13*i+ 4] |= t[3] << 7; r[13*i+ 5] = t[3] >> 1; r[13*i+ 6] = t[3] >> 9; r[13*i+ 6] |= t[4] << 4; r[13*i+ 7] = t[4] >> 4; r[13*i+ 8] = t[4] >> 12; r[13*i+ 8] |= t[5] << 1; r[13*i+ 9] = t[5] >> 7; r[13*i+ 9] |= t[6] << 6; r[13*i+10] = t[6] >> 2; r[13*i+11] = t[6] >> 10; r[13*i+11] |= t[7] << 3; r[13*i+12] = t[7] >> 5; } DBENCH_STOP(*tpack); } /************************************************* * Name: polyt0_unpack * * Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. * * Arguments: - poly *r: pointer to output polynomial * - const uint8_t *a: byte array with bit-packed polynomial **************************************************/ void polyt0_unpack(poly *r, const uint8_t *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N/8; ++i) { r->coeffs[8*i+0] = a[13*i+0]; r->coeffs[8*i+0] |= (uint32_t)a[13*i+1] << 8; r->coeffs[8*i+0] &= 0x1FFF; r->coeffs[8*i+1] = a[13*i+1] >> 5; r->coeffs[8*i+1] |= (uint32_t)a[13*i+2] << 3; r->coeffs[8*i+1] |= (uint32_t)a[13*i+3] << 11; r->coeffs[8*i+1] &= 0x1FFF; r->coeffs[8*i+2] = a[13*i+3] >> 2; r->coeffs[8*i+2] |= (uint32_t)a[13*i+4] << 6; r->coeffs[8*i+2] &= 0x1FFF; r->coeffs[8*i+3] = a[13*i+4] >> 7; r->coeffs[8*i+3] |= (uint32_t)a[13*i+5] << 1; r->coeffs[8*i+3] |= (uint32_t)a[13*i+6] << 9; r->coeffs[8*i+3] &= 0x1FFF; r->coeffs[8*i+4] = a[13*i+6] >> 4; r->coeffs[8*i+4] |= (uint32_t)a[13*i+7] << 4; r->coeffs[8*i+4] |= (uint32_t)a[13*i+8] << 12; r->coeffs[8*i+4] &= 0x1FFF; r->coeffs[8*i+5] = a[13*i+8] >> 1; r->coeffs[8*i+5] |= (uint32_t)a[13*i+9] << 7; r->coeffs[8*i+5] &= 0x1FFF; r->coeffs[8*i+6] = a[13*i+9] >> 6; r->coeffs[8*i+6] |= (uint32_t)a[13*i+10] << 2; r->coeffs[8*i+6] |= (uint32_t)a[13*i+11] << 10; r->coeffs[8*i+6] &= 0x1FFF; r->coeffs[8*i+7] = a[13*i+11] >> 3; r->coeffs[8*i+7] |= (uint32_t)a[13*i+12] << 5; r->coeffs[8*i+7] &= 0x1FFF; r->coeffs[8*i+0] = (1 << (D-1)) - r->coeffs[8*i+0]; r->coeffs[8*i+1] = (1 << (D-1)) - r->coeffs[8*i+1]; r->coeffs[8*i+2] = (1 << (D-1)) - r->coeffs[8*i+2]; r->coeffs[8*i+3] = (1 << (D-1)) - r->coeffs[8*i+3]; r->coeffs[8*i+4] = (1 << (D-1)) - r->coeffs[8*i+4]; r->coeffs[8*i+5] = (1 << (D-1)) - r->coeffs[8*i+5]; r->coeffs[8*i+6] = (1 << (D-1)) - r->coeffs[8*i+6]; r->coeffs[8*i+7] = (1 << (D-1)) - r->coeffs[8*i+7]; } DBENCH_STOP(*tpack); } /************************************************* * Name: polyz_pack * * Description: Bit-pack polynomial with coefficients * in [-(GAMMA1 - 1), GAMMA1]. * * Arguments: - uint8_t *r: pointer to output byte array with at least * POLYZ_PACKEDBYTES bytes * - const poly *a: pointer to input polynomial **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 static void polyz_pack_17(uint8_t *r, const poly *a) { unsigned int i; uint32_t t[4]; DBENCH_START(); for(i = 0; i < N/4; ++i) { t[0] = GAMMA1_17 - a->coeffs[4*i+0]; t[1] = GAMMA1_17 - a->coeffs[4*i+1]; t[2] = GAMMA1_17 - a->coeffs[4*i+2]; t[3] = GAMMA1_17 - a->coeffs[4*i+3]; r[9*i+0] = t[0]; r[9*i+1] = t[0] >> 8; r[9*i+2] = t[0] >> 16; r[9*i+2] |= t[1] << 2; r[9*i+3] = t[1] >> 6; r[9*i+4] = t[1] >> 14; r[9*i+4] |= t[2] << 4; r[9*i+5] = t[2] >> 4; r[9*i+6] = t[2] >> 12; r[9*i+6] |= t[3] << 6; r[9*i+7] = t[3] >> 2; r[9*i+8] = t[3] >> 10; } DBENCH_STOP(*tpack); } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 static void polyz_pack_19(uint8_t *r, const poly *a) { unsigned int i; uint32_t t[4]; DBENCH_START(); for(i = 0; i < N/2; ++i) { t[0] = GAMMA1_19 - a->coeffs[2*i+0]; t[1] = GAMMA1_19 - a->coeffs[2*i+1]; r[5*i+0] = t[0]; r[5*i+1] = t[0] >> 8; r[5*i+2] = t[0] >> 16; r[5*i+2] |= t[1] << 4; r[5*i+3] = t[1] >> 4; r[5*i+4] = t[1] >> 12; } DBENCH_STOP(*tpack); } #endif /************************************************* * Name: polyz_unpack * * Description: Unpack polynomial z with coefficients * in [-(GAMMA1 - 1), GAMMA1]. * * Arguments: - poly *r: pointer to output polynomial * - const uint8_t *a: byte array with bit-packed polynomial **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 static void polyz_unpack_17(poly *r, const uint8_t *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N/4; ++i) { r->coeffs[4*i+0] = a[9*i+0]; r->coeffs[4*i+0] |= (uint32_t)a[9*i+1] << 8; r->coeffs[4*i+0] |= (uint32_t)a[9*i+2] << 16; r->coeffs[4*i+0] &= 0x3FFFF; r->coeffs[4*i+1] = a[9*i+2] >> 2; r->coeffs[4*i+1] |= (uint32_t)a[9*i+3] << 6; r->coeffs[4*i+1] |= (uint32_t)a[9*i+4] << 14; r->coeffs[4*i+1] &= 0x3FFFF; r->coeffs[4*i+2] = a[9*i+4] >> 4; r->coeffs[4*i+2] |= (uint32_t)a[9*i+5] << 4; r->coeffs[4*i+2] |= (uint32_t)a[9*i+6] << 12; r->coeffs[4*i+2] &= 0x3FFFF; r->coeffs[4*i+3] = a[9*i+6] >> 6; r->coeffs[4*i+3] |= (uint32_t)a[9*i+7] << 2; r->coeffs[4*i+3] |= (uint32_t)a[9*i+8] << 10; r->coeffs[4*i+3] &= 0x3FFFF; r->coeffs[4*i+0] = GAMMA1_17 - r->coeffs[4*i+0]; r->coeffs[4*i+1] = GAMMA1_17 - r->coeffs[4*i+1]; r->coeffs[4*i+2] = GAMMA1_17 - r->coeffs[4*i+2]; r->coeffs[4*i+3] = GAMMA1_17 - r->coeffs[4*i+3]; } DBENCH_STOP(*tpack); } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 static void polyz_unpack_19(poly *r, const uint8_t *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N/2; ++i) { r->coeffs[2*i+0] = a[5*i+0]; r->coeffs[2*i+0] |= (uint32_t)a[5*i+1] << 8; r->coeffs[2*i+0] |= (uint32_t)a[5*i+2] << 16; r->coeffs[2*i+0] &= 0xFFFFF; r->coeffs[2*i+1] = a[5*i+2] >> 4; r->coeffs[2*i+1] |= (uint32_t)a[5*i+3] << 4; r->coeffs[2*i+1] |= (uint32_t)a[5*i+4] << 12; /* r->coeffs[2*i+1] &= 0xFFFFF; */ /* No effect, since we're anyway at 20 bits */ r->coeffs[2*i+0] = GAMMA1_19 - r->coeffs[2*i+0]; r->coeffs[2*i+1] = GAMMA1_19 - r->coeffs[2*i+1]; } DBENCH_STOP(*tpack); } #endif /************************************************* * Name: polyw1_pack * * Description: Bit-pack polynomial w1 with coefficients in [0,15] or [0,43]. * Input coefficients are assumed to be standard representatives. * * Arguments: - uint8_t *r: pointer to output byte array with at least * POLYW1_PACKEDBYTES bytes * - const poly *a: pointer to input polynomial **************************************************/ #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 2 static void polyw1_pack_88(uint8_t *r, const poly *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N/4; ++i) { r[3*i+0] = a->coeffs[4*i+0]; r[3*i+0] |= a->coeffs[4*i+1] << 6; r[3*i+1] = a->coeffs[4*i+1] >> 2; r[3*i+1] |= a->coeffs[4*i+2] << 4; r[3*i+2] = a->coeffs[4*i+2] >> 4; r[3*i+2] |= a->coeffs[4*i+3] << 2; } DBENCH_STOP(*tpack); } #endif #if !defined(DILITHIUM_MODE) || DILITHIUM_MODE == 3 || DILITHIUM_MODE == 5 static void polyw1_pack_32(uint8_t *r, const poly *a) { unsigned int i; DBENCH_START(); for(i = 0; i < N/2; ++i) r[i] = a->coeffs[2*i+0] | (a->coeffs[2*i+1] << 4); DBENCH_STOP(*tpack); } #endif /*************** dilithium/ref/reduce.c */ /************************************************* * Name: montgomery_reduce * * Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, * compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. * * Arguments: - int64_t: finite field element a * * Returns r. **************************************************/ int32_t montgomery_reduce(int64_t a) { int32_t t; t = (int64_t)(int32_t)a*QINV; t = (a - (int64_t)t*Q) >> 32; return t; } /************************************************* * Name: reduce32 * * Description: For finite field element a with a <= 2^{31} - 2^{22} - 1, * compute r \equiv a (mod Q) such that -6283008 <= r <= 6283008. * * Arguments: - int32_t: finite field element a * * Returns r. **************************************************/ int32_t reduce32(int32_t a) { int32_t t; t = (a + (1 << 22)) >> 23; t = a - t*Q; return t; } /************************************************* * Name: caddq * * Description: Add Q if input coefficient is negative. * * Arguments: - int32_t: finite field element a * * Returns r. **************************************************/ int32_t caddq(int32_t a) { a += (a >> 31) & Q; return a; } #if 0 /* Not used */ /************************************************* * Name: freeze * * Description: For finite field element a, compute standard * representative r = a mod^+ Q. * * Arguments: - int32_t: finite field element a * * Returns r. **************************************************/ int32_t freeze(int32_t a) { a = reduce32(a); a = caddq(a); return a; } #endif