hash.c 4.23 KB
Newer Older
lwc-tester committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
#include <stdio.h>
#include "api.h"
#include"crypto_hash.h"

typedef unsigned char u8;
typedef unsigned long long u64;
typedef long long i64;
typedef unsigned int u32;

#define RATE (128 / 8)
#define PRH_ROUNDS 80
#define sbox(a, b, c, d, e, f, g, h)                                                                            \
{                                                                                                                             \
	t1 = ~a; t2 = b & t1;t3 = c ^ t2; h = d ^ t3; t5 = b | c; t6 = d ^ t1; g = t5 ^ t6; t8 = b ^ d; t9 = t3 & t6; e = t8 ^ t9; t11 = g & t8; f = t3 ^ t11; \
}

#define ROTR64(x,n) (((x)>>(n))|((x)<<(64-(n))))
#define ROTR32(x,n) (((x)>>(n))|((x)<<(32-(n))))
#define ARR_SIZE(a) (sizeof((a))/sizeof((a[0])))
#define ROTR961(a,b,n) (((a)<<(n))|((b)>>(64-n)))
#define ROTR962(a,b,n) (((b)<<(n))|((a)>>(32-n)))

#define ROTR96MORE321(a,b,n) ((b<<(n-32))>>32)
#define ROTR96MORE322(a,b,n) (b<<n|(u64)a<<(n-32)|b>>(96-n))

#define LITTLE_ENDIAN
//#define BIG_ENDIAN
#ifdef BIG_ENDIAN
#define EXT_BYTE32(x,n) ((u8)((u32)(x)>>(8*(n))))
#define INS_BYTE32(x,n) ((u32)(x)<<(8*(n)))
#define U32BIG(x) (x)
#define EXT_BYTE64(x,n) ((u8)((u64)(x)>>(8*(n))))
#define INS_BYTE64(x,n) ((u64)(x)<<(8*(n)))
#define U64BIG(x) (x)
#endif

#ifdef LITTLE_ENDIAN
#define EXT_BYTE32(x,n) ((u8)((u32)(x)>>(8*(3-(n)))))
#define INS_BYTE32(x,n) ((u32)(x)<<(8*(3-(n))))
#define U32BIG(x) \
    ((ROTR32(x,  8) & (0xFF00FF00)) | \
    ((ROTR32(x, 24) & (0x00FF00FF))))
#define EXT_BYTE64(x,n) ((u8)((u64)(x)>>(8*(7-(n)))))
#define INS_BYTE64(x,n) ((u64)(x)<<(8*(7-(n))))
#define U64BIG(x) \
    ((ROTR64(x, 8) & (0xFF000000FF000000ULL)) | \
     (ROTR64(x,24) & (0x00FF000000FF0000ULL)) | \
     (ROTR64(x,40) & (0x0000FF000000FF00ULL)) | \
     (ROTR64(x,56) & (0x000000FF000000FFULL)))
#endif
u8 constant7[127] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x41, 0x03, 0x06,
		0x0c, 0x18, 0x30, 0x61, 0x42, 0x05, 0x0a, 0x14, 0x28, 0x51, 0x23, 0x47,
		0x0f, 0x1e, 0x3c, 0x79, 0x72, 0x64, 0x48, 0x11, 0x22, 0x45, 0x0b, 0x16,
		0x2c, 0x59, 0x33, 0x67, 0x4e, 0x1d, 0x3a, 0x75, 0x6a, 0x54, 0x29, 0x53,
		0x27, 0x4f, 0x1f, 0x3e, 0x7d, 0x7a, 0x74, 0x68, 0x50, 0x21, 0x43, 0x07,
		0x0e, 0x1c, 0x38, 0x71, 0x62, 0x44, 0x09, 0x12, 0x24, 0x49, 0x13, 0x26,
		0x4d, 0x1b, 0x36, 0x6d, 0x5a, 0x35, 0x6b, 0x56, 0x2d, 0x5b, 0x37, 0x6f,
		0x5e, 0x3d, 0x7b, 0x76, 0x6c, 0x58, 0x31, 0x63, 0x46, 0x0d, 0x1a, 0x34,
		0x69, 0x52, 0x25, 0x4b, 0x17, 0x2e, 0x5d, 0x3b, 0x77, 0x6e, 0x5c, 0x39,
		0x73, 0x66, 0x4c, 0x19, 0x32, 0x65, 0x4a, 0x15, 0x2a, 0x55, 0x2b, 0x57,
		0x2f, 0x5f, 0x3f, 0x7f, 0x7e, 0x7c, 0x78, 0x70, 0x60, 0x40 };
#define ROUND384(i) ({\
		x31^=constant7[i];\
		sbox(x30, x20, x10, x00, b30, b20, b10, b00);\
		sbox(x31, x21, x11, x01, b31, b21, b11, b01);\
		x30=b30;\
		x20=ROTR961(b20,b21,1);\
		x10=ROTR961(b10,b11,8);\
		x00=ROTR96MORE321(b00,b01,55);\
		x31=b31;\
		x21=ROTR962(b20,b21,1);\
		x11=ROTR962(b10,b11,8);\
		x01=ROTR96MORE322(b00,b01,55);\
})

int crypto_hash(unsigned char *out, const unsigned char *in,
		unsigned long long inlen) {

	u64 rlen, i; //RATE=96/8=12
	u64 b01, b11, b21, b31;
	u32 b00, b10, b20, b30;
	u64 t1, t2, t3, t5, t6, t8, t9, t11;
	u32 x30 = 0, x20 = 0, x10 = 0, x00 = 0;
	u64 x31 = 1, x21 = 0, x11 = 0, x01 = 0;

	// initialization
	//absorb
	if (inlen > 0) {
		rlen = inlen;
		//RATE=128/8=16
		while (rlen >= RATE) {
			x21 ^= (u64) U32BIG(*(u32* )in);
			x30 ^= U32BIG(*(u32* )(in + 4));
			x31 ^= U64BIG(*(u64* )(in + 8));
			for (i = 0; i < PRH_ROUNDS; i++) {
				ROUND384(i);
			}
			rlen -= RATE;
			in += RATE;
		}
		for (i = 0; i < rlen; ++i, ++in) {
			if (i >= 8) {
				x31 ^= INS_BYTE64(*in, i - 8);
			} else if (i >= 4) {
				x30 ^= INS_BYTE32(*in, i - 4);
			} else if (i < 4) {
				x21 ^= (u64) INS_BYTE32(*in, i);
			}
		}

		if (i >= 8) {
			x31 ^= INS_BYTE64(0x80, i - 8);
		} else if (i >= 4) {
			x30 ^= INS_BYTE32(0x80, i - 4);
		} else if (i < 4) {
			x21 ^= (u64) INS_BYTE32(0x80, i);
		}
		for (i = 0; i < PRH_ROUNDS; i++) {
			ROUND384(i);
		}

	}
	//sequeez

	*(u32*) (out) =U32BIG(x00);
	*(u64*) (out + 4) = U64BIG(x01);
	*(u32*) (out + 12) = U32BIG(x10);

	out += CRYPTO_BYTES / 2;
	for (i = 0; i < PRH_ROUNDS; i++) {
		ROUND384(i);
	}

	*(u32*) (out) =U32BIG(x00);
	*(u64*) (out + 4) = U64BIG(x01);
	*(u32*) (out + 12) = U32BIG(x10);
	return 0;
}