sam_seos: switch to samCommandGetContentElement2

As PLT-03273 OMNIKEY 5023 Software Developer Guide (https://www.hidglobal.com/documents/omnikey-5023-software-developer-guide) describes a command that returns additional information about SIO object containing PACS data, switching to more verbose one.
This commit is contained in:
Jakub Kramarz 2025-01-06 14:59:26 +01:00
commit 508b63fd2e
3 changed files with 84 additions and 10 deletions

View file

@ -226,7 +226,7 @@ static int sam_send_request_iso14a(const uint8_t * const request, const uint8_t
// send get pacs
static const uint8_t payload[] = {
0xa0, 19, // <- SAM command
0xA1, 17, // <- SamCommandGetContentElement
0xBE, 17, // <- samCommandGetContentElement2
0x80, 1,
0x04, // <- implicitFormatPhysicalAccessBits
0x84, 12,
@ -290,29 +290,43 @@ static int sam_send_request_iso14a(const uint8_t * const request, const uint8_t
);
}
// resp:
// resp for SamCommandGetContentElement:
// c1 64 00 00 00
// bd 09
// 8a 07
// 03 05 <- include tag for pm3 client
// 06 85 80 6d c0 <- decoded PACS data
// 90 00
// resp for samCommandGetContentElement2:
// c1 64 00 00 00
// bd 1e
// b3 1c
// a0 1a
// 80 05
// 06 85 80 6d c0
// 81 0e
// 2b 06 01 04 01 81 e4 38 01 01 02 04 3c ff
// 82 01
// 07
// 90 00
if(request_len == 0){
if(sam_rx_buf[5] != 0xbd && sam_rx_buf[5+2] != 0x8a && sam_rx_buf[5+4] != 0x03){
if(
!(sam_rx_buf[5] == 0xbd && sam_rx_buf[5+2] == 0x8a && sam_rx_buf[5+4] == 0x03)
&&
!(sam_rx_buf[5] == 0xbd && sam_rx_buf[5+2] == 0xb3 && sam_rx_buf[5+4] == 0xa0)
){
if (g_dbglevel >= DBG_ERROR)
Dbprintf("Invalid SAM response");
goto err;
Dbprintf("No PACS data in SAM response");
res=PM3_ESOFT;
}
}
*response_len = sam_rx_buf[5+1] +2;
memcpy(response, sam_rx_buf+5, *response_len);
res=PM3_SUCCESS;
goto out;
err:
res=PM3_ESOFT;
out:
return res;
}

View file

@ -100,6 +100,17 @@ static const known_algo_t known_algorithm_map[] = {
{9, "AES-128_CBC_MODE"},
};
static const sioMediaTypeName_t sioMediaTypeMapping[] = {
{ 0x00, "Unknown"},
{ 0x01, "DESFire"},
{ 0x02, "MIFARE"},
{ 0x03, "iCLASS (PicoPass)"},
{ 0x04, "ISO14443AL4"},
{ 0x06, "MIFARE Plus"},
{ 0x07, "Seos"},
{ 0xFF, "INVALID VALUE"}
};
static int create_cmac (uint8_t* key, uint8_t* input, uint8_t* out, int input_len, int encryption_algorithm) {
uint8_t iv[16] = {0x00};
@ -1707,6 +1718,23 @@ static int dump_PACS_bits(const uint8_t * const data, const uint8_t length, bool
return PM3_SUCCESS;
}
// get a SIO media type based on the UID
// uid[8] tag uid
// returns description of the best match
static const char *getSioMediaTypeInfo(uint8_t uid) {
for (int i = 0; i < ARRAYLEN(sioMediaTypeMapping); ++i) {
if (uid == sioMediaTypeMapping[i].uid) {
return sioMediaTypeMapping[i].desc;
}
}
//No match, return default
return sioMediaTypeMapping[ARRAYLEN(sioMediaTypeMapping) - 1].desc;
}
static int CmdHfSeosSAM(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf seos sam",
@ -1756,9 +1784,7 @@ static int CmdHfSeosSAM(const char *Cmd) {
}
clearCommandBuffer();
// void SendCommandMIX(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, const void *data, size_t len) {
SendCommandMIX(CMD_HF_SAM_SEOS, disconnectAfter, skipDetect, datalen, data, datalen);
// SendCommandNG(CMD_HF_SAM_SEOS, NULL, 0);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_SAM_SEOS, &resp, 4000) == false) {
PrintAndLogEx(WARNING, "SAM timeout");
@ -1789,6 +1815,34 @@ static int CmdHfSeosSAM(const char *Cmd) {
if(res != PM3_SUCCESS){
return res;
}
// check for standard samCommandGetContentElement2:
// bd 1e
// b3 1c
// a0 1a
// 80 05
// 06 85 80 6d c0
// 81 0e
// 2b 06 01 04 01 81 e4 38 01 01 02 04 3c ff
// 82 01
// 07
} else if(d[0]==0xbd && d[2]==0xb3 && d[4]==0xa0){
const uint8_t * pacs = d + 6;
const uint8_t pacs_length = pacs[1];
const uint8_t * pacs_data = pacs + 2;
int res = dump_PACS_bits(pacs_data, pacs_length, verbose);
if(res != PM3_SUCCESS){
return res;
}
const uint8_t * oid = pacs + 2 + pacs_length;
const uint8_t oid_length = oid[1];
const uint8_t * oid_data = oid + 2;
PrintAndLogEx(SUCCESS, "SIO OID.......: " _GREEN_("%s"), sprint_hex_inrow(oid_data, oid_length));
const uint8_t * mediaType = oid + 2 + oid_length;
const uint8_t mediaType_data = mediaType[2];
PrintAndLogEx(SUCCESS, "SIO Media Type: " _GREEN_("%s"), getSioMediaTypeInfo(mediaType_data));
} else {
print_hex(d, resp.length);
}

View file

@ -21,6 +21,12 @@
#include "common.h"
// structure and database for uid -> tagtype lookups
typedef struct {
uint8_t uid;
const char *desc;
} sioMediaTypeName_t;
int infoSeos(bool verbose);
int CmdHFSeos(const char *Cmd);
int seos_kdf(bool encryption, uint8_t* masterKey, uint8_t keyslot,