1*8fb009dcSAndroid Build Coastguard Worker /* Copyright (c) 2023, Google Inc.
2*8fb009dcSAndroid Build Coastguard Worker *
3*8fb009dcSAndroid Build Coastguard Worker * Permission to use, copy, modify, and/or distribute this software for any
4*8fb009dcSAndroid Build Coastguard Worker * purpose with or without fee is hereby granted, provided that the above
5*8fb009dcSAndroid Build Coastguard Worker * copyright notice and this permission notice appear in all copies.
6*8fb009dcSAndroid Build Coastguard Worker *
7*8fb009dcSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8*8fb009dcSAndroid Build Coastguard Worker * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9*8fb009dcSAndroid Build Coastguard Worker * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10*8fb009dcSAndroid Build Coastguard Worker * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11*8fb009dcSAndroid Build Coastguard Worker * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12*8fb009dcSAndroid Build Coastguard Worker * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13*8fb009dcSAndroid Build Coastguard Worker * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14*8fb009dcSAndroid Build Coastguard Worker
15*8fb009dcSAndroid Build Coastguard Worker #define OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER
16*8fb009dcSAndroid Build Coastguard Worker #include <openssl/experimental/kyber.h>
17*8fb009dcSAndroid Build Coastguard Worker
18*8fb009dcSAndroid Build Coastguard Worker #include <assert.h>
19*8fb009dcSAndroid Build Coastguard Worker #include <stdlib.h>
20*8fb009dcSAndroid Build Coastguard Worker
21*8fb009dcSAndroid Build Coastguard Worker #include <openssl/bytestring.h>
22*8fb009dcSAndroid Build Coastguard Worker #include <openssl/rand.h>
23*8fb009dcSAndroid Build Coastguard Worker
24*8fb009dcSAndroid Build Coastguard Worker #include "../internal.h"
25*8fb009dcSAndroid Build Coastguard Worker #include "../keccak/internal.h"
26*8fb009dcSAndroid Build Coastguard Worker #include "./internal.h"
27*8fb009dcSAndroid Build Coastguard Worker
28*8fb009dcSAndroid Build Coastguard Worker
29*8fb009dcSAndroid Build Coastguard Worker // See
30*8fb009dcSAndroid Build Coastguard Worker // https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf
31*8fb009dcSAndroid Build Coastguard Worker
prf(uint8_t * out,size_t out_len,const uint8_t in[33])32*8fb009dcSAndroid Build Coastguard Worker static void prf(uint8_t *out, size_t out_len, const uint8_t in[33]) {
33*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak(out, out_len, in, 33, boringssl_shake256);
34*8fb009dcSAndroid Build Coastguard Worker }
35*8fb009dcSAndroid Build Coastguard Worker
hash_h(uint8_t out[32],const uint8_t * in,size_t len)36*8fb009dcSAndroid Build Coastguard Worker static void hash_h(uint8_t out[32], const uint8_t *in, size_t len) {
37*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak(out, 32, in, len, boringssl_sha3_256);
38*8fb009dcSAndroid Build Coastguard Worker }
39*8fb009dcSAndroid Build Coastguard Worker
hash_g(uint8_t out[64],const uint8_t * in,size_t len)40*8fb009dcSAndroid Build Coastguard Worker static void hash_g(uint8_t out[64], const uint8_t *in, size_t len) {
41*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak(out, 64, in, len, boringssl_sha3_512);
42*8fb009dcSAndroid Build Coastguard Worker }
43*8fb009dcSAndroid Build Coastguard Worker
kdf(uint8_t * out,size_t out_len,const uint8_t * in,size_t len)44*8fb009dcSAndroid Build Coastguard Worker static void kdf(uint8_t *out, size_t out_len, const uint8_t *in, size_t len) {
45*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak(out, out_len, in, len, boringssl_shake256);
46*8fb009dcSAndroid Build Coastguard Worker }
47*8fb009dcSAndroid Build Coastguard Worker
48*8fb009dcSAndroid Build Coastguard Worker #define DEGREE 256
49*8fb009dcSAndroid Build Coastguard Worker #define RANK 3
50*8fb009dcSAndroid Build Coastguard Worker
51*8fb009dcSAndroid Build Coastguard Worker static const size_t kBarrettMultiplier = 5039;
52*8fb009dcSAndroid Build Coastguard Worker static const unsigned kBarrettShift = 24;
53*8fb009dcSAndroid Build Coastguard Worker static const uint16_t kPrime = 3329;
54*8fb009dcSAndroid Build Coastguard Worker static const int kLog2Prime = 12;
55*8fb009dcSAndroid Build Coastguard Worker static const uint16_t kHalfPrime = (/*kPrime=*/3329 - 1) / 2;
56*8fb009dcSAndroid Build Coastguard Worker static const int kDU = 10;
57*8fb009dcSAndroid Build Coastguard Worker static const int kDV = 4;
58*8fb009dcSAndroid Build Coastguard Worker // kInverseDegree is 128^-1 mod 3329; 128 because kPrime does not have a 512th
59*8fb009dcSAndroid Build Coastguard Worker // root of unity.
60*8fb009dcSAndroid Build Coastguard Worker static const uint16_t kInverseDegree = 3303;
61*8fb009dcSAndroid Build Coastguard Worker static const size_t kEncodedVectorSize =
62*8fb009dcSAndroid Build Coastguard Worker (/*kLog2Prime=*/12 * DEGREE / 8) * RANK;
63*8fb009dcSAndroid Build Coastguard Worker static const size_t kCompressedVectorSize = /*kDU=*/10 * RANK * DEGREE / 8;
64*8fb009dcSAndroid Build Coastguard Worker
65*8fb009dcSAndroid Build Coastguard Worker typedef struct scalar {
66*8fb009dcSAndroid Build Coastguard Worker // On every function entry and exit, 0 <= c < kPrime.
67*8fb009dcSAndroid Build Coastguard Worker uint16_t c[DEGREE];
68*8fb009dcSAndroid Build Coastguard Worker } scalar;
69*8fb009dcSAndroid Build Coastguard Worker
70*8fb009dcSAndroid Build Coastguard Worker typedef struct vector {
71*8fb009dcSAndroid Build Coastguard Worker scalar v[RANK];
72*8fb009dcSAndroid Build Coastguard Worker } vector;
73*8fb009dcSAndroid Build Coastguard Worker
74*8fb009dcSAndroid Build Coastguard Worker typedef struct matrix {
75*8fb009dcSAndroid Build Coastguard Worker scalar v[RANK][RANK];
76*8fb009dcSAndroid Build Coastguard Worker } matrix;
77*8fb009dcSAndroid Build Coastguard Worker
78*8fb009dcSAndroid Build Coastguard Worker // This bit of Python will be referenced in some of the following comments:
79*8fb009dcSAndroid Build Coastguard Worker //
80*8fb009dcSAndroid Build Coastguard Worker // p = 3329
81*8fb009dcSAndroid Build Coastguard Worker //
82*8fb009dcSAndroid Build Coastguard Worker // def bitreverse(i):
83*8fb009dcSAndroid Build Coastguard Worker // ret = 0
84*8fb009dcSAndroid Build Coastguard Worker // for n in range(7):
85*8fb009dcSAndroid Build Coastguard Worker // bit = i & 1
86*8fb009dcSAndroid Build Coastguard Worker // ret <<= 1
87*8fb009dcSAndroid Build Coastguard Worker // ret |= bit
88*8fb009dcSAndroid Build Coastguard Worker // i >>= 1
89*8fb009dcSAndroid Build Coastguard Worker // return ret
90*8fb009dcSAndroid Build Coastguard Worker
91*8fb009dcSAndroid Build Coastguard Worker // kNTTRoots = [pow(17, bitreverse(i), p) for i in range(128)]
92*8fb009dcSAndroid Build Coastguard Worker static const uint16_t kNTTRoots[128] = {
93*8fb009dcSAndroid Build Coastguard Worker 1, 1729, 2580, 3289, 2642, 630, 1897, 848, 1062, 1919, 193, 797,
94*8fb009dcSAndroid Build Coastguard Worker 2786, 3260, 569, 1746, 296, 2447, 1339, 1476, 3046, 56, 2240, 1333,
95*8fb009dcSAndroid Build Coastguard Worker 1426, 2094, 535, 2882, 2393, 2879, 1974, 821, 289, 331, 3253, 1756,
96*8fb009dcSAndroid Build Coastguard Worker 1197, 2304, 2277, 2055, 650, 1977, 2513, 632, 2865, 33, 1320, 1915,
97*8fb009dcSAndroid Build Coastguard Worker 2319, 1435, 807, 452, 1438, 2868, 1534, 2402, 2647, 2617, 1481, 648,
98*8fb009dcSAndroid Build Coastguard Worker 2474, 3110, 1227, 910, 17, 2761, 583, 2649, 1637, 723, 2288, 1100,
99*8fb009dcSAndroid Build Coastguard Worker 1409, 2662, 3281, 233, 756, 2156, 3015, 3050, 1703, 1651, 2789, 1789,
100*8fb009dcSAndroid Build Coastguard Worker 1847, 952, 1461, 2687, 939, 2308, 2437, 2388, 733, 2337, 268, 641,
101*8fb009dcSAndroid Build Coastguard Worker 1584, 2298, 2037, 3220, 375, 2549, 2090, 1645, 1063, 319, 2773, 757,
102*8fb009dcSAndroid Build Coastguard Worker 2099, 561, 2466, 2594, 2804, 1092, 403, 1026, 1143, 2150, 2775, 886,
103*8fb009dcSAndroid Build Coastguard Worker 1722, 1212, 1874, 1029, 2110, 2935, 885, 2154,
104*8fb009dcSAndroid Build Coastguard Worker };
105*8fb009dcSAndroid Build Coastguard Worker
106*8fb009dcSAndroid Build Coastguard Worker // kInverseNTTRoots = [pow(17, -bitreverse(i), p) for i in range(128)]
107*8fb009dcSAndroid Build Coastguard Worker static const uint16_t kInverseNTTRoots[128] = {
108*8fb009dcSAndroid Build Coastguard Worker 1, 1600, 40, 749, 2481, 1432, 2699, 687, 1583, 2760, 69, 543,
109*8fb009dcSAndroid Build Coastguard Worker 2532, 3136, 1410, 2267, 2508, 1355, 450, 936, 447, 2794, 1235, 1903,
110*8fb009dcSAndroid Build Coastguard Worker 1996, 1089, 3273, 283, 1853, 1990, 882, 3033, 2419, 2102, 219, 855,
111*8fb009dcSAndroid Build Coastguard Worker 2681, 1848, 712, 682, 927, 1795, 461, 1891, 2877, 2522, 1894, 1010,
112*8fb009dcSAndroid Build Coastguard Worker 1414, 2009, 3296, 464, 2697, 816, 1352, 2679, 1274, 1052, 1025, 2132,
113*8fb009dcSAndroid Build Coastguard Worker 1573, 76, 2998, 3040, 1175, 2444, 394, 1219, 2300, 1455, 2117, 1607,
114*8fb009dcSAndroid Build Coastguard Worker 2443, 554, 1179, 2186, 2303, 2926, 2237, 525, 735, 863, 2768, 1230,
115*8fb009dcSAndroid Build Coastguard Worker 2572, 556, 3010, 2266, 1684, 1239, 780, 2954, 109, 1292, 1031, 1745,
116*8fb009dcSAndroid Build Coastguard Worker 2688, 3061, 992, 2596, 941, 892, 1021, 2390, 642, 1868, 2377, 1482,
117*8fb009dcSAndroid Build Coastguard Worker 1540, 540, 1678, 1626, 279, 314, 1173, 2573, 3096, 48, 667, 1920,
118*8fb009dcSAndroid Build Coastguard Worker 2229, 1041, 2606, 1692, 680, 2746, 568, 3312,
119*8fb009dcSAndroid Build Coastguard Worker };
120*8fb009dcSAndroid Build Coastguard Worker
121*8fb009dcSAndroid Build Coastguard Worker // kModRoots = [pow(17, 2*bitreverse(i) + 1, p) for i in range(128)]
122*8fb009dcSAndroid Build Coastguard Worker static const uint16_t kModRoots[128] = {
123*8fb009dcSAndroid Build Coastguard Worker 17, 3312, 2761, 568, 583, 2746, 2649, 680, 1637, 1692, 723, 2606,
124*8fb009dcSAndroid Build Coastguard Worker 2288, 1041, 1100, 2229, 1409, 1920, 2662, 667, 3281, 48, 233, 3096,
125*8fb009dcSAndroid Build Coastguard Worker 756, 2573, 2156, 1173, 3015, 314, 3050, 279, 1703, 1626, 1651, 1678,
126*8fb009dcSAndroid Build Coastguard Worker 2789, 540, 1789, 1540, 1847, 1482, 952, 2377, 1461, 1868, 2687, 642,
127*8fb009dcSAndroid Build Coastguard Worker 939, 2390, 2308, 1021, 2437, 892, 2388, 941, 733, 2596, 2337, 992,
128*8fb009dcSAndroid Build Coastguard Worker 268, 3061, 641, 2688, 1584, 1745, 2298, 1031, 2037, 1292, 3220, 109,
129*8fb009dcSAndroid Build Coastguard Worker 375, 2954, 2549, 780, 2090, 1239, 1645, 1684, 1063, 2266, 319, 3010,
130*8fb009dcSAndroid Build Coastguard Worker 2773, 556, 757, 2572, 2099, 1230, 561, 2768, 2466, 863, 2594, 735,
131*8fb009dcSAndroid Build Coastguard Worker 2804, 525, 1092, 2237, 403, 2926, 1026, 2303, 1143, 2186, 2150, 1179,
132*8fb009dcSAndroid Build Coastguard Worker 2775, 554, 886, 2443, 1722, 1607, 1212, 2117, 1874, 1455, 1029, 2300,
133*8fb009dcSAndroid Build Coastguard Worker 2110, 1219, 2935, 394, 885, 2444, 2154, 1175,
134*8fb009dcSAndroid Build Coastguard Worker };
135*8fb009dcSAndroid Build Coastguard Worker
136*8fb009dcSAndroid Build Coastguard Worker // reduce_once reduces 0 <= x < 2*kPrime, mod kPrime.
reduce_once(uint16_t x)137*8fb009dcSAndroid Build Coastguard Worker static uint16_t reduce_once(uint16_t x) {
138*8fb009dcSAndroid Build Coastguard Worker assert(x < 2 * kPrime);
139*8fb009dcSAndroid Build Coastguard Worker const uint16_t subtracted = x - kPrime;
140*8fb009dcSAndroid Build Coastguard Worker uint16_t mask = 0u - (subtracted >> 15);
141*8fb009dcSAndroid Build Coastguard Worker // On Aarch64, omitting a |value_barrier_u16| results in a 2x speedup of Kyber
142*8fb009dcSAndroid Build Coastguard Worker // overall and Clang still produces constant-time code using `csel`. On other
143*8fb009dcSAndroid Build Coastguard Worker // platforms & compilers on godbolt that we care about, this code also
144*8fb009dcSAndroid Build Coastguard Worker // produces constant-time output.
145*8fb009dcSAndroid Build Coastguard Worker return (mask & x) | (~mask & subtracted);
146*8fb009dcSAndroid Build Coastguard Worker }
147*8fb009dcSAndroid Build Coastguard Worker
148*8fb009dcSAndroid Build Coastguard Worker // constant time reduce x mod kPrime using Barrett reduction. x must be less
149*8fb009dcSAndroid Build Coastguard Worker // than kPrime + 2×kPrime².
reduce(uint32_t x)150*8fb009dcSAndroid Build Coastguard Worker static uint16_t reduce(uint32_t x) {
151*8fb009dcSAndroid Build Coastguard Worker assert(x < kPrime + 2u * kPrime * kPrime);
152*8fb009dcSAndroid Build Coastguard Worker uint64_t product = (uint64_t)x * kBarrettMultiplier;
153*8fb009dcSAndroid Build Coastguard Worker uint32_t quotient = (uint32_t)(product >> kBarrettShift);
154*8fb009dcSAndroid Build Coastguard Worker uint32_t remainder = x - quotient * kPrime;
155*8fb009dcSAndroid Build Coastguard Worker return reduce_once(remainder);
156*8fb009dcSAndroid Build Coastguard Worker }
157*8fb009dcSAndroid Build Coastguard Worker
scalar_zero(scalar * out)158*8fb009dcSAndroid Build Coastguard Worker static void scalar_zero(scalar *out) { OPENSSL_memset(out, 0, sizeof(*out)); }
159*8fb009dcSAndroid Build Coastguard Worker
vector_zero(vector * out)160*8fb009dcSAndroid Build Coastguard Worker static void vector_zero(vector *out) { OPENSSL_memset(out, 0, sizeof(*out)); }
161*8fb009dcSAndroid Build Coastguard Worker
162*8fb009dcSAndroid Build Coastguard Worker // In place number theoretic transform of a given scalar.
163*8fb009dcSAndroid Build Coastguard Worker // Note that Kyber's kPrime 3329 does not have a 512th root of unity, so this
164*8fb009dcSAndroid Build Coastguard Worker // transform leaves off the last iteration of the usual FFT code, with the 128
165*8fb009dcSAndroid Build Coastguard Worker // relevant roots of unity being stored in |kNTTRoots|. This means the output
166*8fb009dcSAndroid Build Coastguard Worker // should be seen as 128 elements in GF(3329^2), with the coefficients of the
167*8fb009dcSAndroid Build Coastguard Worker // elements being consecutive entries in |s->c|.
scalar_ntt(scalar * s)168*8fb009dcSAndroid Build Coastguard Worker static void scalar_ntt(scalar *s) {
169*8fb009dcSAndroid Build Coastguard Worker int offset = DEGREE;
170*8fb009dcSAndroid Build Coastguard Worker // `int` is used here because using `size_t` throughout caused a ~5% slowdown
171*8fb009dcSAndroid Build Coastguard Worker // with Clang 14 on Aarch64.
172*8fb009dcSAndroid Build Coastguard Worker for (int step = 1; step < DEGREE / 2; step <<= 1) {
173*8fb009dcSAndroid Build Coastguard Worker offset >>= 1;
174*8fb009dcSAndroid Build Coastguard Worker int k = 0;
175*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < step; i++) {
176*8fb009dcSAndroid Build Coastguard Worker const uint32_t step_root = kNTTRoots[i + step];
177*8fb009dcSAndroid Build Coastguard Worker for (int j = k; j < k + offset; j++) {
178*8fb009dcSAndroid Build Coastguard Worker uint16_t odd = reduce(step_root * s->c[j + offset]);
179*8fb009dcSAndroid Build Coastguard Worker uint16_t even = s->c[j];
180*8fb009dcSAndroid Build Coastguard Worker s->c[j] = reduce_once(odd + even);
181*8fb009dcSAndroid Build Coastguard Worker s->c[j + offset] = reduce_once(even - odd + kPrime);
182*8fb009dcSAndroid Build Coastguard Worker }
183*8fb009dcSAndroid Build Coastguard Worker k += 2 * offset;
184*8fb009dcSAndroid Build Coastguard Worker }
185*8fb009dcSAndroid Build Coastguard Worker }
186*8fb009dcSAndroid Build Coastguard Worker }
187*8fb009dcSAndroid Build Coastguard Worker
vector_ntt(vector * a)188*8fb009dcSAndroid Build Coastguard Worker static void vector_ntt(vector *a) {
189*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
190*8fb009dcSAndroid Build Coastguard Worker scalar_ntt(&a->v[i]);
191*8fb009dcSAndroid Build Coastguard Worker }
192*8fb009dcSAndroid Build Coastguard Worker }
193*8fb009dcSAndroid Build Coastguard Worker
194*8fb009dcSAndroid Build Coastguard Worker // In place inverse number theoretic transform of a given scalar, with pairs of
195*8fb009dcSAndroid Build Coastguard Worker // entries of s->v being interpreted as elements of GF(3329^2). Just as with the
196*8fb009dcSAndroid Build Coastguard Worker // number theoretic transform, this leaves off the first step of the normal iFFT
197*8fb009dcSAndroid Build Coastguard Worker // to account for the fact that 3329 does not have a 512th root of unity, using
198*8fb009dcSAndroid Build Coastguard Worker // the precomputed 128 roots of unity stored in |kInverseNTTRoots|.
scalar_inverse_ntt(scalar * s)199*8fb009dcSAndroid Build Coastguard Worker static void scalar_inverse_ntt(scalar *s) {
200*8fb009dcSAndroid Build Coastguard Worker int step = DEGREE / 2;
201*8fb009dcSAndroid Build Coastguard Worker // `int` is used here because using `size_t` throughout caused a ~5% slowdown
202*8fb009dcSAndroid Build Coastguard Worker // with Clang 14 on Aarch64.
203*8fb009dcSAndroid Build Coastguard Worker for (int offset = 2; offset < DEGREE; offset <<= 1) {
204*8fb009dcSAndroid Build Coastguard Worker step >>= 1;
205*8fb009dcSAndroid Build Coastguard Worker int k = 0;
206*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < step; i++) {
207*8fb009dcSAndroid Build Coastguard Worker uint32_t step_root = kInverseNTTRoots[i + step];
208*8fb009dcSAndroid Build Coastguard Worker for (int j = k; j < k + offset; j++) {
209*8fb009dcSAndroid Build Coastguard Worker uint16_t odd = s->c[j + offset];
210*8fb009dcSAndroid Build Coastguard Worker uint16_t even = s->c[j];
211*8fb009dcSAndroid Build Coastguard Worker s->c[j] = reduce_once(odd + even);
212*8fb009dcSAndroid Build Coastguard Worker s->c[j + offset] = reduce(step_root * (even - odd + kPrime));
213*8fb009dcSAndroid Build Coastguard Worker }
214*8fb009dcSAndroid Build Coastguard Worker k += 2 * offset;
215*8fb009dcSAndroid Build Coastguard Worker }
216*8fb009dcSAndroid Build Coastguard Worker }
217*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
218*8fb009dcSAndroid Build Coastguard Worker s->c[i] = reduce(s->c[i] * kInverseDegree);
219*8fb009dcSAndroid Build Coastguard Worker }
220*8fb009dcSAndroid Build Coastguard Worker }
221*8fb009dcSAndroid Build Coastguard Worker
vector_inverse_ntt(vector * a)222*8fb009dcSAndroid Build Coastguard Worker static void vector_inverse_ntt(vector *a) {
223*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
224*8fb009dcSAndroid Build Coastguard Worker scalar_inverse_ntt(&a->v[i]);
225*8fb009dcSAndroid Build Coastguard Worker }
226*8fb009dcSAndroid Build Coastguard Worker }
227*8fb009dcSAndroid Build Coastguard Worker
scalar_add(scalar * lhs,const scalar * rhs)228*8fb009dcSAndroid Build Coastguard Worker static void scalar_add(scalar *lhs, const scalar *rhs) {
229*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
230*8fb009dcSAndroid Build Coastguard Worker lhs->c[i] = reduce_once(lhs->c[i] + rhs->c[i]);
231*8fb009dcSAndroid Build Coastguard Worker }
232*8fb009dcSAndroid Build Coastguard Worker }
233*8fb009dcSAndroid Build Coastguard Worker
scalar_sub(scalar * lhs,const scalar * rhs)234*8fb009dcSAndroid Build Coastguard Worker static void scalar_sub(scalar *lhs, const scalar *rhs) {
235*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
236*8fb009dcSAndroid Build Coastguard Worker lhs->c[i] = reduce_once(lhs->c[i] - rhs->c[i] + kPrime);
237*8fb009dcSAndroid Build Coastguard Worker }
238*8fb009dcSAndroid Build Coastguard Worker }
239*8fb009dcSAndroid Build Coastguard Worker
240*8fb009dcSAndroid Build Coastguard Worker // Multiplying two scalars in the number theoretically transformed state. Since
241*8fb009dcSAndroid Build Coastguard Worker // 3329 does not have a 512th root of unity, this means we have to interpret
242*8fb009dcSAndroid Build Coastguard Worker // the 2*ith and (2*i+1)th entries of the scalar as elements of GF(3329)[X]/(X^2
243*8fb009dcSAndroid Build Coastguard Worker // - 17^(2*bitreverse(i)+1)) The value of 17^(2*bitreverse(i)+1) mod 3329 is
244*8fb009dcSAndroid Build Coastguard Worker // stored in the precomputed |kModRoots| table. Note that our Barrett transform
245*8fb009dcSAndroid Build Coastguard Worker // only allows us to multipy two reduced numbers together, so we need some
246*8fb009dcSAndroid Build Coastguard Worker // intermediate reduction steps, even if an uint64_t could hold 3 multiplied
247*8fb009dcSAndroid Build Coastguard Worker // numbers.
scalar_mult(scalar * out,const scalar * lhs,const scalar * rhs)248*8fb009dcSAndroid Build Coastguard Worker static void scalar_mult(scalar *out, const scalar *lhs, const scalar *rhs) {
249*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE / 2; i++) {
250*8fb009dcSAndroid Build Coastguard Worker uint32_t real_real = (uint32_t)lhs->c[2 * i] * rhs->c[2 * i];
251*8fb009dcSAndroid Build Coastguard Worker uint32_t img_img = (uint32_t)lhs->c[2 * i + 1] * rhs->c[2 * i + 1];
252*8fb009dcSAndroid Build Coastguard Worker uint32_t real_img = (uint32_t)lhs->c[2 * i] * rhs->c[2 * i + 1];
253*8fb009dcSAndroid Build Coastguard Worker uint32_t img_real = (uint32_t)lhs->c[2 * i + 1] * rhs->c[2 * i];
254*8fb009dcSAndroid Build Coastguard Worker out->c[2 * i] =
255*8fb009dcSAndroid Build Coastguard Worker reduce(real_real + (uint32_t)reduce(img_img) * kModRoots[i]);
256*8fb009dcSAndroid Build Coastguard Worker out->c[2 * i + 1] = reduce(img_real + real_img);
257*8fb009dcSAndroid Build Coastguard Worker }
258*8fb009dcSAndroid Build Coastguard Worker }
259*8fb009dcSAndroid Build Coastguard Worker
vector_add(vector * lhs,const vector * rhs)260*8fb009dcSAndroid Build Coastguard Worker static void vector_add(vector *lhs, const vector *rhs) {
261*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
262*8fb009dcSAndroid Build Coastguard Worker scalar_add(&lhs->v[i], &rhs->v[i]);
263*8fb009dcSAndroid Build Coastguard Worker }
264*8fb009dcSAndroid Build Coastguard Worker }
265*8fb009dcSAndroid Build Coastguard Worker
matrix_mult(vector * out,const matrix * m,const vector * a)266*8fb009dcSAndroid Build Coastguard Worker static void matrix_mult(vector *out, const matrix *m, const vector *a) {
267*8fb009dcSAndroid Build Coastguard Worker vector_zero(out);
268*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
269*8fb009dcSAndroid Build Coastguard Worker for (int j = 0; j < RANK; j++) {
270*8fb009dcSAndroid Build Coastguard Worker scalar product;
271*8fb009dcSAndroid Build Coastguard Worker scalar_mult(&product, &m->v[i][j], &a->v[j]);
272*8fb009dcSAndroid Build Coastguard Worker scalar_add(&out->v[i], &product);
273*8fb009dcSAndroid Build Coastguard Worker }
274*8fb009dcSAndroid Build Coastguard Worker }
275*8fb009dcSAndroid Build Coastguard Worker }
276*8fb009dcSAndroid Build Coastguard Worker
matrix_mult_transpose(vector * out,const matrix * m,const vector * a)277*8fb009dcSAndroid Build Coastguard Worker static void matrix_mult_transpose(vector *out, const matrix *m,
278*8fb009dcSAndroid Build Coastguard Worker const vector *a) {
279*8fb009dcSAndroid Build Coastguard Worker vector_zero(out);
280*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
281*8fb009dcSAndroid Build Coastguard Worker for (int j = 0; j < RANK; j++) {
282*8fb009dcSAndroid Build Coastguard Worker scalar product;
283*8fb009dcSAndroid Build Coastguard Worker scalar_mult(&product, &m->v[j][i], &a->v[j]);
284*8fb009dcSAndroid Build Coastguard Worker scalar_add(&out->v[i], &product);
285*8fb009dcSAndroid Build Coastguard Worker }
286*8fb009dcSAndroid Build Coastguard Worker }
287*8fb009dcSAndroid Build Coastguard Worker }
288*8fb009dcSAndroid Build Coastguard Worker
scalar_inner_product(scalar * out,const vector * lhs,const vector * rhs)289*8fb009dcSAndroid Build Coastguard Worker static void scalar_inner_product(scalar *out, const vector *lhs,
290*8fb009dcSAndroid Build Coastguard Worker const vector *rhs) {
291*8fb009dcSAndroid Build Coastguard Worker scalar_zero(out);
292*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
293*8fb009dcSAndroid Build Coastguard Worker scalar product;
294*8fb009dcSAndroid Build Coastguard Worker scalar_mult(&product, &lhs->v[i], &rhs->v[i]);
295*8fb009dcSAndroid Build Coastguard Worker scalar_add(out, &product);
296*8fb009dcSAndroid Build Coastguard Worker }
297*8fb009dcSAndroid Build Coastguard Worker }
298*8fb009dcSAndroid Build Coastguard Worker
299*8fb009dcSAndroid Build Coastguard Worker // Algorithm 1 of the Kyber spec. Rejection samples a Keccak stream to get
300*8fb009dcSAndroid Build Coastguard Worker // uniformly distributed elements. This is used for matrix expansion and only
301*8fb009dcSAndroid Build Coastguard Worker // operates on public inputs.
scalar_from_keccak_vartime(scalar * out,struct BORINGSSL_keccak_st * keccak_ctx)302*8fb009dcSAndroid Build Coastguard Worker static void scalar_from_keccak_vartime(scalar *out,
303*8fb009dcSAndroid Build Coastguard Worker struct BORINGSSL_keccak_st *keccak_ctx) {
304*8fb009dcSAndroid Build Coastguard Worker assert(keccak_ctx->squeeze_offset == 0);
305*8fb009dcSAndroid Build Coastguard Worker assert(keccak_ctx->rate_bytes == 168);
306*8fb009dcSAndroid Build Coastguard Worker static_assert(168 % 3 == 0, "block and coefficient boundaries do not align");
307*8fb009dcSAndroid Build Coastguard Worker
308*8fb009dcSAndroid Build Coastguard Worker int done = 0;
309*8fb009dcSAndroid Build Coastguard Worker while (done < DEGREE) {
310*8fb009dcSAndroid Build Coastguard Worker uint8_t block[168];
311*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_squeeze(keccak_ctx, block, sizeof(block));
312*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < sizeof(block) && done < DEGREE; i += 3) {
313*8fb009dcSAndroid Build Coastguard Worker uint16_t d1 = block[i] + 256 * (block[i + 1] % 16);
314*8fb009dcSAndroid Build Coastguard Worker uint16_t d2 = block[i + 1] / 16 + 16 * block[i + 2];
315*8fb009dcSAndroid Build Coastguard Worker if (d1 < kPrime) {
316*8fb009dcSAndroid Build Coastguard Worker out->c[done++] = d1;
317*8fb009dcSAndroid Build Coastguard Worker }
318*8fb009dcSAndroid Build Coastguard Worker if (d2 < kPrime && done < DEGREE) {
319*8fb009dcSAndroid Build Coastguard Worker out->c[done++] = d2;
320*8fb009dcSAndroid Build Coastguard Worker }
321*8fb009dcSAndroid Build Coastguard Worker }
322*8fb009dcSAndroid Build Coastguard Worker }
323*8fb009dcSAndroid Build Coastguard Worker }
324*8fb009dcSAndroid Build Coastguard Worker
325*8fb009dcSAndroid Build Coastguard Worker // Algorithm 2 of the Kyber spec, with eta fixed to two and the PRF call
326*8fb009dcSAndroid Build Coastguard Worker // included. Creates binominally distributed elements by sampling 2*|eta| bits,
327*8fb009dcSAndroid Build Coastguard Worker // and setting the coefficient to the count of the first bits minus the count of
328*8fb009dcSAndroid Build Coastguard Worker // the second bits, resulting in a centered binomial distribution. Since eta is
329*8fb009dcSAndroid Build Coastguard Worker // two this gives -2/2 with a probability of 1/16, -1/1 with probability 1/4,
330*8fb009dcSAndroid Build Coastguard Worker // and 0 with probability 3/8.
scalar_centered_binomial_distribution_eta_2_with_prf(scalar * out,const uint8_t input[33])331*8fb009dcSAndroid Build Coastguard Worker static void scalar_centered_binomial_distribution_eta_2_with_prf(
332*8fb009dcSAndroid Build Coastguard Worker scalar *out, const uint8_t input[33]) {
333*8fb009dcSAndroid Build Coastguard Worker uint8_t entropy[128];
334*8fb009dcSAndroid Build Coastguard Worker static_assert(sizeof(entropy) == 2 * /*kEta=*/2 * DEGREE / 8, "");
335*8fb009dcSAndroid Build Coastguard Worker prf(entropy, sizeof(entropy), input);
336*8fb009dcSAndroid Build Coastguard Worker
337*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i += 2) {
338*8fb009dcSAndroid Build Coastguard Worker uint8_t byte = entropy[i / 2];
339*8fb009dcSAndroid Build Coastguard Worker
340*8fb009dcSAndroid Build Coastguard Worker uint16_t value = kPrime;
341*8fb009dcSAndroid Build Coastguard Worker value += (byte & 1) + ((byte >> 1) & 1);
342*8fb009dcSAndroid Build Coastguard Worker value -= ((byte >> 2) & 1) + ((byte >> 3) & 1);
343*8fb009dcSAndroid Build Coastguard Worker out->c[i] = reduce_once(value);
344*8fb009dcSAndroid Build Coastguard Worker
345*8fb009dcSAndroid Build Coastguard Worker byte >>= 4;
346*8fb009dcSAndroid Build Coastguard Worker value = kPrime;
347*8fb009dcSAndroid Build Coastguard Worker value += (byte & 1) + ((byte >> 1) & 1);
348*8fb009dcSAndroid Build Coastguard Worker value -= ((byte >> 2) & 1) + ((byte >> 3) & 1);
349*8fb009dcSAndroid Build Coastguard Worker out->c[i + 1] = reduce_once(value);
350*8fb009dcSAndroid Build Coastguard Worker }
351*8fb009dcSAndroid Build Coastguard Worker }
352*8fb009dcSAndroid Build Coastguard Worker
353*8fb009dcSAndroid Build Coastguard Worker // Generates a secret vector by using
354*8fb009dcSAndroid Build Coastguard Worker // |scalar_centered_binomial_distribution_eta_2_with_prf|, using the given seed
355*8fb009dcSAndroid Build Coastguard Worker // appending and incrementing |counter| for entry of the vector.
vector_generate_secret_eta_2(vector * out,uint8_t * counter,const uint8_t seed[32])356*8fb009dcSAndroid Build Coastguard Worker static void vector_generate_secret_eta_2(vector *out, uint8_t *counter,
357*8fb009dcSAndroid Build Coastguard Worker const uint8_t seed[32]) {
358*8fb009dcSAndroid Build Coastguard Worker uint8_t input[33];
359*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(input, seed, 32);
360*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
361*8fb009dcSAndroid Build Coastguard Worker input[32] = (*counter)++;
362*8fb009dcSAndroid Build Coastguard Worker scalar_centered_binomial_distribution_eta_2_with_prf(&out->v[i], input);
363*8fb009dcSAndroid Build Coastguard Worker }
364*8fb009dcSAndroid Build Coastguard Worker }
365*8fb009dcSAndroid Build Coastguard Worker
366*8fb009dcSAndroid Build Coastguard Worker // Expands the matrix of a seed for key generation and for encaps-CPA.
matrix_expand(matrix * out,const uint8_t rho[32])367*8fb009dcSAndroid Build Coastguard Worker static void matrix_expand(matrix *out, const uint8_t rho[32]) {
368*8fb009dcSAndroid Build Coastguard Worker uint8_t input[34];
369*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(input, rho, 32);
370*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
371*8fb009dcSAndroid Build Coastguard Worker for (int j = 0; j < RANK; j++) {
372*8fb009dcSAndroid Build Coastguard Worker input[32] = i;
373*8fb009dcSAndroid Build Coastguard Worker input[33] = j;
374*8fb009dcSAndroid Build Coastguard Worker struct BORINGSSL_keccak_st keccak_ctx;
375*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake128);
376*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, input, sizeof(input));
377*8fb009dcSAndroid Build Coastguard Worker scalar_from_keccak_vartime(&out->v[i][j], &keccak_ctx);
378*8fb009dcSAndroid Build Coastguard Worker }
379*8fb009dcSAndroid Build Coastguard Worker }
380*8fb009dcSAndroid Build Coastguard Worker }
381*8fb009dcSAndroid Build Coastguard Worker
382*8fb009dcSAndroid Build Coastguard Worker static const uint8_t kMasks[8] = {0x01, 0x03, 0x07, 0x0f,
383*8fb009dcSAndroid Build Coastguard Worker 0x1f, 0x3f, 0x7f, 0xff};
384*8fb009dcSAndroid Build Coastguard Worker
scalar_encode(uint8_t * out,const scalar * s,int bits)385*8fb009dcSAndroid Build Coastguard Worker static void scalar_encode(uint8_t *out, const scalar *s, int bits) {
386*8fb009dcSAndroid Build Coastguard Worker assert(bits <= (int)sizeof(*s->c) * 8 && bits != 1);
387*8fb009dcSAndroid Build Coastguard Worker
388*8fb009dcSAndroid Build Coastguard Worker uint8_t out_byte = 0;
389*8fb009dcSAndroid Build Coastguard Worker int out_byte_bits = 0;
390*8fb009dcSAndroid Build Coastguard Worker
391*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
392*8fb009dcSAndroid Build Coastguard Worker uint16_t element = s->c[i];
393*8fb009dcSAndroid Build Coastguard Worker int element_bits_done = 0;
394*8fb009dcSAndroid Build Coastguard Worker
395*8fb009dcSAndroid Build Coastguard Worker while (element_bits_done < bits) {
396*8fb009dcSAndroid Build Coastguard Worker int chunk_bits = bits - element_bits_done;
397*8fb009dcSAndroid Build Coastguard Worker int out_bits_remaining = 8 - out_byte_bits;
398*8fb009dcSAndroid Build Coastguard Worker if (chunk_bits >= out_bits_remaining) {
399*8fb009dcSAndroid Build Coastguard Worker chunk_bits = out_bits_remaining;
400*8fb009dcSAndroid Build Coastguard Worker out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits;
401*8fb009dcSAndroid Build Coastguard Worker *out = out_byte;
402*8fb009dcSAndroid Build Coastguard Worker out++;
403*8fb009dcSAndroid Build Coastguard Worker out_byte_bits = 0;
404*8fb009dcSAndroid Build Coastguard Worker out_byte = 0;
405*8fb009dcSAndroid Build Coastguard Worker } else {
406*8fb009dcSAndroid Build Coastguard Worker out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits;
407*8fb009dcSAndroid Build Coastguard Worker out_byte_bits += chunk_bits;
408*8fb009dcSAndroid Build Coastguard Worker }
409*8fb009dcSAndroid Build Coastguard Worker
410*8fb009dcSAndroid Build Coastguard Worker element_bits_done += chunk_bits;
411*8fb009dcSAndroid Build Coastguard Worker element >>= chunk_bits;
412*8fb009dcSAndroid Build Coastguard Worker }
413*8fb009dcSAndroid Build Coastguard Worker }
414*8fb009dcSAndroid Build Coastguard Worker
415*8fb009dcSAndroid Build Coastguard Worker if (out_byte_bits > 0) {
416*8fb009dcSAndroid Build Coastguard Worker *out = out_byte;
417*8fb009dcSAndroid Build Coastguard Worker }
418*8fb009dcSAndroid Build Coastguard Worker }
419*8fb009dcSAndroid Build Coastguard Worker
420*8fb009dcSAndroid Build Coastguard Worker // scalar_encode_1 is |scalar_encode| specialised for |bits| == 1.
scalar_encode_1(uint8_t out[32],const scalar * s)421*8fb009dcSAndroid Build Coastguard Worker static void scalar_encode_1(uint8_t out[32], const scalar *s) {
422*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i += 8) {
423*8fb009dcSAndroid Build Coastguard Worker uint8_t out_byte = 0;
424*8fb009dcSAndroid Build Coastguard Worker for (int j = 0; j < 8; j++) {
425*8fb009dcSAndroid Build Coastguard Worker out_byte |= (s->c[i + j] & 1) << j;
426*8fb009dcSAndroid Build Coastguard Worker }
427*8fb009dcSAndroid Build Coastguard Worker *out = out_byte;
428*8fb009dcSAndroid Build Coastguard Worker out++;
429*8fb009dcSAndroid Build Coastguard Worker }
430*8fb009dcSAndroid Build Coastguard Worker }
431*8fb009dcSAndroid Build Coastguard Worker
432*8fb009dcSAndroid Build Coastguard Worker // Encodes an entire vector into 32*|RANK|*|bits| bytes. Note that since 256
433*8fb009dcSAndroid Build Coastguard Worker // (DEGREE) is divisible by 8, the individual vector entries will always fill a
434*8fb009dcSAndroid Build Coastguard Worker // whole number of bytes, so we do not need to worry about bit packing here.
vector_encode(uint8_t * out,const vector * a,int bits)435*8fb009dcSAndroid Build Coastguard Worker static void vector_encode(uint8_t *out, const vector *a, int bits) {
436*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
437*8fb009dcSAndroid Build Coastguard Worker scalar_encode(out + i * bits * DEGREE / 8, &a->v[i], bits);
438*8fb009dcSAndroid Build Coastguard Worker }
439*8fb009dcSAndroid Build Coastguard Worker }
440*8fb009dcSAndroid Build Coastguard Worker
441*8fb009dcSAndroid Build Coastguard Worker // scalar_decode parses |DEGREE * bits| bits from |in| into |DEGREE| values in
442*8fb009dcSAndroid Build Coastguard Worker // |out|. It returns one on success and zero if any parsed value is >=
443*8fb009dcSAndroid Build Coastguard Worker // |kPrime|.
scalar_decode(scalar * out,const uint8_t * in,int bits)444*8fb009dcSAndroid Build Coastguard Worker static int scalar_decode(scalar *out, const uint8_t *in, int bits) {
445*8fb009dcSAndroid Build Coastguard Worker assert(bits <= (int)sizeof(*out->c) * 8 && bits != 1);
446*8fb009dcSAndroid Build Coastguard Worker
447*8fb009dcSAndroid Build Coastguard Worker uint8_t in_byte = 0;
448*8fb009dcSAndroid Build Coastguard Worker int in_byte_bits_left = 0;
449*8fb009dcSAndroid Build Coastguard Worker
450*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
451*8fb009dcSAndroid Build Coastguard Worker uint16_t element = 0;
452*8fb009dcSAndroid Build Coastguard Worker int element_bits_done = 0;
453*8fb009dcSAndroid Build Coastguard Worker
454*8fb009dcSAndroid Build Coastguard Worker while (element_bits_done < bits) {
455*8fb009dcSAndroid Build Coastguard Worker if (in_byte_bits_left == 0) {
456*8fb009dcSAndroid Build Coastguard Worker in_byte = *in;
457*8fb009dcSAndroid Build Coastguard Worker in++;
458*8fb009dcSAndroid Build Coastguard Worker in_byte_bits_left = 8;
459*8fb009dcSAndroid Build Coastguard Worker }
460*8fb009dcSAndroid Build Coastguard Worker
461*8fb009dcSAndroid Build Coastguard Worker int chunk_bits = bits - element_bits_done;
462*8fb009dcSAndroid Build Coastguard Worker if (chunk_bits > in_byte_bits_left) {
463*8fb009dcSAndroid Build Coastguard Worker chunk_bits = in_byte_bits_left;
464*8fb009dcSAndroid Build Coastguard Worker }
465*8fb009dcSAndroid Build Coastguard Worker
466*8fb009dcSAndroid Build Coastguard Worker element |= (in_byte & kMasks[chunk_bits - 1]) << element_bits_done;
467*8fb009dcSAndroid Build Coastguard Worker in_byte_bits_left -= chunk_bits;
468*8fb009dcSAndroid Build Coastguard Worker in_byte >>= chunk_bits;
469*8fb009dcSAndroid Build Coastguard Worker
470*8fb009dcSAndroid Build Coastguard Worker element_bits_done += chunk_bits;
471*8fb009dcSAndroid Build Coastguard Worker }
472*8fb009dcSAndroid Build Coastguard Worker
473*8fb009dcSAndroid Build Coastguard Worker if (element >= kPrime) {
474*8fb009dcSAndroid Build Coastguard Worker return 0;
475*8fb009dcSAndroid Build Coastguard Worker }
476*8fb009dcSAndroid Build Coastguard Worker out->c[i] = element;
477*8fb009dcSAndroid Build Coastguard Worker }
478*8fb009dcSAndroid Build Coastguard Worker
479*8fb009dcSAndroid Build Coastguard Worker return 1;
480*8fb009dcSAndroid Build Coastguard Worker }
481*8fb009dcSAndroid Build Coastguard Worker
482*8fb009dcSAndroid Build Coastguard Worker // scalar_decode_1 is |scalar_decode| specialised for |bits| == 1.
scalar_decode_1(scalar * out,const uint8_t in[32])483*8fb009dcSAndroid Build Coastguard Worker static void scalar_decode_1(scalar *out, const uint8_t in[32]) {
484*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i += 8) {
485*8fb009dcSAndroid Build Coastguard Worker uint8_t in_byte = *in;
486*8fb009dcSAndroid Build Coastguard Worker in++;
487*8fb009dcSAndroid Build Coastguard Worker for (int j = 0; j < 8; j++) {
488*8fb009dcSAndroid Build Coastguard Worker out->c[i + j] = in_byte & 1;
489*8fb009dcSAndroid Build Coastguard Worker in_byte >>= 1;
490*8fb009dcSAndroid Build Coastguard Worker }
491*8fb009dcSAndroid Build Coastguard Worker }
492*8fb009dcSAndroid Build Coastguard Worker }
493*8fb009dcSAndroid Build Coastguard Worker
494*8fb009dcSAndroid Build Coastguard Worker // Decodes 32*|RANK|*|bits| bytes from |in| into |out|. It returns one on
495*8fb009dcSAndroid Build Coastguard Worker // success or zero if any parsed value is >= |kPrime|.
vector_decode(vector * out,const uint8_t * in,int bits)496*8fb009dcSAndroid Build Coastguard Worker static int vector_decode(vector *out, const uint8_t *in, int bits) {
497*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
498*8fb009dcSAndroid Build Coastguard Worker if (!scalar_decode(&out->v[i], in + i * bits * DEGREE / 8, bits)) {
499*8fb009dcSAndroid Build Coastguard Worker return 0;
500*8fb009dcSAndroid Build Coastguard Worker }
501*8fb009dcSAndroid Build Coastguard Worker }
502*8fb009dcSAndroid Build Coastguard Worker return 1;
503*8fb009dcSAndroid Build Coastguard Worker }
504*8fb009dcSAndroid Build Coastguard Worker
505*8fb009dcSAndroid Build Coastguard Worker // Compresses (lossily) an input |x| mod 3329 into |bits| many bits by grouping
506*8fb009dcSAndroid Build Coastguard Worker // numbers close to each other together. The formula used is
507*8fb009dcSAndroid Build Coastguard Worker // round(2^|bits|/kPrime*x) mod 2^|bits|.
508*8fb009dcSAndroid Build Coastguard Worker // Uses Barrett reduction to achieve constant time. Since we need both the
509*8fb009dcSAndroid Build Coastguard Worker // remainder (for rounding) and the quotient (as the result), we cannot use
510*8fb009dcSAndroid Build Coastguard Worker // |reduce| here, but need to do the Barrett reduction directly.
compress(uint16_t x,int bits)511*8fb009dcSAndroid Build Coastguard Worker static uint16_t compress(uint16_t x, int bits) {
512*8fb009dcSAndroid Build Coastguard Worker uint32_t shifted = (uint32_t)x << bits;
513*8fb009dcSAndroid Build Coastguard Worker uint64_t product = (uint64_t)shifted * kBarrettMultiplier;
514*8fb009dcSAndroid Build Coastguard Worker uint32_t quotient = (uint32_t)(product >> kBarrettShift);
515*8fb009dcSAndroid Build Coastguard Worker uint32_t remainder = shifted - quotient * kPrime;
516*8fb009dcSAndroid Build Coastguard Worker
517*8fb009dcSAndroid Build Coastguard Worker // Adjust the quotient to round correctly:
518*8fb009dcSAndroid Build Coastguard Worker // 0 <= remainder <= kHalfPrime round to 0
519*8fb009dcSAndroid Build Coastguard Worker // kHalfPrime < remainder <= kPrime + kHalfPrime round to 1
520*8fb009dcSAndroid Build Coastguard Worker // kPrime + kHalfPrime < remainder < 2 * kPrime round to 2
521*8fb009dcSAndroid Build Coastguard Worker assert(remainder < 2u * kPrime);
522*8fb009dcSAndroid Build Coastguard Worker quotient += 1 & constant_time_lt_w(kHalfPrime, remainder);
523*8fb009dcSAndroid Build Coastguard Worker quotient += 1 & constant_time_lt_w(kPrime + kHalfPrime, remainder);
524*8fb009dcSAndroid Build Coastguard Worker return quotient & ((1 << bits) - 1);
525*8fb009dcSAndroid Build Coastguard Worker }
526*8fb009dcSAndroid Build Coastguard Worker
527*8fb009dcSAndroid Build Coastguard Worker // Decompresses |x| by using an equi-distant representative. The formula is
528*8fb009dcSAndroid Build Coastguard Worker // round(kPrime/2^|bits|*x). Note that 2^|bits| being the divisor allows us to
529*8fb009dcSAndroid Build Coastguard Worker // implement this logic using only bit operations.
decompress(uint16_t x,int bits)530*8fb009dcSAndroid Build Coastguard Worker static uint16_t decompress(uint16_t x, int bits) {
531*8fb009dcSAndroid Build Coastguard Worker uint32_t product = (uint32_t)x * kPrime;
532*8fb009dcSAndroid Build Coastguard Worker uint32_t power = 1 << bits;
533*8fb009dcSAndroid Build Coastguard Worker // This is |product| % power, since |power| is a power of 2.
534*8fb009dcSAndroid Build Coastguard Worker uint32_t remainder = product & (power - 1);
535*8fb009dcSAndroid Build Coastguard Worker // This is |product| / power, since |power| is a power of 2.
536*8fb009dcSAndroid Build Coastguard Worker uint32_t lower = product >> bits;
537*8fb009dcSAndroid Build Coastguard Worker // The rounding logic works since the first half of numbers mod |power| have a
538*8fb009dcSAndroid Build Coastguard Worker // 0 as first bit, and the second half has a 1 as first bit, since |power| is
539*8fb009dcSAndroid Build Coastguard Worker // a power of 2. As a 12 bit number, |remainder| is always positive, so we
540*8fb009dcSAndroid Build Coastguard Worker // will shift in 0s for a right shift.
541*8fb009dcSAndroid Build Coastguard Worker return lower + (remainder >> (bits - 1));
542*8fb009dcSAndroid Build Coastguard Worker }
543*8fb009dcSAndroid Build Coastguard Worker
scalar_compress(scalar * s,int bits)544*8fb009dcSAndroid Build Coastguard Worker static void scalar_compress(scalar *s, int bits) {
545*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
546*8fb009dcSAndroid Build Coastguard Worker s->c[i] = compress(s->c[i], bits);
547*8fb009dcSAndroid Build Coastguard Worker }
548*8fb009dcSAndroid Build Coastguard Worker }
549*8fb009dcSAndroid Build Coastguard Worker
scalar_decompress(scalar * s,int bits)550*8fb009dcSAndroid Build Coastguard Worker static void scalar_decompress(scalar *s, int bits) {
551*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
552*8fb009dcSAndroid Build Coastguard Worker s->c[i] = decompress(s->c[i], bits);
553*8fb009dcSAndroid Build Coastguard Worker }
554*8fb009dcSAndroid Build Coastguard Worker }
555*8fb009dcSAndroid Build Coastguard Worker
vector_compress(vector * a,int bits)556*8fb009dcSAndroid Build Coastguard Worker static void vector_compress(vector *a, int bits) {
557*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
558*8fb009dcSAndroid Build Coastguard Worker scalar_compress(&a->v[i], bits);
559*8fb009dcSAndroid Build Coastguard Worker }
560*8fb009dcSAndroid Build Coastguard Worker }
561*8fb009dcSAndroid Build Coastguard Worker
vector_decompress(vector * a,int bits)562*8fb009dcSAndroid Build Coastguard Worker static void vector_decompress(vector *a, int bits) {
563*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < RANK; i++) {
564*8fb009dcSAndroid Build Coastguard Worker scalar_decompress(&a->v[i], bits);
565*8fb009dcSAndroid Build Coastguard Worker }
566*8fb009dcSAndroid Build Coastguard Worker }
567*8fb009dcSAndroid Build Coastguard Worker
568*8fb009dcSAndroid Build Coastguard Worker struct public_key {
569*8fb009dcSAndroid Build Coastguard Worker vector t;
570*8fb009dcSAndroid Build Coastguard Worker uint8_t rho[32];
571*8fb009dcSAndroid Build Coastguard Worker uint8_t public_key_hash[32];
572*8fb009dcSAndroid Build Coastguard Worker matrix m;
573*8fb009dcSAndroid Build Coastguard Worker };
574*8fb009dcSAndroid Build Coastguard Worker
public_key_from_external(const struct KYBER_public_key * external)575*8fb009dcSAndroid Build Coastguard Worker static struct public_key *public_key_from_external(
576*8fb009dcSAndroid Build Coastguard Worker const struct KYBER_public_key *external) {
577*8fb009dcSAndroid Build Coastguard Worker static_assert(sizeof(struct KYBER_public_key) >= sizeof(struct public_key),
578*8fb009dcSAndroid Build Coastguard Worker "Kyber public key is too small");
579*8fb009dcSAndroid Build Coastguard Worker static_assert(alignof(struct KYBER_public_key) >= alignof(struct public_key),
580*8fb009dcSAndroid Build Coastguard Worker "Kyber public key align incorrect");
581*8fb009dcSAndroid Build Coastguard Worker return (struct public_key *)external;
582*8fb009dcSAndroid Build Coastguard Worker }
583*8fb009dcSAndroid Build Coastguard Worker
584*8fb009dcSAndroid Build Coastguard Worker struct private_key {
585*8fb009dcSAndroid Build Coastguard Worker struct public_key pub;
586*8fb009dcSAndroid Build Coastguard Worker vector s;
587*8fb009dcSAndroid Build Coastguard Worker uint8_t fo_failure_secret[32];
588*8fb009dcSAndroid Build Coastguard Worker };
589*8fb009dcSAndroid Build Coastguard Worker
private_key_from_external(const struct KYBER_private_key * external)590*8fb009dcSAndroid Build Coastguard Worker static struct private_key *private_key_from_external(
591*8fb009dcSAndroid Build Coastguard Worker const struct KYBER_private_key *external) {
592*8fb009dcSAndroid Build Coastguard Worker static_assert(sizeof(struct KYBER_private_key) >= sizeof(struct private_key),
593*8fb009dcSAndroid Build Coastguard Worker "Kyber private key too small");
594*8fb009dcSAndroid Build Coastguard Worker static_assert(
595*8fb009dcSAndroid Build Coastguard Worker alignof(struct KYBER_private_key) >= alignof(struct private_key),
596*8fb009dcSAndroid Build Coastguard Worker "Kyber private key align incorrect");
597*8fb009dcSAndroid Build Coastguard Worker return (struct private_key *)external;
598*8fb009dcSAndroid Build Coastguard Worker }
599*8fb009dcSAndroid Build Coastguard Worker
600*8fb009dcSAndroid Build Coastguard Worker // Calls |KYBER_generate_key_external_entropy| with random bytes from
601*8fb009dcSAndroid Build Coastguard Worker // |RAND_bytes|.
KYBER_generate_key(uint8_t out_encoded_public_key[KYBER_PUBLIC_KEY_BYTES],struct KYBER_private_key * out_private_key)602*8fb009dcSAndroid Build Coastguard Worker void KYBER_generate_key(uint8_t out_encoded_public_key[KYBER_PUBLIC_KEY_BYTES],
603*8fb009dcSAndroid Build Coastguard Worker struct KYBER_private_key *out_private_key) {
604*8fb009dcSAndroid Build Coastguard Worker uint8_t entropy[KYBER_GENERATE_KEY_ENTROPY];
605*8fb009dcSAndroid Build Coastguard Worker RAND_bytes(entropy, sizeof(entropy));
606*8fb009dcSAndroid Build Coastguard Worker KYBER_generate_key_external_entropy(out_encoded_public_key, out_private_key,
607*8fb009dcSAndroid Build Coastguard Worker entropy);
608*8fb009dcSAndroid Build Coastguard Worker }
609*8fb009dcSAndroid Build Coastguard Worker
kyber_marshal_public_key(CBB * out,const struct public_key * pub)610*8fb009dcSAndroid Build Coastguard Worker static int kyber_marshal_public_key(CBB *out, const struct public_key *pub) {
611*8fb009dcSAndroid Build Coastguard Worker uint8_t *vector_output;
612*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_space(out, &vector_output, kEncodedVectorSize)) {
613*8fb009dcSAndroid Build Coastguard Worker return 0;
614*8fb009dcSAndroid Build Coastguard Worker }
615*8fb009dcSAndroid Build Coastguard Worker vector_encode(vector_output, &pub->t, kLog2Prime);
616*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_bytes(out, pub->rho, sizeof(pub->rho))) {
617*8fb009dcSAndroid Build Coastguard Worker return 0;
618*8fb009dcSAndroid Build Coastguard Worker }
619*8fb009dcSAndroid Build Coastguard Worker return 1;
620*8fb009dcSAndroid Build Coastguard Worker }
621*8fb009dcSAndroid Build Coastguard Worker
622*8fb009dcSAndroid Build Coastguard Worker // Algorithms 4 and 7 of the Kyber spec. Algorithms are combined since key
623*8fb009dcSAndroid Build Coastguard Worker // generation is not part of the FO transform, and the spec uses Algorithm 7 to
624*8fb009dcSAndroid Build Coastguard Worker // specify the actual key format.
KYBER_generate_key_external_entropy(uint8_t out_encoded_public_key[KYBER_PUBLIC_KEY_BYTES],struct KYBER_private_key * out_private_key,const uint8_t entropy[KYBER_GENERATE_KEY_ENTROPY])625*8fb009dcSAndroid Build Coastguard Worker void KYBER_generate_key_external_entropy(
626*8fb009dcSAndroid Build Coastguard Worker uint8_t out_encoded_public_key[KYBER_PUBLIC_KEY_BYTES],
627*8fb009dcSAndroid Build Coastguard Worker struct KYBER_private_key *out_private_key,
628*8fb009dcSAndroid Build Coastguard Worker const uint8_t entropy[KYBER_GENERATE_KEY_ENTROPY]) {
629*8fb009dcSAndroid Build Coastguard Worker struct private_key *priv = private_key_from_external(out_private_key);
630*8fb009dcSAndroid Build Coastguard Worker uint8_t hashed[64];
631*8fb009dcSAndroid Build Coastguard Worker hash_g(hashed, entropy, 32);
632*8fb009dcSAndroid Build Coastguard Worker const uint8_t *const rho = hashed;
633*8fb009dcSAndroid Build Coastguard Worker const uint8_t *const sigma = hashed + 32;
634*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(priv->pub.rho, hashed, sizeof(priv->pub.rho));
635*8fb009dcSAndroid Build Coastguard Worker matrix_expand(&priv->pub.m, rho);
636*8fb009dcSAndroid Build Coastguard Worker uint8_t counter = 0;
637*8fb009dcSAndroid Build Coastguard Worker vector_generate_secret_eta_2(&priv->s, &counter, sigma);
638*8fb009dcSAndroid Build Coastguard Worker vector_ntt(&priv->s);
639*8fb009dcSAndroid Build Coastguard Worker vector error;
640*8fb009dcSAndroid Build Coastguard Worker vector_generate_secret_eta_2(&error, &counter, sigma);
641*8fb009dcSAndroid Build Coastguard Worker vector_ntt(&error);
642*8fb009dcSAndroid Build Coastguard Worker matrix_mult_transpose(&priv->pub.t, &priv->pub.m, &priv->s);
643*8fb009dcSAndroid Build Coastguard Worker vector_add(&priv->pub.t, &error);
644*8fb009dcSAndroid Build Coastguard Worker
645*8fb009dcSAndroid Build Coastguard Worker CBB cbb;
646*8fb009dcSAndroid Build Coastguard Worker CBB_init_fixed(&cbb, out_encoded_public_key, KYBER_PUBLIC_KEY_BYTES);
647*8fb009dcSAndroid Build Coastguard Worker if (!kyber_marshal_public_key(&cbb, &priv->pub)) {
648*8fb009dcSAndroid Build Coastguard Worker abort();
649*8fb009dcSAndroid Build Coastguard Worker }
650*8fb009dcSAndroid Build Coastguard Worker
651*8fb009dcSAndroid Build Coastguard Worker hash_h(priv->pub.public_key_hash, out_encoded_public_key,
652*8fb009dcSAndroid Build Coastguard Worker KYBER_PUBLIC_KEY_BYTES);
653*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(priv->fo_failure_secret, entropy + 32, 32);
654*8fb009dcSAndroid Build Coastguard Worker }
655*8fb009dcSAndroid Build Coastguard Worker
KYBER_public_from_private(struct KYBER_public_key * out_public_key,const struct KYBER_private_key * private_key)656*8fb009dcSAndroid Build Coastguard Worker void KYBER_public_from_private(struct KYBER_public_key *out_public_key,
657*8fb009dcSAndroid Build Coastguard Worker const struct KYBER_private_key *private_key) {
658*8fb009dcSAndroid Build Coastguard Worker struct public_key *const pub = public_key_from_external(out_public_key);
659*8fb009dcSAndroid Build Coastguard Worker const struct private_key *const priv = private_key_from_external(private_key);
660*8fb009dcSAndroid Build Coastguard Worker *pub = priv->pub;
661*8fb009dcSAndroid Build Coastguard Worker }
662*8fb009dcSAndroid Build Coastguard Worker
663*8fb009dcSAndroid Build Coastguard Worker // Algorithm 5 of the Kyber spec. Encrypts a message with given randomness to
664*8fb009dcSAndroid Build Coastguard Worker // the ciphertext in |out|. Without applying the Fujisaki-Okamoto transform this
665*8fb009dcSAndroid Build Coastguard Worker // would not result in a CCA secure scheme, since lattice schemes are vulnerable
666*8fb009dcSAndroid Build Coastguard Worker // to decryption failure oracles.
encrypt_cpa(uint8_t out[KYBER_CIPHERTEXT_BYTES],const struct public_key * pub,const uint8_t message[32],const uint8_t randomness[32])667*8fb009dcSAndroid Build Coastguard Worker static void encrypt_cpa(uint8_t out[KYBER_CIPHERTEXT_BYTES],
668*8fb009dcSAndroid Build Coastguard Worker const struct public_key *pub, const uint8_t message[32],
669*8fb009dcSAndroid Build Coastguard Worker const uint8_t randomness[32]) {
670*8fb009dcSAndroid Build Coastguard Worker uint8_t counter = 0;
671*8fb009dcSAndroid Build Coastguard Worker vector secret;
672*8fb009dcSAndroid Build Coastguard Worker vector_generate_secret_eta_2(&secret, &counter, randomness);
673*8fb009dcSAndroid Build Coastguard Worker vector_ntt(&secret);
674*8fb009dcSAndroid Build Coastguard Worker vector error;
675*8fb009dcSAndroid Build Coastguard Worker vector_generate_secret_eta_2(&error, &counter, randomness);
676*8fb009dcSAndroid Build Coastguard Worker uint8_t input[33];
677*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(input, randomness, 32);
678*8fb009dcSAndroid Build Coastguard Worker input[32] = counter;
679*8fb009dcSAndroid Build Coastguard Worker scalar scalar_error;
680*8fb009dcSAndroid Build Coastguard Worker scalar_centered_binomial_distribution_eta_2_with_prf(&scalar_error, input);
681*8fb009dcSAndroid Build Coastguard Worker vector u;
682*8fb009dcSAndroid Build Coastguard Worker matrix_mult(&u, &pub->m, &secret);
683*8fb009dcSAndroid Build Coastguard Worker vector_inverse_ntt(&u);
684*8fb009dcSAndroid Build Coastguard Worker vector_add(&u, &error);
685*8fb009dcSAndroid Build Coastguard Worker scalar v;
686*8fb009dcSAndroid Build Coastguard Worker scalar_inner_product(&v, &pub->t, &secret);
687*8fb009dcSAndroid Build Coastguard Worker scalar_inverse_ntt(&v);
688*8fb009dcSAndroid Build Coastguard Worker scalar_add(&v, &scalar_error);
689*8fb009dcSAndroid Build Coastguard Worker scalar expanded_message;
690*8fb009dcSAndroid Build Coastguard Worker scalar_decode_1(&expanded_message, message);
691*8fb009dcSAndroid Build Coastguard Worker scalar_decompress(&expanded_message, 1);
692*8fb009dcSAndroid Build Coastguard Worker scalar_add(&v, &expanded_message);
693*8fb009dcSAndroid Build Coastguard Worker vector_compress(&u, kDU);
694*8fb009dcSAndroid Build Coastguard Worker vector_encode(out, &u, kDU);
695*8fb009dcSAndroid Build Coastguard Worker scalar_compress(&v, kDV);
696*8fb009dcSAndroid Build Coastguard Worker scalar_encode(out + kCompressedVectorSize, &v, kDV);
697*8fb009dcSAndroid Build Coastguard Worker }
698*8fb009dcSAndroid Build Coastguard Worker
699*8fb009dcSAndroid Build Coastguard Worker // Calls KYBER_encap_external_entropy| with random bytes from |RAND_bytes|
KYBER_encap(uint8_t out_ciphertext[KYBER_CIPHERTEXT_BYTES],uint8_t out_shared_secret[KYBER_SHARED_SECRET_BYTES],const struct KYBER_public_key * public_key)700*8fb009dcSAndroid Build Coastguard Worker void KYBER_encap(uint8_t out_ciphertext[KYBER_CIPHERTEXT_BYTES],
701*8fb009dcSAndroid Build Coastguard Worker uint8_t out_shared_secret[KYBER_SHARED_SECRET_BYTES],
702*8fb009dcSAndroid Build Coastguard Worker const struct KYBER_public_key *public_key) {
703*8fb009dcSAndroid Build Coastguard Worker uint8_t entropy[KYBER_ENCAP_ENTROPY];
704*8fb009dcSAndroid Build Coastguard Worker RAND_bytes(entropy, KYBER_ENCAP_ENTROPY);
705*8fb009dcSAndroid Build Coastguard Worker KYBER_encap_external_entropy(out_ciphertext, out_shared_secret, public_key,
706*8fb009dcSAndroid Build Coastguard Worker entropy);
707*8fb009dcSAndroid Build Coastguard Worker }
708*8fb009dcSAndroid Build Coastguard Worker
709*8fb009dcSAndroid Build Coastguard Worker // Algorithm 8 of the Kyber spec, safe for line 2 of the spec. The spec there
710*8fb009dcSAndroid Build Coastguard Worker // hashes the output of the system's random number generator, since the FO
711*8fb009dcSAndroid Build Coastguard Worker // transform will reveal it to the decrypting party. There is no reason to do
712*8fb009dcSAndroid Build Coastguard Worker // this when a secure random number generator is used. When an insecure random
713*8fb009dcSAndroid Build Coastguard Worker // number generator is used, the caller should switch to a secure one before
714*8fb009dcSAndroid Build Coastguard Worker // calling this method.
KYBER_encap_external_entropy(uint8_t out_ciphertext[KYBER_CIPHERTEXT_BYTES],uint8_t out_shared_secret[KYBER_SHARED_SECRET_BYTES],const struct KYBER_public_key * public_key,const uint8_t entropy[KYBER_ENCAP_ENTROPY])715*8fb009dcSAndroid Build Coastguard Worker void KYBER_encap_external_entropy(
716*8fb009dcSAndroid Build Coastguard Worker uint8_t out_ciphertext[KYBER_CIPHERTEXT_BYTES],
717*8fb009dcSAndroid Build Coastguard Worker uint8_t out_shared_secret[KYBER_SHARED_SECRET_BYTES],
718*8fb009dcSAndroid Build Coastguard Worker const struct KYBER_public_key *public_key,
719*8fb009dcSAndroid Build Coastguard Worker const uint8_t entropy[KYBER_ENCAP_ENTROPY]) {
720*8fb009dcSAndroid Build Coastguard Worker const struct public_key *pub = public_key_from_external(public_key);
721*8fb009dcSAndroid Build Coastguard Worker uint8_t input[64];
722*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(input, entropy, KYBER_ENCAP_ENTROPY);
723*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(input + KYBER_ENCAP_ENTROPY, pub->public_key_hash,
724*8fb009dcSAndroid Build Coastguard Worker sizeof(input) - KYBER_ENCAP_ENTROPY);
725*8fb009dcSAndroid Build Coastguard Worker uint8_t prekey_and_randomness[64];
726*8fb009dcSAndroid Build Coastguard Worker hash_g(prekey_and_randomness, input, sizeof(input));
727*8fb009dcSAndroid Build Coastguard Worker encrypt_cpa(out_ciphertext, pub, entropy, prekey_and_randomness + 32);
728*8fb009dcSAndroid Build Coastguard Worker hash_h(prekey_and_randomness + 32, out_ciphertext, KYBER_CIPHERTEXT_BYTES);
729*8fb009dcSAndroid Build Coastguard Worker kdf(out_shared_secret, KYBER_SHARED_SECRET_BYTES, prekey_and_randomness,
730*8fb009dcSAndroid Build Coastguard Worker sizeof(prekey_and_randomness));
731*8fb009dcSAndroid Build Coastguard Worker }
732*8fb009dcSAndroid Build Coastguard Worker
733*8fb009dcSAndroid Build Coastguard Worker // Algorithm 6 of the Kyber spec.
decrypt_cpa(uint8_t out[32],const struct private_key * priv,const uint8_t ciphertext[KYBER_CIPHERTEXT_BYTES])734*8fb009dcSAndroid Build Coastguard Worker static void decrypt_cpa(uint8_t out[32], const struct private_key *priv,
735*8fb009dcSAndroid Build Coastguard Worker const uint8_t ciphertext[KYBER_CIPHERTEXT_BYTES]) {
736*8fb009dcSAndroid Build Coastguard Worker vector u;
737*8fb009dcSAndroid Build Coastguard Worker vector_decode(&u, ciphertext, kDU);
738*8fb009dcSAndroid Build Coastguard Worker vector_decompress(&u, kDU);
739*8fb009dcSAndroid Build Coastguard Worker vector_ntt(&u);
740*8fb009dcSAndroid Build Coastguard Worker scalar v;
741*8fb009dcSAndroid Build Coastguard Worker scalar_decode(&v, ciphertext + kCompressedVectorSize, kDV);
742*8fb009dcSAndroid Build Coastguard Worker scalar_decompress(&v, kDV);
743*8fb009dcSAndroid Build Coastguard Worker scalar mask;
744*8fb009dcSAndroid Build Coastguard Worker scalar_inner_product(&mask, &priv->s, &u);
745*8fb009dcSAndroid Build Coastguard Worker scalar_inverse_ntt(&mask);
746*8fb009dcSAndroid Build Coastguard Worker scalar_sub(&v, &mask);
747*8fb009dcSAndroid Build Coastguard Worker scalar_compress(&v, 1);
748*8fb009dcSAndroid Build Coastguard Worker scalar_encode_1(out, &v);
749*8fb009dcSAndroid Build Coastguard Worker }
750*8fb009dcSAndroid Build Coastguard Worker
751*8fb009dcSAndroid Build Coastguard Worker // Algorithm 9 of the Kyber spec, performing the FO transform by running
752*8fb009dcSAndroid Build Coastguard Worker // encrypt_cpa on the decrypted message. The spec does not allow the decryption
753*8fb009dcSAndroid Build Coastguard Worker // failure to be passed on to the caller, and instead returns a result that is
754*8fb009dcSAndroid Build Coastguard Worker // deterministic but unpredictable to anyone without knowledge of the private
755*8fb009dcSAndroid Build Coastguard Worker // key.
KYBER_decap(uint8_t out_shared_secret[KYBER_SHARED_SECRET_BYTES],const uint8_t ciphertext[KYBER_CIPHERTEXT_BYTES],const struct KYBER_private_key * private_key)756*8fb009dcSAndroid Build Coastguard Worker void KYBER_decap(uint8_t out_shared_secret[KYBER_SHARED_SECRET_BYTES],
757*8fb009dcSAndroid Build Coastguard Worker const uint8_t ciphertext[KYBER_CIPHERTEXT_BYTES],
758*8fb009dcSAndroid Build Coastguard Worker const struct KYBER_private_key *private_key) {
759*8fb009dcSAndroid Build Coastguard Worker const struct private_key *priv = private_key_from_external(private_key);
760*8fb009dcSAndroid Build Coastguard Worker uint8_t decrypted[64];
761*8fb009dcSAndroid Build Coastguard Worker decrypt_cpa(decrypted, priv, ciphertext);
762*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(decrypted + 32, priv->pub.public_key_hash,
763*8fb009dcSAndroid Build Coastguard Worker sizeof(decrypted) - 32);
764*8fb009dcSAndroid Build Coastguard Worker uint8_t prekey_and_randomness[64];
765*8fb009dcSAndroid Build Coastguard Worker hash_g(prekey_and_randomness, decrypted, sizeof(decrypted));
766*8fb009dcSAndroid Build Coastguard Worker uint8_t expected_ciphertext[KYBER_CIPHERTEXT_BYTES];
767*8fb009dcSAndroid Build Coastguard Worker encrypt_cpa(expected_ciphertext, &priv->pub, decrypted,
768*8fb009dcSAndroid Build Coastguard Worker prekey_and_randomness + 32);
769*8fb009dcSAndroid Build Coastguard Worker uint8_t mask =
770*8fb009dcSAndroid Build Coastguard Worker constant_time_eq_int_8(CRYPTO_memcmp(ciphertext, expected_ciphertext,
771*8fb009dcSAndroid Build Coastguard Worker sizeof(expected_ciphertext)),
772*8fb009dcSAndroid Build Coastguard Worker 0);
773*8fb009dcSAndroid Build Coastguard Worker uint8_t input[64];
774*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < 32; i++) {
775*8fb009dcSAndroid Build Coastguard Worker input[i] = constant_time_select_8(mask, prekey_and_randomness[i],
776*8fb009dcSAndroid Build Coastguard Worker priv->fo_failure_secret[i]);
777*8fb009dcSAndroid Build Coastguard Worker }
778*8fb009dcSAndroid Build Coastguard Worker hash_h(input + 32, ciphertext, KYBER_CIPHERTEXT_BYTES);
779*8fb009dcSAndroid Build Coastguard Worker kdf(out_shared_secret, KYBER_SHARED_SECRET_BYTES, input, sizeof(input));
780*8fb009dcSAndroid Build Coastguard Worker }
781*8fb009dcSAndroid Build Coastguard Worker
KYBER_marshal_public_key(CBB * out,const struct KYBER_public_key * public_key)782*8fb009dcSAndroid Build Coastguard Worker int KYBER_marshal_public_key(CBB *out,
783*8fb009dcSAndroid Build Coastguard Worker const struct KYBER_public_key *public_key) {
784*8fb009dcSAndroid Build Coastguard Worker return kyber_marshal_public_key(out, public_key_from_external(public_key));
785*8fb009dcSAndroid Build Coastguard Worker }
786*8fb009dcSAndroid Build Coastguard Worker
787*8fb009dcSAndroid Build Coastguard Worker // kyber_parse_public_key_no_hash parses |in| into |pub| but doesn't calculate
788*8fb009dcSAndroid Build Coastguard Worker // the value of |pub->public_key_hash|.
kyber_parse_public_key_no_hash(struct public_key * pub,CBS * in)789*8fb009dcSAndroid Build Coastguard Worker static int kyber_parse_public_key_no_hash(struct public_key *pub, CBS *in) {
790*8fb009dcSAndroid Build Coastguard Worker CBS t_bytes;
791*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_bytes(in, &t_bytes, kEncodedVectorSize) ||
792*8fb009dcSAndroid Build Coastguard Worker !vector_decode(&pub->t, CBS_data(&t_bytes), kLog2Prime) ||
793*8fb009dcSAndroid Build Coastguard Worker !CBS_copy_bytes(in, pub->rho, sizeof(pub->rho))) {
794*8fb009dcSAndroid Build Coastguard Worker return 0;
795*8fb009dcSAndroid Build Coastguard Worker }
796*8fb009dcSAndroid Build Coastguard Worker matrix_expand(&pub->m, pub->rho);
797*8fb009dcSAndroid Build Coastguard Worker return 1;
798*8fb009dcSAndroid Build Coastguard Worker }
799*8fb009dcSAndroid Build Coastguard Worker
KYBER_parse_public_key(struct KYBER_public_key * public_key,CBS * in)800*8fb009dcSAndroid Build Coastguard Worker int KYBER_parse_public_key(struct KYBER_public_key *public_key, CBS *in) {
801*8fb009dcSAndroid Build Coastguard Worker struct public_key *pub = public_key_from_external(public_key);
802*8fb009dcSAndroid Build Coastguard Worker CBS orig_in = *in;
803*8fb009dcSAndroid Build Coastguard Worker if (!kyber_parse_public_key_no_hash(pub, in) || //
804*8fb009dcSAndroid Build Coastguard Worker CBS_len(in) != 0) {
805*8fb009dcSAndroid Build Coastguard Worker return 0;
806*8fb009dcSAndroid Build Coastguard Worker }
807*8fb009dcSAndroid Build Coastguard Worker hash_h(pub->public_key_hash, CBS_data(&orig_in), CBS_len(&orig_in));
808*8fb009dcSAndroid Build Coastguard Worker return 1;
809*8fb009dcSAndroid Build Coastguard Worker }
810*8fb009dcSAndroid Build Coastguard Worker
KYBER_marshal_private_key(CBB * out,const struct KYBER_private_key * private_key)811*8fb009dcSAndroid Build Coastguard Worker int KYBER_marshal_private_key(CBB *out,
812*8fb009dcSAndroid Build Coastguard Worker const struct KYBER_private_key *private_key) {
813*8fb009dcSAndroid Build Coastguard Worker const struct private_key *const priv = private_key_from_external(private_key);
814*8fb009dcSAndroid Build Coastguard Worker uint8_t *s_output;
815*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_space(out, &s_output, kEncodedVectorSize)) {
816*8fb009dcSAndroid Build Coastguard Worker return 0;
817*8fb009dcSAndroid Build Coastguard Worker }
818*8fb009dcSAndroid Build Coastguard Worker vector_encode(s_output, &priv->s, kLog2Prime);
819*8fb009dcSAndroid Build Coastguard Worker if (!kyber_marshal_public_key(out, &priv->pub) ||
820*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(out, priv->pub.public_key_hash,
821*8fb009dcSAndroid Build Coastguard Worker sizeof(priv->pub.public_key_hash)) ||
822*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(out, priv->fo_failure_secret,
823*8fb009dcSAndroid Build Coastguard Worker sizeof(priv->fo_failure_secret))) {
824*8fb009dcSAndroid Build Coastguard Worker return 0;
825*8fb009dcSAndroid Build Coastguard Worker }
826*8fb009dcSAndroid Build Coastguard Worker return 1;
827*8fb009dcSAndroid Build Coastguard Worker }
828*8fb009dcSAndroid Build Coastguard Worker
KYBER_parse_private_key(struct KYBER_private_key * out_private_key,CBS * in)829*8fb009dcSAndroid Build Coastguard Worker int KYBER_parse_private_key(struct KYBER_private_key *out_private_key,
830*8fb009dcSAndroid Build Coastguard Worker CBS *in) {
831*8fb009dcSAndroid Build Coastguard Worker struct private_key *const priv = private_key_from_external(out_private_key);
832*8fb009dcSAndroid Build Coastguard Worker
833*8fb009dcSAndroid Build Coastguard Worker CBS s_bytes;
834*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_bytes(in, &s_bytes, kEncodedVectorSize) ||
835*8fb009dcSAndroid Build Coastguard Worker !vector_decode(&priv->s, CBS_data(&s_bytes), kLog2Prime) ||
836*8fb009dcSAndroid Build Coastguard Worker !kyber_parse_public_key_no_hash(&priv->pub, in) ||
837*8fb009dcSAndroid Build Coastguard Worker !CBS_copy_bytes(in, priv->pub.public_key_hash,
838*8fb009dcSAndroid Build Coastguard Worker sizeof(priv->pub.public_key_hash)) ||
839*8fb009dcSAndroid Build Coastguard Worker !CBS_copy_bytes(in, priv->fo_failure_secret,
840*8fb009dcSAndroid Build Coastguard Worker sizeof(priv->fo_failure_secret)) ||
841*8fb009dcSAndroid Build Coastguard Worker CBS_len(in) != 0) {
842*8fb009dcSAndroid Build Coastguard Worker return 0;
843*8fb009dcSAndroid Build Coastguard Worker }
844*8fb009dcSAndroid Build Coastguard Worker return 1;
845*8fb009dcSAndroid Build Coastguard Worker }
846