mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-05 20:41:34 -07:00
armsrc/sam_picopass.c: extract common routines to sam_common.c
This commit is contained in:
parent
032619c1f3
commit
661b7bad22
7 changed files with 527 additions and 77 deletions
|
@ -37,7 +37,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
|
|||
SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c
|
||||
SRC_HF = hfops.c
|
||||
SRC_ISO15693 = iso15693.c iso15693tools.c
|
||||
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c sam_mfc.c sam_seos.c
|
||||
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c sam_common.c sam_mfc.c sam_seos.c
|
||||
#UNUSED: mifaresniff.c
|
||||
SRC_ISO14443b = iso14443b.c
|
||||
SRC_FELICA = felica.c
|
||||
|
|
374
armsrc/sam_common.c
Normal file
374
armsrc/sam_common.c
Normal file
|
@ -0,0 +1,374 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Routines to support MFC <-> SAM communication
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <string.h>
|
||||
// #include "sam_picopass.h"
|
||||
#include "sam_common.h"
|
||||
#include "iclass.h"
|
||||
// #include "crc16.h"
|
||||
#include "proxmark3_arm.h"
|
||||
#include "BigBuf.h"
|
||||
// #include "cmd.h"
|
||||
#include "commonutil.h"
|
||||
#include "ticks.h"
|
||||
#include "dbprint.h"
|
||||
#include "i2c.h"
|
||||
#include "iso15693.h"
|
||||
#include "protocols.h"
|
||||
// #include "optimized_cipher.h"
|
||||
// #include "fpgaloader.h"
|
||||
|
||||
/**
|
||||
* @brief Transmits data to and receives data from a HID®'s iCLASS® SE™ Processor.
|
||||
*
|
||||
* This function sends a specified number of bytes to the SAM and receives a response.
|
||||
*
|
||||
* @param data Pointer to the data to be transmitted.
|
||||
* @param n Number of bytes to be transmitted.
|
||||
* @param resp Pointer to the buffer where the response will be stored.
|
||||
* @param resplen Pointer to the variable where the length of the response will be stored.
|
||||
* @return Status code indicating success or failure of the operation.
|
||||
*/
|
||||
int sam_rxtx(const uint8_t *data, uint16_t n, uint8_t *resp, uint16_t *resplen) {
|
||||
bool res = I2C_BufferWrite(data, n, I2C_DEVICE_CMD_SEND_T0, I2C_DEVICE_ADDRESS_MAIN);
|
||||
if (res == false) {
|
||||
DbpString("failed to send to SIM CARD");
|
||||
goto out;
|
||||
}
|
||||
|
||||
*resplen = ISO7816_MAX_FRAME;
|
||||
|
||||
res = sc_rx_bytes(resp, resplen, SIM_WAIT_DELAY);
|
||||
if (res == false) {
|
||||
DbpString("failed to receive from SIM CARD");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (*resplen < 2) {
|
||||
DbpString("received too few bytes from SIM CARD");
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
uint16_t more_len = 0;
|
||||
|
||||
if (resp[*resplen - 2] == 0x61 || resp[*resplen - 2] == 0x9F) {
|
||||
more_len = resp[*resplen - 1];
|
||||
} else {
|
||||
// we done, return
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Don't discard data we already received except the SW code.
|
||||
// If we only received 1 byte, this is the echo of INS, we discard it.
|
||||
*resplen -= 2;
|
||||
if (*resplen == 1) {
|
||||
*resplen = 0;
|
||||
}
|
||||
|
||||
uint8_t cmd_getresp[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, more_len};
|
||||
|
||||
res = I2C_BufferWrite(cmd_getresp, sizeof(cmd_getresp), I2C_DEVICE_CMD_SEND_T0, I2C_DEVICE_ADDRESS_MAIN);
|
||||
if (res == false) {
|
||||
DbpString("failed to send to SIM CARD 2");
|
||||
goto out;
|
||||
}
|
||||
|
||||
more_len = 255 - *resplen;
|
||||
|
||||
res = sc_rx_bytes(resp + *resplen, &more_len, SIM_WAIT_DELAY);
|
||||
if (res == false) {
|
||||
DbpString("failed to receive from SIM CARD 2");
|
||||
goto out;
|
||||
}
|
||||
|
||||
*resplen += more_len;
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static inline void swap_clock_counters(volatile unsigned int * a, unsigned int * b){
|
||||
unsigned int c = *a;
|
||||
*a = *b;
|
||||
*b = c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Swaps the timer counter values.
|
||||
*
|
||||
* AT91SAM7S512 has a single Timer-Counter, that is reused in clocks Ticks
|
||||
* and CountSspClk. This function stops the current clock and restores previous
|
||||
* values. It is used to switch between different clock sources.
|
||||
* It probably makes communication timing off, but at least makes it work.
|
||||
*/
|
||||
static void swap_clocks(void){
|
||||
static unsigned int tc0, tc1, tc2 = 0;
|
||||
StopTicks();
|
||||
swap_clock_counters(&(AT91C_BASE_TC0->TC_CV), &tc0);
|
||||
swap_clock_counters(&(AT91C_BASE_TC1->TC_CV), &tc1);
|
||||
swap_clock_counters(&(AT91C_BASE_TC2->TC_CV), &tc2);
|
||||
}
|
||||
|
||||
void switch_clock_to_ticks(void){
|
||||
swap_clocks();
|
||||
StartTicks();
|
||||
}
|
||||
|
||||
void switch_clock_to_countsspclk(void){
|
||||
swap_clocks();
|
||||
StartCountSspClk();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sends a payload to the SAM
|
||||
*
|
||||
* This function prepends the payload with the necessary APDU and application
|
||||
* headers and sends it to the SAM.
|
||||
*
|
||||
* @param addr_src 0x14 for command from NFC, 0x44 for command from application
|
||||
* @param addr_dest 0x0A for command to SAM
|
||||
* @param addr_reply same as add_src or 0x00 if no reply is expected
|
||||
* @param payload Pointer to the data to be sent.
|
||||
* @param payload_len Length of the data to be sent.
|
||||
* @param response Pointer to the buffer where the response will be stored.
|
||||
* @param response_len Pointer to the variable where the length of the response will be stored.
|
||||
* @param length Length of the data to be sent.
|
||||
* @return Status code indicating success or failure of the operation.
|
||||
*/
|
||||
int sam_send_payload(
|
||||
uint8_t addr_src,
|
||||
uint8_t addr_dest,
|
||||
uint8_t addr_reply,
|
||||
|
||||
uint8_t *payload,
|
||||
uint16_t *payload_len,
|
||||
|
||||
uint8_t *response,
|
||||
uint16_t *response_len
|
||||
){
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
uint8_t * buf = response;
|
||||
|
||||
buf[0] = 0xA0; // CLA
|
||||
buf[1] = 0xDA; // INS (PUT DATA)
|
||||
buf[2] = 0x02; // P1 (TLV format?)
|
||||
buf[3] = 0x63; // P2
|
||||
buf[4] = SAM_TX_ASN1_PREFIX_LENGTH + (uint8_t) *payload_len; // LEN
|
||||
|
||||
buf[5] = addr_src;
|
||||
buf[6] = addr_dest;
|
||||
buf[7] = addr_reply;
|
||||
|
||||
buf[8] = 0x00;
|
||||
buf[9] = 0x00;
|
||||
buf[10] = 0x00;
|
||||
|
||||
memcpy(
|
||||
&buf[11],
|
||||
payload,
|
||||
*payload_len
|
||||
);
|
||||
|
||||
uint16_t length = SAM_TX_ASN1_PREFIX_LENGTH + SAM_TX_APDU_PREFIX_LENGTH + (uint8_t) *payload_len;
|
||||
|
||||
LogTrace(buf, length, 0, 0, NULL, true);
|
||||
if (g_dbglevel >= DBG_INFO){
|
||||
DbpString("SAM REQUEST APDU: ");
|
||||
Dbhexdump(length, buf, false);
|
||||
}
|
||||
|
||||
if (sam_rxtx(buf, length, response, response_len) == false) {
|
||||
if (g_dbglevel >= DBG_ERROR)
|
||||
DbpString("SAM ERROR");
|
||||
res = PM3_ECARDEXCHANGE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
LogTrace(response, *response_len, 0, 0, NULL, false);
|
||||
if (g_dbglevel >= DBG_INFO){
|
||||
DbpString("SAM RESPONSE APDU: ");
|
||||
Dbhexdump(*response_len, response, false);
|
||||
}
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retreives SAM firmware version.
|
||||
*
|
||||
* Used just as ping or sanity check here.
|
||||
*
|
||||
* @return Status code indicating success or failure of the operation.
|
||||
*/
|
||||
int sam_get_version(void){
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
DbpString("start sam_get_version");
|
||||
|
||||
uint8_t * response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||
|
||||
uint8_t payload[] = {
|
||||
0xa0, 0x02, // <- SAM command
|
||||
0x82, 0x00 // <- get version
|
||||
};
|
||||
uint16_t payload_len = sizeof(payload);
|
||||
|
||||
sam_send_payload(
|
||||
0x44, 0x0a, 0x44,
|
||||
payload,
|
||||
&payload_len,
|
||||
response,
|
||||
&response_len
|
||||
);
|
||||
|
||||
// resp:
|
||||
// c1 64 00 00 00
|
||||
// bd 11 <- SAM response
|
||||
// 8a 0f <- get version response
|
||||
// 80 02
|
||||
// 01 29 <- version
|
||||
// 81 06
|
||||
// 68 3d 05 20 26 b6 <- build ID
|
||||
// 82 01
|
||||
// 01
|
||||
// 90 00
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
DbpString("end sam_get_version");
|
||||
|
||||
if(response[5] != 0xbd){
|
||||
Dbprintf("Invalid SAM response");
|
||||
goto error;
|
||||
}else{
|
||||
uint8_t * sam_response_an = sam_find_asn1_node(response + 5, 0x8a);
|
||||
if(sam_response_an == NULL){
|
||||
if (g_dbglevel >= DBG_ERROR)
|
||||
DbpString("SAM get response failed");
|
||||
goto error;
|
||||
}
|
||||
uint8_t * sam_version_an = sam_find_asn1_node(sam_response_an, 0x80);
|
||||
if(sam_version_an == NULL){
|
||||
if (g_dbglevel >= DBG_ERROR)
|
||||
DbpString("SAM get version failed");
|
||||
goto error;
|
||||
}
|
||||
uint8_t * sam_build_an = sam_find_asn1_node(sam_response_an, 0x81);
|
||||
if(sam_build_an == NULL){
|
||||
if (g_dbglevel >= DBG_ERROR)
|
||||
DbpString("SAM get firmware ID failed");
|
||||
goto error;
|
||||
}
|
||||
if (g_dbglevel >= DBG_INFO){
|
||||
DbpString("SAM get version successful");
|
||||
Dbprintf("Firmware version: %X.%X", sam_version_an[2], sam_version_an[3]);
|
||||
Dbprintf("Firmware ID: ");
|
||||
Dbhexdump(sam_build_an[1], sam_build_an+2, false);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
error:
|
||||
res = PM3_ESOFT;
|
||||
|
||||
out:
|
||||
BigBuf_free();
|
||||
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
DbpString("end sam_get_version");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Finds an ASN.1 node of a specified type within a given root node.
|
||||
*
|
||||
* This function searches through a single level of the ASN.1 structure starting
|
||||
* from the root node to find a node of the specified type.
|
||||
*
|
||||
* @param root Pointer to the root node of the ASN.1 structure.
|
||||
* @param type The type of the ASN.1 node to find.
|
||||
* @return Pointer to the ASN.1 node of the specified type if found, otherwise NULL.
|
||||
*/
|
||||
uint8_t * sam_find_asn1_node(uint8_t * root, const uint8_t type){
|
||||
const uint8_t * end = root + *(root+1);
|
||||
uint8_t * current = root + 2;
|
||||
while(current < end){
|
||||
if(*current == type){
|
||||
return current;
|
||||
}else{
|
||||
current += 2 + *(current+1);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @brief Appends an ASN.1 node to the end of a given node.
|
||||
// *
|
||||
// * This function appends an ASN.1 node of a specified type and length to the end of
|
||||
// * the ASN.1 structure at specified node level.
|
||||
// * It would make the code cleaner, but I can't get it to work - it calculates fields lengths incorrectly.
|
||||
// *
|
||||
// * @param root Pointer to the root node of the ASN.1 structure.
|
||||
// * @param root Pointer to the node to be appended of the ASN.1 structure.
|
||||
// * @param type The type of the ASN.1 node to append.
|
||||
// * @param data Pointer to the data to be appended.
|
||||
// * @param len The length of the data to be appended.
|
||||
// */
|
||||
// void sam_append_asn1_node(uint8_t * root, uint8_t * node, uint8_t type, uint8_t * data, uint8_t len){
|
||||
// uint8_t * end = root + *(root+1);
|
||||
|
||||
// *(end) = type;
|
||||
// *(end+1) = len;
|
||||
// memcpy(end+2, data, len);
|
||||
|
||||
// for(uint8_t * current = root; current < node; current += 2){
|
||||
// *(current+1) += 2 + len;
|
||||
// };
|
||||
// return;
|
||||
// }
|
||||
|
||||
void sam_send_ack(void){
|
||||
uint8_t * response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||
|
||||
uint8_t payload[] = {
|
||||
0xa0, 0
|
||||
};
|
||||
uint16_t payload_len = sizeof(payload);
|
||||
|
||||
sam_send_payload(
|
||||
0x44, 0x0a, 0x00,
|
||||
payload,
|
||||
&payload_len,
|
||||
response,
|
||||
&response_len
|
||||
);
|
||||
|
||||
BigBuf_free();
|
||||
}
|
49
armsrc/sam_common.h
Normal file
49
armsrc/sam_common.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __SAM_COMMON_H
|
||||
#define __SAM_COMMON_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static const uint8_t SAM_TX_APDU_PREFIX_LENGTH = 5;
|
||||
static const uint8_t SAM_TX_ASN1_PREFIX_LENGTH = 6;
|
||||
static const uint8_t SAM_RX_ASN1_PREFIX_LENGTH = 5;
|
||||
|
||||
int sam_rxtx(const uint8_t *data, uint16_t n, uint8_t *resp, uint16_t *resplen);
|
||||
|
||||
void switch_clock_to_ticks(void);
|
||||
void switch_clock_to_countsspclk(void);
|
||||
|
||||
int sam_send_payload(
|
||||
uint8_t addr_src,
|
||||
uint8_t addr_dest,
|
||||
uint8_t addr_reply,
|
||||
|
||||
uint8_t *payload,
|
||||
uint16_t *payload_len,
|
||||
|
||||
uint8_t *response,
|
||||
uint16_t *response_len
|
||||
);
|
||||
|
||||
int sam_get_version(void);
|
||||
|
||||
uint8_t * sam_find_asn1_node(uint8_t * root, const uint8_t type);
|
||||
//void sam_append_asn1_node(uint8_t * root, uint8_t * node, uint8_t type, uint8_t * data, uint8_t len);
|
||||
|
||||
void sam_send_ack(void);
|
||||
|
||||
#endif
|
|
@ -16,7 +16,7 @@
|
|||
// Routines to support MFC <-> SAM communication
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "sam_mfc.h"
|
||||
#include "sam_seos.h"
|
||||
#include "sam_common.h"
|
||||
#include "iclass.h"
|
||||
|
||||
#include "proxmark3_arm.h"
|
||||
|
|
|
@ -17,5 +17,6 @@
|
|||
#define __SAM_MFC_H
|
||||
|
||||
#include "common.h"
|
||||
#include "sam_common.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
// Routines to support Picopass <-> SAM communication
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "sam_picopass.h"
|
||||
#include "sam_common.h"
|
||||
#include "iclass.h"
|
||||
#include "crc16.h"
|
||||
#include "proxmark3_arm.h"
|
||||
|
@ -30,66 +31,79 @@
|
|||
#include "optimized_cipher.h"
|
||||
#include "fpgaloader.h"
|
||||
|
||||
static int sam_rxtx(const uint8_t *data, uint16_t n, uint8_t *resp, uint16_t *resplen) {
|
||||
|
||||
StartTicks();
|
||||
/**
|
||||
* @brief Sets the card detected status for the SAM (Secure Access Module).
|
||||
*
|
||||
* This function informs that a card has been detected by the reader and
|
||||
* initializes SAM communication with the card.
|
||||
*
|
||||
* @param card_select Pointer to the descriptor of the detected card.
|
||||
* @return Status code indicating success or failure of the operation.
|
||||
*/
|
||||
static int sam_set_card_detected(picopass_hdr_t * card_select){
|
||||
int res = PM3_SUCCESS;
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
DbpString("start sam_set_card_detected");
|
||||
|
||||
bool res = I2C_BufferWrite(data, n, I2C_DEVICE_CMD_SEND_T0, I2C_DEVICE_ADDRESS_MAIN);
|
||||
if (res == false) {
|
||||
DbpString("failed to send to SIM CARD");
|
||||
uint8_t * response = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint16_t response_len = ISO7816_MAX_FRAME;
|
||||
|
||||
// a0 12
|
||||
// ad 10
|
||||
// a0 0e
|
||||
// 80 02
|
||||
// 00 04 <- Picopass
|
||||
// 81 08
|
||||
// 9b fc a4 00 fb ff 12 e0 <- CSN
|
||||
|
||||
uint8_t payload[] = {
|
||||
0xa0, 18, // <- SAM command
|
||||
0xad, 16, // <- set detected card
|
||||
0xa0, 4+10,
|
||||
0x80, 2, // <- protocol
|
||||
0x00, 0x04, // <- Picopass
|
||||
0x81, 8, // <- CSN
|
||||
card_select->csn[0], card_select->csn[1], card_select->csn[2], card_select->csn[3],
|
||||
card_select->csn[4], card_select->csn[5], card_select->csn[6], card_select->csn[7]
|
||||
};
|
||||
uint16_t payload_len = sizeof(payload);
|
||||
|
||||
sam_send_payload(
|
||||
0x44, 0x0a, 0x44,
|
||||
payload,
|
||||
&payload_len,
|
||||
response,
|
||||
&response_len
|
||||
);
|
||||
|
||||
// resp:
|
||||
// c1 64 00 00 00
|
||||
// bd 02 <- response
|
||||
// 8a 00 <- empty response (accepted)
|
||||
// 90 00
|
||||
|
||||
if(response[5] != 0xbd){
|
||||
if (g_dbglevel >= DBG_ERROR)
|
||||
Dbprintf("Invalid SAM response");
|
||||
goto error;
|
||||
}else{
|
||||
// uint8_t * sam_response_an = sam_find_asn1_node(response + 5, 0x8a);
|
||||
// if(sam_response_an == NULL){
|
||||
// if (g_dbglevel >= DBG_ERROR)
|
||||
// Dbprintf("Invalid SAM response");
|
||||
// goto error;
|
||||
// }
|
||||
goto out;
|
||||
}
|
||||
error:
|
||||
res = PM3_ESOFT;
|
||||
|
||||
*resplen = ISO7816_MAX_FRAME;
|
||||
out:
|
||||
BigBuf_free();
|
||||
|
||||
res = sc_rx_bytes(resp, resplen, SIM_WAIT_DELAY);
|
||||
if (res == false) {
|
||||
DbpString("failed to receive from SIM CARD");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (*resplen < 2) {
|
||||
DbpString("received too few bytes from SIM CARD");
|
||||
res = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
uint16_t more_len = 0;
|
||||
|
||||
if (resp[*resplen - 2] == 0x61 || resp[*resplen - 2] == 0x9F) {
|
||||
more_len = resp[*resplen - 1];
|
||||
} else {
|
||||
// we done, return
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Don't discard data we already received except the SW code.
|
||||
// If we only received 1 byte, this is the echo of INS, we discard it.
|
||||
*resplen -= 2;
|
||||
if (*resplen == 1) {
|
||||
*resplen = 0;
|
||||
}
|
||||
|
||||
uint8_t cmd_getresp[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, more_len};
|
||||
|
||||
res = I2C_BufferWrite(cmd_getresp, sizeof(cmd_getresp), I2C_DEVICE_CMD_SEND_T0, I2C_DEVICE_ADDRESS_MAIN);
|
||||
if (res == false) {
|
||||
DbpString("failed to send to SIM CARD 2");
|
||||
goto out;
|
||||
}
|
||||
|
||||
more_len = 255 - *resplen;
|
||||
|
||||
res = sc_rx_bytes(resp + *resplen, &more_len, SIM_WAIT_DELAY);
|
||||
if (res == false) {
|
||||
DbpString("failed to receive from SIM CARD 2");
|
||||
goto out;
|
||||
}
|
||||
|
||||
*resplen += more_len;
|
||||
|
||||
out:
|
||||
StopTicks();
|
||||
if (g_dbglevel >= DBG_DEBUG)
|
||||
DbpString("end sam_set_card_detected");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -218,23 +232,19 @@ int sam_picopass_get_pacs(void) {
|
|||
uint8_t *sam_apdu = BigBuf_calloc(ISO7816_MAX_FRAME);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// first
|
||||
// a0 da 02 63 1a 44 0a 44 00 00 00 a0 12 ad 10 a0 0e 80 02 00 04 81 08 9b fc a4 00 fb ff 12 e0
|
||||
hexstr_to_byte_array("a0da02631a440a44000000a012ad10a00e800200048108", sam_apdu, &sam_len);
|
||||
memcpy(sam_apdu + sam_len, hdr.csn, sizeof(hdr.csn));
|
||||
sam_len += sizeof(hdr.csn);
|
||||
|
||||
if (sam_rxtx(sam_apdu, sam_len, resp, &resp_len) == false) {
|
||||
res = PM3_ECARDEXCHANGE;
|
||||
goto out;
|
||||
}
|
||||
print_dbg("-- 1", resp, resp_len);
|
||||
// first - set detected card (0xAD)
|
||||
switch_clock_to_ticks();
|
||||
sam_set_card_detected(&hdr);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// second
|
||||
// a0 da 02 63 0d 44 0a 44 00 00 00 a0 05 a1 03 80 01 04
|
||||
hexstr_to_byte_array("a0da02630d440a44000000a005a103800104", sam_apdu, &sam_len);
|
||||
if (sam_rxtx(sam_apdu, sam_len, resp, &resp_len) == false) {
|
||||
// second - get PACS (0xA1)
|
||||
|
||||
// a0 05
|
||||
// a1 03
|
||||
// 80 01
|
||||
// 04
|
||||
hexstr_to_byte_array("a005a103800104", sam_apdu, &sam_len);
|
||||
if(sam_send_payload(0x44, 0x0a, 0x44, sam_apdu, &sam_len, resp, &resp_len) != PM3_SUCCESS) {
|
||||
res = PM3_ECARDEXCHANGE;
|
||||
goto out;
|
||||
}
|
||||
|
@ -245,7 +255,7 @@ int sam_picopass_get_pacs(void) {
|
|||
// Tag|c00a140a000000a110a10e8004 0c05de64 8102 0004 820201f4
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// third AIA block 5
|
||||
// third AIA block 5 (emulated tag <-> SAM exchange starts here)
|
||||
// a0da02631c140a00000000bd14a012a010800a ffffff0006fffffff88e 81020000
|
||||
// picopass legacy is fixed. wants AIA and crc. ff ff ff ff ff ff ff ff ea f5
|
||||
// picpoasss SE ff ff ff 00 06 ff ff ff f8 8e
|
||||
|
@ -300,7 +310,7 @@ int sam_picopass_get_pacs(void) {
|
|||
}
|
||||
|
||||
// start ssp clock again...
|
||||
StartCountSspClk();
|
||||
switch_clock_to_countsspclk();
|
||||
|
||||
// NOW we auth against tag
|
||||
uint8_t cmd_check[9] = { ICLASS_CMD_CHECK };
|
||||
|
@ -325,6 +335,7 @@ int sam_picopass_get_pacs(void) {
|
|||
hexstr_to_byte_array("A0DA026316140A00000000BD0EA00CA00A8004311E32E981020000", sam_apdu, &sam_len);
|
||||
memcpy(sam_apdu + 19, mac, sizeof(mac));
|
||||
|
||||
switch_clock_to_ticks();
|
||||
if (sam_rxtx(sam_apdu, sam_len, resp, &resp_len) == false) {
|
||||
res = PM3_ECARDEXCHANGE;
|
||||
goto out;
|
||||
|
@ -355,7 +366,7 @@ int sam_picopass_get_pacs(void) {
|
|||
// c1 61 c1 00 00 a1 10 a1 0e 80 04 0c 06 45 56 81 02 00 04 82 02 01 f4 90 00
|
||||
|
||||
// read block 6
|
||||
StartCountSspClk();
|
||||
switch_clock_to_countsspclk();
|
||||
start_time = GetCountSspClk();
|
||||
iclass_send_as_reader(resp + 11, 4, &start_time, &eof_time, shallow_mod);
|
||||
|
||||
|
@ -373,6 +384,7 @@ int sam_picopass_get_pacs(void) {
|
|||
hexstr_to_byte_array("A0DA02631C140A00000000BD14A012A010800A030303030003E017432381020000", sam_apdu, &sam_len);
|
||||
memcpy(sam_apdu + 19, resp, resp_len);
|
||||
|
||||
switch_clock_to_ticks();
|
||||
if (sam_rxtx(sam_apdu, sam_len, resp, &resp_len) == false) {
|
||||
res = PM3_ECARDEXCHANGE;
|
||||
goto out;
|
||||
|
@ -382,7 +394,7 @@ int sam_picopass_get_pacs(void) {
|
|||
// c161c10000a110a10e8004 0606455681020004820201f49000
|
||||
|
||||
// read the credential blocks
|
||||
StartCountSspClk();
|
||||
switch_clock_to_countsspclk();
|
||||
start_time = GetCountSspClk();
|
||||
iclass_send_as_reader(resp + 11, 4, &start_time, &eof_time, shallow_mod);
|
||||
|
||||
|
@ -400,6 +412,7 @@ int sam_picopass_get_pacs(void) {
|
|||
hexstr_to_byte_array("A0DA026334140A00000000BD2CA02AA0288022030303030003E017769CB4A198E0DEC82AD4C8211F9968712BE7393CF8E71D7E804C81020000", sam_apdu, &sam_len);
|
||||
memcpy(sam_apdu + 19, resp, resp_len);
|
||||
|
||||
switch_clock_to_ticks();
|
||||
if (sam_rxtx(sam_apdu, sam_len, resp, &resp_len) == false) {
|
||||
res = PM3_ECARDEXCHANGE;
|
||||
goto out;
|
||||
|
@ -409,7 +422,13 @@ int sam_picopass_get_pacs(void) {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// TEN ask for PACS data
|
||||
// A0DA02630C440A00000000BD04A0028200
|
||||
// A0 DA 02 63 0C
|
||||
// 44 0A 00 00 00 00
|
||||
// BD 04
|
||||
// A0 02
|
||||
// 82 00
|
||||
|
||||
// (emulated tag <-> SAM exchange ends here)
|
||||
hexstr_to_byte_array("A0DA02630C440A00000000BD04A0028200", sam_apdu, &sam_len);
|
||||
memcpy(sam_apdu + 19, resp, resp_len);
|
||||
|
||||
|
@ -424,7 +443,12 @@ int sam_picopass_get_pacs(void) {
|
|||
goto out;
|
||||
}
|
||||
|
||||
// c164000000bd098a07 030506951f9a00 9000
|
||||
// resp:
|
||||
// c1 64 00 00 00
|
||||
// bd 09
|
||||
// 8a 07
|
||||
// 03 05 06 95 1f 9a 00 <- decoded PACS data
|
||||
// 90 00
|
||||
uint8_t *pacs = BigBuf_calloc(resp[8]);
|
||||
memcpy(pacs, resp + 9, resp[8]);
|
||||
|
||||
|
@ -439,6 +463,7 @@ out:
|
|||
|
||||
off:
|
||||
switch_off();
|
||||
StopTicks();
|
||||
BigBuf_free();
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#define __SAM_PICOPASS_H
|
||||
|
||||
#include "common.h"
|
||||
#include "sam_common.h"
|
||||
|
||||
int sam_picopass_get_pacs(void);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue