static public 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; } } }
//No IV support! static public 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; } } }
static public 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); } } }
static public 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]; } } }
static public 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]; } } }
static public void AES_encrypt(AES_ctx *ctx, byte *src, byte *dst) { rijndaelEncrypt(ctx->ek, ctx->Nr, src, dst); }
static public void AES_decrypt(AES_ctx *ctx, byte *src, byte *dst) { rijndaelDecrypt(ctx->dk, ctx->Nr, src, dst); }
static public int AES_set_key(AES_ctx *ctx, byte *key, int bits) { return(rijndael_set_key((rijndael_ctx *)ctx, key, bits)); }