Classic McEliece on arch which doesn't like unaligned access

NIIBE Yutaka <[email protected]>
Newsgroups gmane.comp.encryption.gpg.libgcrypt.devel
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.