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 _______________________________________________ Gcrypt-devel mailing list Gcrypt-devel@gnupg.org https://lists.gnupg.org/mailman/listinfo/gcrypt-devel