|  | @@ -11,6 +11,29 @@
 | 
	
		
			
				|  |  |  #include <string.h>
 | 
	
		
			
				|  |  |  #include "crypto.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/******** Endianness conversion helpers ********/
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static inline uint64_t
 | 
	
		
			
				|  |  | +loadu64le(const unsigned char *x) {
 | 
	
		
			
				|  |  | +  uint64_t r = 0;
 | 
	
		
			
				|  |  | +  size_t i;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  for (i = 0; i < 8; ++i) {
 | 
	
		
			
				|  |  | +    r |= (uint64_t)x[i] << 8 * i;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return r;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static inline void
 | 
	
		
			
				|  |  | +storeu64le(uint8_t *x, uint64_t u) {
 | 
	
		
			
				|  |  | +  size_t i;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  for(i=0; i<8; ++i) {
 | 
	
		
			
				|  |  | +    x[i] = u;
 | 
	
		
			
				|  |  | +    u >>= 8;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /******** The Keccak-f[1600] permutation ********/
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /*** Constants. ***/
 | 
	
	
		
			
				|  | @@ -80,24 +103,26 @@ static inline void keccakf(void* state) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /*** Some helper macros. ***/
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define _(S) do { S } while (0)
 | 
	
		
			
				|  |  | -#define FOR(i, ST, L, S) \
 | 
	
		
			
				|  |  | -  _(for (size_t i = 0; i < L; i += ST) { S; })
 | 
	
		
			
				|  |  | -#define mkapply_ds(NAME, S)                                          \
 | 
	
		
			
				|  |  | -  static inline void NAME(uint8_t* dst,                              \
 | 
	
		
			
				|  |  | -                          const uint8_t* src,                        \
 | 
	
		
			
				|  |  | -                          size_t len) {                              \
 | 
	
		
			
				|  |  | -    FOR(i, 1, len, S);                                               \
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -#define mkapply_sd(NAME, S)                                          \
 | 
	
		
			
				|  |  | -  static inline void NAME(const uint8_t* src,                        \
 | 
	
		
			
				|  |  | -                          uint8_t* dst,                              \
 | 
	
		
			
				|  |  | -                          size_t len) {                              \
 | 
	
		
			
				|  |  | -    FOR(i, 1, len, S);                                               \
 | 
	
		
			
				|  |  | +// `xorin` modified to handle Big Endian systems, `buf` being unaligned on
 | 
	
		
			
				|  |  | +// systems that care about such things.  Assumes that len is a multiple of 8,
 | 
	
		
			
				|  |  | +// which is always true for the rates we use, and the modified finalize.
 | 
	
		
			
				|  |  | +static inline void
 | 
	
		
			
				|  |  | +xorin8(uint8_t *dst, const uint8_t *src, size_t len) {
 | 
	
		
			
				|  |  | +  uint64_t* a = (uint64_t*)dst; // Always aligned.
 | 
	
		
			
				|  |  | +  for (size_t i = 0; i < len; i += 8) {
 | 
	
		
			
				|  |  | +    a[i/8] ^= loadu64le(src + i);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -mkapply_ds(xorin, dst[i] ^= src[i])  // xorin
 | 
	
		
			
				|  |  | -mkapply_sd(setout, dst[i] = src[i])  // setout
 | 
	
		
			
				|  |  | +// `setout` likewise modified to handle Big Endian systems.  Assumes that len
 | 
	
		
			
				|  |  | +// is a multiple of 8, which is true for every rate we use.
 | 
	
		
			
				|  |  | +static inline void
 | 
	
		
			
				|  |  | +setout8(const uint8_t *src, uint8_t *dst, size_t len) {
 | 
	
		
			
				|  |  | +  const uint64_t *si = (const uint64_t*)src; // Always aligned.
 | 
	
		
			
				|  |  | +  for (size_t i = 0; i < len; i+= 8) {
 | 
	
		
			
				|  |  | +    storeu64le(dst+i, si[i/8]);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #define P keccakf
 | 
	
		
			
				|  |  |  #define Plen KECCAK_MAX_RATE
 | 
	
	
		
			
				|  | @@ -118,7 +143,7 @@ static inline void
 | 
	
		
			
				|  |  |  keccak_absorb_blocks(keccak_state *s, const uint8_t *buf, size_t nr_blocks)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    size_t blen = nr_blocks * s->rate;
 | 
	
		
			
				|  |  | -  foldP(buf, blen, xorin);
 | 
	
		
			
				|  |  | +  foldP(buf, blen, xorin8);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int
 | 
	
	
		
			
				|  | @@ -161,10 +186,14 @@ static void
 | 
	
		
			
				|  |  |  keccak_finalize(keccak_state *s)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    // Xor in the DS and pad frame.
 | 
	
		
			
				|  |  | -  s->a[s->offset] ^= s->delim;
 | 
	
		
			
				|  |  | -  s->a[s->rate - 1] ^= 0x80;
 | 
	
		
			
				|  |  | +  s->block[s->offset++] = s->delim; // DS.
 | 
	
		
			
				|  |  | +  for (size_t i = s->offset; i < s->rate; i++) {
 | 
	
		
			
				|  |  | +    s->block[i] = 0;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  s->block[s->rate - 1] |= 0x80; // Pad frame.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    // Xor in the last block.
 | 
	
		
			
				|  |  | -  xorin(s->a, s->block, s->offset);
 | 
	
		
			
				|  |  | +  xorin8(s->a, s->block, s->rate);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    memwipe(s->block, 0, sizeof(s->block));
 | 
	
		
			
				|  |  |    s->finalized = 1;
 | 
	
	
		
			
				|  | @@ -176,7 +205,7 @@ keccak_squeeze_blocks(keccak_state *s, uint8_t *out, size_t nr_blocks)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    for (size_t n = 0; n < nr_blocks; n++) {
 | 
	
		
			
				|  |  |      keccakf(s->a);
 | 
	
		
			
				|  |  | -    setout(s->a, out, s->rate);
 | 
	
		
			
				|  |  | +    setout8(s->a, out, s->rate);
 | 
	
		
			
				|  |  |      out += s->rate;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -321,6 +350,7 @@ static inline int hash(uint8_t* out, size_t outlen,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    int ret = 0;
 | 
	
		
			
				|  |  |    keccak_state s;
 | 
	
		
			
				|  |  | +  keccak_cleanse(&s);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    switch (delim) {
 | 
	
		
			
				|  |  |      case KECCAK_DELIM_DIGEST:
 |