encrypt.c 8.62 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
#include"api.h"
typedef unsigned char u8;
typedef unsigned long long u64;
typedef long long i64;
typedef long long i64;
typedef unsigned int u32;

#define RATE (192 / 8)
#define PR0_ROUNDS 76
#define PR_ROUNDS 28
#define PRF_ROUNDS 32
#define ROTR64(x,n) (((x)>>(n))|((x)<<(64-(n))))
#define LOTR64(x,n) (((x)<<(n))|((x)>>(64-(n))))
#define ROTR32(x,n) (((x)>>(n))|((x)<<(32-(n))))
#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 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 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)
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 };
lwc-tester committed
44 45 46 47 48 49 50 51 52 53 54 55
#define ROUND384(i)({\
x00 ^= constant7[i];\
sbox(x00, x10, x20, x30, x40, x50, x60, x70);\
sbox(x01, x11, x21, x31, x41, x51, x61, x71);\
x00 = x40;\
x01 = x41;\
x11 = ROTR961(x51, x50, 1);\
x10 = ROTR962(x51, x50, 1);\
x21 = ROTR961(x61, x60, 8);\
x20 = ROTR962(x61, x60, 8);\
x31 = ROTR96MORE321(x71, x70, 55);\
x30 = ROTR96MORE322(x71, x70, 55);\
lwc-tester committed
56 57
})
int crypto_aead_encrypt(unsigned char *c, unsigned long long *clen,
lwc-tester committed
58 59 60 61
	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
62 63 64

	u64 rlen, i; //RATE=192/8=24
	u64 t1, t2, t3, t5, t6, t8, t9, t11;
lwc-tester committed
65 66
	u64 x30 = 0, x20 = 0, x10 = 0, x00 = 0;
	u32 x31 = 0, x21 = 0, x11 = 0, x01 = 0;
lwc-tester committed
67

lwc-tester committed
68 69
	u64 x40, x50, x60, x70;
	u32 x41, x51, x61, x71;
lwc-tester committed
70 71
	// initialization

lwc-tester committed
72 73 74 75 76 77 78 79
	x00 = U64BIG(*(u64*)(npub));
	x01 = U32BIG(*(u32*)(npub + 8));
	x10 = ((u64)U32BIG(*(u32*)(k)) << 32)
		| ((u64)U32BIG(*(u32*)(npub + 12)));
	x11 = U32BIG(*(u32*)(k + 4));
	x20 = U64BIG(*(u64*)(k + 8));

	x31 = 0x80000000;
lwc-tester committed
80 81 82 83 84 85 86
	for (i = 0; i < PR0_ROUNDS; i++) {
		ROUND384(i);
	}
	// process associated data
	if (adlen) {
		rlen = adlen;
		while (rlen >= RATE) {
lwc-tester committed
87 88 89 90 91

			x00 ^= U64BIG(*(u64*)(ad));
			x01 ^= U32BIG(*(u32*)(ad + 8));
			x10 ^= U64BIG(*(u64*)(ad + 12));
			x11 ^= U32BIG(*(u32*)(ad + 20));
lwc-tester committed
92 93 94 95 96 97 98
			for (i = 0; i < PR_ROUNDS; i++) {
				ROUND384(i);
			}
			rlen -= RATE;
			ad += RATE;
		}
		for (i = 0; i < rlen; ++i, ++ad) {
lwc-tester committed
99 100 101 102 103
			if (i >= 20) {
				x11 ^= INS_BYTE32(*ad, i - 20);
			}
			else if (i >= 12) {
				x10 ^= INS_BYTE64(*ad, i - 12);
lwc-tester committed
104
			}
lwc-tester committed
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
			else if (i >= 8) {
				x01 ^= INS_BYTE32(*ad, i - 8);
			}
			else if (i < 8) {
				x00 ^= INS_BYTE64(*ad, i);
			}
		}
		if (rlen >= 20) {
			x11 ^= INS_BYTE32(0x01, rlen - 20);
		}
		else if (rlen >= 12) {
			x10 ^= INS_BYTE64(0x01, rlen - 12);
		}
		else if (rlen >= 8) {
			x01 ^= INS_BYTE32(0x01, rlen - 8);
lwc-tester committed
120
		}
lwc-tester committed
121 122
		else {
			x00 ^= INS_BYTE64(0x01, rlen);
lwc-tester committed
123 124 125 126
		}
		for (i = 0; i < PR_ROUNDS; i++) {
			ROUND384(i);
		}
lwc-tester committed
127

lwc-tester committed
128
	}
lwc-tester committed
129
	x31 ^= 0x80000000;
lwc-tester committed
130 131 132 133 134 135
	// process plaintext

	rlen = mlen;

	if (rlen) {
		while (rlen >= RATE) {
lwc-tester committed
136 137 138 139 140 141 142 143 144

			x00 ^= U64BIG(*(u64*)(m));
			x01 ^= U32BIG(*(u32*)(m + 8));
			x10 ^= U64BIG(*(u64*)(m + 12));
			x11 ^= U32BIG(*(u32*)(m + 20));
			*(u64*)c = U64BIG(x00);
			*(u32*)(c + 8) = U32BIG(x01);
			*(u64*)(c + 12) = U64BIG(x10);
			*(u32*)(c + 20) = U32BIG(x11);
lwc-tester committed
145 146 147 148 149 150 151 152 153

			for (i = 0; i < PR_ROUNDS; i++) {
				ROUND384(i);
			}
			rlen -= RATE;
			m += RATE;
			c += RATE;
		}
		for (i = 0; i < rlen; ++i, ++m, ++c) {
lwc-tester committed
154 155 156 157 158 159 160 161 162 163 164
			if (i >= 20) {
				x11 ^= INS_BYTE32(*m, i - 20);
				*c = EXT_BYTE32(x11, i - 20);
			}
			else if (i >= 12) {
				x10 ^= INS_BYTE64(*m, i - 12);
				*c = EXT_BYTE64(x10, i - 12);
			}
			else if (i >= 8) {
				x01 ^= INS_BYTE32(*m, i - 8);
				*c = EXT_BYTE32(x01, i - 8);
lwc-tester committed
165

lwc-tester committed
166 167 168 169
			}
			else if (i < 8) {
				x00 ^= INS_BYTE64(*m, i);
				*c = EXT_BYTE64(x00, i);
lwc-tester committed
170 171
			}
		}
lwc-tester committed
172 173 174 175 176 177 178 179 180 181 182
		if (rlen >= 20) {
			x11 ^= INS_BYTE32(0x01, rlen - 20);
		}
		else if (rlen >= 12) {
			x10 ^= INS_BYTE64(0x01, rlen - 12);
		}
		else if (rlen >= 8) {
			x01 ^= INS_BYTE32(0x01, rlen - 8);
		}
		else {
			x00 ^= INS_BYTE64(0x01, rlen);
lwc-tester committed
183 184 185 186 187 188 189
		}
	}
	// finalization
	for (i = 0; i < PRF_ROUNDS; i++) {
		ROUND384(i);
	}
	// return tag
lwc-tester committed
190 191 192
	*(u64*)c = U64BIG(x00);
	*(u32*)(c + 8) = U32BIG(x01);
	*(u32*)(c + 12) = U32BIG(x10);
lwc-tester committed
193 194 195 196 197

	*clen = mlen + CRYPTO_KEYBYTES;
	return 0;
}
int crypto_aead_decrypt(unsigned char *m, unsigned long long *mlen,
lwc-tester committed
198 199 200 201 202
	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) {
	if (clen < CRYPTO_KEYBYTES)
		return -1;
lwc-tester committed
203 204
	u64 rlen, i; //RATE=192/8=24
	u64 t1, t2, t3, t5, t6, t8, t9, t11;
lwc-tester committed
205 206
	u64 x30 = 0, x20 = 0, x10 = 0, x00 = 0;
	u32 x31 = 0, x21 = 0, x11 = 0, x01 = 0;
lwc-tester committed
207

lwc-tester committed
208 209
	u64 x40, x50, x60, x70;
	u32 x41, x51, x61, x71;
lwc-tester committed
210 211
	// initialization

lwc-tester committed
212 213 214 215 216 217 218 219
	x00 = U64BIG(*(u64*)(npub));
	x01 = U32BIG(*(u32*)(npub + 8));
	x10 = ((u64)U32BIG(*(u32*)(k)) << 32)
		| ((u64)U32BIG(*(u32*)(npub + 12)));
	x11 = U32BIG(*(u32*)(k + 4));
	x20 = U64BIG(*(u64*)(k + 8));

	x31 = 0x80000000;
lwc-tester committed
220 221 222 223 224 225 226
	for (i = 0; i < PR0_ROUNDS; i++) {
		ROUND384(i);
	}
	// process associated data
	if (adlen) {
		rlen = adlen;
		while (rlen >= RATE) {
lwc-tester committed
227 228 229 230 231

			x00 ^= U64BIG(*(u64*)(ad));
			x01 ^= U32BIG(*(u32*)(ad + 8));
			x10 ^= U64BIG(*(u64*)(ad + 12));
			x11 ^= U32BIG(*(u32*)(ad + 20));
lwc-tester committed
232 233 234 235 236 237
			for (i = 0; i < PR_ROUNDS; i++) {
				ROUND384(i);
			}
			rlen -= RATE;
			ad += RATE;
		}
lwc-tester committed
238

lwc-tester committed
239
		for (i = 0; i < rlen; ++i, ++ad) {
lwc-tester committed
240 241 242 243 244
			if (i >= 20) {
				x11 ^= INS_BYTE32(*ad, i - 20);
			}
			else if (i >= 12) {
				x10 ^= INS_BYTE64(*ad, i - 12);
lwc-tester committed
245
			}
lwc-tester committed
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
			else if (i >= 8) {
				x01 ^= INS_BYTE32(*ad, i - 8);
			}
			else if (i < 8) {
				x00 ^= INS_BYTE64(*ad, i);
			}
		}
		if (rlen >= 20) {
			x11 ^= INS_BYTE32(0x01, rlen - 20);
		}
		else if (rlen >= 12) {
			x10 ^= INS_BYTE64(0x01, rlen - 12);
		}
		else if (rlen >= 8) {
			x01 ^= INS_BYTE32(0x01, rlen - 8);
lwc-tester committed
261
		}
lwc-tester committed
262 263
		else {
			x00 ^= INS_BYTE64(0x01, rlen);
lwc-tester committed
264 265 266 267 268
		}
		for (i = 0; i < PR_ROUNDS; i++) {
			ROUND384(i);
		}
	}
lwc-tester committed
269
	x31 ^= 0x80000000;
lwc-tester committed
270
	// process plaintext
lwc-tester committed
271

lwc-tester committed
272 273 274 275
	rlen = clen - CRYPTO_KEYBYTES;
	if (rlen) {
		while (rlen >= RATE) {

lwc-tester committed
276 277 278 279 280 281 282 283
			*(u64*)(m) = U64BIG(x00) ^ (*(u64*)(c));
			*(u32*)(m + 8) = U32BIG(x01) ^ (*(u32*)(c + 8));
			*(u64*)(m + 12) = U64BIG(x10) ^ (*(u64*)(c + 12));
			*(u32*)(m + 20) = U32BIG(x11) ^ (*(u32*)(c + 20));
			x00 = U64BIG(*(u64*)(c));
			x01 = U32BIG(*(u32*)(c + 8));
			x10 = U64BIG(*(u64*)(c + 12));
			x11 = U32BIG(*(u32*)(c + 20));
lwc-tester committed
284 285 286 287 288 289 290 291
			for (i = 0; i < PR_ROUNDS; i++) {
				ROUND384(i);
			}
			rlen -= RATE;
			m += RATE;
			c += RATE;
		}
		for (i = 0; i < rlen; ++i, ++m, ++c) {
lwc-tester committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
			if (i >= 20) {
				*m = EXT_BYTE32(x11, i - 20) ^ *c;
				x11 &= ~INS_BYTE32(0xff, i - 20);
				x11 |= INS_BYTE32(*c, i - 20);
			}
			else if (i >= 12) {
				*m = EXT_BYTE64(x10, i - 12) ^ *c;
				x10 &= ~INS_BYTE64(0xff, i - 12);
				x10 |= INS_BYTE64(*c, i - 12);
			}
			else if (i >= 8) {
				*m = EXT_BYTE32(x01, i - 8) ^ *c;
				x01 &= ~INS_BYTE32(0xff, i - 8);
				x01 |= INS_BYTE32(*c, i - 8);
			}
			else if (i < 8) {
				*m = EXT_BYTE64(x00, i) ^ *c;
				x00 &= ~INS_BYTE64(0xff, i);
				x00 |= INS_BYTE64(*c, i);
lwc-tester committed
311 312
			}
		}
lwc-tester committed
313 314 315 316 317 318 319 320 321 322 323
		if (rlen >= 20) {
			x11 ^= INS_BYTE32(0x01, rlen - 20);
		}
		else if (rlen >= 12) {
			x10 ^= INS_BYTE64(0x01, rlen - 12);
		}
		else if (rlen >= 8) {
			x01 ^= INS_BYTE32(0x01, rlen - 8);
		}
		else if (i < 8) {
			x00 ^= INS_BYTE64(0x01, rlen);
lwc-tester committed
324 325 326 327 328 329 330
		}
	}
	// finalization
	for (i = 0; i < PRF_ROUNDS; i++) {
		ROUND384(i);
	}
	// return -1 if verification fails
lwc-tester committed
331 332
	if ((*(u64*)(c) != U64BIG(x00)) || (*(u32*)(c + 8) != U32BIG(x01))
		|| (*(u32*)(c + 12) != (u32)U64BIG(x10))) {
lwc-tester committed
333
		return -1;
lwc-tester committed
334
	}
lwc-tester committed
335 336 337 338 339 340
	// return plaintext
	*mlen = clen - CRYPTO_KEYBYTES;

	return 0;
}