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

/*non-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, feedback;
lwc-tester committed
28 29 30 31 32 33 34
	//in each iteration, we compute 256 steps of the state update function. 
	for (i = 0; i < (number_of_steps >> 5); i++)
	{
		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
		feedback = state[0] ^ t1 ^ (~(t2 & t3)) ^ t4 ^ ((uint32_t*)key)[i & 7];
lwc-tester committed
36 37 38 39 40 41 42 43
		// shift 32 bit positions 
		state[0] = state[1]; state[1] = state[2]; state[2] = state[3];
		state[3] = feedback;
	}
}
  
// The initialization  
/* The input to initialization is the 128-bit key; 96-bit IV;*/
44
void initialization(const unsigned char *key, const unsigned char *iv, uint32_t *state)
lwc-tester committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58
{
        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); 
59
			state[3] ^= ((uint32_t*)iv)[i]; 
lwc-tester committed
60 61 62 63
		}   
}

//process the associated data   
64
void process_ad(const unsigned char *k, const unsigned char *ad, unsigned long long adlen, uint32_t *state)
lwc-tester committed
65 66
{
	unsigned long long i; 
67
	uint32_t j; 
lwc-tester committed
68 69 70 71 72

	for (i = 0; i < (adlen >> 2); i++)
	{
		state[1] ^= FrameBitsAD;
		state_update(state, k, NROUND1);
73
		state[3] ^= ((uint32_t*)ad)[i];
lwc-tester committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
	}

	// 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;
97
	uint32_t j; 
lwc-tester committed
98
    unsigned char mac[8]; 
99
    uint32_t state[4];   
lwc-tester committed
100 101 102 103 104 105 106 107 108 109 110 111

    //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); 
112 113
		state[3] ^= ((uint32_t*)m)[i];  
		((uint32_t*)c)[i] = state[2] ^ ((uint32_t*)m)[i];  
lwc-tester committed
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
	}
	// 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);
131
	((uint32_t*)mac)[0] = state[2];
lwc-tester committed
132 133 134

	state[1] ^= FrameBitsFinalization;
	state_update(state, k, NROUND1);
135
	((uint32_t*)mac)[1] = state[2];
lwc-tester committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

    *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;
154
	uint32_t j, check = 0;
lwc-tester committed
155
 	unsigned char mac[8];
156
	uint32_t state[4];
lwc-tester committed
157 158 159 160 161 162 163 164 165 166 167 168 169 170

	*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);
171 172
		((uint32_t*)m)[i] = state[2] ^ ((uint32_t*)c)[i];
		state[3] ^= ((uint32_t*)m)[i]; 
lwc-tester committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
 	}
	// 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);
190
	((uint32_t*)mac)[0] = state[2];
lwc-tester committed
191 192 193

	state[1] ^= FrameBitsFinalization;
	state_update(state, k, NROUND1);
194
	((uint32_t*)mac)[1] = state[2];
lwc-tester committed
195 196 197 198 199 200

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