encrypt.c 4.64 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
#include "api.h"

typedef unsigned char u8;
typedef unsigned long long u64;
typedef long long i64;
#define RATE (64 / 8)

#define PR0_ROUNDS 52
#define PR_ROUNDS 28
#define PRF_ROUNDS 32

#define ROTR(x,n) (((x)>>(n))|((x)<<(64-(n))))
#define LOTR64(x,n) (((x)<<(n))|((x)>>(64-(n))))

#define EXT_BYTE(x,n) ((u8)((u64)(x)>>(8*(n))))
#define INS_BYTE(x,n) ((u64)(x)<<(8*(n)))
#define U64BIG(x) (x)
static const u8 constant6[63] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x21, 0x03,
		0x06, 0x0c, 0x18, 0x31, 0x22, 0x05, 0x0a, 0x14, 0x29, 0x13, 0x27, 0x0f,
		0x1e, 0x3d, 0x3a, 0x34, 0x28, 0x11, 0x23, 0x07, 0x0e, 0x1c, 0x39, 0x32,
		0x24, 0x09, 0x12, 0x25, 0x0b, 0x16, 0x2d, 0x1b, 0x37, 0x2e, 0x1d, 0x3b,
		0x36, 0x2c, 0x19, 0x33, 0x26, 0x0d, 0x1a, 0x35, 0x2a, 0x15, 0x2b, 0x17,
		0x2f, 0x1f, 0x3f, 0x3e, 0x3c, 0x38, 0x30, 0x20 };

#define ARR_SIZE(a) (sizeof((a))/sizeof((a[0])))
#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 ROUND256(i) ({\
lwc-tester committed
31 32 33 34 35 36
x0^=constant6[i];\
sbox(x0, x1, x2, x3,x4, x5, x6, x7);\
x0=x4;\
x1=LOTR64(x5,1);\
x2=LOTR64(x6,8);\
x3=LOTR64(x7,25);\
lwc-tester committed
37 38 39
})

int crypto_aead_encrypt(unsigned char *c, unsigned long long *clen,
lwc-tester committed
40 41 42 43
	const unsigned char *m, unsigned long long mlen,
	const unsigned char *ad, unsigned long long adlen,
	const unsigned char *nsec, const unsigned char *npub,
	const unsigned char *k) {
lwc-tester committed
44

lwc-tester committed
45 46 47 48
	u64 K0 = U64BIG(((u64*)k)[0]);
	u64 K1 = U64BIG(((u64*)k)[1]);
	u64 N0 = U64BIG(((u64*)npub)[0]);
	u64 N1 = U64BIG(((u64*)npub)[1]);
lwc-tester committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

	u64 t1, t2, t3, t5, t6, t8, t9, t11;
	u64 x3, x2, x1, x0, x7, x6, x5, x4;
	u64 rlen, i;

	// initialization
	x0 = N0;
	x1 = N1;
	x2 = K0;
	x3 = K1;

	for (i = 0; i < PR0_ROUNDS; i++) {
		ROUND256(i);
	}
	// process associated data
	if (adlen) {
		rlen = adlen;
		while (rlen >= RATE) {
lwc-tester committed
67
			x0 ^= U64BIG(*(u64*)ad);
lwc-tester committed
68 69 70 71 72 73 74 75
			for (i = 0; i < PR_ROUNDS; i++) {
				ROUND256(i);
			}
			rlen -= RATE;
			ad += RATE;
		}
		for (i = 0; i < rlen; ++i, ++ad)
			x0 ^= INS_BYTE(*ad, i);
lwc-tester committed
76
		x0 ^= INS_BYTE(0x01, rlen);
lwc-tester committed
77 78 79 80 81

		for (i = 0; i < PR_ROUNDS; i++) {
			ROUND256(i);
		}
	}
lwc-tester committed
82
	x3 ^= 0x8000000000000000;
lwc-tester committed
83 84 85 86 87
	// process plaintext

	if (mlen) {
		rlen = mlen;
		while (rlen >= RATE) {
lwc-tester committed
88 89
			x0 ^= U64BIG(*(u64*)m);
			*(u64*)c = U64BIG(x0);
lwc-tester committed
90 91 92 93 94 95 96 97 98 99 100 101

			for (i = 0; i < PR_ROUNDS; i++) {
				ROUND256(i);
			}
			rlen -= RATE;
			m += RATE;
			c += RATE;
		}
		for (i = 0; i < rlen; ++i, ++m, ++c) {
			x0 ^= INS_BYTE(*m, i);
			*c = EXT_BYTE(x0, i);
		}
lwc-tester committed
102
		x0 ^= INS_BYTE(0x01, rlen);
lwc-tester committed
103 104 105 106 107 108 109 110
	}
	// finalization
	for (i = 0; i < PRF_ROUNDS; i++) {
		ROUND256(i);
	}
	// return tag

	for (i = 0; i < 8; ++i) {
lwc-tester committed
111
		*c = EXT_BYTE(U64BIG(x0), i);
lwc-tester committed
112 113 114
		c++;
	}
	for (i = 0; i < 8; ++i) {
lwc-tester committed
115
		*c = EXT_BYTE(U64BIG(x1), i);
lwc-tester committed
116 117 118 119 120 121 122
		c++;
	}
	*clen = mlen + CRYPTO_KEYBYTES;
	return 0;
}

int crypto_aead_decrypt(unsigned char *m, unsigned long long *mlen,
lwc-tester committed
123 124 125
	unsigned char *nsec, const unsigned char *c, unsigned long long clen,
	const unsigned char *ad, unsigned long long adlen,
	const unsigned char *npub, const unsigned char *k) {
lwc-tester committed
126 127 128 129

	*mlen = 0;
	if (clen < CRYPTO_KEYBYTES)
		return -1;
lwc-tester committed
130 131 132 133
	u64 K0 = U64BIG(((u64*)k)[0]);
	u64 K1 = U64BIG(((u64*)k)[1]);
	u64 N0 = U64BIG(((u64*)npub)[0]);
	u64 N1 = U64BIG(((u64*)npub)[1]);
lwc-tester committed
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

	u64 t1, t2, t3, t5, t6, t8, t9, t11;
	u64 x3, x2, x1, x0, x7, x6, x5, x4;
	u64 rlen, i;

	// initialization
	x0 = N0;
	x1 = N1;
	x2 = K0;
	x3 = K1;

	for (i = 0; i < PR0_ROUNDS; i++) {
		ROUND256(i);
	}
	// process associated data
	if (adlen) {
		rlen = adlen;
		while (rlen >= RATE) {
lwc-tester committed
152
			x0 ^= U64BIG(*(u64*)ad);
lwc-tester committed
153 154 155 156 157 158 159 160
			for (i = 0; i < PR_ROUNDS; i++) {
				ROUND256(i);
			}
			rlen -= RATE;
			ad += RATE;
		}
		for (i = 0; i < rlen; ++i, ++ad)
			x0 ^= INS_BYTE(*ad, i);
lwc-tester committed
161
		x0 ^= INS_BYTE(0x01, rlen);
lwc-tester committed
162 163 164 165 166

		for (i = 0; i < PR_ROUNDS; i++) {
			ROUND256(i);
		}
	}
lwc-tester committed
167
	x3 ^= 0x8000000000000000;
lwc-tester committed
168 169 170 171 172 173
	// process plaintext

	rlen = clen - CRYPTO_KEYBYTES;

	if (rlen) {
		while (rlen >= RATE) {
lwc-tester committed
174 175
			*(u64*)m = U64BIG(x0) ^ *(u64*)c;
			x0 = U64BIG(*((u64*)c));
lwc-tester committed
176 177 178 179 180 181 182 183 184 185 186 187 188

			for (i = 0; i < PR_ROUNDS; i++) {
				ROUND256(i);
			}
			rlen -= RATE;
			m += RATE;
			c += RATE;
		}
		for (i = 0; i < rlen; ++i, ++m, ++c) {
			*m = EXT_BYTE(x0, i) ^ *c;
			x0 &= ~INS_BYTE(0xff, i);
			x0 |= INS_BYTE(*c, i);
		}
lwc-tester committed
189
		x0 ^= INS_BYTE(0x01, rlen);
lwc-tester committed
190 191 192 193 194 195
	}
	// finalization
	for (i = 0; i < PRF_ROUNDS; i++) {
		ROUND256(i);
	}
	// return -1 if verification fails
lwc-tester committed
196
	t1 = *((u64*)c);
lwc-tester committed
197
	c += RATE;
lwc-tester committed
198
	t2 = *((u64*)c);
lwc-tester committed
199

lwc-tester committed
200
	if (t1 != U64BIG(x0) || t2 != U64BIG(x1)) {
lwc-tester committed
201
		return -1;
lwc-tester committed
202
	}
lwc-tester committed
203 204 205 206
	*mlen = clen - CRYPTO_KEYBYTES;
	return 0;
}

lwc-tester committed
207