encrypt.c 6.05 KB
Newer Older
lwc-tester committed
1 2 3 4 5 6 7 8 9 10 11
/*   
     TinyJAMBU-128: 128-bit key, 96-bit IV
	 Optimized implementation 
     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*8

/*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;
	uint32_t t1, t2, t3, t4;
lwc-tester committed
28 29 30 31 32 33 34 35

	//in each iteration, we compute 128 rounds of the state update function. 
	for (i = 0; i < (number_of_steps >> 5); i = i+4)
	{
		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 
36
		state[0] ^= t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[0]; 
lwc-tester committed
37 38 39 40 41
        
		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);    
42
		state[1] ^= t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[1];
lwc-tester committed
43 44 45 46 47

		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);
48
		state[2] ^= t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[2];  
lwc-tester committed
49 50 51 52 53

		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);
54
		state[3] ^= t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[3];
lwc-tester committed
55 56 57 58 59
	}
}
  
// The initialization  
/* The input to initialization is the 128-bit key; 96-bit IV;*/
60
void initialization(const unsigned char *key, const unsigned char *iv, uint32_t *state)
lwc-tester committed
61 62 63 64 65 66 67 68 69 70 71 72 73 74
{
        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); 
75
			state[3] ^= ((uint32_t*)iv)[i]; 
lwc-tester committed
76 77 78 79
		}   
}

//process the associated data   
80
void process_ad(const unsigned char *k, const unsigned char *ad, unsigned long long adlen, uint32_t *state)
lwc-tester committed
81 82
{
	unsigned long long i; 
83
	uint32_t j; 
lwc-tester committed
84 85 86 87 88

	for (i = 0; i < (adlen >> 2); i++)
	{
		state[1] ^= FrameBitsAD;
		state_update(state, k, NROUND1);
89
		state[3] ^= ((uint32_t*)ad)[i];
lwc-tester committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
	}

	// 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 plaintext   
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;
113
	uint32_t j;
lwc-tester committed
114
	unsigned char mac[8];
115
	uint32_t state[4];
lwc-tester committed
116 117 118 119 120 121 122 123 124 125 126 127

	//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);
128 129
		state[3] ^= ((uint32_t*)m)[i];
		((uint32_t*)c)[i] = state[2] ^ ((uint32_t*)m)[i];
lwc-tester committed
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
	}
	// 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);
147
	((uint32_t*)mac)[0] = state[2];
lwc-tester committed
148 149 150

	state[1] ^= FrameBitsFinalization;
	state_update(state, k, NROUND1);
151
	((uint32_t*)mac)[1] = state[2];
lwc-tester committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

	*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;
170
	uint32_t j, check = 0;
lwc-tester committed
171
	unsigned char mac[8];
172
	uint32_t state[4];
lwc-tester committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186

	*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);
187 188
		((uint32_t*)m)[i] = state[2] ^ ((uint32_t*)c)[i];
		state[3] ^= ((uint32_t*)m)[i];
lwc-tester committed
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
	}
	// 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);
206
	((uint32_t*)mac)[0] = state[2];
lwc-tester committed
207 208 209

	state[1] ^= FrameBitsFinalization;
	state_update(state, k, NROUND1);
210
	((uint32_t*)mac)[1] = state[2];
lwc-tester committed
211 212 213 214 215 216 217

	//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;
}