
/*
 * block mode TEA
 *
 * Written by Roger M Needham and David J Wheeler
 *
 * v is a block of n words of data
 * k is a 4-word key
 * n is positive for encoding, negative for decoding
 */

#include "misc/compat.h"
#include "base/logger.h"
#include "crypt/xtea.h"

void xteabEncode(uint32 *v, uint32 n, uint32 *k) {
	uint32 z;
	uint32 sum;
	uint32 e;
	uint32 DELTA = 0x9e3779b9;
	uint32 p, q;
	
	/* Coding part */
	if (n > 1) {
		MY_ENDIAN_ARRAY32(v, n);
		MY_ENDIAN_ARRAY32(k, 4);
		z = v[n - 1];
		sum = 0;
		q = 6 + 52/n;
		while (q-- > 0)
		{
			sum += DELTA;
			e = sum >> 2 & 3;
			for (p = 0; p < n; p++)
				z = v[p] += ((z << 4) ^ (z >> 5)) + (z ^ k[(p & 3)^e]) + sum;
		}
		
		MY_ENDIAN_ARRAY32(v, n);
		MY_ENDIAN_ARRAY32(k, 4);
		return;
	}
	LOGERROR("Tried to encode 1 or fewer words with xteab.");
}
void xteabDecode(uint32 *v, uint32 n, uint32 *k) {
	uint32 z;
	uint32 sum;
	uint32 e;
	uint32 DELTA = 0x9e3779b9;
	uint32 p, q;
	
		
	/* decoding part */
	if (n > 1) {
		MY_ENDIAN_ARRAY32(v, n);
		MY_ENDIAN_ARRAY32(k, 4);
		q = 6 + 52/n;
		sum = q * DELTA;
		while (sum != 0)
		{
			e = sum >> 2 & 3;
			for (p = n - 1; p > 0; p--)
			{
				z = v[p - 1];
				v[p] -= ((z << 4) ^ (z >> 5)) + (z ^ k[(p & 3) ^ e]) + sum;
			}
			
			z = v[n-1];
			v[0] -= ((z << 4) ^ (z >> 5)) + (z ^ k[(p & 3) ^ e]) + sum;
			sum -= DELTA;
		}
	
		MY_ENDIAN_ARRAY32(v, n);
		MY_ENDIAN_ARRAY32(k, 4);
		return;
	}
	
	LOGERROR("Tried to decode 1 or fewer words with xteab.");
}

