Skip to content

Commit 8df5b1a

Browse files
committed
cmov proposal
This proposal does not conditionally load a value, which could be less future proof. Indeed, having only one "branch" load a value is what could cause a compiler to create a branch, as it can avoid a load from memory given a condition - which is usually considered as an effective optimization.
1 parent 441c051 commit 8df5b1a

File tree

4 files changed

+24
-11
lines changed

4 files changed

+24
-11
lines changed

ref/compat.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef COMPAT_H
2+
#define COMPAT_H
3+
4+
#ifdef _MSC_VER
5+
#define KYBER_NOINLINE __declspec(noinline)
6+
#else
7+
#define KYBER_NOINLINE __attribute__((noinline))
8+
#endif
9+
10+
#endif

ref/poly.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,7 @@ void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
174174

175175
for(i=0;i<KYBER_N/8;i++) {
176176
for(j=0;j<8;j++) {
177-
r->coeffs[8*i+j] = 0;
178-
cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1);
177+
r->coeffs[8*i+j] = cmov_int16(0, ((KYBER_Q+1)/2), (msg[i] >> j)&1);
179178
}
180179
}
181180
}

ref/verify.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <stddef.h>
22
#include <stdint.h>
33
#include "verify.h"
4+
#include "compat.h"
45

56
/*************************************************
67
* Name: verify
@@ -59,16 +60,19 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b)
5960
/*************************************************
6061
* Name: cmov_int16
6162
*
62-
* Description: Copy input v to *r if b is 1, don't modify *r if b is 0.
63-
* Requires b to be in {0,1};
63+
* Description: Returns a if select == 1, or b if select == 0.
64+
* Requires select to be in {0,1}.
6465
* Runs in constant time.
6566
*
66-
* Arguments: int16_t *r: pointer to output int16_t
67-
* int16_t v: input int16_t
68-
* uint8_t b: Condition bit; has to be in {0,1}
67+
* Arguments: int16_t a: first int16_t input
68+
* int16_t b: second int16_t input
69+
* uint8_t select: Condition bit; has to be in {0,1}
70+
*
71+
* Returns a if select == 1 or b if select == 0, or
72+
* an undefined value otherwise.
6973
**************************************************/
70-
void cmov_int16(int16_t *r, int16_t v, uint16_t b)
74+
KYBER_NOINLINE int16_t cmov_int16(int16_t a, int16_t b, uint16_t select)
7175
{
72-
b = -b;
73-
*r ^= b & ((*r) ^ v);
76+
const uint16_t mask = -select;
77+
return a ^ (mask & (a ^ b));
7478
}

ref/verify.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
1212
void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
1313

1414
#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
15-
void cmov_int16(int16_t *r, int16_t v, uint16_t b);
15+
int16_t cmov_int16(int16_t a, int16_t b, uint16_t select);
1616

1717
#endif

0 commit comments

Comments
 (0)