Classic McEliece on arch which doesn't like unaligned access
NIIBE Yutaka
gniibe at fsij.org
Tue May 7 04:11:34 CEST 2024
Hello,
The Classic McEliece implementation assumes that unaligned access for
64-bit and 32-bit are OK. It is not the case for some architectures.
Here is a patch to point out the issue. Better patch is welcome.
--
diff --git a/cipher/mceliece6688128f.c b/cipher/mceliece6688128f.c
index 63d20a68..fc8f921c 100644
--- a/cipher/mceliece6688128f.c
+++ b/cipher/mceliece6688128f.c
@@ -841,7 +841,7 @@ static int decrypt(unsigned char *, const unsigned char *, const unsigned char *
#ifndef ENCRYPT_H
#define ENCRYPT_H
-static void pke_encrypt(unsigned char *, const unsigned char *, unsigned char *);
+static void pke_encrypt(unsigned char *, const unsigned char *, uint64_t *);
#endif
@@ -2248,12 +2248,12 @@ static void gen_e(unsigned char *e)
/* input: public key pk, error vector e */
/* output: syndrome s */
-static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e)
+static void syndrome(unsigned char *s, const unsigned char *pk, const uint64_t *e_aligned)
{
+ const unsigned char *e = (const unsigned char *)e_aligned;
uint64_t b;
- const uint64_t *pk_ptr;
- const uint64_t *e_ptr = ((uint64_t *) (e + SYND_BYTES));
+ const uint64_t *e_ptr = (e_aligned + SYND_BYTES/8);
int i, j;
@@ -2264,13 +2264,19 @@ static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e
for (i = 0; i < PK_NROWS; i++)
{
- pk_ptr = ((uint64_t *) (pk + PK_ROW_BYTES * i));
+ const unsigned char *pk_ptr = pk + PK_ROW_BYTES * i;
+ uint64_t v64;
+ uint32_t v32;
b = 0;
for (j = 0; j < PK_NCOLS/64; j++)
- b ^= pk_ptr[j] & e_ptr[j];
+ {
+ v64 = buf_get_he64 (pk_ptr + j * 8);
+ b ^= v64 & e_ptr[j];
+ }
- b ^= ((uint32_t *) &pk_ptr[j])[0] & ((uint32_t *) &e_ptr[j])[0];
+ v32 = buf_get_he32 (pk_ptr + j * 8);
+ b ^= v32 & ((uint32_t *) &e_ptr[j])[0];
b ^= b >> 32;
b ^= b >> 16;
@@ -2286,8 +2292,10 @@ static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e
/* input: public key pk */
/* output: error vector e, syndrome s */
-static void pke_encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e)
+static void pke_encrypt(unsigned char *s, const unsigned char *pk, uint64_t *e_aligned)
{
+ unsigned char *e = (unsigned char *)e_aligned;
+
gen_e(e);
#ifdef KAT
@@ -2301,7 +2309,7 @@ static void pke_encrypt(unsigned char *s, const unsigned char *pk, unsigned char
}
#endif
- syndrome(s, pk, e);
+ syndrome(s, pk, e_aligned);
}
@@ -3059,12 +3067,13 @@ static void operation_enc(
const unsigned char *pk
)
{
- unsigned char e[ SYS_N/8 ];
+ uint64_t e_aligned[ (SYS_N+63)/64 ];
+ unsigned char *e = (unsigned char *)e_aligned;
unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1};
/**/
- pke_encrypt(c, pk, e);
+ pke_encrypt(c, pk, e_aligned);
memcpy(one_ec + 1, e, SYS_N/8);
memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES);
diff --git a/cipher/mceliece6688128f.h b/cipher/mceliece6688128f.h
index eb9f23a0..05ecac32 100644
--- a/cipher/mceliece6688128f.h
+++ b/cipher/mceliece6688128f.h
@@ -29,6 +29,7 @@
/**** Start of the glue code to libgcrypt ****/
#include "g10lib.h" /* for GCC_ATTR_UNUSED */
#include "gcrypt-int.h"
+#include "bufhelp.h"
#define mceliece6688128f_keypair _gcry_mceliece6688128f_keypair
#define mceliece6688128f_enc _gcry_mceliece6688128f_enc
@@ -41,6 +42,8 @@
#define GCC_ATTR_UNUSED
#endif
+/* Please implement Host-endian get macros: buf_get_he32 and buf_get_he64 */
+
#define MCELIECE6688128F_SECRETKEY_SIZE 13932
#define MCELIECE6688128F_PUBLICKEY_SIZE 1044992
#define MCELIECE6688128F_CIPHERTEXT_SIZE 208
More information about the Gcrypt-devel
mailing list