void decrypt_key(unsigned char* decryptedSap, unsigned char* keyIn, unsigned char* iv, unsigned char* keyOut) { unsigned char blockIn[16]; uint32_t key_schedule[11][4]; uint32_t mode_key_schedule[11][4]; generate_key_schedule(&decryptedSap[8], key_schedule); printf("Generating mode key:\n"); generate_key_schedule(initial_session_key, mode_key_schedule); z_xor(keyIn, blockIn, 1); print_block("Input to cycle is: ", blockIn); cycle(blockIn, key_schedule); for (int j = 0; j < 16; j++) keyOut[j] = blockIn[j] ^ iv[j]; print_block("Output from cycle is: ", keyOut); x_xor(keyOut, keyOut, 1); }
void test_generate_key_schedule() { des_block_t key; key.c = 0x13345779; key.d = 0x9BBCDFF1; des_block_t* key_schedule = generate_key_schedule(key); assert(key_schedule[0].c == 0x1B02EF); assert(key_schedule[0].d == 0xFC7072); assert(key_schedule[15].c == 0xCB3D8B); assert(key_schedule[15].d == 0x0E17F5); }
void test_block_decode() { des_block_t key; key.c = 0x13345779; key.d = 0x9BBCDFF1; des_block_t* key_schedule = generate_key_schedule(key); des_block_t message_block; message_block.c = 0x01234567; message_block.d = 0x89ABCDEF; des_block_t decoded = encode_block(message_block, key_schedule, DECODE); assert(decoded.c == 0xEE0F7C12); assert(decoded.d == 0xE0B09338); free(key_schedule); }
void test_block_encode() { des_block_t key; key.c = 0x13345779; key.d = 0x9BBCDFF1; des_block_t* key_schedule = generate_key_schedule(key); des_block_t message_block; message_block.c = 0x01234567; message_block.d = 0x89ABCDEF; des_block_t encoded = encode_block(message_block, key_schedule, ENCODE); assert(encoded.c == 0x85E81354); assert(encoded.d == 0x0F0AB405); free(key_schedule); }
void decrypt_sap(unsigned char* sapIn, unsigned char* sapOut) { uint32_t key_schedule[11][4]; unsigned char* iv; print_block("Base sap: ", &sapIn[0xf0]); z_xor(sapIn, sapOut, 16); generate_key_schedule(sap_key_material, key_schedule); print_block("lastSap before cycle: ", &sapOut[0xf0]); for (int i = 0xf0; i >= 0x00; i-=0x10) { printf("Ready to cycle %02X\n", i); cycle(&sapOut[i], key_schedule); print_block("After cycling, block is: ", &sapOut[i]); if (i > 0) { // xor with previous block iv = &sapOut[i-0x10]; } else { // xor with sap IV iv = sap_iv; } for (int j = 0; j < 16; j++) { printf("%02X ^ %02X -> %02X\n", sapOut[i+j], iv[j], sapOut[i+j] ^ iv[j]); sapOut[i+j] = sapOut[i+j] ^ iv[j]; } printf("Decrypted SAP %02X-%02X:\n", i, i+0xf); print_block("", &sapOut[i]); } // Lastly grind the whole thing through x_key. This is the last time we modify sap x_xor(sapOut, sapOut, 16); printf("Sap is decrypted to\n"); for (int i = 0xf0; i >= 0x00; i-=0x10) { printf("Final SAP %02X-%02X: ", i, i+0xf); print_block("", &sapOut[i]); } }
void decryptMessage(unsigned char* messageIn, unsigned char* decryptedMessage) { unsigned char buffer[16]; int i, j; unsigned char tmp; uint32_t key_schedule[11][4]; int mode = messageIn[12]; // 0,1,2,3 printf("mode = %02x\n", mode); generate_key_schedule(initial_session_key, key_schedule); // For M0-M6 we follow the same pattern for (i = 0; i < 8; i++) { // First, copy in the nth block (we must start with the last one) for (j = 0; j < 16; j++) { if (mode == 3) buffer[j] = messageIn[(0x80-0x10*i)+j]; else if (mode == 2 || mode == 1 || mode == 0) buffer[j] = messageIn[(0x10*(i+1))+j]; } // do this permutation and update 9 times. Could this be cycle(), or the reverse of cycle()? for (j = 0; j < 9; j++) { int base = 0x80 - 0x10*j; //print_block("About to cycle. Buffer is currently: ", buffer); buffer[0x0] = message_table_index(base+0x0)[buffer[0x0]] ^ message_key[mode][base+0x0]; buffer[0x4] = message_table_index(base+0x4)[buffer[0x4]] ^ message_key[mode][base+0x4]; buffer[0x8] = message_table_index(base+0x8)[buffer[0x8]] ^ message_key[mode][base+0x8]; buffer[0xc] = message_table_index(base+0xc)[buffer[0xc]] ^ message_key[mode][base+0xc]; tmp = buffer[0x0d]; buffer[0xd] = message_table_index(base+0xd)[buffer[0x9]] ^ message_key[mode][base+0xd]; buffer[0x9] = message_table_index(base+0x9)[buffer[0x5]] ^ message_key[mode][base+0x9]; buffer[0x5] = message_table_index(base+0x5)[buffer[0x1]] ^ message_key[mode][base+0x5]; buffer[0x1] = message_table_index(base+0x1)[tmp] ^ message_key[mode][base+0x1]; tmp = buffer[0x02]; buffer[0x2] = message_table_index(base+0x2)[buffer[0xa]] ^ message_key[mode][base+0x2]; buffer[0xa] = message_table_index(base+0xa)[tmp] ^ message_key[mode][base+0xa]; tmp = buffer[0x06]; buffer[0x6] = message_table_index(base+0x6)[buffer[0xe]] ^ message_key[mode][base+0x6]; buffer[0xe] = message_table_index(base+0xe)[tmp] ^ message_key[mode][base+0xe]; tmp = buffer[0x3]; buffer[0x3] = message_table_index(base+0x3)[buffer[0x7]] ^ message_key[mode][base+0x3]; buffer[0x7] = message_table_index(base+0x7)[buffer[0xb]] ^ message_key[mode][base+0x7]; buffer[0xb] = message_table_index(base+0xb)[buffer[0xf]] ^ message_key[mode][base+0xb]; buffer[0xf] = message_table_index(base+0xf)[tmp] ^ message_key[mode][base+0xf]; // Now we must replace the entire buffer with 4 words that we read and xor together uint32_t word; uint32_t* block = (uint32_t*)buffer; block[0] = table_s9[0x000 + buffer[0x0]] ^ table_s9[0x100 + buffer[0x1]] ^ table_s9[0x200 + buffer[0x2]] ^ table_s9[0x300 + buffer[0x3]]; block[1] = table_s9[0x000 + buffer[0x4]] ^ table_s9[0x100 + buffer[0x5]] ^ table_s9[0x200 + buffer[0x6]] ^ table_s9[0x300 + buffer[0x7]]; block[2] = table_s9[0x000 + buffer[0x8]] ^ table_s9[0x100 + buffer[0x9]] ^ table_s9[0x200 + buffer[0xa]] ^ table_s9[0x300 + buffer[0xb]]; block[3] = table_s9[0x000 + buffer[0xc]] ^ table_s9[0x100 + buffer[0xd]] ^ table_s9[0x200 + buffer[0xe]] ^ table_s9[0x300 + buffer[0xf]]; } // Next, another permute with a different table buffer[0x0] = table_s10[(0x0 << 8) + buffer[0x0]]; buffer[0x4] = table_s10[(0x4 << 8) + buffer[0x4]]; buffer[0x8] = table_s10[(0x8 << 8) + buffer[0x8]]; buffer[0xc] = table_s10[(0xc << 8) + buffer[0xc]]; tmp = buffer[0x0d]; buffer[0xd] = table_s10[(0xd << 8) + buffer[0x9]]; buffer[0x9] = table_s10[(0x9 << 8) + buffer[0x5]]; buffer[0x5] = table_s10[(0x5 << 8) + buffer[0x1]]; buffer[0x1] = table_s10[(0x1 << 8) + tmp]; tmp = buffer[0x02]; buffer[0x2] = table_s10[(0x2 << 8) + buffer[0xa]]; buffer[0xa] = table_s10[(0xa << 8) + tmp]; tmp = buffer[0x06]; buffer[0x6] = table_s10[(0x6 << 8) + buffer[0xe]]; buffer[0xe] = table_s10[(0xe << 8) + tmp]; tmp = buffer[0x3]; buffer[0x3] = table_s10[(0x3 << 8) + buffer[0x7]]; buffer[0x7] = table_s10[(0x7 << 8) + buffer[0xb]]; buffer[0xb] = table_s10[(0xb << 8) + buffer[0xf]]; buffer[0xf] = table_s10[(0xf << 8) + tmp]; // And finally xor with the previous block of the message, except in mode-2 where we do this in reverse if (mode == 2 || mode == 1 || mode == 0) { if (i > 0) { xor_blocks(buffer, &messageIn[0x10*i], &decryptedMessage[0x10*i]); // remember that the first 0x10 bytes are the header } else xor_blocks(buffer, message_iv[mode], &decryptedMessage[0x10*i]); print_block(" ", &decryptedMessage[0x10*i]); } else { if (i < 7) xor_blocks(buffer, &messageIn[0x70 - 0x10*i], &decryptedMessage[0x70 - 0x10*i]); else xor_blocks(buffer, message_iv[mode], &decryptedMessage[0x70 - 0x10*i]); printf("Decrypted message block %02X-%02X:", 0x70 - 0x10*i, 0x70 - 0x10*i+0xf); print_block(" ", &decryptedMessage[0x70 - 0x10*i]); } } }