CVE-2024-36405 (published 2024-06-10T13:15Z)

liboqs is a C-language cryptographic library that provides implementations of post-quantum cryptography algorithms. A control-flow timing lean has been identified in the reference implementation of the Kyber key encapsulation mechanism when it is compiled with Clang 15-18 for `-Os`, `-O1`, and other compilation options. A proof-of-concept local attack on the reference implementation leaks the entire ML-KEM 512 secret key in ~10 minutes using end-to-end decapsulation timing measurements. The issue has been fixed in version 0.10.1. As a possible workaround, some compiler options may produce vectorized code that does not leak secret information, however relying on these compiler options as a workaround may not be reliable.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/open-quantum-safe/liboqs
commit_details: repo_url: https://github.com/open-quantum-safe/liboqs
author: Basil Hess
author_date: 2024-06-03 15:26:57+02:00
msg: Pull Kyber/ML-KEM CT-Fix from upstream

Signed-off-by: Basil Hess <bhe@zurich.ibm.com>
repository: repo_url: https://github.com/open-quantum-safe/liboqs
repo_name: open-quantum-safe/liboqs
description: C library for prototyping and experimenting with quantum-resistant cryptography
repo_language: C
owner: open-quantum-safe
file_changes: filename: kyber.md
change_type: ModificationType.MODIFY
diff: @@ -7,9 +7,9 @@
 - **Authors' website**: https://pq-crystals.org/
 - **Specification version**: NIST Round 3 submission.
 - **Primary Source**<a name="primary-source"></a>:
-  - **Source**: https://github.com/pq-crystals/kyber/commit/b628ba78711bc28327dc7d2d5c074a00f061884e with copy_from_upstream patches
+  - **Source**: https://github.com/pq-crystals/kyber/commit/441c0519a07e8b86c8d079954a6b10bd31d29efc with copy_from_upstream patches
   - **Implementation license (SPDX-Identifier)**: CC0-1.0 or Apache-2.0
-- **Optimized Implementation sources**: https://github.com/pq-crystals/kyber/commit/b628ba78711bc28327dc7d2d5c074a00f061884e with copy_from_upstream patches
+- **Optimized Implementation sources**: https://github.com/pq-crystals/kyber/commit/441c0519a07e8b86c8d079954a6b10bd31d29efc with copy_from_upstream patches
   - **oldpqclean-aarch64**:<a name="oldpqclean-aarch64"></a>
       - **Source**: https://github.com/PQClean/PQClean/commit/8e220a87308154d48fdfac40abbb191ac7fce06a with copy_from_upstream patches
       - **Implementation license (SPDX-Identifier)**: CC0-1.0 and (CC0-1.0 or Apache-2.0) and (CC0-1.0 or MIT) and MIT

programming_language: Markdown
filename: kyber.yml
change_type: ModificationType.MODIFY
diff: @@ -17,7 +17,7 @@ website: https://pq-crystals.org/
 nist-round: 3
 spec-version: NIST Round 3 submission
 primary-upstream:
-  source: https://github.com/pq-crystals/kyber/commit/b628ba78711bc28327dc7d2d5c074a00f061884e
+  source: https://github.com/pq-crystals/kyber/commit/441c0519a07e8b86c8d079954a6b10bd31d29efc
     with copy_from_upstream patches
   spdx-license-identifier: CC0-1.0 or Apache-2.0
 optimized-upstreams:

programming_language: Markdown
filename: ml_kem.md
change_type: ModificationType.MODIFY
diff: @@ -7,7 +7,7 @@
 - **Authors' website**: https://pq-crystals.org/kyber/ and https://csrc.nist.gov/pubs/fips/203/ipd
 - **Specification version**: ML-KEM-ipd.
 - **Primary Source**<a name="primary-source"></a>:
-  - **Source**: https://github.com/pq-crystals/kyber/commit/11d00ff1f20cfca1f72d819e5a45165c1e0a2816 with copy_from_upstream patches
+  - **Source**: https://github.com/pq-crystals/kyber/commit/d1321ce5ac0b53f583eb47a040dc3625ee8e7e37 with copy_from_upstream patches
   - **Implementation license (SPDX-Identifier)**: CC0-1.0 or Apache-2.0
 
 

programming_language: Markdown
filename: ml_kem.yml
change_type: ModificationType.MODIFY
diff: @@ -17,7 +17,7 @@ website: https://pq-crystals.org/kyber/ and https://csrc.nist.gov/pubs/fips/203/
 nist-round: ipd
 spec-version: ML-KEM-ipd
 primary-upstream:
-  source: https://github.com/pq-crystals/kyber/commit/11d00ff1f20cfca1f72d819e5a45165c1e0a2816
+  source: https://github.com/pq-crystals/kyber/commit/d1321ce5ac0b53f583eb47a040dc3625ee8e7e37
     with copy_from_upstream patches
   spdx-license-identifier: CC0-1.0 or Apache-2.0
 parameter-sets:

programming_language: Markdown
filename: copy_from_upstream.yml
change_type: ModificationType.MODIFY
diff: @@ -25,7 +25,7 @@ upstreams:
     name: pqcrystals-kyber
     git_url: https://github.com/pq-crystals/kyber.git
     git_branch: master
-    git_commit: b628ba78711bc28327dc7d2d5c074a00f061884e
+    git_commit: 441c0519a07e8b86c8d079954a6b10bd31d29efc
     kem_meta_path: '{pretty_name_full}_META.yml'
     kem_scheme_path: '.'
     patches: [pqcrystals-kyber-yml.patch, pqcrystals-kyber-ref-shake-aes.patch, pqcrystals-kyber-avx2-shake-aes.patch]
@@ -33,7 +33,7 @@ upstreams:
     name: pqcrystals-kyber-standard
     git_url: https://github.com/pq-crystals/kyber.git
     git_branch: standard
-    git_commit: 11d00ff1f20cfca1f72d819e5a45165c1e0a2816
+    git_commit: d1321ce5ac0b53f583eb47a040dc3625ee8e7e37
     kem_meta_path: '{pretty_name_full}_META.yml'
     kem_scheme_path: '.'
     patches: [pqcrystals-ml_kem_ipd.patch]

programming_language: Markdown
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: poly.c
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,7 @@
 #include "reduce.h"
 #include "cbd.h"
 #include "symmetric.h"
+#include "verify.h"
 
 /*************************************************
 * Name:        poly_compress
@@ -166,7 +167,6 @@ void poly_frombytes(poly *r, const uint8_t a[KYBER_POLYBYTES])
 void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 {
   unsigned int i,j;
-  int16_t mask;
 
 #if (KYBER_INDCPA_MSGBYTES != KYBER_N/8)
 #error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!"
@@ -174,8 +174,8 @@ void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 
   for(i=0;i<KYBER_N/8;i++) {
     for(j=0;j<8;j++) {
-      mask = -(int16_t)((msg[i] >> j)&1);
-      r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2);
+      r->coeffs[8*i+j] = 0;
+      cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1);
     }
   }
 }

programming_language: C
filename: verify.c
change_type: ModificationType.MODIFY
diff: @@ -55,3 +55,20 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b)
   for(i=0;i<len;i++)
     r[i] ^= b & (r[i] ^ x[i]);
 }
+
+/*************************************************
+* Name:        cmov_int16
+*
+* Description: Copy input v to *r if b is 1, don't modify *r if b is 0. 
+*              Requires b to be in {0,1};
+*              Runs in constant time.
+*
+* Arguments:   int16_t *r:       pointer to output int16_t
+*              int16_t v:        input int16_t 
+*              uint8_t b:        Condition bit; has to be in {0,1}
+**************************************************/
+void cmov_int16(int16_t *r, int16_t v, uint16_t b)
+{
+  b = -b;
+  *r ^= b & ((*r) ^ v);
+}

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: poly.c
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,7 @@
 #include "reduce.h"
 #include "cbd.h"
 #include "symmetric.h"
+#include "verify.h"
 
 /*************************************************
 * Name:        poly_compress
@@ -166,7 +167,6 @@ void poly_frombytes(poly *r, const uint8_t a[KYBER_POLYBYTES])
 void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 {
   unsigned int i,j;
-  int16_t mask;
 
 #if (KYBER_INDCPA_MSGBYTES != KYBER_N/8)
 #error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!"
@@ -174,8 +174,8 @@ void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 
   for(i=0;i<KYBER_N/8;i++) {
     for(j=0;j<8;j++) {
-      mask = -(int16_t)((msg[i] >> j)&1);
-      r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2);
+      r->coeffs[8*i+j] = 0;
+      cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1);
     }
   }
 }

programming_language: C
filename: verify.c
change_type: ModificationType.MODIFY
diff: @@ -55,3 +55,20 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b)
   for(i=0;i<len;i++)
     r[i] ^= b & (r[i] ^ x[i]);
 }
+
+/*************************************************
+* Name:        cmov_int16
+*
+* Description: Copy input v to *r if b is 1, don't modify *r if b is 0. 
+*              Requires b to be in {0,1};
+*              Runs in constant time.
+*
+* Arguments:   int16_t *r:       pointer to output int16_t
+*              int16_t v:        input int16_t 
+*              uint8_t b:        Condition bit; has to be in {0,1}
+**************************************************/
+void cmov_int16(int16_t *r, int16_t v, uint16_t b)
+{
+  b = -b;
+  *r ^= b & ((*r) ^ v);
+}

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: poly.c
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,7 @@
 #include "reduce.h"
 #include "cbd.h"
 #include "symmetric.h"
+#include "verify.h"
 
 /*************************************************
 * Name:        poly_compress
@@ -166,7 +167,6 @@ void poly_frombytes(poly *r, const uint8_t a[KYBER_POLYBYTES])
 void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 {
   unsigned int i,j;
-  int16_t mask;
 
 #if (KYBER_INDCPA_MSGBYTES != KYBER_N/8)
 #error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!"
@@ -174,8 +174,8 @@ void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 
   for(i=0;i<KYBER_N/8;i++) {
     for(j=0;j<8;j++) {
-      mask = -(int16_t)((msg[i] >> j)&1);
-      r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2);
+      r->coeffs[8*i+j] = 0;
+      cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1);
     }
   }
 }

programming_language: C
filename: verify.c
change_type: ModificationType.MODIFY
diff: @@ -55,3 +55,20 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b)
   for(i=0;i<len;i++)
     r[i] ^= b & (r[i] ^ x[i]);
 }
+
+/*************************************************
+* Name:        cmov_int16
+*
+* Description: Copy input v to *r if b is 1, don't modify *r if b is 0. 
+*              Requires b to be in {0,1};
+*              Runs in constant time.
+*
+* Arguments:   int16_t *r:       pointer to output int16_t
+*              int16_t v:        input int16_t 
+*              uint8_t b:        Condition bit; has to be in {0,1}
+**************************************************/
+void cmov_int16(int16_t *r, int16_t v, uint16_t b)
+{
+  b = -b;
+  *r ^= b & ((*r) ^ v);
+}

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: poly.c
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,7 @@
 #include "reduce.h"
 #include "cbd.h"
 #include "symmetric.h"
+#include "verify.h"
 
 /*************************************************
 * Name:        poly_compress
@@ -167,7 +168,6 @@ void poly_frombytes(poly *r, const uint8_t a[KYBER_POLYBYTES])
 void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 {
   unsigned int i,j;
-  int16_t mask;
 
 #if (KYBER_INDCPA_MSGBYTES != KYBER_N/8)
 #error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!"
@@ -175,8 +175,8 @@ void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 
   for(i=0;i<KYBER_N/8;i++) {
     for(j=0;j<8;j++) {
-      mask = -(int16_t)((msg[i] >> j)&1);
-      r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2);
+      r->coeffs[8*i+j] = 0;
+      cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1);
     }
   }
 }

programming_language: C
filename: verify.c
change_type: ModificationType.MODIFY
diff: @@ -45,3 +45,21 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b)
   for(i=0;i<len;i++)
     r[i] ^= b & (r[i] ^ x[i]);
 }
+
+
+/*************************************************
+* Name:        cmov_int16
+*
+* Description: Copy input v to *r if b is 1, don't modify *r if b is 0. 
+*              Requires b to be in {0,1};
+*              Runs in constant time.
+*
+* Arguments:   int16_t *r:       pointer to output int16_t
+*              int16_t v:        input int16_t 
+*              uint8_t b:        Condition bit; has to be in {0,1}
+**************************************************/
+void cmov_int16(int16_t *r, int16_t v, uint16_t b)
+{
+  b = -b;
+  *r ^= b & ((*r) ^ v);
+}

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: poly.c
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,7 @@
 #include "reduce.h"
 #include "cbd.h"
 #include "symmetric.h"
+#include "verify.h"
 
 /*************************************************
 * Name:        poly_compress
@@ -167,7 +168,6 @@ void poly_frombytes(poly *r, const uint8_t a[KYBER_POLYBYTES])
 void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 {
   unsigned int i,j;
-  int16_t mask;
 
 #if (KYBER_INDCPA_MSGBYTES != KYBER_N/8)
 #error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!"
@@ -175,8 +175,8 @@ void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 
   for(i=0;i<KYBER_N/8;i++) {
     for(j=0;j<8;j++) {
-      mask = -(int16_t)((msg[i] >> j)&1);
-      r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2);
+      r->coeffs[8*i+j] = 0;
+      cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1);
     }
   }
 }

programming_language: C
filename: verify.c
change_type: ModificationType.MODIFY
diff: @@ -45,3 +45,21 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b)
   for(i=0;i<len;i++)
     r[i] ^= b & (r[i] ^ x[i]);
 }
+
+
+/*************************************************
+* Name:        cmov_int16
+*
+* Description: Copy input v to *r if b is 1, don't modify *r if b is 0. 
+*              Requires b to be in {0,1};
+*              Runs in constant time.
+*
+* Arguments:   int16_t *r:       pointer to output int16_t
+*              int16_t v:        input int16_t 
+*              uint8_t b:        Condition bit; has to be in {0,1}
+**************************************************/
+void cmov_int16(int16_t *r, int16_t v, uint16_t b)
+{
+  b = -b;
+  *r ^= b & ((*r) ^ v);
+}

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
filename: poly.c
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,7 @@
 #include "reduce.h"
 #include "cbd.h"
 #include "symmetric.h"
+#include "verify.h"
 
 /*************************************************
 * Name:        poly_compress
@@ -167,7 +168,6 @@ void poly_frombytes(poly *r, const uint8_t a[KYBER_POLYBYTES])
 void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 {
   unsigned int i,j;
-  int16_t mask;
 
 #if (KYBER_INDCPA_MSGBYTES != KYBER_N/8)
 #error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!"
@@ -175,8 +175,8 @@ void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 
   for(i=0;i<KYBER_N/8;i++) {
     for(j=0;j<8;j++) {
-      mask = -(int16_t)((msg[i] >> j)&1);
-      r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2);
+      r->coeffs[8*i+j] = 0;
+      cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1);
     }
   }
 }

programming_language: C
filename: verify.c
change_type: ModificationType.MODIFY
diff: @@ -45,3 +45,21 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b)
   for(i=0;i<len;i++)
     r[i] ^= b & (r[i] ^ x[i]);
 }
+
+
+/*************************************************
+* Name:        cmov_int16
+*
+* Description: Copy input v to *r if b is 1, don't modify *r if b is 0. 
+*              Requires b to be in {0,1};
+*              Runs in constant time.
+*
+* Arguments:   int16_t *r:       pointer to output int16_t
+*              int16_t v:        input int16_t 
+*              uint8_t b:        Condition bit; has to be in {0,1}
+**************************************************/
+void cmov_int16(int16_t *r, int16_t v, uint16_t b)
+{
+  b = -b;
+  *r ^= b & ((*r) ^ v);
+}

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C
repo_url: https://github.com/pq-crystals/kyber
commit_details: repo_url: https://github.com/pq-crystals/kyber
author: Peter Schwabe
author_date: 2024-06-03 09:00:59+02:00
msg: Fixed secret-dependent branch in poly_frommsg introduced by recent versions of clang with some flags (Thanks to Antoon Purnal for pointing this out!)
repository: repo_url: https://github.com/pq-crystals/kyber
repo_name: pq-crystals/kyber
repo_language: C
owner: pq-crystals
file_changes: filename: poly.c
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,7 @@
 #include "reduce.h"
 #include "cbd.h"
 #include "symmetric.h"
+#include "verify.h"
 
 /*************************************************
 * Name:        poly_compress
@@ -166,7 +167,6 @@ void poly_frombytes(poly *r, const uint8_t a[KYBER_POLYBYTES])
 void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 {
   unsigned int i,j;
-  int16_t mask;
 
 #if (KYBER_INDCPA_MSGBYTES != KYBER_N/8)
 #error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!"
@@ -174,8 +174,8 @@ void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES])
 
   for(i=0;i<KYBER_N/8;i++) {
     for(j=0;j<8;j++) {
-      mask = -(int16_t)((msg[i] >> j)&1);
-      r->coeffs[8*i+j] = mask & ((KYBER_Q+1)/2);
+      r->coeffs[8*i+j] = 0;
+      cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1);
     }
   }
 }

programming_language: C
filename: verify.c
change_type: ModificationType.MODIFY
diff: @@ -55,3 +55,10 @@ void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b)
   for(i=0;i<len;i++)
     r[i] ^= b & (r[i] ^ x[i]);
 }
+
+
+void cmov_int16(int16_t *r, int16_t v, uint16_t b)
+{
+  b = -b;
+  *r ^= b & ((*r) ^ v);
+}

programming_language: C
filename: verify.h
change_type: ModificationType.MODIFY
diff: @@ -11,4 +11,7 @@ int verify(const uint8_t *a, const uint8_t *b, size_t len);
 #define cmov KYBER_NAMESPACE(cmov)
 void cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b);
 
+#define cmov_int16 KYBER_NAMESPACE(cmov_int16)
+void cmov_int16(int16_t *r, int16_t v, uint16_t b);
+
 #endif

programming_language: C