static void generate_subkey(struct crypto_cipher *tfm, u8 *k1, u8 *k2)
{
        u8 l[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
        u8 const_rb[AES_BLOCK_SIZE] = {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87};
        u8 const_zero[AES_BLOCK_SIZE] = {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

        crypto_cipher_encrypt_one(tfm, l, const_zero);

        if ((l[0] & 0x80) == 0) { /* If MSB(l) = 0, then k1 = l << 1 */
                leftshift_onebit(l, k1);
        } else {    /* Else k1 = ( l << 1 ) (+) Rb */
                leftshift_onebit(l, tmp);
                xor_128(tmp, const_rb, k1);
        }

        if ((k1[0] & 0x80) == 0) {
                leftshift_onebit(k1, k2);
        } else {
                leftshift_onebit(k1, tmp);
                xor_128(tmp, const_rb, k2);
        }
}
예제 #2
0
void generate_subkey(unsigned char *key, unsigned char *K1, unsigned
	char *K2)
{
	unsigned char L[16];
	unsigned char Z[16];
	unsigned char tmp[16];
	int i;

	for (i = 0; i<16; i++) Z[i] = 0;

	AES_128(key, Z, L);

	if ((L[0] & 0x80) == 0) { /* If MSB(L) = 0, then K1 = L << 1 */
		leftshift_onebit(L, K1);
	}
	else {    /* Else K1 = ( L << 1 ) (+) Rb */
		leftshift_onebit(L, tmp);
		xor_128(tmp, const_Rb, K1);
	}

	if ((K1[0] & 0x80) == 0) {
		leftshift_onebit(K1, K2);
	}
	else {
		leftshift_onebit(K1, tmp);
		xor_128(tmp, const_Rb, K2);
	}
	return;
}
예제 #3
0
static void ccGenAESSubKey(const struct ccmode_ecb *aesmode, ccecb_ctx *ctx, void *key1, void *key2)
{
    uint8_t L[16];
    uint8_t Z[16];
    uint8_t tmp[16];
    
	memset(Z, 0, 16);
    
    aesmode->ecb(ctx, 1, Z, L);
    
    if ( (L[0] & 0x80) == 0 ) { /* If MSB(L) = 0, then K1 = L << 1 */
        leftshift_onebit(L, key1);
    } else {    /* Else K1 = ( L << 1 ) (+) Rb */
        leftshift_onebit(L, tmp);
        xor_128(tmp,const_Rb, key1);
    }
    
    if ( (((uint8_t *)key1)[0] & 0x80) == 0 ) {
        leftshift_onebit(key1, key2);
    } else {
        leftshift_onebit(key1, tmp);
        xor_128(tmp,const_Rb, key2);
    }
    return;
    
}
예제 #4
0
void CCAESCmac(const void *key,
               const uint8_t *data,
               size_t dataLength,			/* length of data in bytes */
               void *macOut)				/* MAC written here */
{
    uint8_t       X[16],Y[16], M_last[16], padded[16];
    uint8_t       K1[16], K2[16];
    int         flag;
    size_t      n;
    const struct ccmode_ecb *aesmode = getCipherMode(kCCAlgorithmAES128, kCCModeECB, kCCEncrypt).ecb;
    ccecb_ctx_decl(aesmode->size, ctx);

    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");

	// CMacInit
    
    aesmode->init(aesmode, ctx, 16, key);
    aesmode->ecb(ctx, 1, Y, X);
    ccGenAESSubKey(aesmode, ctx, K1, K2);
    
    // CMacUpdates (all in this case)
    
    n = (dataLength+15) / 16;       /* n is number of rounds */
    
    if ( 0 == n ) {
        n = 1;
        flag = 0;
    } else {
        if ( (dataLength%16) == 0 ) flag = 1;
        else  flag = 0;
    }
    
    if ( flag ) { /* last block is complete block */
        xor_128(&data[16*(n-1)],K1,M_last);
    } else {
        ccAESCMacPadding(&data[16*(n-1)],padded,dataLength%16);
        xor_128(padded,K2,M_last);
    }
    
    memset(X, 0, 16);
    for (size_t i=0; i<n-1; i++ ) {
        xor_128(X,&data[16*i],Y); /* Y := Mi (+) X  */
        aesmode->ecb(ctx, 1, Y, X);
    }
    
    // CMacFinal
    
    xor_128(X,M_last,Y);
    aesmode->ecb(ctx, 1, Y, X);
    
    memcpy(macOut, X, 16);
}
void Generate_Subkey(Aes *aes, unsigned char *k1, unsigned char *k2) {
	unsigned char l[BLOCKSIZE];
	aes_encrypt(aes, l, const_Zero);
	leftshift_onebit(l, k1);
	if (MSB(l[0]) != 0) {
		xor_128(k1, const_Rb, k1);
	}

	leftshift_onebit(k1, k2);
	if (MSB(k1[0]) != 0) {
		xor_128(k2, const_Rb, k2);
	}
}
예제 #6
0
void AES_CMAC(unsigned char *key, unsigned char *input, int length,
	unsigned char *mac)
{
	unsigned char       X[16], Y[16], M_last[16], padded[16];
	unsigned char       K1[16], K2[16];
	int         n, i, flag;
	generate_subkey(key, K1, K2);

	n = (length + 15) / 16;       /* n is number of rounds */

	if (n == 0) {
		n = 1;
		flag = 0;
	}
	else {
		if ((length % 16) == 0) { /* last block is a complete block */
			flag = 1;
		}
		else { /* last block is not complete block */
			flag = 0;
		}
	}

	if (flag) { /* last block is complete block */
		xor_128(&input[16 * (n - 1)], K1, M_last);
	}
	else {
		padding(&input[16 * (n - 1)], padded, length % 16);
		xor_128(padded, K2, M_last);
	}

	for (i = 0; i<16; i++) X[i] = 0;
	for (i = 0; i<n - 1; i++) {
		xor_128(X, &input[16 * i], Y); /* Y := Mi (+) X  */
		AES_128(key, Y, X);      /* X := AES-128(KEY, Y); */
	}

	xor_128(X, M_last, Y);
	AES_128(key, Y, X);

	for (i = 0; i<16; i++) {
		mac[i] = X[i];
	}
}
void cmac_calc_mic(struct crypto_cipher *tfm, u8 *m,
                                u16 length, u8 *mac)
{
        u8 x[AES_BLOCK_SIZE], y[AES_BLOCK_SIZE];
        u8 m_last[AES_BLOCK_SIZE], padded[AES_BLOCK_SIZE];
        u8 k1[AES_KEYSIZE_128], k2[AES_KEYSIZE_128];
        int cmpBlk;
        int i, nBlocks = (length + 15)/AES_BLOCK_SIZE;

        generate_subkey(tfm, k1, k2);

        if (nBlocks == 0) {
                nBlocks = 1;
                cmpBlk = 0;
        } else {
                cmpBlk = ((length % AES_BLOCK_SIZE) == 0) ? 1 : 0;
        }

        if (cmpBlk) { /* Last block is complete block */
                xor_128(&m[AES_BLOCK_SIZE * (nBlocks - 1)], k1, m_last);
        } else { /* Last block is not complete block */
                padding(&m[AES_BLOCK_SIZE * (nBlocks - 1)], padded,
                        length % AES_BLOCK_SIZE);
                xor_128(padded, k2, m_last);
        }

        for (i = 0; i < AES_BLOCK_SIZE; i++)
                x[i] = 0;

        for (i = 0; i < (nBlocks - 1); i++) {
                xor_128(x, &m[AES_BLOCK_SIZE * i], y); /* y = Mi (+) x */
                crypto_cipher_encrypt_one(tfm, x, y); /* x = AES-128(KEY, y) */
        }

        xor_128(x, m_last, y);
        crypto_cipher_encrypt_one(tfm, x, y);

        vos_mem_copy(mac, x, CMAC_TLEN);
}
void aes_cmac(const unsigned char *key, const unsigned char *message, int len,
		unsigned char *mac) {
	Aes aes;
	wc_AesSetKey(&aes, key, BLOCKSIZE, 0, AES_ENCRYPTION);

	unsigned char k1[BLOCKSIZE], k2[BLOCKSIZE], xorResult[BLOCKSIZE],
			lastBlock[BLOCKSIZE];

	Generate_Subkey(&aes, k1, k2);

	int nBlocks = (len + BLOCKSIZE - 1) / BLOCKSIZE;
	bool needs_padding;

	if (nBlocks == 0) {
		nBlocks = 1;
		needs_padding = true;
	} else {
		needs_padding = (len % BLOCKSIZE) != 0;
	}

	if (needs_padding) {
		padding(&message[BLOCKSIZE * (nBlocks - 1)], lastBlock,
				len % BLOCKSIZE);
		xor_128(lastBlock, k2, lastBlock);
	} else {
		xor_128(&message[BLOCKSIZE * (nBlocks - 1)], k1, lastBlock);
	}

	for (int i = 0; i < BLOCKSIZE; i++)
		mac[i] = 0x00;

	for (int i = 0; i < nBlocks - 1; i++) {
		xor_128(&message[i * BLOCKSIZE], mac, xorResult);
		aes_encrypt(&aes, mac, xorResult);
	}

	xor_128(lastBlock, mac, xorResult);
	aes_encrypt(&aes, mac, xorResult);
}
예제 #9
0
void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext)
{
    int round;
    int i;
    unsigned char intermediatea[16];
    unsigned char intermediateb[16];
    unsigned char round_key[16];

    for(i=0; i<16; i++) round_key[i] = key[i];

    for (round = 0; round < 11; round++)
    {
        if (round == 0)
        {
            xor_128(round_key, data, ciphertext);
            next_key(round_key, round);
        }
        else if (round == 10)
        {
            byte_sub(ciphertext, intermediatea);
            shift_row(intermediatea, intermediateb);
            xor_128(intermediateb, round_key, ciphertext);
        }
        else    /* 1 - 9 */
        {
            byte_sub(ciphertext, intermediatea);
            shift_row(intermediatea, intermediateb);
            mix_column(&intermediateb[0], &intermediatea[0]);
            mix_column(&intermediateb[4], &intermediatea[4]);
            mix_column(&intermediateb[8], &intermediatea[8]);
            mix_column(&intermediateb[12], &intermediatea[12]);
            xor_128(intermediatea, round_key, ciphertext);
            next_key(round_key, round);
        }
    }

}
예제 #10
0
int crypto_aead_decrypt(
  unsigned char *m,unsigned long long *outputmlen,
  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
)
{
	u64 mlen, n, origmlen, start ;
	const byte *ptr, *origc;
	byte temp[AES_BYTES], *p ;
	int i ;

	assert( m != NULL ) ;
	assert( outputmlen != NULL ) ;
	assert( c != NULL ) ;
	assert( ad != NULL ) ;
	assert( npub != NULL ) ;
	assert( k != NULL ) ;

	if( clen < AUTH_BYTES)		return -1;

	/* where auth data should be */
	mlen = clen - AUTH_BYTES ;
	ptr = c + mlen ;
	*outputmlen = mlen;

	setup(mlen, adlen, npub, k) ;
	do_additional( ad, adlen ) ;

	origc = c;
	origmlen = mlen;

#ifdef TESTING
	printf("decrypt: total %llu text %llu ad %llu\n", clen, mlen, adlen ) ;
	printf("decrypt: ciphertext starts with %08xu\n", ((u32 *) origc)[0] ) ;
	printf("decrypt: starting authentication check %08x\n", ((u32 *) ptr)[0] ) ;
#endif

	/*
	authenticate
	*/
	start = mlen ;
	while( (mlen > 0) && (mlen <= start) ) {
		n = (u64) ((mlen >= AES_BYTES) ? AES_BYTES : mlen) ;
		addmul( (byte *) accum, c, n, (byte *) H) ;
		c += n;
		mlen -= n;
	}
	if( mlen > start )	{
#ifdef TESTING
		printf("decrypt: mlen out of bounds\n" ) ;
#endif
		return -2 ;
	}
#ifdef TESTING
		printf("decrypt: auth before finalisation %08x %08x\n", accum[0], accum[1] ) ;
#endif
	mix_in(finalblock) ;
	xor_128( accum, I ) ;

	/* see if we have a match */
	if( memcmp((void *) accum, (void *) ptr, AUTH_BYTES) != 0)	{
#ifdef TESTING
		printf("decrypt: auth failed, result here %08x\n", accum[0] ) ;
#endif
		return -3;
	}

#ifdef TESTING
	printf("decrypt: auth matched, going to decrypt\n" ) ;
	printf("decrypt: 1st ciphertext word %08x\n", *((u32 *) c)  ) ;
#endif

	/*
	reset things
	start encryption with correct ChaCha state
	*/
	c = origc;
	mlen = origmlen;
	setup(mlen, adlen, npub, k) ;

	/*
	decrypt, simpler than encryption
	no authentication to do
	*/
	start = mlen ;
	while( (mlen > 0) && (mlen <= start) ) {
		n = (u64) ((mlen >= AES_BYTES)? AES_BYTES : mlen) ;
		white_aes( temp ) ;
		for( i = 0, p = temp ; i < n ; i++, c++, m++, p++ )
			*m = *c ^ *p ;
		mlen -= n;
	}
	if( mlen > start )	{
#ifdef TESTING
		printf("decrypt: mlen out of bounds\n" ) ;
#endif
		return -2 ;
	}
#ifdef TESTING
	printf("decrypt: reached end, showing first words\n" ) ;
	printf("plaintext %08x ciphertext %08x auth %08x\n",*((u32 *) m), *((u32 *) c), accum[0]  ) ;
#endif
	memset( temp, 0, AES_BYTES ) ;
	cleanup() ;
	return 0;
}
예제 #11
0
/*
	declarations for this and decrypt
	copied from Bernstein's example AES-GCM code
	to be sure they match test framework
*/
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
)
{
	u64 n, start ;
	byte temp[AES_BYTES] ;
	byte *p, *q, *ptr ;
	int i ;
#ifdef TESTING
	byte *origm, *origc ;

	assert( c != NULL ) ;
	/* are framework declarations compatible with mine? */
	assert( sizeof(long long) == sizeof( u64) ) ;

	printf("encrypt: plaintext %llu ad %llu\n", mlen, adlen ) ;
	origm = m ;
	origc = c ;
#endif
	/*
	Bernstein's example aes-gcm code sets *clen
	I copy that, assuming the interface needs it
	*/
	*clen = mlen+AUTH_BYTES ;
	
	/* address for authentication data */
	ptr = c + mlen ;

	/* key schedule */
	setup( mlen, (u64) adlen, npub, k) ;
	/* data authenticated but not encrypted */
	do_additional( ad, (u64) adlen ) ;

	/*
	encryption
	mlen is unsigned so always > = 0
	use start for an error check
	*/
	start = mlen ;
	while( (mlen != 0) && (mlen <= start) ) {
		n = (u64) ((mlen >= AES_BYTES)? AES_BYTES : mlen) ;
		white_aes( temp ) ;
		for( i = 0, p = temp, q = c ; i < n ; i++, q++, m++, p++ )
			*q = *m ^ *p ;
		addmul( (byte *) accum, c, n, (byte *) H) ;
		mlen -= n;
		c += n ;
	}
	if( mlen > start )	{
#ifdef TESTING
		printf("encrypt: mlen out of bounds\n" ) ;
#endif
		return -2 ;
	}
#ifdef TESTING
		printf("encrypt: auth before finalisation %08x %08x\n", accum[0], accum[1] ) ;
#endif
	/*
	finish authentication
	*/
	mix_in(finalblock) ;
	xor_128( accum, I ) ;
	memcpy( ptr, (void *) accum, AES_BYTES ) ;

#ifdef TESTING
	printf("encrypt: reached end, showing first words\n" ) ;
	printf("plaintext %08x ciphertext %08x auth %08x\n", *((u32 *) origm), *((u32 *) origc), accum[0]  ) ;
#endif
	memset( temp,  0, AES_BYTES ) ;
	cleanup() ;
	return 0 ;
}
예제 #12
0
int crypto_aead_decrypt(unsigned char *m, unsigned long long *outputmlen,
			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)
{
    AES_KEY key[1];
    AES_KEY kappa_0[1];
    AES_KEY kappa_m[1];
    unsigned char nonce[BLOCK_LENGTH];
    CPFB_BLOCK X[1];
    CPFB_BLOCK P[1];
    CPFB_BLOCK stream[1];
    unsigned long long counter;
    unsigned long long mlen;
    (void)nsec; /* avoid warning */

    if (clen < TAG_LENGTH)
	return -1;
    *outputmlen = mlen = clen - TAG_LENGTH;


    init(npub,k,kappa_0,key,nonce);

    /* Block encoding alen and mlen
     * In an online implementation, it would be done at the end, and X would be 0
     */
    store64(X->u8, mlen);
    X->u32[2] = htobe32((crypto_uint32)adlen);
    X->counter = 0;
    AES_encrypt(X, X, kappa_0);

    /* AD processing */
    counter = 0;
    while (adlen > PAYLOAD_LENGTH) {
        load_96_ctr(P,ad,++counter);
	AES_encrypt(P, stream, kappa_0);
	xor_128(X, stream, X);
	ad += PAYLOAD_LENGTH;
	adlen -= PAYLOAD_LENGTH;
    }
    if (adlen > 0) {
        load_partial_ctr(P,ad,adlen,++counter);
	AES_encrypt(P, stream, kappa_0);
	xor_128(X, stream, X);
    }

    /* Plaintext processing */
    if (mlen > 0) {
	/* New kappa */
	gen_next_kappa(nonce,kappa_0,kappa_m,key);
	counter = 0;

	/* P_0 processing */
	P->u64[0] = P->u64[1] = 0;
	AES_encrypt(P, stream, kappa_m);

	while (mlen > PAYLOAD_LENGTH) {
	    store_xor_96(m,(CPFB_BLOCK*)c,stream);
	    load_96_ctr(P,m,++counter);
	    AES_encrypt(P, stream, kappa_m);
	    xor_128(X, stream, X);
	    c += PAYLOAD_LENGTH;
	    m += PAYLOAD_LENGTH;
	    mlen -= PAYLOAD_LENGTH;
	}
	if (mlen > 0) {
	    store_xor_partial(m,(CPFB_BLOCK*)c,stream,mlen);
	    load_partial_ctr(P,m,mlen,++counter);
	    AES_encrypt(P, stream, kappa_m);
	    xor_128(X, stream, X);
	    c += mlen;
	}
    }
    AES_encrypt(X, X, kappa_0);
    return verify_tag(c,X->u8);
}
예제 #13
0
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)
{
    AES_KEY key[1];
    AES_KEY kappa_0[1];
    AES_KEY kappa_m[1];
    unsigned char nonce[BLOCK_LENGTH];
    CPFB_BLOCK X[1];
    CPFB_BLOCK P[1];
    CPFB_BLOCK stream[1];
    unsigned long long i;
    unsigned long long counter;
    (void)nsec; /* avoid warning */

    *clen = mlen + TAG_LENGTH;
    /* Key schedule, nonce initialization and generation of first kappa */
    init(npub,k,kappa_0,key,nonce);

    /* Block encoding alen and mlen
     * In an online implementation, it would be done at the end, and X would be 0
     */
    store64(X->u8, mlen);
    X->u32[2] = htobe32((crypto_uint32)adlen);
    X->counter = 0;
    AES_encrypt(X, X, kappa_0);

    /* AD processing */
    counter = 0;
    while (adlen > PAYLOAD_LENGTH) {
        load_96_ctr(P,ad,++counter);
	AES_encrypt(P, stream, kappa_0);
	xor_128(X, stream, X);
	ad += PAYLOAD_LENGTH;
	adlen -= PAYLOAD_LENGTH;
    }
    if (adlen > 0) {
        load_partial_ctr(P,ad,adlen,++counter);
	AES_encrypt(P, stream, kappa_0);
	xor_128(X, stream, X);
    }

    /* Plaintext processing */
    if (mlen > 0) {
	/* Increment nonce and generate new kappa
	 * First subkey of kappa_m is modified
	 * (xored with first subkey of kappa_0)
	 */ 
	gen_next_kappa(nonce,kappa_0, kappa_m,key);
 	counter = 0;

	/* P_0 processing */
	P->u64[0] = P->u64[1] = 0;
	AES_encrypt(P, stream, kappa_m);

	while (mlen > PAYLOAD_LENGTH) {
	    load_96_ctr(P,m,++counter);
	    store_xor_96(c,P,stream);
 	    AES_encrypt(P, stream, kappa_m);
	    xor_128(X, stream, X);
	    c += PAYLOAD_LENGTH;
	    m += PAYLOAD_LENGTH;
	    mlen -= PAYLOAD_LENGTH;
	}
	if (mlen > 0) {
	    load_partial_ctr(P,m,mlen,++counter);
	    store_xor_partial(c,P,stream,mlen);
 	    AES_encrypt(P, stream, kappa_m);
	    xor_128(X, stream, X);
	    c += mlen;
	}
    }
    AES_encrypt(X, X, kappa_0);
    for (i = 0; i < TAG_LENGTH; i++)
	c[i] = X->u8[i];
    return 0;
}