encrypt.c 6.63 KB
Newer Older
lwc-tester committed
1 2 3 4 5 6 7 8 9 10 11
/*
     TinyJAMBU-192: 192-bit key, 96-bit IV 
	 Optimized Implementation for 32-bit processor 
     The state consists of four 32-bit registers       
     state[3] || state[2] || state[1] || state[0]

	 Implemented by Hongjun Wu
*/   

#include <string.h>  
#include <stdio.h> 
12
#include <stdint.h>
lwc-tester committed
13 14 15 16 17 18 19 20 21 22 23
#include "crypto_aead.h"

#define FrameBitsIV  0x10  
#define FrameBitsAD  0x30  
#define FrameBitsPC  0x50  //Framebits for plaintext/ciphertext      
#define FrameBitsFinalization 0x70       

#define NROUND1 128*3 
#define NROUND2 128*9

/*optimized state update function*/    
24
void state_update(uint32_t *state, const unsigned char *key, uint32_t number_of_steps)
lwc-tester committed
25
{
26 27
	uint32_t i, temp; 
	uint32_t t1, t2, t3, t4;
lwc-tester committed
28 29 30 31 32 33 34
	//in each iteration, we compute 192 rounds of the state update function. 
	for (i = 0; i < (number_of_steps >> 5); i = i+6) 
	{
		t1 = (state[1] >> 15) | (state[2] << 17);  // 47 = 1*32+15 
		t2 = (state[2] >> 6)  | (state[3] << 26);  // 47 + 23 = 70 = 2*32 + 6 
		t3 = (state[2] >> 21) | (state[3] << 11);  // 47 + 23 + 15 = 85 = 2*32 + 21      
		t4 = (state[2] >> 27) | (state[3] << 5);   // 47 + 23 + 15 + 6 = 91 = 2*32 + 27 
35
		state[0] ^= t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[0];
lwc-tester committed
36 37 38 39 40

		t1 = (state[2] >> 15) | (state[3] << 17);   
		t2 = (state[3] >> 6)  | (state[0] << 26);  
		t3 = (state[3] >> 21) | (state[0] << 11);        
		t4 = (state[3] >> 27) | (state[0] << 5);    
41
		state[1] ^= t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[1];
lwc-tester committed
42 43 44 45 46

		t1 = (state[3] >> 15) | (state[0] << 17);
		t2 = (state[0] >> 6)  | (state[1] << 26);
		t3 = (state[0] >> 21) | (state[1] << 11);
		t4 = (state[0] >> 27) | (state[1] << 5);
47
		state[2] ^= t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[2];
lwc-tester committed
48 49 50 51 52

		t1 = (state[0] >> 15) | (state[1] << 17);
		t2 = (state[1] >> 6)  | (state[2] << 26);
		t3 = (state[1] >> 21) | (state[2] << 11);
		t4 = (state[1] >> 27) | (state[2] << 5);
53
		state[3] ^= t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[3];
lwc-tester committed
54 55 56 57 58

		t1 = (state[1] >> 15) | (state[2] << 17);
		t2 = (state[2] >> 6)  | (state[3] << 26);
		t3 = (state[2] >> 21) | (state[3] << 11);
		t4 = (state[2] >> 27) | (state[3] << 5);
59
		state[0] ^= t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[4];
lwc-tester committed
60 61 62 63 64

		t1 = (state[2] >> 15) | (state[3] << 17);
		t2 = (state[3] >> 6)  | (state[0] << 26);
		t3 = (state[3] >> 21) | (state[0] << 11);
		t4 = (state[3] >> 27) | (state[0] << 5);
65
		state[1] ^= t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[5];  
lwc-tester committed
66 67 68 69 70 71 72 73 74

		//shift the state by 64-bit position 
		temp = state[0]; state[0] = state[2]; state[2] = temp;  
		temp = state[1]; state[1] = state[3]; state[3] = temp;  
	}
}

// The initialization  
/* The input to initialization is the 192-bit key; 96-bit IV;*/
75
void initialization(const unsigned char *key, const unsigned char *iv, uint32_t *state)
lwc-tester committed
76 77 78 79 80 81 82 83 84 85 86 87 88 89
{
	int i;

	//initialize the state as 0  
	for (i = 0; i < 4; i++) state[i] = 0;

	//update the state with the key  
	state_update(state, key, NROUND2);

	//introduce IV into the state  
	for (i = 0; i < 3; i++)
	{
		state[1] ^= FrameBitsIV;
		state_update(state, key, NROUND1);
90
		state[3] ^= ((uint32_t*)iv)[i];
lwc-tester committed
91 92 93 94
	}
}

//process the associated data   
95
void process_ad(const unsigned char *k, const unsigned char *ad, unsigned long long adlen, uint32_t *state)
lwc-tester committed
96 97
{
	unsigned long long i;
98
	uint32_t j;
lwc-tester committed
99 100 101 102 103

	for (i = 0; i < (adlen >> 2); i++)
	{
		state[1] ^= FrameBitsAD;
		state_update(state, k, NROUND1);
104
		state[3] ^= ((uint32_t*)ad)[i];
lwc-tester committed
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
	}

	// if adlen is not a multiple of 4, we process the remaining bytes
	if ((adlen & 3) > 0)
	{
		state[1] ^= FrameBitsAD;
		state_update(state, k, NROUND1);
		for (j = 0; j < (adlen & 3); j++)  ((unsigned char*)state)[12 + j] ^= ad[(i << 2) + j];
		state[1] ^= adlen & 3;
	}
}

//encrypt a message  
int crypto_aead_encrypt(
	unsigned char *c, unsigned long long *clen,
	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
)
{
	unsigned long long i;
128
	uint32_t j;
lwc-tester committed
129
	unsigned char mac[8];
130
	uint32_t state[4];
lwc-tester committed
131 132 133 134 135 136 137 138 139 140 141 142

	//initialization stage
	initialization(k, npub, state);

	//process the associated data   
	process_ad(k, ad, adlen, state);

	//process the plaintext    
	for (i = 0; i < (mlen >> 2); i++)
	{
		state[1] ^= FrameBitsPC;
		state_update(state, k, NROUND2);
143 144
		state[3] ^= ((uint32_t*)m)[i];
		((uint32_t*)c)[i] = state[2] ^ ((uint32_t*)m)[i];
lwc-tester committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
	}
	// if mlen is not a multiple of 4, we process the remaining bytes
	if ((mlen & 3) > 0)
	{
		state[1] ^= FrameBitsPC;
		state_update(state, k, NROUND2);
		for (j = 0; j < (mlen & 3); j++)
		{
			((unsigned char*)state)[12 + j] ^= m[(i << 2) + j];
			c[(i << 2) + j] = ((unsigned char*)state)[8 + j] ^ m[(i << 2) + j];
		}
		state[1] ^= mlen & 3;
	}

	//finalization stage, we assume that the tag length is 8 bytes
	state[1] ^= FrameBitsFinalization;
	state_update(state, k, NROUND2);
162
	((uint32_t*)mac)[0] = state[2];
lwc-tester committed
163 164 165

	state[1] ^= FrameBitsFinalization;
	state_update(state, k, NROUND1);
166
	((uint32_t*)mac)[1] = state[2];
lwc-tester committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184

	*clen = mlen + 8;
	memcpy(c + mlen, mac, 8);

	return 0;
}

//decrypt a message
int crypto_aead_decrypt(
	unsigned char *m, unsigned long long *mlen,
	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
)
{
	unsigned long long i;
185
	uint32_t j, check = 0;
lwc-tester committed
186
	unsigned char mac[8];
187
	uint32_t state[4];
lwc-tester committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201

	*mlen = clen - 8;

	//initialization stage
	initialization(k, npub, state);

	//process the associated data   
	process_ad(k, ad, adlen, state);

	//process the ciphertext    
	for (i = 0; i < (*mlen >> 2); i++)
	{
		state[1] ^= FrameBitsPC;
		state_update(state, k, NROUND2);
202 203
		((uint32_t*)m)[i] = state[2] ^ ((uint32_t*)c)[i];
		state[3] ^= ((uint32_t*)m)[i];
lwc-tester committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
	}
	// if mlen is not a multiple of 4, we process the remaining bytes
	if ((*mlen & 3) > 0)
	{
		state[1] ^= FrameBitsPC;
		state_update(state, k, NROUND2);
		for (j = 0; j < (*mlen & 3); j++)
		{
			m[(i << 2) + j] = c[(i << 2) + j] ^ ((unsigned char*)state)[8 + j];
			((unsigned char*)state)[12 + j] ^= m[(i << 2) + j];
		}
		state[1] ^= *mlen & 3;
	}


	//finalization stage, we assume that the tag length is 8 bytes
	state[1] ^= FrameBitsFinalization;
	state_update(state, k, NROUND2);
222
	((uint32_t*)mac)[0] = state[2];
lwc-tester committed
223 224 225

	state[1] ^= FrameBitsFinalization;
	state_update(state, k, NROUND1);
226
	((uint32_t*)mac)[1] = state[2];
lwc-tester committed
227 228 229 230 231 232

	//verification of the authentication tag   
	for (j = 0; j < 8; j++) { check |= (mac[j] ^ c[clen - 8 + j]); }
	if (check == 0) return 0;
	else return -1;
}