public static void AES_cbc_decrypt(AES_ctx* ctx, byte* src, byte* dst, int size) { var _block_buff = new byte[16]; var _block_buff_previous = new byte[16]; fixed (byte* block_buff = _block_buff) fixed (byte* block_buff_previous = _block_buff_previous) { memcpy(block_buff, src, 16); memcpy(block_buff_previous, src, 16); AES_decrypt(ctx, src, dst); dst += 16; src += 16; int i; for(i = 16; i < size; i+=16) { //step1: backup current block for next block decrypt memcpy(block_buff, src, 16); //step2: copy current block to destination memcpy(dst, src, 16); //step3: decrypt current buffer in place AES_decrypt(ctx, dst, dst); //step4: XOR current buffer with previous buffer xor_128(dst, block_buff_previous, dst); //step5: swap buffers memcpy(block_buff_previous, block_buff, 16); dst += 16; src += 16; } } }
public static void AES_CMAC(AES_ctx* ctx, byte* input, int length, byte* mac) { var _X = new byte[16]; var _Y = new byte[16]; var _M_last = new byte[16]; var _padded = new byte[16]; var _K1 = new byte[16]; var _K2 = new byte[16]; int n, i, flag; fixed (byte* X = _X) fixed (byte* Y = _Y) fixed (byte* M_last = _M_last) fixed (byte* padded = _padded) fixed (byte* K1 = _K1) fixed (byte* K2 = _K2) { generate_subkey(ctx,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 != 0 ) { /* 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_encrypt(ctx, Y, X); /* X := AES-128(KEY, Y); */ } xor_128(X,M_last,Y); AES_encrypt(ctx, Y, X); for ( i=0; i<16; i++ ) { mac[i] = X[i]; } } }
//No IV support! public static void AES_cbc_encrypt(AES_ctx* ctx, byte* src, byte* dst, int size) { var _block_buff = new byte[16]; fixed (byte* block_buff = _block_buff) { int i; for(i = 0; i < size; i+=16) { //step 1: copy block to dst memcpy(dst, src, 16); //step 2: XOR with previous block if(i != 0) xor_128(dst, block_buff, dst); //step 3: encrypt the block -> it land in block buffer AES_encrypt(ctx, dst, block_buff); //step 4: copy back the encrypted block to destination memcpy(dst, block_buff, 16); dst += 16; src += 16; } } }
public static void generate_subkey(AES_ctx* ctx, byte* K1, byte* K2) { var _L = new byte[16]; var _Z = new byte[16]; var _tmp = new byte[16]; int i; fixed (byte* tmp = _tmp) fixed (byte* L = _L) fixed (byte* Z = _Z) fixed (byte* const_Rb = _const_Rb) { for ( i=0; i<16; i++ ) Z[i] = 0; AES_encrypt(ctx, 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); } } }
public static int AES_set_key(AES_ctx *ctx, byte *key, int bits) { return rijndael_set_key((rijndael_ctx *)ctx, key, bits); }
public static void AES_encrypt(AES_ctx* ctx, byte* src, byte* dst) { rijndaelEncrypt(ctx->ek, ctx->Nr, src, dst); }
public static void AES_decrypt(AES_ctx* ctx, byte* src, byte* dst) { rijndaelDecrypt(ctx->dk, ctx->Nr, src, dst); }
public static void AES_CMAC_forge(AES_ctx* ctx, byte* input, int length, byte* forge) { var _X = new byte[16]; var _Y = new byte[16]; var _M_last = new byte[16]; var _padded = new byte[16]; var _K1 = new byte[16]; var _K2 = new byte[16]; int n, i, flag; fixed (byte* X = _X) fixed (byte* Y = _Y) fixed (byte* M_last = _M_last) fixed (byte* padded = _padded) fixed (byte* K1 = _K1) fixed (byte* K2 = _K2) { generate_subkey(ctx,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 != 0 ) { /* 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_encrypt(ctx, Y, X); /* X := AES-128(KEY, Y); */ } xor_128(X,M_last,Y); AES_decrypt(ctx, forge, X); //printf("Pre-crypt value: "); for(i=0;i<0x10;i++) printf("%02x", X[i]); printf("\n"); xor_128(X,Y,forge); xor_128(forge,&input[16*(n-1)],Y); //AES_encrypt(Y, X, &aes); //Update original input file so it produces the correct CMAC for ( i=0; i<16; i++ ) { input[(16*(n-1))+i]= Y[i]; } } }