Skip to content

Commit

Permalink
sam_seos: add option to send arbitrary requests
Browse files Browse the repository at this point in the history
  • Loading branch information
jkramarz committed Jan 6, 2025
1 parent 4d6a075 commit a1377e1
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 136 deletions.
2 changes: 1 addition & 1 deletion armsrc/appmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -2246,7 +2246,7 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_SAM_SEOS: {
sam_seos_get_pacs();
sam_seos_get_pacs(packet);
break;
}

Expand Down
187 changes: 104 additions & 83 deletions armsrc/sam_seos.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "protocols.h"
#include "optimized_cipher.h"
#include "fpgaloader.h"
#include "pm3_cmd.h"

#include "cmd.h"

Expand Down Expand Up @@ -146,10 +147,10 @@ inline static uint16_t sam_seos_copy_payload_nfc2sam(uint8_t *sam_tx, uint8_t *
};

memcpy(sam_tx, payload, sizeof(payload));

sam_append_asn1_node(sam_tx, sam_tx+4, 0x80, nfc_rx, nfc_len);
sam_append_asn1_node(sam_tx, sam_tx+4, 0x81, tag81, sizeof(tag81));

return sam_tx[1] + 2; // length of the ASN1 tree
}

Expand Down Expand Up @@ -187,18 +188,21 @@ inline static uint16_t sam_seos_copy_payload_sam2nfc(uint8_t * nfc_tx_buf, uint8
}

/**
* @brief Copies the payload from the SAM receive buffer to the NFC transmit buffer.
* @brief Sends a request to the SAM and retrieves the response.
*
* Unpacks data to be transmitted from ASN1 tree in APDU received from SAM.
* Unpacks request to the SAM and relays ISO14A traffic to the card.
* If no request data provided, sends a request to get PACS data.
*
* @param pacs Pointer to the buffer where the decoded PACS data will be stored.
* @param pacs_len Pointer to the variable where the length of the PACS data will be stored.
* @param request Pointer to the buffer containing the request to be sent to the SAM.
* @param request_len Length of the request to be sent to the SAM.
* @param response Pointer to the buffer where the retreived data will be stored.
* @param response_len Pointer to the variable where the length of the retreived data will be stored.
* @return Status code indicating success or failure of the operation.
*/
static int sam_request_pacs(uint8_t * pacs, uint8_t * pacs_len){
static int sam_send_request_iso14a(const uint8_t * const request, const uint8_t request_len, uint8_t * response, uint8_t * response_len){
int res = PM3_SUCCESS;
if (g_dbglevel >= DBG_DEBUG)
DbpString("start sam_request_pacs");
DbpString("start sam_send_request_iso14a");

uint8_t buf1[ISO7816_MAX_FRAME] = {0};
uint8_t buf2[ISO7816_MAX_FRAME] = {0};
Expand All @@ -215,84 +219,94 @@ static int sam_request_pacs(uint8_t * pacs, uint8_t * pacs_len){
uint8_t * nfc_rx_buf = buf2;
uint16_t nfc_rx_len;

// send get pacs
static const uint8_t payload[] = {
0xa0, 19, // <- SAM command
0xA1, 17, // <- SamCommandGetContentElement
0x80, 1,
0x04, // <- implicitFormatPhysicalAccessBits
0x84, 12,
0x2B, 0x06, 0x01, 0x04, 0x01, 0x81, 0xE4, 0x38, 0x01, 0x01, 0x02, 0x04 // <- SoRootOID
};

sam_tx_len = sizeof(payload);
memcpy(sam_tx_buf, payload, sam_tx_len);
if(request_len > 0){
sam_tx_len = request_len;
memcpy(sam_tx_buf, request, sam_tx_len);
}else{
// send get pacs
static const uint8_t payload[] = {
0xa0, 19, // <- SAM command
0xA1, 17, // <- SamCommandGetContentElement
0x80, 1,
0x04, // <- implicitFormatPhysicalAccessBits
0x84, 12,
0x2B, 0x06, 0x01, 0x04, 0x01, 0x81, 0xE4, 0x38, 0x01, 0x01, 0x02, 0x04 // <- SoRootOID
};

sam_tx_len = sizeof(payload);
memcpy(sam_tx_buf, payload, sam_tx_len);
}

sam_send_payload(
0x44, 0x0a, 0x44,
sam_tx_buf, &sam_tx_len,
sam_rx_buf, &sam_rx_len
);

// tag <-> SAM exchange starts here
for(int i = 0; i < 20; i++){
switch_clock_to_countsspclk();
nfc_tx_len = sam_seos_copy_payload_sam2nfc(nfc_tx_buf, sam_rx_buf);

nfc_rx_len = iso14_apdu(
nfc_tx_buf,
nfc_tx_len,
false,
nfc_rx_buf,
ISO7816_MAX_FRAME,
NULL
);
if(sam_rx_buf[1] == 0x61){ // commands to be relayed to card starts with 0x61
// tag <-> SAM exchange starts here
while(sam_rx_buf[1] == 0x61){
switch_clock_to_countsspclk();
nfc_tx_len = sam_seos_copy_payload_sam2nfc(nfc_tx_buf, sam_rx_buf);

nfc_rx_len = iso14_apdu(
nfc_tx_buf,
nfc_tx_len,
false,
nfc_rx_buf,
ISO7816_MAX_FRAME,
NULL
);

switch_clock_to_ticks();
sam_tx_len = sam_seos_copy_payload_nfc2sam(sam_tx_buf, nfc_rx_buf, nfc_rx_len-2);

sam_send_payload(
0x14, 0x0a, 0x14,
sam_tx_buf, &sam_tx_len,
sam_rx_buf, &sam_rx_len
);

// last SAM->TAG
// c1 61 c1 00 00 a1 02 >>82<< 00 90 00
if(sam_rx_buf[7] == 0x82){
// tag <-> SAM exchange ends here
break;
}

}

switch_clock_to_ticks();
sam_tx_len = sam_seos_copy_payload_nfc2sam(sam_tx_buf, nfc_rx_buf, nfc_rx_len-2);
static const uint8_t hfack[] = {
0xbd, 0x04, 0xa0, 0x02, 0x82, 0x00
};

sam_tx_len = sizeof(hfack);
memcpy(sam_tx_buf, hfack, sam_tx_len);

sam_send_payload(
0x14, 0x0a, 0x14,
0x14, 0x0a, 0x00,
sam_tx_buf, &sam_tx_len,
sam_rx_buf, &sam_rx_len
);

// last SAM->TAG
// c1 61 c1 00 00 a1 02 >>82<< 00 90 00
if(sam_rx_buf[7] == 0x82){
// tag <-> SAM exchange ends here
break;
}

}

static const uint8_t hfack[] = {
0xbd, 0x04, 0xa0, 0x02, 0x82, 0x00
};

sam_tx_len = sizeof(hfack);
memcpy(sam_tx_buf, hfack, sam_tx_len);

sam_send_payload(
0x14, 0x0a, 0x00,
sam_tx_buf, &sam_tx_len,
sam_rx_buf, &sam_rx_len
);

// resp:
// 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
if(sam_rx_buf[5+2] != 0x8a && sam_rx_buf[5+4] != 0x03){
if (g_dbglevel >= DBG_ERROR)
Dbprintf("Invalid SAM response");
goto err;
if(request_len == 0){
if(sam_rx_buf[5] != 0xbd && sam_rx_buf[5+2] != 0x8a && sam_rx_buf[5+4] != 0x03){
if (g_dbglevel >= DBG_ERROR)
Dbprintf("Invalid SAM response");
goto err;
}
}
*pacs_len = sam_rx_buf[5+5] +2;
memcpy(pacs, sam_rx_buf+5+4, *pacs_len);

*response_len = sam_rx_buf[5+1] +2;
memcpy(response, sam_rx_buf+5, *response_len);
res=PM3_SUCCESS;

goto out;
Expand All @@ -312,7 +326,13 @@ static int sam_request_pacs(uint8_t * pacs, uint8_t * pacs_len){
*
* @return Status code indicating success or failure of the operation.
*/
int sam_seos_get_pacs(void){
int sam_seos_get_pacs(PacketCommandNG *c) {
bool disconnectAfter = c->oldarg[0] & 0x01;
bool skipDetect = c->oldarg[1] & 0x01;

uint8_t *cmd = c->data.asBytes;
uint16_t cmd_len = (uint16_t) c->oldarg[2];

int res = PM3_EFAILED;

clear_trace();
Expand All @@ -324,32 +344,31 @@ int sam_seos_get_pacs(void){
// step 1: ping SAM
sam_get_version();

// step 2: get card information
iso14a_card_select_t card_a_info;
if(!skipDetect){
// step 2: get card information
iso14a_card_select_t card_a_info;

// implicit StartSspClk() happens here
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
if (!iso14443a_select_card(NULL, &card_a_info, NULL, true, 0, false)){
goto err;
}
// implicit StartSspClk() happens here
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
if (!iso14443a_select_card(NULL, &card_a_info, NULL, true, 0, false)){
goto err;
}

switch_clock_to_ticks();
switch_clock_to_ticks();

// step 3: SamCommand CardDetected
sam_set_card_detected(&card_a_info);
// step 3: SamCommand CardDetected
sam_set_card_detected(&card_a_info);
}

// step 3: SamCommand RequestPACS, relay NFC communication

uint8_t pacs[10] = { 0x00 };
uint8_t pacs_len = 0;
res = sam_request_pacs(pacs, &pacs_len);
uint8_t sam_response[ISO7816_MAX_FRAME] = { 0x00 };
uint8_t sam_response_len = 0;
res = sam_send_request_iso14a(cmd, cmd_len, sam_response, &sam_response_len);
if(res != PM3_SUCCESS){
goto err;
}
if (g_dbglevel >= DBG_INFO)
print_result("PACS data", pacs, pacs_len);

sam_send_ack();
print_result("Response data", sam_response, sam_response_len);

goto out;
goto off;
Expand All @@ -359,10 +378,12 @@ int sam_seos_get_pacs(void){
reply_ng(CMD_HF_SAM_SEOS, res, NULL, 0);
goto off;
out:
reply_ng(CMD_HF_SAM_SEOS, PM3_SUCCESS, pacs, pacs_len);
reply_ng(CMD_HF_SAM_SEOS, PM3_SUCCESS, sam_response, sam_response_len);
goto off;
off:
switch_off();
if(disconnectAfter){
switch_off();
}
set_tracing(false);
StopTicks();
BigBuf_free();
Expand Down
3 changes: 2 additions & 1 deletion armsrc/sam_seos.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
#define __SAM_SEOS_H

#include "common.h"
#include "pm3_cmd.h"

int sam_seos_get_pacs(void);
int sam_seos_get_pacs(PacketCommandNG *c);

#endif
2 changes: 2 additions & 0 deletions client/src/cmdhficlass.c
Original file line number Diff line number Diff line change
Expand Up @@ -5434,6 +5434,8 @@ static int CmdHFiClassSAM(const char *Cmd) {

// CSN, config, epurse, NR/MAC, AIA
// PACS
// 03 05
// 06 85 80 6d c0
// first byte skip
// second byte length
// third padded
Expand Down
Loading

0 comments on commit a1377e1

Please sign in to comment.