void inv_cipher(uint8_t *in, uint8_t *out, uint8_t *w) { uint8_t state[4*Nb]; uint8_t r, i, j; for (i = 0; i < 4; i++) { for (j = 0; j < Nb; j++) { state[Nb*i+j] = in[i+4*j]; } } add_round_key(state, w, Nr); for (r = Nr-1; r >= 1; r--) { inv_shift_rows(state); inv_sub_bytes(state); add_round_key(state, w, r); inv_mix_columns(state); } inv_shift_rows(state); inv_sub_bytes(state); add_round_key(state, w, 0); for (i = 0; i < 4; i++) { for (j = 0; j < Nb; j++) { out[i+4*j] = state[Nb*i+j]; } } }
void inv_cipher(uint8_t *in, uint8_t **key_schedule, uint8_t n_k, uint8_t n_r) { uint8_t *state; state = malloc(BLOCK_LENGTH_IN_BYTES * sizeof(uint8_t)); if(state == NULL) { printf("malloc returned NULL in inv_cipher"); exit(1); } memcpy(state, in, BLOCK_LENGTH_IN_BYTES * sizeof(uint8_t)); if (DEBUG) { printf("\nRound 0\n"); debug_print_block(state, " Start: "); } add_round_key(state, key_schedule, n_r); if (DEBUG) { debug_print_key_schedule(key_schedule, n_r); } for (int rnd = 1; rnd < n_r; rnd++) { if (DEBUG) printf("\n\nRound %2d\n", rnd); debug_print_block(state, " Start: "); inv_shift_rows(state); debug_print_block(state, " Shift: "); inv_sub_bytes(state); debug_print_block(state, " Subst: "); add_round_key(state, key_schedule, n_r - rnd); inv_mix_columns(state); debug_print_block(state, " Mxcol: "); debug_print_key_schedule(key_schedule, rnd); } if (DEBUG) printf("\n\nRound 10\n"); debug_print_block(state, " Start: "); inv_shift_rows(state); debug_print_block(state, " Shift: "); inv_sub_bytes(state); debug_print_block(state, " Subst: "); add_round_key(state, key_schedule, 0); debug_print_key_schedule(key_schedule, 10); debug_print_block(state, "\n\nPLAINTEXT\n"); }
void aes_dec(aes_ctx_t *ctx) { int i; uint32_t *expkey = ctx->expkey; uint8_t *state = ctx->state; add_roundkey(state, expkey, NR); inv_shift_rows(state); inv_sub_bytes(state); for(i = NR - 1; i > 0; i--) { add_roundkey(state, expkey, i); mix_columns(state, INV_MIX); inv_shift_rows(state); inv_sub_bytes(state); } add_roundkey(state, expkey, 0); }
void aes_decrypt(aes_ctx *ctx, const byte *in, byte *out) { int i; byte state[16]; memcpy(state, in, 16); add_round_key(state, ctx->sub_key); for (i = 1; i < 10; i++) { inv_shift_rows(state); inv_sub_bytes(state); add_round_key(state, ctx->sub_key + (i * 16)); inv_mix_columns(state); } inv_shift_rows(state); inv_sub_bytes(state); add_round_key(state, ctx->sub_key + (i * 16)); memcpy(out, state, 16); }
void lnc_aes_dec(void *context) { lnc_aes_ctx_t *ctx = context; int i; uint32_t *expkey = ctx->expkey; uint8_t *state = ctx->state; add_roundkey(state, expkey, Nr); inv_shift_rows(state); inv_sub_bytes(state); for(i = Nr - 1; i > 0; i--) { add_roundkey(state, expkey, i); mix_columns(state, INV_MIX); inv_shift_rows(state); inv_sub_bytes(state); } add_roundkey(state, expkey, 0); }
void aes128_ecb_decrypt(uint8_t *plaintext, const uint8_t *key, const uint8_t *ciphertext) { int round; memcpy(plaintext, ciphertext, 16); key_schedule(key, round_keys); add_round_key(plaintext, round_keys + 160); inv_shift_rows(plaintext); inv_sub_bytes(plaintext); for (round = N_ROUNDS - 1; round > 0; round--) { add_round_key(plaintext, round_keys + 16 * round); inv_mix_columns(plaintext); inv_shift_rows(plaintext); inv_sub_bytes(plaintext); } add_round_key(plaintext, round_keys); }
void test_shift_rows_back() { uint8_t state[16] = { 0x01,0x02,0x03,0x04, 0x05,0x06,0x07,0x08, 0x09,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0x10 }; uint8_t tmp_state[16]; memcpy(tmp_state, state, sizeof(tmp_state)); shift_rows(tmp_state); inv_shift_rows(tmp_state); int ret = memcmp(tmp_state, state, sizeof(tmp_state)); CU_ASSERT_EQUAL(ret, 0); }
void test_shift_rows(){ char msg[] = "0123456789ABCDE"; print_block(msg, 16); printf("\n"); shift_rows(msg, 16); print_block(msg, 16); printf("\n"); inv_shift_rows(msg, 16); print_block(msg, 16); // TODO: cannot use strcmp because it stops on 0! // TODO: assert inv is equal to original assert( strcmp(msg, "0123456789ABCDE") == 0 ); }
void test_inv_shift_rows() { uint8_t state[16] = { 0x01,0x02,0x03,0x04, 0x05,0x06,0x07,0x08, 0x09,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0x10 }; uint8_t ret_state[16] = { 0x01,0x0e,0x0b,0x08, 0x05,0x02,0x0f,0x0c, 0x09,0x06,0x03,0x10, 0x0d,0x0a,0x07,0x04 }; inv_shift_rows(state); int ret = memcmp(ret_state, state, sizeof(ret_state)); CU_ASSERT_EQUAL(ret, 0); }
// Decrypts the input using AES-128 driven by tablefile; stores in output[4][4] void decrypt_block(unsigned char input_block[16], unsigned char output_block[16], unsigned char round_key[44][4], FILE* table, bool first) { unsigned char state[4][4] = { { 0 } }; // Carries state of block through encryption unsigned char* inv_poly = (unsigned char*)calloc(1,4); // Initialize Substitution Boxes unsigned char* s_box = (unsigned char*)calloc(1,256); unsigned char* inv_s_box = (unsigned char*)calloc(1,256); init_s_box(s_box, table); invert_s_box(s_box, inv_s_box); free(s_box); init_poly(inv_poly, table, "INVP="); // Copy input to initital state for(int i=0; i<16; i++) { state[i%4][i/4] = input_block[i]; } // Print initial inputs and key schedule inv_print_state(state, 0, "iinput", first); inv_print_state(&(round_key[4*10]), 0, "ik_sch", first); // Add initial round key add_round_key(state, round_key, 10); // Perform operations for rounds 1 to 9 for(int i=9; i>0; i--) { inv_print_state(state, 10-i, "istart", first); // Inverse Shift Rows inv_shift_rows(state); inv_print_state(state, 10-i, "is_row", first); // Substitute Bytes sub_bytes(state, inv_s_box); inv_print_state(state, 10-i, "is_box", first); // Add Round Key inv_print_state(&(round_key[4*i]), 10-i, "ik_sch", first); add_round_key(state, round_key, i); inv_print_state(state, 10-i, "ik_add", first); // Mix Columns mix_columns(state, inv_poly); } // Final round operations inv_print_state(state, 10, "istart", first); // Shift Rows inv_shift_rows(state); inv_print_state(state, 10, "is_row", first); // Substitute Bytes sub_bytes(state, inv_s_box); inv_print_state(state, 10, "is_box", first); // Add Round Key add_round_key(state, round_key, 0); inv_print_state(&(round_key[4*0]), 10, "ik_sch", first); // Store final state value in output_block, done for(int i=0; i<16; i++) { output_block[i] = state[i%4][i/4]; } inv_print_state(state, 10, "ioutput", first); free(inv_poly); free(inv_s_box); }
void test_decryption() { gf2matrix *mix_columns_mixing_bijection, *inv_mix_columns_mixing_bijection; tbox_mixing_bijections_t tbox_mixing_bijections, inv_tbox_mixing_bijections; gf2matrix *initial_encoding, *initial_decoding; gf2matrix *final_encoding, *final_decoding; tbox_t tbox; typeIA_t typeIAs; typeII_t typeIIs; typeIII_t typeIIIs; typeIB_t typeIBs; typeIV_IA_t typeIV_IAs; typeIV_IB_t typeIV_IBs; typeIV_II_round_t typeIV_IIs[NR - 1]; typeIV_III_round_t typeIV_IIIs[NR - 1]; uint32_t mixed_key_schedule[4 * (NR + 1)]; uint8_t key[KEY_SIZE] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; sboxes_8bit_t typeIA_input_sbox, typeIA_input_sbox_inv; sboxes_128bit_t typeIA_interim_sbox, typeIA_interim_sbox_inv; sboxes_8bit_t typeII_input_sbox[NR], typeII_input_sbox_inv[NR]; sboxes_32bit_t typeII_interim_sbox[NR - 1], typeII_interim_sbox_inv[NR - 1]; sboxes_8bit_t typeII_output_sbox[NR - 1], typeII_output_sbox_inv[NR - 1]; sboxes_32bit_t typeIII_interim_sbox[NR - 1], typeIII_interim_sbox_inv[NR - 1]; sboxes_128bit_t typeIB_interim_sbox, typeIB_interim_sbox_inv; sboxes_8bit_t typeIB_output_sbox, typeIB_output_sbox_inv; uint8_t state[4][4]; uint8_t in[16]; uint8_t out[16], out2[16]; _4bit_strip32_t strips32; _4bit_strip128_t strips128; int round, row, col, i; int tries = 3; for (; tries != 0; --tries) { randomize_key(key); make_block_invertible_matrix_pair(&mix_columns_mixing_bijection, &inv_mix_columns_mixing_bijection, 32); /* mix_columns_mixing_bijection = make_identity_matrix(32); */ /* inv_mix_columns_mixing_bijection = make_identity_matrix(32); */ make_tbox_mixing_bijections(tbox_mixing_bijections, inv_tbox_mixing_bijections); /* make_identity_tbox_mixing_bijections(tbox_mixing_bijections); */ /* make_identity_tbox_mixing_bijections(inv_tbox_mixing_bijections); */ make_block_invertible_matrix_pair(&initial_encoding, &initial_decoding, 128); /* initial_encoding = make_identity_matrix(128); */ /* initial_decoding = make_identity_matrix(128); */ make_block_invertible_matrix_pair(&final_encoding, &final_decoding, 128); /* final_encoding = make_identity_matrix(128); */ /* final_decoding = make_identity_matrix(128); */ expand_key(key, SBox, mixed_key_schedule, 4); mix_expanded_key(mixed_key_schedule); make_inv_tbox(tbox, ISBox, mixed_key_schedule, tbox_mixing_bijections); make_sbox_pair_8(typeIA_input_sbox, typeIA_input_sbox_inv); /* make_identity_sboxes8(typeIA_input_sbox); */ /* make_identity_sboxes8(typeIA_input_sbox_inv); */ make_sbox_pair_128(typeIA_interim_sbox, typeIA_interim_sbox_inv); /* make_identity_sboxes128(typeIA_interim_sbox); */ /* make_identity_sboxes128(typeIA_interim_sbox_inv); */ make_rounds_sbox_pair_8(typeII_input_sbox, typeII_input_sbox_inv, NR); /* for(i =0; i < NR; ++i) { */ /* make_identity_sboxes8(typeII_input_sbox[i]); */ /* make_identity_sboxes8(typeII_input_sbox_inv[i]); */ /* } */ make_rounds_sbox_pair_32(typeII_interim_sbox, typeII_interim_sbox_inv, NR - 1); /* for(i =0; i < NR-1; ++i) { */ /* make_identity_sboxes32(typeII_interim_sbox[i]); */ /* make_identity_sboxes32(typeII_interim_sbox_inv[i]); */ /* } */ make_rounds_sbox_pair_8(typeII_output_sbox, typeII_output_sbox_inv, NR - 1); /* for(i =0; i < NR-1; ++i) { */ /* make_identity_sboxes8(typeII_output_sbox[i]); */ /* make_identity_sboxes8(typeII_output_sbox_inv[i]); */ /* } */ make_rounds_sbox_pair_32(typeIII_interim_sbox, typeIII_interim_sbox_inv, NR - 1); /* for(i =0; i < NR-1; ++i) { */ /* make_identity_sboxes32(typeIII_interim_sbox[i]); */ /* make_identity_sboxes32(typeIII_interim_sbox_inv[i]); */ /* } */ make_sbox_pair_128(typeIB_interim_sbox, typeIB_interim_sbox_inv); /* make_identity_sboxes128(typeIB_interim_sbox); */ /* make_identity_sboxes128(typeIB_interim_sbox_inv); */ make_sbox_pair_8(typeIB_output_sbox, typeIB_output_sbox_inv); /* make_identity_sboxes8(typeIB_output_sbox); */ /* make_identity_sboxes8(typeIB_output_sbox_inv); */ make_typeIA(typeIAs, inv_tbox_mixing_bijections[NR - 1], initial_decoding, typeIA_input_sbox_inv, typeIA_interim_sbox); make_typeIV_IA(typeIV_IAs, typeIA_interim_sbox_inv, typeII_input_sbox[NR - 1], typeII_input_sbox_inv[NR-1]); make_inv_typeII(typeIIs, tbox, mix_columns_mixing_bijection, &typeII_input_sbox_inv[1], typeII_interim_sbox); make_typeIV_II(typeIV_IIs, typeII_interim_sbox_inv, typeII_output_sbox, typeII_output_sbox_inv); make_typeIII(typeIIIs, inv_mix_columns_mixing_bijection, inv_tbox_mixing_bijections, typeII_output_sbox_inv, typeIII_interim_sbox); make_typeIV_III(typeIV_IIIs, typeIII_interim_sbox_inv, typeII_input_sbox, typeII_input_sbox_inv); make_inv_typeIB(typeIBs, tbox[0], final_encoding, typeII_input_sbox_inv[0], typeIB_interim_sbox); make_typeIV_IB(typeIV_IBs, typeIB_interim_sbox_inv, typeIB_output_sbox, typeIB_output_sbox_inv); for (i = 0; i < 16; ++i) { in[i] = rand(); } dump_hex("input: ", in, 16); printf("White-box inverse cipher:\n"); do_input(state, in, initial_encoding, typeIA_input_sbox); dump_state("State before ", state); do_typeIA(strips128, state, typeIAs); do_typeIV_IA(state, strips128, typeIV_IAs); for (round = NR - 2; round != -1; --round) { printf("round %d: ", round + 2); dump_state("", state); inv_shift_rows(state); do_typeII(strips32, state, typeIIs[round]); do_typeIV_II(state, strips32, typeIV_IIs[round]); do_typeIII(strips32, state, typeIIIs[round]); do_typeIV_III(state, strips32, typeIV_IIIs[round]); } inv_shift_rows(state); dump_state("rounds 1 and 0: ", state); do_typeIB(strips128, state, typeIBs); do_typeIV_IB(state, strips128, typeIV_IBs); do_output(out, state, final_decoding, typeIB_output_sbox_inv); printf("Original AES Equivalent Inverse Cipher on same input using same key:\n"); eqv_decipher(in, out2, ISBox, mixed_key_schedule); dump_hex("WB Output ", out, 16); dump_hex("AES Output ", out2, 16); ASSERT(memcmp(out, out2, 16) == 0); free_matrix(mix_columns_mixing_bijection); free_matrix(inv_mix_columns_mixing_bijection); free_tbox_mixing_bijections(tbox_mixing_bijections); free_tbox_mixing_bijections(inv_tbox_mixing_bijections); free_matrix(final_decoding); free_matrix(final_encoding); free_matrix(initial_decoding); free_matrix(initial_encoding); } }
void test_inv_tbox() { tbox_mixing_bijections_t tbox_mixing_bijections, inv_tbox_mixing_bijections; tbox_t tbox; uint32_t expanded_key[(NR + 1) * 4]; uint8_t state[4][4]; uint8_t state2[4][4]; int round, row, col, i; make_tbox_mixing_bijections(tbox_mixing_bijections, inv_tbox_mixing_bijections); for (i = 0; i < (NR + 1) * 4; ++i) expanded_key[i] = (uint8_t) rand(); /* identity key expansion */ make_inv_tbox(tbox, ISBox, expanded_key, tbox_mixing_bijections); for (round = NR - 1; round != 1; --round) { printf("round: %d \n", round); randomize_state(state); memcpy(&state2[0][0], &state[0][0], 16); /* for validation */ dump_state("State before ", state); inv_shift_rows(state); for (row = 0; row < 4; ++row) { for (col = 0; col < 4; ++col) { state[row][col] = tbox[round][row][col][(state[row][col])]; } } dump_state("State after TBox ", state); /* validation */ /* The above should be equal to: */ /* 0. mix */ /* 1. addroundkey */ /* 2. subbytes */ /* 3. shiftrows */ for (row = 0; row < 4; ++row) { for (col = 0; col < 4; ++col) { mul_byte_by_matrix(&state2[row][col], tbox_mixing_bijections[round][row][col], state2[row][col]); } } add_round_key(state2, expanded_key, round+1); inv_sub_bytes(state2, ISBox); inv_shift_rows(state2); dump_state("Validation State ", state2); ASSERT(comp_states(state, state2)); } /* validation for the last round is different */ round = 0; { printf("rounds 9 and 10\n"); randomize_state(state); memcpy(&state2[0][0], &state[0][0], 16); /* for validation */ dump_state("State before ", state); inv_shift_rows(state); for (row = 0; row < 4; ++row) { for (col = 0; col < 4; ++col) { state[row][col] = tbox[round][row][col][(state[row][col])]; } } dump_state("State after TBox ", state); /* validation */ /* The above should be equal to: */ /* 0. mix */ /* 1. addroundkey */ /* 2. subbytes */ /* 3. shiftrows */ /* 4. addroundkey */ for (row = 0; row < 4; ++row) { for (col = 0; col < 4; ++col) { mul_byte_by_matrix(&state2[row][col], tbox_mixing_bijections[round][row][col], state2[row][col]); } } add_round_key(state2, expanded_key, 1); inv_sub_bytes(state2, ISBox); inv_shift_rows(state2); add_round_key(state2, expanded_key, 0); /* the last key */ dump_state("Validation State ", state2); ASSERT(comp_states(state, state2)); } free_tbox_mixing_bijections(tbox_mixing_bijections); free_tbox_mixing_bijections(inv_tbox_mixing_bijections); }
void test_inv_typeII() { gf2matrix *mix_columns_mixing_bijection; tbox_mixing_bijections_t tbox_mixing_bijections; typeII_t typeIIs; tbox_t tbox; uint32_t expanded_key[(NR + 1) * 4]; sboxes_8bit_t input_sbox[NR - 1], input_sbox_inv[NR - 1]; sboxes_32bit_t output_sbox[NR - 1], output_sbox_inv[NR - 1]; uint8_t state[4][4]; uint8_t pre_enc_state[4][4]; _4bit_strip32_t strips; _4bit_strip32_t strips2; int round, row, col, i, j; make_block_invertible_matrix_pair(&mix_columns_mixing_bijection, NULL, 32); make_tbox_mixing_bijections(tbox_mixing_bijections, NULL); for (i = 0; i < (NR + 1) * 4; ++i) expanded_key[i] = (uint8_t) rand(); /* identity key expansion */ make_tbox(tbox, ISBox, expanded_key, tbox_mixing_bijections); make_rounds_sbox_pair_8(input_sbox, input_sbox_inv, NR - 1); make_rounds_sbox_pair_32(output_sbox, output_sbox_inv, NR - 1); make_inv_typeII(typeIIs, tbox, mix_columns_mixing_bijection, input_sbox_inv, output_sbox); for (round = NR - 2; round != -1; --round) { printf("round %d\n", round); /* prepare encoded input to the step */ for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { pre_enc_state[i][j] = rand(); state[i][j] = sub_bytes_hi_lo(pre_enc_state[i][j], input_sbox[round][i][j]); } } inv_shift_rows(state); /* there's always shift rows before Type II */ do_typeII(strips, state, typeIIs[round]); /* decode output and present */ for (row = 0; row < 4; ++row) { for (col = 0; col < 4; ++col) { sub_bytes_hi_lo32(strips[row][col], output_sbox_inv[round][row][col]); } } dump_4bit_strip32("strips: ", strips); /* comparative section */ inv_shift_rows(pre_enc_state); /* there's always shift rows before Type II */ for (col = 0; col < 4; ++col) { uint8_t slice[4]; for (row = 0; row < 4; ++row) { int new_row; uint8_t temp = tbox[round + 1][row][col][pre_enc_state[row][col]]; calc_inv_mixing_slices(slice, temp, row); mul_array_by_matrix_32x32(slice, mix_columns_mixing_bijection, slice); for (new_row = 0; new_row < 4; ++new_row) { strips2[new_row][col][row] = slice[new_row]; } } } dump_4bit_strip32("Comparative strips: ", strips2); ASSERT(comp_4bit_strips32(strips, strips2)); } free_matrix(mix_columns_mixing_bijection); free_tbox_mixing_bijections(tbox_mixing_bijections); }