This commit is contained in:
iceman1001 2025-01-14 18:20:55 +01:00
commit c32ef83812

View file

@ -55,41 +55,41 @@ typedef struct {
keyset_t keys[] = { keyset_t keys[] = {
{ {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Nonce { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Nonce
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // privEncKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // privEncKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // privMacKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // privMacKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // readKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // readKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // writeKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // writeKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } // adminKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // adminKey
}, },
{ {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Nonce { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Nonce
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // privEncKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // privEncKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // privMacKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // privMacKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // readKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // readKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // writeKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // writeKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } // adminKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // adminKey
}, },
{ {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Nonce { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Nonce
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // privEncKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // privEncKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // privMacKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // privMacKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // readKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // readKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // writeKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // writeKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } // adminKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // adminKey
}, },
{ {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Nonce { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Nonce
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // privEncKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // privEncKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // privMacKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // privMacKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // readKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // readKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // writeKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // writeKey
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } // adminKey { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // adminKey
}, },
}; };
typedef struct { typedef struct {
const int value; const int value;
const char* name; const char *name;
} known_algo_t; } known_algo_t;
static const known_algo_t known_algorithm_map[] = { static const known_algo_t known_algorithm_map[] = {
@ -111,18 +111,17 @@ static const sioMediaTypeName_t sioMediaTypeMapping[] = {
{ 0xFF, "INVALID VALUE"} { 0xFF, "INVALID VALUE"}
}; };
static int create_cmac (uint8_t* key, uint8_t* input, uint8_t* out, int input_len, int encryption_algorithm) { static int create_cmac(uint8_t *key, uint8_t *input, uint8_t *out, int input_len, int encryption_algorithm) {
uint8_t iv[16] = {0x00}; uint8_t iv[16] = {0x00};
if (encryption_algorithm == 0x09) { if (encryption_algorithm == 0x09) {
// Working as expected // Working as expected
aes_cmac(iv, key, input, out, input_len); aes_cmac(iv, key, input, out, input_len);
} } else if (encryption_algorithm == 0x02) {
else if (encryption_algorithm == 0x02) {
// CMAC Requires a 24 byte key, but the 2k3DES uses the 1st part for the 3rd part of the key // CMAC Requires a 24 byte key, but the 2k3DES uses the 1st part for the 3rd part of the key
memcpy(&key[16], &key[0], 8); memcpy(&key[16], &key[0], 8);
const mbedtls_cipher_info_t* ctx; const mbedtls_cipher_info_t *ctx;
ctx = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_EDE3_ECB); ctx = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_EDE3_ECB);
mbedtls_cipher_cmac(ctx, key, 192, input, input_len, out); mbedtls_cipher_cmac(ctx, key, 192, input, input_len, out);
} else { } else {
@ -132,7 +131,7 @@ static int create_cmac (uint8_t* key, uint8_t* input, uint8_t* out, int input_le
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int create_cryptogram (uint8_t* key, uint8_t* input, uint8_t* out, int input_len, int encryption_algorithm) { static int create_cryptogram(uint8_t *key, uint8_t *input, uint8_t *out, int input_len, int encryption_algorithm) {
uint8_t iv[16] = {}; uint8_t iv[16] = {};
if (encryption_algorithm == 0x09) { if (encryption_algorithm == 0x09) {
@ -150,7 +149,7 @@ static int create_cryptogram (uint8_t* key, uint8_t* input, uint8_t* out, int in
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int decrypt_cryptogram (uint8_t* key, uint8_t* input, uint8_t* out, int input_len, int encryption_algorithm) { static int decrypt_cryptogram(uint8_t *key, uint8_t *input, uint8_t *out, int input_len, int encryption_algorithm) {
uint8_t iv[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t iv[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (encryption_algorithm == 0x09) { if (encryption_algorithm == 0x09) {
@ -168,34 +167,32 @@ static int decrypt_cryptogram (uint8_t* key, uint8_t* input, uint8_t* out, int i
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static void increment_command_wrapper(uint8_t* input, int input_len) { static void increment_command_wrapper(uint8_t *input, int input_len) {
input[input_len-1]++; // Increment the last element of the header by 1 input[input_len - 1]++; // Increment the last element of the header by 1
} }
static void padToBlockSize(const uint8_t* input, int inputSize, int blockSize, uint8_t* output) { static void padToBlockSize(const uint8_t *input, int inputSize, int blockSize, uint8_t *output) {
int paddingSize = blockSize - (inputSize % blockSize); int paddingSize = blockSize - (inputSize % blockSize);
memcpy(output, input, inputSize); memcpy(output, input, inputSize);
memset(output + inputSize, 0x80, 1); memset(output + inputSize, 0x80, 1);
memset(output + inputSize + 1, 0x00, paddingSize - 1); memset(output + inputSize + 1, 0x00, paddingSize - 1);
} }
static void generate_command_wrapping(uint8_t *command_Header, int command_header_len, uint8_t *unencrypted_Command, int unencrypted_command_len ,uint8_t *rndICC, uint8_t *rndIFD, uint8_t *diversified_enc_key, uint8_t *diversified_mac_key, int encryption_algorithm, uint8_t *command, int *command_len) { static void generate_command_wrapping(uint8_t *command_Header, int command_header_len, uint8_t *unencrypted_Command, int unencrypted_command_len, uint8_t *rndICC, uint8_t *rndIFD, uint8_t *diversified_enc_key, uint8_t *diversified_mac_key, int encryption_algorithm, uint8_t *command, int *command_len) {
int block_size = 0; int block_size = 0;
if (encryption_algorithm == 0x02) { if (encryption_algorithm == 0x02) {
block_size = 8; block_size = 8;
} } else if (encryption_algorithm == 0x09) {
else if (encryption_algorithm == 0x09) {
block_size = 16; block_size = 16;
} } else {
else {
PrintAndLogEx(ERR, _RED_("Unknown Encryption Algorithm")); PrintAndLogEx(ERR, _RED_("Unknown Encryption Algorithm"));
return; return;
} }
uint8_t rndCounter[block_size]; uint8_t rndCounter[block_size];
memcpy (rndCounter, rndICC, block_size / 2); memcpy(rndCounter, rndICC, block_size / 2);
memcpy (rndCounter + block_size / 2, rndIFD, block_size/2); memcpy(rndCounter + block_size / 2, rndIFD, block_size / 2);
increment_command_wrapper(rndCounter, block_size); increment_command_wrapper(rndCounter, block_size);
// Command Header is for the APDU Command to be sent // Command Header is for the APDU Command to be sent
@ -209,9 +206,9 @@ static void generate_command_wrapping(uint8_t *command_Header, int command_heade
uint8_t padded_encrypted_Command[block_size]; uint8_t padded_encrypted_Command[block_size];
create_cryptogram(diversified_enc_key, padded_unencrypted_Command, padded_encrypted_Command, sizeof(padded_unencrypted_Command), encryption_algorithm); create_cryptogram(diversified_enc_key, padded_unencrypted_Command, padded_encrypted_Command, sizeof(padded_unencrypted_Command), encryption_algorithm);
uint8_t asn1_tag_cryptograph[2] = {0x85,ARRAYLEN(padded_encrypted_Command)}; uint8_t asn1_tag_cryptograph[2] = {0x85, ARRAYLEN(padded_encrypted_Command)};
uint8_t asn1_tag_mac[2] = {0x8e,0x08}; uint8_t asn1_tag_mac[2] = {0x8e, 0x08};
uint8_t command_trailer[2] = {0x97,0x00}; uint8_t command_trailer[2] = {0x97, 0x00};
uint8_t padded_command_trailer[block_size - ARRAYLEN(command_trailer)]; uint8_t padded_command_trailer[block_size - ARRAYLEN(command_trailer)];
padToBlockSize(command_trailer, sizeof(command_trailer), block_size, padded_command_trailer); padToBlockSize(command_trailer, sizeof(command_trailer), block_size, padded_command_trailer);
@ -236,10 +233,10 @@ static void generate_command_wrapping(uint8_t *command_Header, int command_heade
// PrintAndLogEx(SUCCESS, "toEncrypt........................ " _YELLOW_("%s"), sprint_hex_inrow(toEncrypt,sizeof(toEncrypt))); // PrintAndLogEx(SUCCESS, "toEncrypt........................ " _YELLOW_("%s"), sprint_hex_inrow(toEncrypt,sizeof(toEncrypt)));
// PrintAndLogEx(SUCCESS, "MAC.............................. " _YELLOW_("%s"), sprint_hex_inrow(mac,sizeof(mac))); // PrintAndLogEx(SUCCESS, "MAC.............................. " _YELLOW_("%s"), sprint_hex_inrow(mac,sizeof(mac)));
uint8_t sizeofcommand[1] = {ARRAYLEN(asn1_tag_cryptograph) + ARRAYLEN(padded_encrypted_Command) + ARRAYLEN(command_trailer) + ARRAYLEN(asn1_tag_mac)+ ARRAYLEN(mac)}; uint8_t sizeofcommand[1] = {ARRAYLEN(asn1_tag_cryptograph) + ARRAYLEN(padded_encrypted_Command) + ARRAYLEN(command_trailer) + ARRAYLEN(asn1_tag_mac) + ARRAYLEN(mac)};
uint8_t respondTo[1] = {0x00}; uint8_t respondTo[1] = {0x00};
uint8_t completedCommand[command_header_len + 1 + ARRAYLEN(asn1_tag_cryptograph) + ARRAYLEN(padded_encrypted_Command) + ARRAYLEN(command_trailer) + ARRAYLEN(asn1_tag_mac)+ ARRAYLEN(mac) + 1]; uint8_t completedCommand[command_header_len + 1 + ARRAYLEN(asn1_tag_cryptograph) + ARRAYLEN(padded_encrypted_Command) + ARRAYLEN(command_trailer) + ARRAYLEN(asn1_tag_mac) + ARRAYLEN(mac) + 1];
memcpy(completedCommand, command_Header, command_header_len); memcpy(completedCommand, command_Header, command_header_len);
memcpy(completedCommand + command_header_len, sizeofcommand, ARRAYLEN(sizeofcommand)); memcpy(completedCommand + command_header_len, sizeofcommand, ARRAYLEN(sizeofcommand));
memcpy(completedCommand + command_header_len + ARRAYLEN(sizeofcommand), asn1_tag_cryptograph, ARRAYLEN(asn1_tag_cryptograph)); memcpy(completedCommand + command_header_len + ARRAYLEN(sizeofcommand), asn1_tag_cryptograph, ARRAYLEN(asn1_tag_cryptograph));
@ -259,7 +256,7 @@ static void generate_command_wrapping(uint8_t *command_Header, int command_heade
//return; //return;
} }
static int seos_get_data(uint8_t *rndICC, uint8_t *rndIFD, uint8_t *diversified_enc_key, uint8_t *diversified_mac_key, uint8_t *sioOutput, int* sio_size, int encryption_algorithm, uint8_t* get_data_tlv, int get_data_tlv_len) { static int seos_get_data(uint8_t *rndICC, uint8_t *rndIFD, uint8_t *diversified_enc_key, uint8_t *diversified_mac_key, uint8_t *sioOutput, int *sio_size, int encryption_algorithm, uint8_t *get_data_tlv, int get_data_tlv_len) {
// Intergrating our command generation with the GetData request to make my life easier in the future // Intergrating our command generation with the GetData request to make my life easier in the future
// Command Header is for the Get Data Command using // Command Header is for the Get Data Command using
@ -338,7 +335,7 @@ static int seos_get_data(uint8_t *rndICC, uint8_t *rndIFD, uint8_t *diversified_
uint8_t cryptogram[64]; uint8_t cryptogram[64];
uint8_t responseCode[2]; uint8_t responseCode[2];
uint8_t tag[2] = {0x00,0x00}; uint8_t tag[2] = {0x00, 0x00};
int getDataSize = 0; int getDataSize = 0;
// ------------------- Cryptogram Response ------------------- // ------------------- Cryptogram Response -------------------
@ -368,8 +365,7 @@ static int seos_get_data(uint8_t *rndICC, uint8_t *rndIFD, uint8_t *diversified_
PrintAndLogEx(SUCCESS, "Response Code.................... " _YELLOW_("%s"), sprint_hex_inrow(responseCode, (ARRAYLEN(responseCode)))); PrintAndLogEx(SUCCESS, "Response Code.................... " _YELLOW_("%s"), sprint_hex_inrow(responseCode, (ARRAYLEN(responseCode))));
PrintAndLogEx(SUCCESS, "Output........................... " _YELLOW_("%s"), sprint_hex_inrow(sioOutput, getDataSize)); PrintAndLogEx(SUCCESS, "Output........................... " _YELLOW_("%s"), sprint_hex_inrow(sioOutput, getDataSize));
} } else if (resplen >= 2 && response[0] == 0x99) {
else if (resplen >= 2 && response[0] == 0x99) {
memcpy(responseCode, response + 2, 2); memcpy(responseCode, response + 2, 2);
// PrintAndLogEx(SUCCESS, "Raw Response..................... " _YELLOW_("%s"), sprint_hex_inrow(response, (resplen - 2))); // PrintAndLogEx(SUCCESS, "Raw Response..................... " _YELLOW_("%s"), sprint_hex_inrow(response, (resplen - 2)));
PrintAndLogEx(SUCCESS, "Response Code.................... " _YELLOW_("%s"), sprint_hex_inrow(responseCode, (ARRAYLEN(responseCode)))); PrintAndLogEx(SUCCESS, "Response Code.................... " _YELLOW_("%s"), sprint_hex_inrow(responseCode, (ARRAYLEN(responseCode))));
@ -385,7 +381,7 @@ static void set_counter_big_endian(uint8_t *buffer, uint32_t counter) {
buffer[3] = counter & 0xFF; buffer[3] = counter & 0xFF;
} }
static void create_mutual_auth_key(uint8_t* KEYIFD, uint8_t* KEYICC, uint8_t* RNDICC, uint8_t* RNDIFD, uint8_t* EncryptionKey, uint8_t* MACKey, int encryptionAlgorithm ,int HashingAlgorithm) { static void create_mutual_auth_key(uint8_t *KEYIFD, uint8_t *KEYICC, uint8_t *RNDICC, uint8_t *RNDIFD, uint8_t *EncryptionKey, uint8_t *MACKey, int encryptionAlgorithm, int HashingAlgorithm) {
// Creating Mutual Authentication Keys // Creating Mutual Authentication Keys
// Structure // Structure
// Prefix = 00000000 // Prefix = 00000000
@ -398,8 +394,8 @@ static void create_mutual_auth_key(uint8_t* KEYIFD, uint8_t* KEYICC, uint8_t* RN
// //
// 00000000 E0EC1F2D7B000000 F0EC1F2D7B000000 09 09 B0EC1F2D7B000000B8EC1F2D7B000000 // 00000000 E0EC1F2D7B000000 F0EC1F2D7B000000 09 09 B0EC1F2D7B000000B8EC1F2D7B000000
uint8_t prefix[4] = {0x00,0x00,0x00,0x00}; uint8_t prefix[4] = {0x00, 0x00, 0x00, 0x00};
uint8_t aHashingAlgorithm[2] = {encryptionAlgorithm,encryptionAlgorithm}; uint8_t aHashingAlgorithm[2] = {encryptionAlgorithm, encryptionAlgorithm};
uint8_t hash_in[38]; uint8_t hash_in[38];
memcpy(hash_in, prefix, 4); memcpy(hash_in, prefix, 4);
@ -435,12 +431,10 @@ static void create_mutual_auth_key(uint8_t* KEYIFD, uint8_t* KEYICC, uint8_t* RN
sha1hash(hash_in, sizeof(hash_in), hashedOutput); sha1hash(hash_in, sizeof(hash_in), hashedOutput);
memcpy(output + 20, hashedOutput, 20); memcpy(output + 20, hashedOutput, 20);
//PrintAndLogEx(SUCCESS, "key_out_temp..................... " _YELLOW_("%s"), sprint_hex_inrow(hash_in,ARRAYLEN(hash_in))); //PrintAndLogEx(SUCCESS, "key_out_temp..................... " _YELLOW_("%s"), sprint_hex_inrow(hash_in,ARRAYLEN(hash_in)));
} } else if (HashingAlgorithm == 0x07) {
else if (HashingAlgorithm == 0x07) {
sha256hash(hash_in, sizeof(hash_in), hashedOutput); sha256hash(hash_in, sizeof(hash_in), hashedOutput);
memcpy(output, hashedOutput, 32); memcpy(output, hashedOutput, 32);
} } else {
else {
// Yes they generate their encryption keys and mac keys in a weird way for no fucking reason, the 2nd cycle isn't required. // Yes they generate their encryption keys and mac keys in a weird way for no fucking reason, the 2nd cycle isn't required.
PrintAndLogEx(ERR, _RED_("Unknown Hashing Algorithm")); PrintAndLogEx(ERR, _RED_("Unknown Hashing Algorithm"));
return; return;
@ -457,7 +451,7 @@ static void create_mutual_auth_key(uint8_t* KEYIFD, uint8_t* KEYICC, uint8_t* RN
// PrintAndLogEx(SUCCESS, "MAC Key.......................... " _YELLOW_("%s"), sprint_hex_inrow(MACKey, 16)); // PrintAndLogEx(SUCCESS, "MAC Key.......................... " _YELLOW_("%s"), sprint_hex_inrow(MACKey, 16));
} }
static int seos_challenge_get(uint8_t* RNDICC, uint8_t RNDICC_len) { static int seos_challenge_get(uint8_t *RNDICC, uint8_t RNDICC_len) {
uint8_t response[PM3_CMD_DATA_SIZE]; uint8_t response[PM3_CMD_DATA_SIZE];
int resplen = 0; int resplen = 0;
@ -500,7 +494,7 @@ static int seos_challenge_get(uint8_t* RNDICC, uint8_t RNDICC_len) {
// 7C 0A 81 08 18 1E 43 80 10 10 20 11 // 7C 0A 81 08 18 1E 43 80 10 10 20 11
// 81 is the ASN.1 tag // 81 is the ASN.1 tag
uint8_t staticResponse[8] = {0x01,0x81,0xE4,0x38,0x01,0x01,0x02,0x01}; uint8_t staticResponse[8] = {0x01, 0x81, 0xE4, 0x38, 0x01, 0x01, 0x02, 0x01};
PrintAndLogEx(INFO, "--- " _CYAN_("Get Challenge") " ---------------------------"); PrintAndLogEx(INFO, "--- " _CYAN_("Get Challenge") " ---------------------------");
//PrintAndLogEx(SUCCESS, "Challenge Input: " _YELLOW_("%s"), getChallengePre); //PrintAndLogEx(SUCCESS, "Challenge Input: " _YELLOW_("%s"), getChallengePre);
@ -513,8 +507,8 @@ static int seos_challenge_get(uint8_t* RNDICC, uint8_t RNDICC_len) {
return PM3_SUCCESS; return PM3_SUCCESS;
}; };
int seos_kdf(bool encryption, uint8_t* masterKey, uint8_t keyslot, int seos_kdf(bool encryption, uint8_t *masterKey, uint8_t keyslot,
uint8_t* adfOid, size_t adfoid_len, uint8_t* diversifier, uint8_t diversifier_len, uint8_t* out, int encryption_algorithm, int hash_algorithm) { uint8_t *adfOid, size_t adfoid_len, uint8_t *diversifier, uint8_t diversifier_len, uint8_t *out, int encryption_algorithm, int hash_algorithm) {
// Encryption key = 04 // Encryption key = 04
// KEK Encryption key = 05 // KEK Encryption key = 05
@ -557,7 +551,7 @@ int seos_kdf(bool encryption, uint8_t* masterKey, uint8_t keyslot,
return PM3_SUCCESS; return PM3_SUCCESS;
}; };
static int select_DF_verify(uint8_t* response, uint8_t response_length, uint8_t* MAC_value, size_t MAC_value_len, int encryption_algorithm, int key_index) { static int select_DF_verify(uint8_t *response, uint8_t response_length, uint8_t *MAC_value, size_t MAC_value_len, int encryption_algorithm, int key_index) {
uint8_t input[response_length - 10]; uint8_t input[response_length - 10];
// Response is an ASN.1 encoded structure // Response is an ASN.1 encoded structure
// Extract everything before the 8E tag // Extract everything before the 8E tag
@ -571,7 +565,7 @@ static int select_DF_verify(uint8_t* response, uint8_t response_length, uint8_t*
// ----------------- MAC Key Generation ----------------- // ----------------- MAC Key Generation -----------------
uint8_t cmac[8]; uint8_t cmac[8];
uint8_t MAC_key[24] = {0x00}; uint8_t MAC_key[24] = {0x00};
memcpy(MAC_key, keys[key_index].privMacKey, 16); memcpy(MAC_key, keys[key_index].privMacKey, 16);
create_cmac(MAC_key, input, cmac, sizeof(input), encryption_algorithm); create_cmac(MAC_key, input, cmac, sizeof(input), encryption_algorithm);
@ -592,7 +586,7 @@ static int select_DF_verify(uint8_t* response, uint8_t response_length, uint8_t*
return PM3_ESOFT; return PM3_ESOFT;
} }
static int select_df_decode(uint8_t* response, uint8_t response_length, int* ALGORITHM_INFO_value1, int* ALGORITHM_INFO_value2, uint8_t* CRYPTOGRAM_encrypted_data, uint8_t* MAC_value) { static int select_df_decode(uint8_t *response, uint8_t response_length, int *ALGORITHM_INFO_value1, int *ALGORITHM_INFO_value2, uint8_t *CRYPTOGRAM_encrypted_data, uint8_t *MAC_value) {
// Response is an ASN.1 encoded structure // Response is an ASN.1 encoded structure
// ASN.1 Information // ASN.1 Information
// CF = Diversifier // CF = Diversifier
@ -652,7 +646,7 @@ static int select_df_decode(uint8_t* response, uint8_t response_length, int* ALG
} }
} }
const char* algorithm_name1 = NULL; const char *algorithm_name1 = NULL;
for (int i = 0; i < ARRAYLEN(known_algorithm_map); i++) { for (int i = 0; i < ARRAYLEN(known_algorithm_map); i++) {
if ((known_algorithm_map[i].value) == ALGORITHM_INFO_value1_n) { if ((known_algorithm_map[i].value) == ALGORITHM_INFO_value1_n) {
algorithm_name1 = known_algorithm_map[i].name; algorithm_name1 = known_algorithm_map[i].name;
@ -660,7 +654,7 @@ static int select_df_decode(uint8_t* response, uint8_t response_length, int* ALG
} }
} }
const char* algorithm_name2 = NULL; const char *algorithm_name2 = NULL;
for (int i = 0; i < ARRAYLEN(known_algorithm_map); i++) { for (int i = 0; i < ARRAYLEN(known_algorithm_map); i++) {
if (known_algorithm_map[i].value == ALGORITHM_INFO_value2_n) { if (known_algorithm_map[i].value == ALGORITHM_INFO_value2_n) {
algorithm_name2 = known_algorithm_map[i].name; algorithm_name2 = known_algorithm_map[i].name;
@ -676,7 +670,7 @@ static int select_df_decode(uint8_t* response, uint8_t response_length, int* ALG
} }
if (algorithm_name2 != NULL) { if (algorithm_name2 != NULL) {
PrintAndLogEx(SUCCESS, "algoIdHash (MAC)................. "_YELLOW_("%i (%s)"),ALGORITHM_INFO_value2_n, algorithm_name2); PrintAndLogEx(SUCCESS, "algoIdHash (MAC)................. "_YELLOW_("%i (%s)"), ALGORITHM_INFO_value2_n, algorithm_name2);
} else { } else {
PrintAndLogEx(ERR, "algoIdHash (MAC)............... %d (Unknown)", ALGORITHM_INFO_value2_n); PrintAndLogEx(ERR, "algoIdHash (MAC)............... %d (Unknown)", ALGORITHM_INFO_value2_n);
} }
@ -688,7 +682,7 @@ static int select_df_decode(uint8_t* response, uint8_t response_length, int* ALG
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int select_ADF_decrypt(const char* selectADFOID, uint8_t* CRYPTOGRAM_encrypted_data_raw, uint8_t* CRYPTOGRAM_Diversifier, int encryption_algorithm, int key_index) { static int select_ADF_decrypt(const char *selectADFOID, uint8_t *CRYPTOGRAM_encrypted_data_raw, uint8_t *CRYPTOGRAM_Diversifier, int encryption_algorithm, int key_index) {
// --------------- Decrypt ---------------- // --------------- Decrypt ----------------
// 1. MAC Verify - AES/CBC-decrypt (IV || cryptogram || 16 bytes after 8e 08) with the MAC key & keep the last block // 1. MAC Verify - AES/CBC-decrypt (IV || cryptogram || 16 bytes after 8e 08) with the MAC key & keep the last block
@ -724,15 +718,15 @@ static int select_ADF_decrypt(const char* selectADFOID, uint8_t* CRYPTOGRAM_encr
adf_length = ((CRYPTOGRAM_decrypted_data[i + 1])); adf_length = ((CRYPTOGRAM_decrypted_data[i + 1]));
diversifier_length = CRYPTOGRAM_decrypted_data[i + adf_length + 3]; diversifier_length = CRYPTOGRAM_decrypted_data[i + adf_length + 3];
uint8_t CRYPTOGRAM_ADF[strlen(selectADFOID)/2]; uint8_t CRYPTOGRAM_ADF[strlen(selectADFOID) / 2];
memcpy(CRYPTOGRAM_ADF, &CRYPTOGRAM_decrypted_data[i], strlen(selectADFOID)/2); memcpy(CRYPTOGRAM_ADF, &CRYPTOGRAM_decrypted_data[i], strlen(selectADFOID) / 2);
memcpy(CRYPTOGRAM_Diversifier, &CRYPTOGRAM_decrypted_data[i + adf_length + 4], diversifier_length); memcpy(CRYPTOGRAM_Diversifier, &CRYPTOGRAM_decrypted_data[i + adf_length + 4], diversifier_length);
const char* CRYPTOGRAM_ADF_CMP = (sprint_hex_inrow(CRYPTOGRAM_ADF,ARRAYLEN(CRYPTOGRAM_ADF))); const char *CRYPTOGRAM_ADF_CMP = (sprint_hex_inrow(CRYPTOGRAM_ADF, ARRAYLEN(CRYPTOGRAM_ADF)));
char* CRYPTOGRAM_ADF_UPPER = strdup(CRYPTOGRAM_ADF_CMP); char *CRYPTOGRAM_ADF_UPPER = strdup(CRYPTOGRAM_ADF_CMP);
char* selectADFOID_UPPER = strdup(selectADFOID); char *selectADFOID_UPPER = strdup(selectADFOID);
// Convert both strings to uppercase // Convert both strings to uppercase
for (int x = 0; CRYPTOGRAM_ADF_UPPER[x]; x++) { for (int x = 0; CRYPTOGRAM_ADF_UPPER[x]; x++) {
@ -763,7 +757,7 @@ static int select_ADF_decrypt(const char* selectADFOID, uint8_t* CRYPTOGRAM_encr
return PM3_SUCCESS; return PM3_SUCCESS;
}; };
static int seos_mutual_auth(uint8_t* randomICC, uint8_t* CRYPTOGRAM_Diversifier, uint8_t diversifier_len, uint8_t* mutual_auth_randomIFD, uint8_t* mutual_auth_keyICC, uint8_t* randomIFD, uint8_t randomIFD_len, uint8_t* keyIFD, uint8_t keyIFD_len, int encryption_algorithm, int hash_algorithm, int key_index) { static int seos_mutual_auth(uint8_t *randomICC, uint8_t *CRYPTOGRAM_Diversifier, uint8_t diversifier_len, uint8_t *mutual_auth_randomIFD, uint8_t *mutual_auth_keyICC, uint8_t *randomIFD, uint8_t randomIFD_len, uint8_t *keyIFD, uint8_t keyIFD_len, int encryption_algorithm, int hash_algorithm, int key_index) {
uint8_t response[PM3_CMD_DATA_SIZE]; uint8_t response[PM3_CMD_DATA_SIZE];
// ---------------- Diversify Keys ---------------- // ---------------- Diversify Keys ----------------
@ -773,10 +767,10 @@ static int seos_mutual_auth(uint8_t* randomICC, uint8_t* CRYPTOGRAM_Diversifier,
uint8_t keyslot = 0x01; // up to 0x0F uint8_t keyslot = 0x01; // up to 0x0F
uint8_t AES_key[24] = {0x00}; uint8_t AES_key[24] = {0x00};
uint8_t MAC_key[24] = {0x00}; uint8_t MAC_key[24] = {0x00};
uint8_t adfOID[17] = {0x2b,0x06,0x01,0x04,0x01,0x81,0xe4,0x38,0x01,0x01,0x02,0x01,0x18,0x01,0x01,0x02,0x02}; uint8_t adfOID[17] = {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0xe4, 0x38, 0x01, 0x01, 0x02, 0x01, 0x18, 0x01, 0x01, 0x02, 0x02};
// Null AES IV // Null AES IV
uint8_t nullDiversifier[7] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t nullDiversifier[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (memcmp(CRYPTOGRAM_Diversifier, nullDiversifier, sizeof(nullDiversifier)) == 0) { if (memcmp(CRYPTOGRAM_Diversifier, nullDiversifier, sizeof(nullDiversifier)) == 0) {
PrintAndLogEx(ERR, "No Diversifier found"); PrintAndLogEx(ERR, "No Diversifier found");
@ -824,22 +818,22 @@ static int seos_mutual_auth(uint8_t* randomICC, uint8_t* CRYPTOGRAM_Diversifier,
// ----------------- Command Generation ----------------- // ----------------- Command Generation -----------------
const char* prefixLenHex = "2c"; const char *prefixLenHex = "2c";
const char* ASN1_tagAboveLenHex = "2a"; const char *ASN1_tagAboveLenHex = "2a";
const char* ASN1_auth_encryptedLenHex = "28"; const char *ASN1_auth_encryptedLenHex = "28";
const char* mutual_auth_message = sprint_hex_inrow(message_authenticated, sizeof(message_authenticated)); const char *mutual_auth_message = sprint_hex_inrow(message_authenticated, sizeof(message_authenticated));
char keyslot_str[3]; char keyslot_str[3];
snprintf(keyslot_str, sizeof(keyslot_str), "%02X", keyslot); snprintf(keyslot_str, sizeof(keyslot_str), "%02X", keyslot);
const char* prefix = "008700"; const char *prefix = "008700";
const char* ASN1_tagAbove = "7c"; const char *ASN1_tagAbove = "7c";
const char* ASN1_auth_encrypted = "82"; const char *ASN1_auth_encrypted = "82";
const char* suffix = "00"; const char *suffix = "00";
char mutual_auth[102]; char mutual_auth[102];
snprintf(mutual_auth, sizeof(mutual_auth), "%s%s%s%s%s%s%s%s%s", prefix, keyslot_str, prefixLenHex, ASN1_tagAbove, ASN1_tagAboveLenHex,ASN1_auth_encrypted, ASN1_auth_encryptedLenHex, mutual_auth_message, suffix); snprintf(mutual_auth, sizeof(mutual_auth), "%s%s%s%s%s%s%s%s%s", prefix, keyslot_str, prefixLenHex, ASN1_tagAbove, ASN1_tagAboveLenHex, ASN1_auth_encrypted, ASN1_auth_encryptedLenHex, mutual_auth_message, suffix);
// PrintAndLogEx(SUCCESS, "Mutual Auth Encrypted Request.... " _YELLOW_("%s"), mutual_auth); // PrintAndLogEx(SUCCESS, "Mutual Auth Encrypted Request.... " _YELLOW_("%s"), mutual_auth);
// BLOCKS MUTUAL AUTH BEFORE REQUIRED // BLOCKS MUTUAL AUTH BEFORE REQUIRED
@ -886,7 +880,7 @@ static int seos_mutual_auth(uint8_t* randomICC, uint8_t* CRYPTOGRAM_Diversifier,
uint8_t mutual_auth_response_decrypted[32]; uint8_t mutual_auth_response_decrypted[32];
if (encryption_algorithm == 0x09) { if (encryption_algorithm == 0x09) {
aes_decode(iv, AES_key, mutual_auth_response, mutual_auth_response_decrypted, sizeof(mutual_auth_response)); aes_decode(iv, AES_key, mutual_auth_response, mutual_auth_response_decrypted, sizeof(mutual_auth_response));
} else if (encryption_algorithm == 0x02) { } else if (encryption_algorithm == 0x02) {
mbedtls_des3_context ctx3; mbedtls_des3_context ctx3;
mbedtls_des3_set2key_dec(&ctx3, AES_key); mbedtls_des3_set2key_dec(&ctx3, AES_key);
@ -928,8 +922,8 @@ static int seos_aid_select(void) {
// --------------- Select AID for SEOS Card ---------------- // --------------- Select AID for SEOS Card ----------------
typedef struct { typedef struct {
const char* name; const char *name;
const char* value; const char *value;
} seos_aid_t; } seos_aid_t;
static const seos_aid_t known_AID_map[] = { static const seos_aid_t known_AID_map[] = {
@ -942,16 +936,16 @@ static int seos_aid_select(void) {
//PrintAndLogEx(INFO, "--- " _CYAN_("AID Selection") " ---------------------------"); //PrintAndLogEx(INFO, "--- " _CYAN_("AID Selection") " ---------------------------");
for (i = 0; i < ARRAYLEN(known_AID_map); i++) { for (i = 0; i < ARRAYLEN(known_AID_map); i++) {
const char* selectedAID = known_AID_map[i].value; const char *selectedAID = known_AID_map[i].value;
// Select command prefixed with a 00 // Select command prefixed with a 00
const char* prefix = "00A404"; const char *prefix = "00A404";
uint16_t aidlen = strlen(selectedAID) >> 1; uint16_t aidlen = strlen(selectedAID) >> 1;
char aidlenHex[5]; char aidlenHex[5];
snprintf(aidlenHex, sizeof(aidlenHex), "%04X", aidlen); snprintf(aidlenHex, sizeof(aidlenHex), "%04X", aidlen);
const char* suffix = "0"; const char *suffix = "0";
char combinedString[100]; char combinedString[100];
snprintf(combinedString, sizeof(combinedString), "%s%s%s%s", prefix, aidlenHex, selectedAID, suffix); snprintf(combinedString, sizeof(combinedString), "%s%s%s%s", prefix, aidlenHex, selectedAID, suffix);
@ -987,7 +981,7 @@ static int seos_aid_select(void) {
return res; return res;
}; };
static int seos_pacs_adf_select(char* oid, int oid_len, uint8_t* get_data, int get_data_len, int key_index) { static int seos_pacs_adf_select(char *oid, int oid_len, uint8_t *get_data, int get_data_len, int key_index) {
int resplen = 0; int resplen = 0;
uint8_t response[PM3_CMD_DATA_SIZE]; uint8_t response[PM3_CMD_DATA_SIZE];
bool activate_field = false; bool activate_field = false;
@ -1001,22 +995,22 @@ static int seos_pacs_adf_select(char* oid, int oid_len, uint8_t* get_data, int g
// 2b0601040181e438010102011801010202 = ADF-OID // 2b0601040181e438010102011801010202 = ADF-OID
// --------------- OID Selection ---------------- // --------------- OID Selection ----------------
const char* ADFprefix = "06"; const char *ADFprefix = "06";
char selectedOID[100]; char selectedOID[100];
snprintf(selectedOID, sizeof(selectedOID), "%s", oid); snprintf(selectedOID, sizeof(selectedOID), "%s", oid);
uint16_t selectedOIDLen = strlen(selectedOID); uint16_t selectedOIDLen = strlen(selectedOID);
char selectedOIDLenHex[3]; char selectedOIDLenHex[3];
snprintf(selectedOIDLenHex, sizeof(selectedOIDLenHex), "%02X", (selectedOIDLen)/2); snprintf(selectedOIDLenHex, sizeof(selectedOIDLenHex), "%02X", (selectedOIDLen) / 2);
char selectedADF[strlen(ADFprefix) + strlen(selectedOIDLenHex) + selectedOIDLen + 1]; char selectedADF[strlen(ADFprefix) + strlen(selectedOIDLenHex) + selectedOIDLen + 1];
snprintf(selectedADF, sizeof(selectedADF), "%s%s%s", ADFprefix, selectedOIDLenHex, selectedOID); snprintf(selectedADF, sizeof(selectedADF), "%s%s%s", ADFprefix, selectedOIDLenHex, selectedOID);
// --------------- Command Builder Selection ---------------- // --------------- Command Builder Selection ----------------
// prefix is the APDU command we are sending // prefix is the APDU command we are sending
const char* prefix = "80A504"; const char *prefix = "80A504";
const char* suffix = "00"; const char *suffix = "00";
const char* keyReference = "00"; const char *keyReference = "00";
uint16_t selectedADFLen = strlen(selectedADF); uint16_t selectedADFLen = strlen(selectedADF);
@ -1058,11 +1052,11 @@ static int seos_pacs_adf_select(char* oid, int oid_len, uint8_t* get_data, int g
uint8_t CRYPTOGRAM_encrypted_data[64]; // Encrypted Data uint8_t CRYPTOGRAM_encrypted_data[64]; // Encrypted Data
uint8_t MAC_value[8] = {0}; // MAC Value uint8_t MAC_value[8] = {0}; // MAC Value
uint8_t diversifier[7] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t diversifier[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t RNDICC[8] = {0}; uint8_t RNDICC[8] = {0};
uint8_t KeyICC[16] = {0}; uint8_t KeyICC[16] = {0};
uint8_t RNDIFD[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t RNDIFD[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t KeyIFD[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t KeyIFD[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t Diversified_New_EncryptionKey[24] = {0}; uint8_t Diversified_New_EncryptionKey[24] = {0};
uint8_t Diversified_New_MACKey[24] = {0}; uint8_t Diversified_New_MACKey[24] = {0};
@ -1098,7 +1092,7 @@ static int seos_pacs_adf_select(char* oid, int oid_len, uint8_t* get_data, int g
PrintAndLogEx(INFO, "--- " _CYAN_("Key Data") " ---------------------------"); PrintAndLogEx(INFO, "--- " _CYAN_("Key Data") " ---------------------------");
PrintAndLogEx(SUCCESS, "SIO.............................. "_YELLOW_("%s"), sprint_hex_inrow(sioOutput, sizeof(sioOutput))); // SIO PrintAndLogEx(SUCCESS, "SIO.............................. "_YELLOW_("%s"), sprint_hex_inrow(sioOutput, sizeof(sioOutput))); // SIO
PrintAndLogEx(SUCCESS, "SIO Size......................... "_YELLOW_("%i"), sio_size); // SIO Size PrintAndLogEx(SUCCESS, "SIO Size......................... "_YELLOW_("%i"), sio_size); // SIO Size
PrintAndLogEx(SUCCESS, "Diversifier...................... "_YELLOW_("%s"), sprint_hex_inrow(diversifier,ARRAYLEN(diversifier))); // Diversifier PrintAndLogEx(SUCCESS, "Diversifier...................... "_YELLOW_("%s"), sprint_hex_inrow(diversifier, ARRAYLEN(diversifier))); // Diversifier
}; };
} else { } else {
@ -1109,29 +1103,29 @@ static int seos_pacs_adf_select(char* oid, int oid_len, uint8_t* get_data, int g
return PM3_SUCCESS; return PM3_SUCCESS;
}; };
static int seos_adf_select(char* oid, int oid_len, int key_index) { static int seos_adf_select(char *oid, int oid_len, int key_index) {
int resplen = 0; int resplen = 0;
uint8_t response[PM3_CMD_DATA_SIZE]; uint8_t response[PM3_CMD_DATA_SIZE];
bool activate_field = false; bool activate_field = false;
bool keep_field_on = true; bool keep_field_on = true;
// --------------- OID Selection ---------------- // --------------- OID Selection ----------------
const char* ADFprefix = "06"; const char *ADFprefix = "06";
char selectedOID[100]; char selectedOID[100];
snprintf(selectedOID, sizeof(selectedOID), "%s", oid); snprintf(selectedOID, sizeof(selectedOID), "%s", oid);
uint16_t selectedOIDLen = strlen(selectedOID); uint16_t selectedOIDLen = strlen(selectedOID);
char selectedOIDLenHex[3]; char selectedOIDLenHex[3];
snprintf(selectedOIDLenHex, sizeof(selectedOIDLenHex), "%02X", (selectedOIDLen)/2); snprintf(selectedOIDLenHex, sizeof(selectedOIDLenHex), "%02X", (selectedOIDLen) / 2);
char selectedADF[strlen(ADFprefix) + strlen(selectedOIDLenHex) + selectedOIDLen + 1]; char selectedADF[strlen(ADFprefix) + strlen(selectedOIDLenHex) + selectedOIDLen + 1];
snprintf(selectedADF, sizeof(selectedADF), "%s%s%s", ADFprefix, selectedOIDLenHex, selectedOID); snprintf(selectedADF, sizeof(selectedADF), "%s%s%s", ADFprefix, selectedOIDLenHex, selectedOID);
// --------------- Command Builder Selection ---------------- // --------------- Command Builder Selection ----------------
// prefix is the APDU command we are sending // prefix is the APDU command we are sending
const char* prefix = "80A504"; const char *prefix = "80A504";
const char* suffix = "00"; const char *suffix = "00";
const char* keyReference = "00"; const char *keyReference = "00";
uint16_t selectedADFLen = strlen(selectedADF); uint16_t selectedADFLen = strlen(selectedADF);
char adflenHex[3]; char adflenHex[3];
@ -1190,7 +1184,7 @@ static int seos_gdf_select(int key_index) {
// 00A5070600 // 00A5070600
// SelectGlobalDF = 00A50000 // SelectGlobalDF = 00A50000
const char* getGDF = "00A5070600"; const char *getGDF = "00A5070600";
uint8_t agetGDF[10]; uint8_t agetGDF[10];
int agetGDF_n = 0; int agetGDF_n = 0;
@ -1230,14 +1224,14 @@ static int seos_select(void) {
return res; return res;
} }
const char* oid = "2B0601040181E438010102011801010202"; const char *oid = "2B0601040181E438010102011801010202";
int oid_len = strlen(oid); int oid_len = strlen(oid);
res = seos_adf_select((char*)oid, oid_len, 0); res = seos_adf_select((char *)oid, oid_len, 0);
DropField(); DropField();
return res; return res;
} }
static int seos_pacs(char* oid, int oid_len, uint8_t* get_data, int get_data_len, int key_index) { static int seos_pacs(char *oid, int oid_len, uint8_t *get_data, int get_data_len, int key_index) {
int res = seos_aid_select(); int res = seos_aid_select();
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
DropField(); DropField();
@ -1271,8 +1265,7 @@ static int seos_print_keys(bool verbose) {
PrintAndLogEx(INFO, "Admin Key........................ " _YELLOW_("%s"), sprint_hex(keys[i].adminKey, 16)); PrintAndLogEx(INFO, "Admin Key........................ " _YELLOW_("%s"), sprint_hex(keys[i].adminKey, 16));
PrintAndLogEx(INFO, "----------------------------"); PrintAndLogEx(INFO, "----------------------------");
} }
} } else {
else {
PrintAndLogEx(INFO, "idx| key"); PrintAndLogEx(INFO, "idx| key");
PrintAndLogEx(INFO, "---+------------------------"); PrintAndLogEx(INFO, "---+------------------------");
for (uint8_t i = 0; i < ARRAYLEN(keys); i++) { for (uint8_t i = 0; i < ARRAYLEN(keys); i++) {
@ -1333,7 +1326,7 @@ static int CmdHfSeosInfo(const char *Cmd) {
"- Are static RND.ICC keys used (can detect SEOS default keyset)\n" "- Are static RND.ICC keys used (can detect SEOS default keyset)\n"
"- What encryption and hashing algorithm is use\n", "- What encryption and hashing algorithm is use\n",
"hf seos info" "hf seos info"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_param_end arg_param_end
@ -1351,7 +1344,7 @@ static int CmdHfSeosGDF(const char *Cmd) {
" - Key Index: 0\n", " - Key Index: 0\n",
"hf seos gdf" "hf seos gdf"
"hf seos gdf --ki 0" "hf seos gdf --ki 0"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_int0(NULL, "ki", "<dec>", "Specify key index to set key in memory"), arg_int0(NULL, "ki", "<dec>", "Specify key index to set key in memory"),
@ -1368,14 +1361,14 @@ static int CmdHfSeosGDF(const char *Cmd) {
static int CmdHfSeosPACS(const char *Cmd) { static int CmdHfSeosPACS(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf seos pacs", CLIParserInit(&ctx, "hf seos pacs",
"Make a GET DATA request to an ADF of a SEOS card\n\n" "Make a GET DATA request to an ADF of a SEOS card\n\n"
"By default:\n" "By default:\n"
" - ADF OID : 2B0601040181E438010102011801010202\n" " - ADF OID : 2B0601040181E438010102011801010202\n"
" - Key Index: 0\n", " - Key Index: 0\n",
"hf seos pacs\n" "hf seos pacs\n"
"hf seos pacs --ki 1\n" "hf seos pacs --ki 1\n"
"hf seos pacs -o 2B0601040181E438010102011801010202 --ki 0\n" "hf seos pacs -o 2B0601040181E438010102011801010202 --ki 0\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
@ -1386,10 +1379,10 @@ static int CmdHfSeosPACS(const char *Cmd) {
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
int get_data_len = 4; int get_data_len = 4;
uint8_t get_data[] = {0x5c,0x02,0xff,0x00}; uint8_t get_data[] = {0x5c, 0x02, 0xff, 0x00};
int oid_len = 0; int oid_len = 0;
uint8_t oid_hex[256] = {0x2B,0x06,0x01,0x04,0x01,0x81,0xE4,0x38,0x01,0x01,0x02,0x01,0x18,0x01,0x01,0x02}; uint8_t oid_hex[256] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0x81, 0xE4, 0x38, 0x01, 0x01, 0x02, 0x01, 0x18, 0x01, 0x01, 0x02};
CLIGetHexWithReturn(ctx, 1, oid_hex, &oid_len); CLIGetHexWithReturn(ctx, 1, oid_hex, &oid_len);
int key_index = arg_get_int_def(ctx, 2, 0); int key_index = arg_get_int_def(ctx, 2, 0);
@ -1408,31 +1401,31 @@ static int CmdHfSeosPACS(const char *Cmd) {
sprintf(oid_buffer + (i * 2), "%02X", oid_hex[i]); sprintf(oid_buffer + (i * 2), "%02X", oid_hex[i]);
} }
const char* oid = oid_buffer; const char *oid = oid_buffer;
if (oid_len == 0) { if (oid_len == 0) {
PrintAndLogEx(ERR, "OID value must be supplied"); PrintAndLogEx(ERR, "OID value must be supplied");
return PM3_ESOFT; return PM3_ESOFT;
} }
return seos_pacs((char*)oid, oid_len, get_data, get_data_len, key_index); return seos_pacs((char *)oid, oid_len, get_data, get_data_len, key_index);
} }
static int CmdHfSeosADF(const char *Cmd) { static int CmdHfSeosADF(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf seos adf", CLIParserInit(&ctx, "hf seos adf",
"Make a GET DATA request to an Application Data File (ADF) of a SEOS Tag\n" "Make a GET DATA request to an Application Data File (ADF) of a SEOS Tag\n"
"The ADF is meant to be read by an application\n" "The ADF is meant to be read by an application\n"
"You still need the valid authentication keys to read a card\n\n" "You still need the valid authentication keys to read a card\n\n"
"By default:\n" "By default:\n"
" - ADF OID : 2B0601040181E438010102011801010202\n" " - ADF OID : 2B0601040181E438010102011801010202\n"
" - Key Index: 0\n" " - Key Index: 0\n"
" - Tag List : 5c02ff00\n", " - Tag List : 5c02ff00\n",
"hf seos adf\n" "hf seos adf\n"
"hf seos adf -o 2B0601040181E438010102011801010202\n" "hf seos adf -o 2B0601040181E438010102011801010202\n"
"hf seos adf -o 2B0601040181E438010102011801010202 --ki 0\n" "hf seos adf -o 2B0601040181E438010102011801010202 --ki 0\n"
"hf seos adf -o 2B0601040181E438010102011801010202 -c 5c02ff41\n" "hf seos adf -o 2B0601040181E438010102011801010202 -c 5c02ff41\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
@ -1444,11 +1437,11 @@ static int CmdHfSeosADF(const char *Cmd) {
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
int get_data_len = 0; int get_data_len = 0;
uint8_t get_data[256] = {0x5c,0x02,0xff,0x00}; uint8_t get_data[256] = {0x5c, 0x02, 0xff, 0x00};
CLIGetHexWithReturn(ctx, 1, get_data, &get_data_len); CLIGetHexWithReturn(ctx, 1, get_data, &get_data_len);
int oid_len = 0; int oid_len = 0;
uint8_t oid_hex[256] = {0x2B,0x06,0x01,0x04,0x01,0x81,0xE4,0x38,0x01,0x01,0x02,0x01,0x18,0x01,0x01,0x02}; uint8_t oid_hex[256] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0x81, 0xE4, 0x38, 0x01, 0x01, 0x02, 0x01, 0x18, 0x01, 0x01, 0x02};
CLIGetHexWithReturn(ctx, 2, oid_hex, &oid_len); CLIGetHexWithReturn(ctx, 2, oid_hex, &oid_len);
int key_index = arg_get_int_def(ctx, 3, 0); int key_index = arg_get_int_def(ctx, 3, 0);
@ -1470,14 +1463,14 @@ static int CmdHfSeosADF(const char *Cmd) {
sprintf(oid_buffer + (i * 2), "%02X", oid_hex[i]); sprintf(oid_buffer + (i * 2), "%02X", oid_hex[i]);
} }
const char* oid = oid_buffer; const char *oid = oid_buffer;
if (oid_len == 0) { if (oid_len == 0) {
PrintAndLogEx(ERR, "OID value must be supplied"); PrintAndLogEx(ERR, "OID value must be supplied");
return PM3_ESOFT; return PM3_ESOFT;
} }
return seos_pacs((char*)oid, oid_len, get_data, get_data_len, key_index); return seos_pacs((char *)oid, oid_len, get_data, get_data_len, key_index);
} }
static int CmdHfSeosManageKeys(const char *Cmd) { static int CmdHfSeosManageKeys(const char *Cmd) {
@ -1489,7 +1482,7 @@ static int CmdHfSeosManageKeys(const char *Cmd) {
"hf seos managekeys --ki 0 --nonce 0102030405060708 -> Set nonce value at key index 0\n" "hf seos managekeys --ki 0 --nonce 0102030405060708 -> Set nonce value at key index 0\n"
"hf seos managekeys --load -f mykeys.bin -p -> load from file and prints keys\n" "hf seos managekeys --load -f mykeys.bin -p -> load from file and prints keys\n"
"hf seos managekeys --save -f mykeys.bin -> saves keys to file\n" "hf seos managekeys --save -f mykeys.bin -> saves keys to file\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
@ -1542,26 +1535,25 @@ static int CmdHfSeosManageKeys(const char *Cmd) {
if (key_index >= 0) { if (key_index >= 0) {
operation += 3; operation += 3;
if (key_index < 4) { if (key_index < 4) {
if (nonce_len != 0) { if (nonce_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for nonce[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].nonce, 8)); PrintAndLogEx(SUCCESS, "Current value for nonce[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].nonce, 8));
}
if (privenc_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for Priv Enc[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].privEncKey, 16));
}
if (privmac_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for Priv Mac[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].privMacKey, 16));
}
if (read_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for Read Key[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].readKey, 16));
}
if (write_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for Write Key[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].writeKey, 16));
}
if (admin_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for Admin Key[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].adminKey, 16));
}
} }
else { if (privenc_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for Priv Enc[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].privEncKey, 16));
}
if (privmac_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for Priv Mac[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].privMacKey, 16));
}
if (read_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for Read Key[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].readKey, 16));
}
if (write_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for Write Key[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].writeKey, 16));
}
if (admin_len != 0) {
PrintAndLogEx(SUCCESS, "Current value for Admin Key[%d] " _GREEN_("%s"), key_index, sprint_hex_inrow(keys[key_index].adminKey, 16));
}
} else {
PrintAndLogEx(ERR, "Key index is out-of-range"); PrintAndLogEx(ERR, "Key index is out-of-range");
CLIParserFree(ctx); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;