Example #1
0
// PMAC1'(N)
// Param: pointers to V, n (nonce) and k (key)
// Modifies v.
void pmac1(unsigned char *v, const unsigned char *n, const unsigned char *k) {

	unsigned char delta0[NUM_BYTES];
	
	getl(delta0, k);

	// delta0 <- 3^3 * L
	for (int j = 0; j < 3; j++) {
		
		multiplyby3(delta0);

	}

	// 3*delta0
	multiplyby3(delta0);

	// N xor 3*delta0
	for (int i = 0; i < NUM_BYTES; i++) {
		delta0[i] = delta0[i] ^ n[i];
	}

	// V = E_k(N xor 3*delta0)
	aes128e(v, delta0, k);
}
/* Under the 16-byte (128-bit) key at k and the 12-byte (96-bit) nonce at n, encrypt the plaintext at p and store it at c. 
   The length of the plaintext is a multiple of 16 bytes given at len (e.g., len = 2 for a 32-byte p). The length of the
   ciphertext c is (len+1)*16 bytes. */
void aes128ocb(unsigned char *c, const unsigned char *k, const unsigned char *n, const unsigned char *p, const unsigned int len) {

    /* Array of zeros for use with aes128e */
    unsigned char zeros[16];
    int i;
    for (i = 0; i < 16; ++i) {
        zeros[i] = 0x00;
    }

    unsigned char l[16];
    unsigned char l_dollar[16];

    aes128e(l, zeros, k);
    /* Now l is l_star */

    doubleB(l, 16);
    /* Now l is l_dollar */

    /* We keep l_dollar for using it for calculate the tag */
    for (i = 0; i < 16; ++i) {
        l_dollar[i] = l[i];
    }

    doubleB(l, 16);
    /* Now l is l_0 */

    /* m = bitlen(P)/128 */
    unsigned int m = ((16*len)*8)/128;

    /* numL is the maximum value of trailing zeros for the given size m */
    unsigned int numL = msb(m) + 1;

    /* ls is the array of all the l_i arrays */
    unsigned char ls[numL][16];

    int a;
    for (a = 0; a < numL; ++a) {
        for (i = 0; i < 16; ++i) {
            ls[a][i] = l[i];
        }
        doubleB(l, 16);
    }

    /* Addition of 0x00000001 to the nonce */
    unsigned char nonce[20];
    nonce[0] = nonce[1] = nonce[2] = 0x00;
    nonce[3] = 0x01;

    a = 0;
    for (i = 4; i < 20; ++i) {
        nonce[i] = n[a];
        ++a;
    }

    /* Bottom is the integer value of the last 6 bits of nonce */
    unsigned int bottom = nonce[15]&0x3F;

    /* Temporal array for aes128e with last 6 bits of nonce to zero */
    unsigned char top[16];
    
    for (i = 0; i < 16; ++i) {
        top[i] = nonce[i];
    }
    top[15] = nonce[15]&0xC0;

    /* Calculation of ktop using the block cipher */
    unsigned char ktop[16];

    aes128e(ktop, top, k);

    /* Stretch is ktop concatenated with the xor of the bits 1...64 and 9...72 of ktop */
    unsigned char stretch[24];
    
    for (i = 0; i < 16; ++i) {
        stretch[i] = ktop[i];
    }
    a = 0;
    for (i = 16; i < 24; ++i) {
        stretch[i] = (ktop[a] ^ ktop[a + 1]);
        ++a;
    }

    /* Array of the m offset arrays */
    unsigned char offset[m][16];

    /* Array of the m checksum arrays */
    unsigned char checksum[m][16];

    /* Temporal array for get stretch[1 + bottom...128 + bottom] */
    unsigned char tempS[24];
    
    for (i = 0; i < 24; ++i) {
        tempS[i] = stretch[i];
    }

    /* Shifting of stretch bottom times to the left */
    for (i = 0; i < bottom; ++i) {
        shiftB(tempS, 24);
    }

    /* Copy of temp array to offset and inicialization of checksum */
    for (i = 0; i < 16; ++i) {
        offset[0][i] = tempS[i];
        checksum[0][i] = 0x00;
    }

    /* Temporal arrays for use them with aes128 as plaintext and ciphertext */
    unsigned char temp1[16];
    unsigned char temp2[16];

    int ntzV;

    /* Counters */
    int countP1 = 0;
    int countP2 = 0;
    int countC = 0;
    
    /* Loop over the m blocks */
    for (i = 1; i <= m; ++i) {

        /* Number of trailing zeros in i */
        ntzV = ntz(i);

        /* Calculation of the offset_i with xor betwen offset_{i-1} and l_{ntz(i)} */
        for (a = 0; a < 16; ++a) {
            offset[i][a] = offset[i - 1][a] ^ ls[ntzV][a];
        }

        /* Calculation of xor betwen p_i and offset_i for use it in aes128 */
        for (a = 0; a < 16; ++a) {
            temp1[a] = (p[countP1] ^ offset[i][a]);
            ++countP1;
        }
        
        aes128e(temp2, temp1, k);

        /* Calculation of c_i with xor betwen offset_i and result of aes128 */
        for (a = 0; a < 16; ++a) {
           c[countC] = offset[i][a] ^ temp2[a];
           ++countC;
        }

        /* Calculation of checksum_i with the xor betwen checksum_{i-1} and p_i */
        for (a = 0; a < 16; ++a) {
            checksum[i][a] = checksum[i - 1][a] ^ p[countP2];
            ++countP2;
        }
    }

    unsigned char tag[16];
    unsigned char tempTag[16];
        
    /* Calculation of the xor betwen checksum_m, offset_m and l_dollar for use it in aes128 to calculate the tag */
    int w;
    for (w = 0; w < 16; ++w) {
        tempTag[w] = ((l_dollar[w] ^ offset[m][w]) ^ checksum[m][w]);
    }

    aes128e(tag, tempTag, k);

    /* Concatenation of the tag at the end of the ciphertext. 16*m is the 
    current lenght of the cipher lenght and 16*m +16 is the total lenght */
    int countTag = 0;
    for (a = 16*m; a < (16*m + 16); ++a) {
        c[a] = tag[countTag];
        ++countTag;
    }
}
Example #3
0
/* Under the 16-byte key at k and the 16-byte nonce at n, encrypt the plaintext at m and store it at c.
   Store the 16-byte tag in the end of c. The length of the plaintext is a multiple of 16 bytes given at d (e.g., 
   d = 2 for a 32-byte m). */
void aescopa(unsigned char *c, const unsigned char *k, const unsigned char *n, const unsigned char *m, const unsigned int d) {

	unsigned char v[NUM_BYTES];
	unsigned char s[NUM_BYTES];
	unsigned char sigma[NUM_BYTES];
	unsigned char l[NUM_BYTES];
	unsigned char aes1[NUM_BYTES];
	unsigned char aes2[NUM_BYTES];
	unsigned char t[NUM_BYTES];

	// V <- PMAC1'(N)
	pmac1(v, n, k);

	// (C,S) <- ENCRYPT(V,M)
	encrypt(v, m, c, s, k, d);

	// Sigma <- M[1] xor M[2] xor ... M[d]
	// Initial sigma == M[1]
	memcpy(sigma, m, NUM_BYTES);

	for (int i = 1; i < d; i++) {
		for (int j = 0; j < NUM_BYTES; j++) {
			sigma[j] = sigma[j] ^ m[i*NUM_BYTES+j];
		}
	}

	// Sigma xor (2^(d-1)*3^2*L)
	// 3^2 L
	getl(l, k);
	multiplyby3(l);
	multiplyby3(l);

	// 2^(d-1) (3^2 L)
	for (int i = 0; i < d-1; i++) {
		multiplyby2(l);
	}

	// Sigma xor ...
	for (int i = 0; i < NUM_BYTES; i++) {
		sigma[i] = sigma[i] ^ l[i];
	}

	// E_k(sigma xor ...) = aes1
	aes128e(aes1, sigma, k);

	// aes1 xor S
	for (int i = 0; i < NUM_BYTES; i++) {
		aes1[i] = aes1[i] ^ s[i];
	}

	// E_k(aes1 xor S) = aes2
	aes128e(aes2, aes1, k);

	// 7L
	getl(l, k);
	multiplyby7(l);

	// 2^d*7L
	for (int i = 0; i < d; i++) {
		multiplyby2(l);
	}

	// T = aes2 xor 2^d*7L
	for (int i = 0; i < NUM_BYTES; i++) {
		t[i] = aes2[i] ^ l[i];
	}

	// Copy T to the end of C.
	memcpy((c+d*NUM_BYTES), t, NUM_BYTES);
	
}
Example #4
0
// (C,S) <- ENCRYPT(V,M)
// Params: pointers to v, m, c, s, key k, length d
void encrypt(unsigned char *v, const unsigned char *m, unsigned char *c, unsigned char *s, const unsigned char *k, const unsigned int d) {

	unsigned char delta0[NUM_BYTES];
	unsigned char delta1[NUM_BYTES];
	unsigned char l[NUM_BYTES];
	// Holder for the current block.
	unsigned char tempm[NUM_BYTES];
	unsigned char tempm2[NUM_BYTES];
	unsigned char tempv[NUM_BYTES];
	unsigned char v1[NUM_BYTES];

	// delta0 <- 3L
	getl(delta0, k);
	multiplyby3(delta0);

	// delta1 <- 2L
	getl(delta1, k);
	multiplyby2(delta1);

	// V[0] <- V xor L
	getl(l, k);
	
	for (int i = 0; i < NUM_BYTES; i++) {
		v[i] = v[i] ^ l[i];
	}

	// One 128-bit block at a time.
	for (int i = 0; i < d; i++) {

		// Copy the block to the temp holder.
		memcpy(tempm, m+i*NUM_BYTES, NUM_BYTES);

		// M[i] xor delta0
		for (int j = 0; j < NUM_BYTES; j++) {
			tempm[j] = tempm[j] ^ delta0[j];
		}

		// E_k(M[i] xor delta0)
		aes128e(tempm2, tempm, k);

		// V[i] <- E_k(M[i] xor delta0) xor V[i-1]
		for (int j = 0; j < NUM_BYTES; j++) {
			v1[j] = tempm2[j] ^ v[j];
		}
		
		// E_k(V[i])
		aes128e(tempv, v1, k);

		// C[i] = E_k(V[i]) xor delta1
		for (int j = 0; j < NUM_BYTES; j++) {
			c[i*NUM_BYTES+j] = tempv[j] ^ delta1[j];
		}

		// Set up next round:
		// 2*delta0, 2*delta1, V[i-1] = V[i]
		multiplyby2(delta0);
		multiplyby2(delta1);
		memcpy(v, v1, NUM_BYTES);
	}

	// Copy the final value of v[i] to s
	memcpy(s, v1, NUM_BYTES);

}
Example #5
0
// Helper function to generate L=E_k(0) when needed.
void getl(unsigned char *l, const unsigned char *k) {

	unsigned char temp[NUM_BYTES] = {0x00};
	aes128e(l, temp, k);

}