Skip to content

Commit 058dae1

Browse files
mkannwischerthomwiggers
authored andcommitted
Port KyberSlash fixes to AArch64
Port Kyber branch vulnerability fixes to AArch64
1 parent 47fb218 commit 058dae1

File tree

18 files changed

+183
-79
lines changed

18 files changed

+183
-79
lines changed

crypto_kem/kyber1024/aarch64/poly.c

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "reduce.h"
4040
#include "cbd.h"
4141
#include "symmetric.h"
42+
#include "verify.h"
4243

4344
/*************************************************
4445
* Name: poly_compress
@@ -51,23 +52,29 @@
5152
**************************************************/
5253
void poly_compress(uint8_t r[KYBER_POLYCOMPRESSEDBYTES], const int16_t a[KYBER_N]) {
5354
unsigned int i, j;
54-
int16_t u;
55+
int32_t u;
56+
uint32_t d0;
5557
uint8_t t[8];
5658

59+
5760
for (i = 0; i < KYBER_N / 8; i++) {
5861
for (j = 0; j < 8; j++) {
5962
// map to positive standard representatives
6063
u = a[8 * i + j];
6164
u += (u >> 15) & KYBER_Q;
62-
t[j] = ((((uint32_t)u << 5) + KYBER_Q / 2) / KYBER_Q) & 31;
65+
/* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */
66+
d0 = u << 4;
67+
d0 += 1665;
68+
d0 *= 80635;
69+
d0 >>= 28;
70+
t[j] = d0 & 0xf;
6371
}
6472

65-
r[0] = (t[0] >> 0) | (t[1] << 5);
66-
r[1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7);
67-
r[2] = (t[3] >> 1) | (t[4] << 4);
68-
r[3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6);
69-
r[4] = (t[6] >> 2) | (t[7] << 3);
70-
r += 5;
73+
r[0] = t[0] | (t[1] << 4);
74+
r[1] = t[2] | (t[3] << 4);
75+
r[2] = t[4] | (t[5] << 4);
76+
r[3] = t[6] | (t[7] << 4);
77+
r += 4;
7178
}
7279
}
7380

@@ -182,14 +189,13 @@ void poly_frombytes(int16_t r[KYBER_N], const uint8_t a[KYBER_POLYBYTES]) {
182189
* Arguments: - poly *r: pointer to output polynomial
183190
* - const uint8_t *msg: pointer to input message
184191
**************************************************/
185-
void poly_frommsg(int16_t r[KYBER_N], const uint8_t msg[KYBER_INDCPA_MSGBYTES]) {
186-
unsigned int i, j;
187-
int16_t mask;
192+
void poly_frommsg(int16_t r[KYBER_N], const uint8_t msg[KYBER_INDCPA_MSGBYTES]) {
193+
size_t i, j;
188194

189195
for (i = 0; i < KYBER_N / 8; i++) {
190196
for (j = 0; j < 8; j++) {
191-
mask = -(int16_t)((msg[i] >> j) & 1);
192-
r[8 * i + j] = mask & ((KYBER_Q + 1) / 2);
197+
r[8 * i + j] = 0;
198+
cmov_int16(r + 8 * i + j, ((KYBER_Q + 1) / 2), (msg[i] >> j) & 1);
193199
}
194200
}
195201
}
@@ -204,14 +210,19 @@ void poly_frommsg(int16_t r[KYBER_N], const uint8_t msg[KYBER_INDCPA_MSGBYTES])
204210
**************************************************/
205211
void poly_tomsg(uint8_t msg[KYBER_INDCPA_MSGBYTES], const int16_t a[KYBER_N]) {
206212
unsigned int i, j;
207-
uint16_t t;
213+
uint32_t t;
208214

209215
for (i = 0; i < KYBER_N / 8; i++) {
210216
msg[i] = 0;
211217
for (j = 0; j < 8; j++) {
212218
t = a[8 * i + j];
213-
t += ((int16_t)t >> 15) & KYBER_Q;
214-
t = (((t << 1) + KYBER_Q / 2) / KYBER_Q) & 1;
219+
// t += ((int16_t)t >> 15) & KYBER_Q;
220+
// t = (((t << 1) + KYBER_Q/2)/KYBER_Q) & 1;
221+
t <<= 1;
222+
t += 1665;
223+
t *= 80635;
224+
t >>= 28;
225+
t &= 1;
215226
msg[i] |= t << j;
216227
}
217228
}

crypto_kem/kyber1024/aarch64/poly.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ void poly_decompress(int16_t r[KYBER_N], const uint8_t a[KYBER_POLYCOMPRESSEDBYT
2828
void poly_tobytes(uint8_t r[KYBER_POLYBYTES], const int16_t a[KYBER_N]);
2929

3030
#define poly_frommsg KYBER_NAMESPACE(poly_frommsg)
31-
void poly_frommsg(int16_t r[KYBER_N], const uint8_t msg[KYBER_INDCPA_MSGBYTES]);
31+
void poly_frommsg(int16_t r[KYBER_N], const uint8_t msg[KYBER_INDCPA_MSGBYTES]) ;
3232
#define poly_tomsg KYBER_NAMESPACE(poly_tomsg)
33-
void poly_tomsg(uint8_t msg[KYBER_INDCPA_MSGBYTES], const int16_t r[KYBER_N]);
33+
void poly_tomsg(uint8_t msg[KYBER_INDCPA_MSGBYTES], const int16_t a[KYBER_N]);
3434

3535
// NEON
3636

crypto_kem/kyber1024/aarch64/polyvec.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,31 @@
1919
* (needs space for KYBER_POLYVECCOMPRESSEDBYTES)
2020
* - const polyvec *a: pointer to input vector of polynomials
2121
**************************************************/
22-
void polyvec_compress(uint8_t r[KYBER_POLYVECCOMPRESSEDBYTES], const int16_t a[KYBER_K][KYBER_N]) {
22+
void polyvec_compress(uint8_t r[KYBER_POLYVECCOMPRESSEDBYTES], const int16_t b[KYBER_K][KYBER_N]) {
2323
unsigned int i, j, k;
24+
uint64_t d0;
2425

25-
uint16_t t[8];
26+
uint16_t t[4];
2627
for (i = 0; i < KYBER_K; i++) {
27-
for (j = 0; j < KYBER_N / 8; j++) {
28-
for (k = 0; k < 8; k++) {
29-
t[k] = a[i][8 * j + k];
28+
for (j = 0; j < KYBER_N / 4; j++) {
29+
for (k = 0; k < 4; k++) {
30+
t[k] = b[i][4 * j + k];
3031
t[k] += ((int16_t)t[k] >> 15) & KYBER_Q;
31-
t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q / 2) / KYBER_Q) & 0x7ff;
32+
/* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */
33+
d0 = t[k];
34+
d0 <<= 10;
35+
d0 += 1665;
36+
d0 *= 1290167;
37+
d0 >>= 32;
38+
t[k] = d0 & 0x3ff;
3239
}
3340

34-
r[ 0] = (t[0] >> 0);
35-
r[ 1] = (t[0] >> 8) | (t[1] << 3);
36-
r[ 2] = (t[1] >> 5) | (t[2] << 6);
37-
r[ 3] = (t[2] >> 2);
38-
r[ 4] = (t[2] >> 10) | (t[3] << 1);
39-
r[ 5] = (t[3] >> 7) | (t[4] << 4);
40-
r[ 6] = (t[4] >> 4) | (t[5] << 7);
41-
r[ 7] = (t[5] >> 1);
42-
r[ 8] = (t[5] >> 9) | (t[6] << 2);
43-
r[ 9] = (t[6] >> 6) | (t[7] << 5);
44-
r[10] = (t[7] >> 3);
45-
r += 11;
41+
r[0] = (uint8_t)(t[0] >> 0);
42+
r[1] = (uint8_t)((t[0] >> 8) | (t[1] << 2));
43+
r[2] = (uint8_t)((t[1] >> 6) | (t[2] << 4));
44+
r[3] = (uint8_t)((t[2] >> 4) | (t[3] << 6));
45+
r[4] = (uint8_t)(t[3] >> 2);
46+
r += 5;
4647
}
4748
}
4849
}

crypto_kem/kyber1024/aarch64/polyvec.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ typedef struct {
4444
} polyvec;
4545

4646
#define polyvec_compress KYBER_NAMESPACE(polyvec_compress)
47-
void polyvec_compress(uint8_t r[KYBER_POLYVECCOMPRESSEDBYTES], const int16_t a[KYBER_K][KYBER_N]);
47+
void polyvec_compress(uint8_t r[KYBER_POLYVECCOMPRESSEDBYTES], const int16_t b[KYBER_K][KYBER_N]);
4848
#define polyvec_decompress KYBER_NAMESPACE(polyvec_decompress)
4949
void polyvec_decompress(int16_t r[KYBER_K][KYBER_N], const uint8_t a[KYBER_POLYVECCOMPRESSEDBYTES]);
5050

crypto_kem/kyber1024/aarch64/verify.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,19 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) {
5252
r[i] ^= b & (r[i] ^ x[i]);
5353
}
5454
}
55+
56+
/*************************************************
57+
* Name: cmov_int16
58+
*
59+
* Description: Copy input v to *r if b is 1, don't modify *r if b is 0.
60+
* Requires b to be in {0,1};
61+
* Runs in constant time.
62+
*
63+
* Arguments: int16_t *r: pointer to output int16_t
64+
* int16_t v: input int16_t
65+
* uint8_t b: Condition bit; has to be in {0,1}
66+
**************************************************/
67+
void cmov_int16(int16_t *r, int16_t v, uint16_t b) {
68+
b = -b;
69+
*r ^= b & ((*r) ^ v);
70+
}

crypto_kem/kyber1024/aarch64/verify.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,6 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
1717
#define cmov KYBER_NAMESPACE(cmov)
1818
void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
1919

20+
#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
21+
void cmov_int16(int16_t *r, int16_t v, uint16_t b);
2022
#endif

crypto_kem/kyber512/aarch64/poly.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "reduce.h"
4040
#include "cbd.h"
4141
#include "symmetric.h"
42+
#include "verify.h"
4243

4344
/*************************************************
4445
* Name: poly_compress
@@ -51,15 +52,22 @@
5152
**************************************************/
5253
void poly_compress(uint8_t r[KYBER_POLYCOMPRESSEDBYTES], const int16_t a[KYBER_N]) {
5354
unsigned int i, j;
54-
int16_t u;
55+
int32_t u;
56+
uint32_t d0;
5557
uint8_t t[8];
5658

59+
5760
for (i = 0; i < KYBER_N / 8; i++) {
5861
for (j = 0; j < 8; j++) {
5962
// map to positive standard representatives
6063
u = a[8 * i + j];
6164
u += (u >> 15) & KYBER_Q;
62-
t[j] = ((((uint16_t)u << 4) + KYBER_Q / 2) / KYBER_Q) & 15;
65+
/* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */
66+
d0 = u << 4;
67+
d0 += 1665;
68+
d0 *= 80635;
69+
d0 >>= 28;
70+
t[j] = d0 & 0xf;
6371
}
6472

6573
r[0] = t[0] | (t[1] << 4);
@@ -169,14 +177,13 @@ void poly_frombytes(int16_t r[KYBER_N], const uint8_t a[KYBER_POLYBYTES]) {
169177
* Arguments: - poly *r: pointer to output polynomial
170178
* - const uint8_t *msg: pointer to input message
171179
**************************************************/
172-
void poly_frommsg(int16_t r[KYBER_N], const uint8_t msg[KYBER_INDCPA_MSGBYTES]) {
173-
unsigned int i, j;
174-
int16_t mask;
180+
void poly_frommsg(int16_t r[KYBER_N], const uint8_t msg[KYBER_INDCPA_MSGBYTES]) {
181+
size_t i, j;
175182

176183
for (i = 0; i < KYBER_N / 8; i++) {
177184
for (j = 0; j < 8; j++) {
178-
mask = -(int16_t)((msg[i] >> j) & 1);
179-
r[8 * i + j] = mask & ((KYBER_Q + 1) / 2);
185+
r[8 * i + j] = 0;
186+
cmov_int16(r + 8 * i + j, ((KYBER_Q + 1) / 2), (msg[i] >> j) & 1);
180187
}
181188
}
182189
}
@@ -191,14 +198,19 @@ void poly_frommsg(int16_t r[KYBER_N], const uint8_t msg[KYBER_INDCPA_MSGBYTES])
191198
**************************************************/
192199
void poly_tomsg(uint8_t msg[KYBER_INDCPA_MSGBYTES], const int16_t a[KYBER_N]) {
193200
unsigned int i, j;
194-
uint16_t t;
201+
uint32_t t;
195202

196203
for (i = 0; i < KYBER_N / 8; i++) {
197204
msg[i] = 0;
198205
for (j = 0; j < 8; j++) {
199206
t = a[8 * i + j];
200-
t += ((int16_t)t >> 15) & KYBER_Q;
201-
t = (((t << 1) + KYBER_Q / 2) / KYBER_Q) & 1;
207+
// t += ((int16_t)t >> 15) & KYBER_Q;
208+
// t = (((t << 1) + KYBER_Q/2)/KYBER_Q) & 1;
209+
t <<= 1;
210+
t += 1665;
211+
t *= 80635;
212+
t >>= 28;
213+
t &= 1;
202214
msg[i] |= t << j;
203215
}
204216
}

crypto_kem/kyber512/aarch64/poly.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ void poly_decompress(int16_t r[KYBER_N], const uint8_t a[KYBER_POLYCOMPRESSEDBYT
2828
void poly_tobytes(uint8_t r[KYBER_POLYBYTES], const int16_t a[KYBER_N]);
2929

3030
#define poly_frommsg KYBER_NAMESPACE(poly_frommsg)
31-
void poly_frommsg(int16_t r[KYBER_N], const uint8_t msg[KYBER_INDCPA_MSGBYTES]);
31+
void poly_frommsg(int16_t r[KYBER_N], const uint8_t msg[KYBER_INDCPA_MSGBYTES]) ;
3232
#define poly_tomsg KYBER_NAMESPACE(poly_tomsg)
33-
void poly_tomsg(uint8_t msg[KYBER_INDCPA_MSGBYTES], const int16_t r[KYBER_N]);
33+
void poly_tomsg(uint8_t msg[KYBER_INDCPA_MSGBYTES], const int16_t a[KYBER_N]);
3434

3535
// NEON
3636

crypto_kem/kyber512/aarch64/polyvec.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,30 @@
1919
* (needs space for KYBER_POLYVECCOMPRESSEDBYTES)
2020
* - const polyvec *a: pointer to input vector of polynomials
2121
**************************************************/
22-
void polyvec_compress(uint8_t r[KYBER_POLYVECCOMPRESSEDBYTES], const int16_t a[KYBER_K][KYBER_N]) {
22+
void polyvec_compress(uint8_t r[KYBER_POLYVECCOMPRESSEDBYTES], const int16_t b[KYBER_K][KYBER_N]) {
2323
unsigned int i, j, k;
24+
uint64_t d0;
2425

2526
uint16_t t[4];
2627
for (i = 0; i < KYBER_K; i++) {
2728
for (j = 0; j < KYBER_N / 4; j++) {
2829
for (k = 0; k < 4; k++) {
29-
t[k] = a[i][4 * j + k];
30+
t[k] = b[i][4 * j + k];
3031
t[k] += ((int16_t)t[k] >> 15) & KYBER_Q;
31-
t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff;
32+
/* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */
33+
d0 = t[k];
34+
d0 <<= 10;
35+
d0 += 1665;
36+
d0 *= 1290167;
37+
d0 >>= 32;
38+
t[k] = d0 & 0x3ff;
3239
}
3340

34-
r[0] = (t[0] >> 0);
35-
r[1] = (t[0] >> 8) | (t[1] << 2);
36-
r[2] = (t[1] >> 6) | (t[2] << 4);
37-
r[3] = (t[2] >> 4) | (t[3] << 6);
38-
r[4] = (t[3] >> 2);
41+
r[0] = (uint8_t)(t[0] >> 0);
42+
r[1] = (uint8_t)((t[0] >> 8) | (t[1] << 2));
43+
r[2] = (uint8_t)((t[1] >> 6) | (t[2] << 4));
44+
r[3] = (uint8_t)((t[2] >> 4) | (t[3] << 6));
45+
r[4] = (uint8_t)(t[3] >> 2);
3946
r += 5;
4047
}
4148
}

crypto_kem/kyber512/aarch64/polyvec.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ typedef struct {
4444
} polyvec;
4545

4646
#define polyvec_compress KYBER_NAMESPACE(polyvec_compress)
47-
void polyvec_compress(uint8_t r[KYBER_POLYVECCOMPRESSEDBYTES], const int16_t a[KYBER_K][KYBER_N]);
47+
void polyvec_compress(uint8_t r[KYBER_POLYVECCOMPRESSEDBYTES], const int16_t b[KYBER_K][KYBER_N]);
4848
#define polyvec_decompress KYBER_NAMESPACE(polyvec_decompress)
4949
void polyvec_decompress(int16_t r[KYBER_K][KYBER_N], const uint8_t a[KYBER_POLYVECCOMPRESSEDBYTES]);
5050

0 commit comments

Comments
 (0)