1 /* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2  * SPDX-License-Identifier: Apache-2.0"
3  *
4  * Written by Nir Drucker, Shay Gueron, and Dusan Kostic,
5  * AWS Cryptographic Algorithms Group.
6  */
7 
8 #include "decode.h"
9 #include "gf2x.h"
10 #include "sampling.h"
11 #include "sha.h"
12 #include "tls/s2n_kem.h"
13 #include "pq-crypto/s2n_pq.h"
14 
15 // m_t and seed_t have the same size and thus can be considered
16 // to be of the same type. However, for security reasons we distinguish
17 // these types, even on the costs of small extra complexity.
convert_seed_to_m_type(OUT m_t * m,IN const seed_t * seed)18 _INLINE_ void convert_seed_to_m_type(OUT m_t *m, IN const seed_t *seed)
19 {
20   bike_static_assert(sizeof(*m) == sizeof(*seed), m_size_eq_seed_size);
21   bike_memcpy(m->raw, seed->raw, sizeof(*m));
22 }
23 
convert_m_to_seed_type(OUT seed_t * seed,IN const m_t * m)24 _INLINE_ void convert_m_to_seed_type(OUT seed_t *seed, IN const m_t *m)
25 {
26   bike_static_assert(sizeof(*m) == sizeof(*seed), m_size_eq_seed_size);
27   bike_memcpy(seed->raw, m->raw, sizeof(*seed));
28 }
29 
30 // (e0, e1) = H(m)
function_h(OUT pad_e_t * e,IN const m_t * m)31 _INLINE_ ret_t function_h(OUT pad_e_t *e, IN const m_t *m)
32 {
33   DEFER_CLEANUP(seed_t seed = {0}, seed_cleanup);
34 
35   convert_m_to_seed_type(&seed, m);
36   return generate_error_vector(e, &seed);
37 }
38 
39 // out = L(e)
function_l(OUT m_t * out,IN const pad_e_t * e)40 _INLINE_ ret_t function_l(OUT m_t *out, IN const pad_e_t *e)
41 {
42   DEFER_CLEANUP(sha_dgst_t dgst = {0}, sha_dgst_cleanup);
43   DEFER_CLEANUP(e_t tmp, e_cleanup);
44 
45   // Take the padding away
46   tmp.val[0] = e->val[0].val;
47   tmp.val[1] = e->val[1].val;
48 
49   POSIX_GUARD(sha(&dgst, sizeof(tmp), (uint8_t *)&tmp));
50 
51   // Truncate the SHA384 digest to a 256-bits m_t
52   bike_static_assert(sizeof(dgst) >= sizeof(*out), dgst_size_lt_m_size);
53   bike_memcpy(out->raw, dgst.u.raw, sizeof(*out));
54 
55   return SUCCESS;
56 }
57 
58 // Generate the Shared Secret K(m, c0, c1)
function_k(OUT ss_t * out,IN const m_t * m,IN const ct_t * ct)59 _INLINE_ ret_t function_k(OUT ss_t *out, IN const m_t *m, IN const ct_t *ct)
60 {
61   DEFER_CLEANUP(func_k_t tmp, func_k_cleanup);
62   DEFER_CLEANUP(sha_dgst_t dgst = {0}, sha_dgst_cleanup);
63 
64   // Copy every element, padded to the nearest byte
65   tmp.m  = *m;
66   tmp.c0 = ct->c0;
67   tmp.c1 = ct->c1;
68 
69   POSIX_GUARD(sha(&dgst, sizeof(tmp), (uint8_t *)&tmp));
70 
71   // Truncate the SHA384 digest to a 256-bits value
72   // to subsequently use it as a seed.
73   bike_static_assert(sizeof(dgst) >= sizeof(*out), dgst_size_lt_out_size);
74   bike_memcpy(out->raw, dgst.u.raw, sizeof(*out));
75 
76   return SUCCESS;
77 }
78 
encrypt(OUT ct_t * ct,IN const pad_e_t * e,IN const pk_t * pk,IN const m_t * m)79 _INLINE_ ret_t encrypt(OUT ct_t *ct,
80                        IN const pad_e_t *e,
81                        IN const pk_t *pk,
82                        IN const m_t *m)
83 {
84   // Pad the public key and the ciphertext
85   pad_r_t p_ct = {0};
86   pad_r_t p_pk = {0};
87   p_pk.val     = *pk;
88 
89   // Generate the ciphertext
90   // ct = pk * e1 + e0
91   gf2x_mod_mul(&p_ct, &e->val[1], &p_pk);
92   gf2x_mod_add(&p_ct, &p_ct, &e->val[0]);
93 
94   ct->c0 = p_ct.val;
95 
96   // c1 = L(e0, e1)
97   POSIX_GUARD(function_l(&ct->c1, e));
98 
99   // m xor L(e0, e1)
100   for(size_t i = 0; i < sizeof(*m); i++) {
101     ct->c1.raw[i] ^= m->raw[i];
102   }
103 
104   return SUCCESS;
105 }
106 
reencrypt(OUT m_t * m,IN const pad_e_t * e,IN const ct_t * l_ct)107 _INLINE_ ret_t reencrypt(OUT m_t *m, IN const pad_e_t *e, IN const ct_t *l_ct)
108 {
109   DEFER_CLEANUP(m_t tmp, m_cleanup);
110 
111   POSIX_GUARD(function_l(&tmp, e));
112 
113   // m' = c1 ^ L(e')
114   for(size_t i = 0; i < sizeof(*m); i++) {
115     m->raw[i] = tmp.raw[i] ^ l_ct->c1.raw[i];
116   }
117 
118   return SUCCESS;
119 }
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 // The three APIs below (keypair, encapsulate, decapsulate) are defined by NIST:
123 ////////////////////////////////////////////////////////////////////////////////
BIKE_L1_R3_crypto_kem_keypair(OUT unsigned char * pk,OUT unsigned char * sk)124 int BIKE_L1_R3_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk)
125 {
126   POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
127   POSIX_ENSURE_REF(sk);
128   POSIX_ENSURE_REF(pk);
129 
130   DEFER_CLEANUP(aligned_sk_t l_sk = {0}, sk_cleanup);
131 
132   // The secret key is (h0, h1),
133   // and the public key h=(h0^-1 * h1).
134   // Padded structures are used internally, and are required by the
135   // decoder and the gf2x multiplication.
136   DEFER_CLEANUP(pad_r_t h0 = {0}, pad_r_cleanup);
137   DEFER_CLEANUP(pad_r_t h1 = {0}, pad_r_cleanup);
138   DEFER_CLEANUP(pad_r_t h0inv = {0}, pad_r_cleanup);
139   DEFER_CLEANUP(pad_r_t h = {0}, pad_r_cleanup);
140 
141   // The randomness of the key generation
142   DEFER_CLEANUP(seeds_t seeds = {0}, seeds_cleanup);
143 
144   // An AES_PRF state for the secret key
145   DEFER_CLEANUP(aes_ctr_prf_state_t h_prf_state = {0}, aes_ctr_prf_state_cleanup);
146 
147   POSIX_GUARD(get_seeds(&seeds));
148   POSIX_GUARD(init_aes_ctr_prf_state(&h_prf_state, MAX_AES_INVOKATION, &seeds.seed[0]));
149 
150   // Generate the secret key (h0, h1) with weight w/2
151   POSIX_GUARD(generate_sparse_rep(&h0, l_sk.wlist[0].val, &h_prf_state));
152   POSIX_GUARD(generate_sparse_rep(&h1, l_sk.wlist[1].val, &h_prf_state));
153 
154   // Generate sigma
155   convert_seed_to_m_type(&l_sk.sigma, &seeds.seed[1]);
156 
157   // Calculate the public key
158   gf2x_mod_inv(&h0inv, &h0);
159   gf2x_mod_mul(&h, &h1, &h0inv);
160 
161   // Fill the secret key data structure with contents - cancel the padding
162   l_sk.bin[0] = h0.val;
163   l_sk.bin[1] = h1.val;
164   l_sk.pk     = h.val;
165 
166   // Copy the data to the output buffers
167   bike_memcpy(sk, &l_sk, sizeof(l_sk));
168   bike_memcpy(pk, &l_sk.pk, sizeof(l_sk.pk));
169 
170   return SUCCESS;
171 }
172 
173 // Encapsulate - pk is the public key,
174 //               ct is a key encapsulation message (ciphertext),
175 //               ss is the shared secret.
BIKE_L1_R3_crypto_kem_enc(OUT unsigned char * ct,OUT unsigned char * ss,IN const unsigned char * pk)176 int BIKE_L1_R3_crypto_kem_enc(OUT unsigned char *     ct,
177                    OUT unsigned char *     ss,
178                    IN const unsigned char *pk)
179 {
180   POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
181   POSIX_ENSURE_REF(pk);
182   POSIX_ENSURE_REF(ct);
183   POSIX_ENSURE_REF(ss);
184 
185   // Public values (they do not require cleanup on exit).
186   pk_t l_pk;
187   ct_t l_ct;
188 
189   DEFER_CLEANUP(m_t m, m_cleanup);
190   DEFER_CLEANUP(ss_t l_ss, ss_cleanup);
191   DEFER_CLEANUP(seeds_t seeds = {0}, seeds_cleanup);
192   DEFER_CLEANUP(pad_e_t e, pad_e_cleanup);
193 
194   // Copy the data from the input buffer. This is required in order to avoid
195   // alignment issues on non x86_64 processors.
196   bike_memcpy(&l_pk, pk, sizeof(l_pk));
197 
198   POSIX_GUARD(get_seeds(&seeds));
199 
200   // e = H(m) = H(seed[0])
201   convert_seed_to_m_type(&m, &seeds.seed[0]);
202   POSIX_GUARD(function_h(&e, &m));
203 
204   // Calculate the ciphertext
205   POSIX_GUARD(encrypt(&l_ct, &e, &l_pk, &m));
206 
207   // Generate the shared secret
208   POSIX_GUARD(function_k(&l_ss, &m, &l_ct));
209 
210   // Copy the data to the output buffers
211   bike_memcpy(ct, &l_ct, sizeof(l_ct));
212   bike_memcpy(ss, &l_ss, sizeof(l_ss));
213 
214   return SUCCESS;
215 }
216 
217 // Decapsulate - ct is a key encapsulation message (ciphertext),
218 //               sk is the private key,
219 //               ss is the shared secret
BIKE_L1_R3_crypto_kem_dec(OUT unsigned char * ss,IN const unsigned char * ct,IN const unsigned char * sk)220 int BIKE_L1_R3_crypto_kem_dec(OUT unsigned char *     ss,
221                    IN const unsigned char *ct,
222                    IN const unsigned char *sk)
223 {
224   POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
225   POSIX_ENSURE_REF(sk);
226   POSIX_ENSURE_REF(ct);
227   POSIX_ENSURE_REF(ss);
228 
229   // Public values, does not require a cleanup on exit
230   ct_t l_ct;
231 
232   DEFER_CLEANUP(seeds_t seeds = {0}, seeds_cleanup);
233 
234   DEFER_CLEANUP(ss_t l_ss, ss_cleanup);
235   DEFER_CLEANUP(aligned_sk_t l_sk, sk_cleanup);
236   DEFER_CLEANUP(e_t e, e_cleanup);
237   DEFER_CLEANUP(m_t m_prime, m_cleanup);
238   DEFER_CLEANUP(pad_e_t e_tmp, pad_e_cleanup);
239   DEFER_CLEANUP(pad_e_t e_prime, pad_e_cleanup);
240 
241   // Copy the data from the input buffers. This is required in order to avoid
242   // alignment issues on non x86_64 processors.
243   bike_memcpy(&l_ct, ct, sizeof(l_ct));
244   bike_memcpy(&l_sk, sk, sizeof(l_sk));
245 
246   // Generate a random error vector to be used in case of decoding failure
247   // (Note: possibly, a "fixed" zeroed error vector could suffice too,
248   // and serve this generation)
249   POSIX_GUARD(get_seeds(&seeds));
250   POSIX_GUARD(generate_error_vector(&e_prime, &seeds.seed[0]));
251 
252   // Decode and on success check if |e|=T (all in constant-time)
253   volatile uint32_t success_cond = (decode(&e, &l_ct, &l_sk) == SUCCESS);
254   success_cond &= secure_cmp32(T1, r_bits_vector_weight(&e.val[0]) +
255                                     r_bits_vector_weight(&e.val[1]));
256 
257   // Set appropriate error based on the success condition
258   uint8_t mask = ~secure_l32_mask(0, success_cond);
259   for(size_t i = 0; i < R_BYTES; i++) {
260     PE0_RAW(&e_prime)[i] &= u8_barrier(~mask);
261     PE0_RAW(&e_prime)[i] |= (u8_barrier(mask) & E0_RAW(&e)[i]);
262     PE1_RAW(&e_prime)[i] &= u8_barrier(~mask);
263     PE1_RAW(&e_prime)[i] |= (u8_barrier(mask) & E1_RAW(&e)[i]);
264   }
265 
266   POSIX_GUARD(reencrypt(&m_prime, &e_prime, &l_ct));
267 
268   // Check if H(m') is equal to (e0', e1')
269   // (in constant-time)
270   POSIX_GUARD(function_h(&e_tmp, &m_prime));
271   success_cond = secure_cmp(PE0_RAW(&e_prime), PE0_RAW(&e_tmp), R_BYTES);
272   success_cond &= secure_cmp(PE1_RAW(&e_prime), PE1_RAW(&e_tmp), R_BYTES);
273 
274   // Compute either K(m', C) or K(sigma, C) based on the success condition
275   mask = secure_l32_mask(0, success_cond);
276   for(size_t i = 0; i < M_BYTES; i++) {
277     m_prime.raw[i] &= u8_barrier(~mask);
278     m_prime.raw[i] |= (u8_barrier(mask) & l_sk.sigma.raw[i]);
279   }
280 
281   // Generate the shared secret
282   POSIX_GUARD(function_k(&l_ss, &m_prime, &l_ct));
283 
284   // Copy the data into the output buffer
285   bike_memcpy(ss, &l_ss, sizeof(l_ss));
286 
287   return SUCCESS;
288 }
289