void 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, 0); for (r = 1; r < Nr; r++) { sub_bytes(state); shift_rows(state); mix_columns(state); add_round_key(state, w, r); } sub_bytes(state); shift_rows(state); add_round_key(state, w, Nr); 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 *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"); }
// Cipher is the main function that encrypts the PlainText. void cipher(int offset) { int i, j, round = 0; //Copy the input PlainText to state array. for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { state[i][j] = temp_buffer[i][j]; } } #ifdef SHIFT_ROWS for (round = 0; round <= nr; round++) shift_rows(); #elif defined(MIX_COLUMNS) for (round = 0; round <= nr; round++) mix_columns(); #elif defined(ADD_ROUND_KEY) for (round = 0; round <= nr; round++) add_round_key(nr); #elif defined(SUB_BYTES) for (round = 0; round <= nr; round++) sub_bytes(); #else // Add the First round key to the state before starting the rounds. add_round_key(0); // There will be nr rounds. // The first nr-1 rounds are identical. // These nr-1 rounds are executed in the loop below. for (round = 1; round < nr; round++) { sub_bytes(); shift_rows(); mix_columns(); add_round_key(round); } // The last round is given below. // The MixColumns function is not here in the last round. sub_bytes(); shift_rows(); add_round_key(nr); #endif // The encryption process is over. // Copy the state array to output array. for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { output_file_buffer[offset + i * 4 + j] = state[i][j]; } } }
return_type aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) { if( ctx->rnd ) { uint_8t s1[N_BLOCK], r; copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK ); inv_shift_sub_rows( s1 ); for( r = ctx->rnd ; --r ; ) #if defined( VERSION_1 ) { add_round_key( s1, ctx->ksch + r * N_BLOCK ); inv_mix_sub_columns( s1 ); } #else { uint_8t s2[N_BLOCK]; copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK ); inv_mix_sub_columns( s1, s2 ); } #endif copy_and_key( out, s1, ctx->ksch ); } else return (return_type) -1; return 0; }
void aes_encrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] ) { uint_8t s1[N_BLOCK], r, rc = 1; if(o_key != key) block16_copy( o_key, key ); copy_and_key( s1, in, o_key ); for( r = 1 ; r < 10 ; ++r ) #if defined( VERSION_1 ) { mix_sub_columns( s1 ); update_encrypt_key_128( o_key, &rc ); add_round_key( s1, o_key ); } #else { uint_8t s2[N_BLOCK]; mix_sub_columns( s2, s1 ); update_encrypt_key_128( o_key, &rc ); copy_and_key( s1, s2, o_key ); } #endif shift_sub_rows( s1 ); update_encrypt_key_128( o_key, &rc ); copy_and_key( out, s1, o_key ); }
return_type aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) { if( ctx->rnd ) { uint_8t s1[N_BLOCK], r; copy_and_key( s1, in, ctx->ksch ); for( r = 1 ; r < ctx->rnd ; ++r ) #if defined( VERSION_1 ) { mix_sub_columns( s1 ); add_round_key( s1, ctx->ksch + r * N_BLOCK); } #else { uint_8t s2[N_BLOCK]; mix_sub_columns( s2, s1 ); copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK); } #endif shift_sub_rows( s1 ); copy_and_key( out, s1, ctx->ksch + r * N_BLOCK ); } else return -1; return 0; }
void aes_decrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] ) { uint_8t s1[N_BLOCK], r, rc = 0x6c; if(o_key != key) block16_copy( o_key, key ); copy_and_key( s1, in, o_key ); inv_shift_sub_rows( s1 ); for( r = 10 ; --r ; ) #if defined( VERSION_1 ) { update_decrypt_key_128( o_key, &rc ); add_round_key( s1, o_key ); inv_mix_sub_columns( s1 ); } #else { uint_8t s2[N_BLOCK]; update_decrypt_key_128( o_key, &rc ); copy_and_key( s2, s1, o_key ); inv_mix_sub_columns( s1, s2 ); } #endif update_decrypt_key_128( o_key, &rc ); copy_and_key( out, s1, o_key ); }
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); }
static void aes_main(aes_key *key, uint8_t *state) { int i = 0; uint8_t rk[16]; create_round_key(key->data, rk); add_round_key(state, rk); for (i = 1; i < key->nbr; i++) { create_round_key(key->data + 16 * i, rk); shift_rows(state); mix_columns(state); add_round_key(state, rk); } create_round_key(key->data + 16 * key->nbr, rk); shift_rows(state); add_round_key(state, rk); }
/** * This function is the overall application of the AES cipher in the context of * a single state block matrix. * * For each state, we perform the four AES functions several times, in what are * referred to as "rounds". The number of rounds we do depends on the size of * the encryption key. */ void aes_cipher(uint8_t **state, aes_key_t *key) { int round, num_rounds; num_rounds = (key->size / 4) + 6; add_round_key(state, 0, key->exp_block); for (round = 1; round < num_rounds; round++) { sub_bytes(state); shift_rows(state); mix_columns(state); add_round_key(state, round, key->exp_block); } /* Don't mix columns on the last round */ sub_bytes(state); shift_rows(state); add_round_key(state, num_rounds, key->exp_block); }
static void aes_main_inv(aes_key *key, uint8_t *state) { int i = 0; uint8_t rk[16]; create_round_key(key->data + 16 * key->nbr, rk); add_round_key(state, rk); for (i = key->nbr - 1; i > 0; i--) { create_round_key(key->data + 16 * i, rk); shift_rows_inv(state); add_round_key(state, rk); mix_columns_inv(state); } create_round_key(key->data, rk); shift_rows_inv(state); add_round_key(state, rk); }
void Aes256::encrypt(unsigned char* buffer) { unsigned char i, rcon; copy_key(); add_round_key(buffer, 0); for (i = 1, rcon = 1; i < NUM_ROUNDS; ++i) { sub_bytes(buffer); shift_rows(buffer); mix_columns(buffer); if (!(i & 1)) expand_enc_key(&rcon); add_round_key(buffer, i); } sub_bytes(buffer); shift_rows(buffer); expand_enc_key(&rcon); add_round_key(buffer, i); }
void Aes256Encoder::Encrypt(MemoryData& rkey, const MemoryData& key,const MemoryData& salt, unsigned char* buffer) { unsigned char i, rcon; copy_key(rkey, key, salt); add_round_key(rkey.MutableData(), buffer, 0); for (i = 1, rcon = 1; i < RoundCount; ++i) { sub_bytes(buffer); shift_rows(buffer); mix_columns(buffer); if (!(i & 1)) expand_enc_key(rkey.MutableData(), &rcon); add_round_key(rkey.MutableData(), buffer, i); } sub_bytes(buffer); shift_rows(buffer); expand_enc_key(rkey.MutableData(), &rcon); add_round_key(rkey.MutableData(), buffer, i); }
void aes128_ecb_encrypt(const uint8_t *plaintext, const uint8_t *key, uint8_t *ciphertext) { int round; memcpy(ciphertext, plaintext, 16); key_schedule(key, round_keys); add_round_key(ciphertext, round_keys); for (round = 1; round < N_ROUNDS; round++) { sub_bytes(ciphertext); shift_rows(ciphertext); mix_columns(ciphertext); add_round_key(ciphertext, round_keys + 16 * round); } sub_bytes(ciphertext); shift_rows(ciphertext); add_round_key(ciphertext, round_keys + 160); }
/* encrypt one 128 bit block */ void nv_aes_encrypt(u_int8_t *in, u_int8_t *expkey, u_int8_t *out) { u_int8_t state[NVAES_STATECOLS * 4]; u_int32_t round; memcpy(state, in, NVAES_STATECOLS * 4); add_round_key((u_int32_t *)state, (u_int32_t *)expkey); for (round = 1; round < NVAES_ROUNDS + 1; round++) { if (round < NVAES_ROUNDS) mix_sub_columns (state); else shift_rows (state); add_round_key((u_int32_t *)state, (u_int32_t *)expkey + round * NVAES_STATECOLS); } memcpy(out, state, sizeof(state)); }
void test_add_round_key() { uint8_t state[16] = { 0x01,0x02,0x03,0x04, 0x05,0x06,0x07,0x08, 0x09,0x0a,0x0b,0x0c, 0x0d,0x0e,0x0f,0x10 }; uint8_t key[16] = { 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05 }; uint8_t tmp_state[16]; memcpy(tmp_state, state, sizeof(tmp_state)); add_round_key(tmp_state, key); add_round_key(tmp_state, key); int ret = memcmp(tmp_state, state, sizeof(tmp_state)); CU_ASSERT_EQUAL(ret, 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); }
int Aes128cbc_Enc(bw4 * state,int slen,const word_t * wkey,const bw4 * iv) { if(!state || slen!=16 || !wkey ) return -1; int i=0,j,round=0; byte_t k; bw tr; for(i=0;i<4;i++) state->w[i]^=iv->w[i]; //Add Round Key add_round_key(state->w,wkey+round*4,i); round++; while(round<10){ //shift rows shift_rows_left(state->b,k); //subbytes & mixcolumns for(i=0;i<4;i++) { state->w[i]= sm0[state->b[i*4]].w ^ sm1[state->b[i*4+1]].w ^ sm2[state->b[i*4+2]].w ^ sm3[state->b[i*4+3]].w ^ (wkey+round*4)[i]; } round++; } //subBytes & ShiftRows sbox_shift_rows_left(state->b,k); //AddRoundKey add_round_key(state->w,wkey+round*4,i); return 0; }
/* Decrypt a single block of 16 bytes with 'on the fly' 256 bit keying */ void aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] ) { uint_8t s1[N_BLOCK], r, rc = 0x80; if(o_key != key) { block16_copy( o_key, key ); block16_copy( o_key + 16, key + 16 ); } copy_and_key( s1, in, o_key ); inv_shift_sub_rows( s1 ); for( r = 14 ; --r ; ) #if defined( VERSION_1 ) { if( ( r & 1 ) ) { update_decrypt_key_256( o_key, &rc ); add_round_key( s1, o_key + 16 ); } else add_round_key( s1, o_key ); inv_mix_sub_columns( s1 ); } #else { uint_8t s2[N_BLOCK]; if( ( r & 1 ) ) { update_decrypt_key_256( o_key, &rc ); copy_and_key( s2, s1, o_key + 16 ); } else copy_and_key( s2, s1, o_key ); inv_mix_sub_columns( s1, s2 ); } #endif copy_and_key( out, s1, o_key ); }
int Aes128cbc_Pkcs7_Enc(bw4 * input,int inlen,const word_t * wkey,bw4 * output,const bw4 * iv) { int i=0,j,round = 0; byte_t k; bw tr; if(inlen<16){ PKCS7_Pad(input->b,inlen,16,output->b); for(i=0;i<4;i++) output->w[i]^=iv->w[i]; }else{ for(i=0;i<4;i++) output->w[i]=input->w[i]^iv->w[i]; } //Add Round Key add_round_key(output->w,wkey+round*4,i); round++; while(round<10){ //ShiftRows shift_rows_left(output->b,k); for(i=0;i<4;i++) { output->w[i]=sm0[output->b[i*4]].w ^ sm1[output->b[i*4+1]].w ^ sm2[output->b[i*4+2]].w ^ sm3[output->b[i*4+3]].w ^ (wkey+round*4)[i]; } round++; } //subbytes & ShiftRows sbox_shift_rows_left(output->b,k); //AddRoundKey add_round_key(output->w,wkey+round*4,i); return 0; }
/*AES128 encryption*/ int Aes128_Enc(bw4 * input,int inlen,const bw4 * key,int keylen,bw4 * output) { if(!input || inlen!=16 || !key || keylen!=16 || !output) return -1; int i=0,j,round=0; byte_t k; bw tr; for(i=0;i<4;i++) output->w[i]=input->w[i]; key_expansion(key,W); //Add Round Key add_round_key(output->w,W+round*4,i); round++; while(round<10){ //ShiftRows shift_rows_left(output->b,k); //subbytes & mixcolumns for(i=0;i<4;i++) { output->w[i]=sm0[output->b[i*4]].w ^ sm1[output->b[i*4+1]].w ^ sm2[output->b[i*4+2]].w ^ sm3[output->b[i*4+3]].w ^ (W+round*4)[i]; } round++; } //subBytes & ShiftRows sbox_shift_rows_left(output->b,k); //AddRoundKey add_round_key(output->w,W+round*4,i); return 0; }
void Aes256::decrypt(unsigned char* buffer) { unsigned char i, rcon = 1; copy_key(); for (i = NUM_ROUNDS / 2; i > 0; --i) expand_enc_key(&rcon); add_round_key(buffer, NUM_ROUNDS); shift_rows_inv(buffer); sub_bytes_inv(buffer); for (i = NUM_ROUNDS, rcon = 0x80; --i;) { if ((i & 1)) expand_dec_key(&rcon); add_round_key(buffer, i); mix_columns_inv(buffer); shift_rows_inv(buffer); sub_bytes_inv(buffer); } add_round_key(buffer, i); }
/** * Decrypts a single block of 16 bytes * @param in Buffer holding the input data * @param out Buffer holding the output data * @param ctx AES context * @return Status from the result */ aes_result AES::aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) { if( ctx->rnd ) { uint_8t s1[N_BLOCK], r; copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK ); inv_shift_sub_rows( s1 ); for( r = ctx->rnd ; --r ; ) { add_round_key( s1, ctx->ksch + r * N_BLOCK ); inv_mix_sub_columns( s1 ); } copy_and_key( out, s1, ctx->ksch ); } else return -1; return 0; }
/** * Encrypts a single block of 16 bytes * @param in Buffer holding the input data * @param out Buffer holding the output data * @param ctx AES context * @return Status from the result */ aes_result AES::aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) { if( ctx->rnd ) { uint_8t s1[N_BLOCK], r; copy_and_key( s1, in, ctx->ksch ); for( r = 1 ; r < ctx->rnd ; ++r ) { mix_sub_columns( s1 ); add_round_key( s1, ctx->ksch + r * N_BLOCK); } shift_sub_rows( s1 ); copy_and_key( out, s1, ctx->ksch + r * N_BLOCK ); } else return -1; return 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); }
static Aes aes_encrypt(OE oe, Aes key, Aes in) { Aes plx = Aes_new(oe); uint round = 0; Aes tmp = 0; *plx = *in; /* Add the round key to the state to obtain the final state in {plx} of this round. */ plx=add_round_key(oe,tmp=plx,key); //oe->p("Final state from this round:"); //print_aes(oe,plx); Aes_destroy(oe,&tmp); for(round = 1;round < 11;++round) { byte b[32] = {0}; /* Run the key schedule getting the new key in {key1} from the round number and the old key previously (e.g. before this line) stored in {key1}. */ key = key_schedule(oe,tmp=key,round); Aes_destroy(oe,&tmp); /* Print what round we are at */ //osal_sprintf(b,"Round %u:",round); //oe->p(b); /* Perform the S-Box on the state i {plx} which is out AES state. */ plx=subbytes(oe,tmp=plx); //oe->p("After SubBytes:"); //print_aes(oe,plx); Aes_destroy(oe,&tmp); /* Perform the shift rows step from {plx} assigning the new state to {plx}. plx = shift_rows(oe,plx); oe->p("After Shift rows:"); print_aes(oe,plx); */ /* Perform the mix columns step from {plx} assignment the new state to {plx} again. */ if (round < 10) { //plx = mix_columns(oe,plx); plx = shift_row_mix_cols(oe,tmp=plx); Aes_destroy(oe,&tmp); } else { plx = shift_rows(oe, tmp=plx); Aes_destroy(oe,&tmp); } //oe->p("After linear transform: "); //print_aes(oe,plx); /* Add the round key to the state to obtain the final state in {plx} of this round. */ plx=add_round_key(oe,tmp=plx,key); //oe->p("Final state from this round:"); //print_aes(oe,plx); Aes_destroy(oe,&tmp); /* Print the round key. */ //oe->p("Key"); //print_aes(oe,key); } return plx; }
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); }