mirror of
https://github.com/bettse/seader.git
synced 2026-05-25 14:14:20 +00:00
Use PACS2-only HF credential parsing
This commit is contained in:
@@ -17,9 +17,9 @@ static const asn_INTEGER_enum_map_t asn_MAP_FrameProtocol_value2enum_1[] = {
|
||||
{ 4, 6, "iclass" }
|
||||
};
|
||||
static const unsigned int asn_MAP_FrameProtocol_enum2value_1[] = {
|
||||
0, /* none(0) */
|
||||
2, /* iclass(4) */
|
||||
1 /* nfc(2) */
|
||||
1, /* nfc(2) */
|
||||
0 /* none(0) */
|
||||
};
|
||||
static const asn_INTEGER_specifics_t asn_SPC_FrameProtocol_specs_1 = {
|
||||
asn_MAP_FrameProtocol_value2enum_1, /* "tag" => N; sorted by tag */
|
||||
@@ -47,3 +47,4 @@ asn_TYPE_descriptor_t asn_DEF_FrameProtocol = {
|
||||
0, 0, /* Defined elsewhere */
|
||||
&asn_SPC_FrameProtocol_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
|
||||
+9
-19
@@ -8,15 +8,6 @@
|
||||
#include "SamCommand.h"
|
||||
|
||||
asn_TYPE_member_t asn_MBR_SamCommand_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct SamCommand, choice.requestPacs),
|
||||
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_RequestPacs,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"requestPacs"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct SamCommand, choice.version),
|
||||
(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
@@ -82,14 +73,13 @@ asn_TYPE_member_t asn_MBR_SamCommand_1[] = {
|
||||
},
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_SamCommand_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* requestPacs */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, 0, 0 }, /* version */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (13 << 2)), 2, 0, 0 }, /* cardDetected */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (20 << 2)), 3, 0, 0 }, /* processSNMPMessage */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (22 << 2)), 4, 0, 0 }, /* serialNumber */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (26 << 2)), 7, 0, 0 }, /* processConfigCard */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (30 << 2)), 6, 0, 0 }, /* requestPacs2 */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (43 << 2)), 5, 0, 0 } /* getItemKCV */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 0, 0, 0 }, /* version */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (13 << 2)), 1, 0, 0 }, /* cardDetected */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (20 << 2)), 2, 0, 0 }, /* processSNMPMessage */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (22 << 2)), 3, 0, 0 }, /* serialNumber */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (26 << 2)), 6, 0, 0 }, /* processConfigCard */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (30 << 2)), 5, 0, 0 }, /* requestPacs2 */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (43 << 2)), 4, 0, 0 } /* getItemKCV */
|
||||
};
|
||||
asn_CHOICE_specifics_t asn_SPC_SamCommand_specs_1 = {
|
||||
sizeof(struct SamCommand),
|
||||
@@ -97,7 +87,7 @@ asn_CHOICE_specifics_t asn_SPC_SamCommand_specs_1 = {
|
||||
offsetof(struct SamCommand, present),
|
||||
sizeof(((struct SamCommand *)0)->present),
|
||||
asn_MAP_SamCommand_tag2el_1,
|
||||
8, /* Count of tags in the map */
|
||||
7, /* Count of tags in the map */
|
||||
0, 0,
|
||||
-1 /* Extensions start */
|
||||
};
|
||||
@@ -111,7 +101,7 @@ asn_TYPE_descriptor_t asn_DEF_SamCommand = {
|
||||
0, /* No tags (count) */
|
||||
{ 0, 0, CHOICE_constraint },
|
||||
asn_MBR_SamCommand_1,
|
||||
8, /* Elements count */
|
||||
7, /* Elements count */
|
||||
&asn_SPC_SamCommand_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include "RequestPacs.h"
|
||||
#include <NULL.h>
|
||||
#include "CardDetected.h"
|
||||
#include <OCTET_STRING.h>
|
||||
#include "NoArguments.h"
|
||||
#include "RequestPacs.h"
|
||||
#include <constr_CHOICE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -26,7 +26,6 @@ extern "C" {
|
||||
/* Dependencies */
|
||||
typedef enum SamCommand_PR {
|
||||
SamCommand_PR_NOTHING, /* No components present */
|
||||
SamCommand_PR_requestPacs,
|
||||
SamCommand_PR_version,
|
||||
SamCommand_PR_cardDetected,
|
||||
SamCommand_PR_processSNMPMessage,
|
||||
@@ -40,7 +39,6 @@ typedef enum SamCommand_PR {
|
||||
typedef struct SamCommand {
|
||||
SamCommand_PR present;
|
||||
union SamCommand_u {
|
||||
RequestPacs_t requestPacs;
|
||||
NULL_t version;
|
||||
CardDetected_t cardDetected;
|
||||
OCTET_STRING_t processSNMPMessage;
|
||||
@@ -57,7 +55,7 @@ typedef struct SamCommand {
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_SamCommand;
|
||||
extern asn_CHOICE_specifics_t asn_SPC_SamCommand_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_SamCommand_1[8];
|
||||
extern asn_TYPE_member_t asn_MBR_SamCommand_1[7];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -180,10 +180,8 @@ static void seader_sam_set_state(
|
||||
static SeaderSamIntent seader_sam_card_intent(const Seader* seader) {
|
||||
if(seader->credential->type == SeaderCredentialTypeConfig) {
|
||||
return SeaderSamIntentConfig;
|
||||
} else if(seader->is_debug_enabled) {
|
||||
return SeaderSamIntentReadPacs2;
|
||||
} else {
|
||||
return SeaderSamIntentReadPacs;
|
||||
return SeaderSamIntentReadPacs2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,24 +498,6 @@ void seader_send_response(
|
||||
seader_send_payload(seader, &payload, from, to, replyTo);
|
||||
}
|
||||
|
||||
void seader_send_request_pacs(Seader* seader) {
|
||||
RequestPacs_t requestPacs = {0};
|
||||
requestPacs.contentElementTag = ContentElementTag_implicitFormatPhysicalAccessBits;
|
||||
|
||||
SamCommand_t samCommand = {0};
|
||||
samCommand.present = SamCommand_PR_requestPacs;
|
||||
seader_sam_set_state(
|
||||
seader, SeaderSamStateConversation, SeaderSamIntentReadPacs, samCommand.present);
|
||||
samCommand.choice.requestPacs = requestPacs;
|
||||
|
||||
Payload_t payload = {0};
|
||||
payload.present = Payload_PR_samCommand;
|
||||
payload.choice.samCommand = samCommand;
|
||||
|
||||
seader_send_payload(
|
||||
seader, &payload, ExternalApplicationA, SAMInterface, ExternalApplicationA);
|
||||
}
|
||||
|
||||
void seader_send_request_pacs2(Seader* seader) {
|
||||
OCTET_STRING_t oid = {
|
||||
.buf = (uint8_t*)seader_oid,
|
||||
@@ -607,83 +587,86 @@ void seader_send_no_card_detected(Seader* seader) {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_CardDetails, &cardDetails);
|
||||
}
|
||||
|
||||
bool seader_unpack_pacs(Seader* seader, uint8_t* buf, size_t size) {
|
||||
SeaderCredential* seader_credential = seader->credential;
|
||||
PAC_t pac = {0};
|
||||
PAC_t* pac_p = &pac;
|
||||
bool rtn = false;
|
||||
|
||||
asn_dec_rval_t rval = asn_decode(0, ATS_DER, &asn_DEF_PAC, (void**)&pac_p, buf, size);
|
||||
|
||||
if(rval.code == RC_OK) {
|
||||
#ifdef ASN1_DEBUG
|
||||
char pacDebug[384] = {0};
|
||||
(&asn_DEF_PAC)
|
||||
->op->print_struct(&asn_DEF_PAC, &pac, 1, seader_print_struct_callback, pacDebug);
|
||||
if(strlen(pacDebug) > 0) {
|
||||
FURI_LOG_D(TAG, "Received pac: %s", pacDebug);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(seader_credential->sio[0] == 0x30) {
|
||||
seader_log_hex_data(TAG, "SIO", seader_credential->sio, seader_credential->sio_len);
|
||||
|
||||
#ifdef ASN1_DEBUG
|
||||
SIO_t sio = {0};
|
||||
SIO_t* sio_p = &sio;
|
||||
rval = asn_decode(
|
||||
0,
|
||||
ATS_DER,
|
||||
&asn_DEF_SIO,
|
||||
(void**)&sio_p,
|
||||
seader_credential->sio,
|
||||
seader_credential->sio_len);
|
||||
|
||||
if(rval.code == RC_OK) {
|
||||
FURI_LOG_D(TAG, "Decoded SIO");
|
||||
char sioDebug[384] = {0};
|
||||
(&asn_DEF_SIO)
|
||||
->op->print_struct(
|
||||
&asn_DEF_SIO, &sio, 1, seader_print_struct_callback, sioDebug);
|
||||
if(strlen(sioDebug) > 0) {
|
||||
FURI_LOG_D(TAG, "SIO: %s", sioDebug);
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "Failed to decode SIO %d consumed", rval.consumed);
|
||||
}
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_SIO, &sio);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(pac.size <= sizeof(seader_credential->credential)) {
|
||||
// TODO: make credential into a 12 byte array
|
||||
seader_credential->bit_length = pac.size * 8 - pac.bits_unused;
|
||||
uint64_t credential_val = 0;
|
||||
memcpy(&credential_val, pac.buf, pac.size);
|
||||
credential_val = __builtin_bswap64(credential_val);
|
||||
// After bswap64, the bits are left-aligned in the 64-bit word
|
||||
// We need to shift them right by (64 - bit_length) to get the value
|
||||
seader_credential->credential = credential_val >> (64 - seader_credential->bit_length);
|
||||
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"credential (%d) %016llx",
|
||||
seader_credential->bit_length,
|
||||
seader_credential->credential);
|
||||
|
||||
rtn = true;
|
||||
} else {
|
||||
// PACS too big (probably bad data)
|
||||
seader_abort_active_read(seader);
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "Failed to decode PAC %d consumed, size %d", rval.consumed, size);
|
||||
seader_abort_active_read(seader);
|
||||
static bool seader_store_pacs_bits(
|
||||
SeaderCredential* credential,
|
||||
const uint8_t* payload,
|
||||
size_t payload_size,
|
||||
uint8_t unused_bits) {
|
||||
if(!credential || !payload || payload_size == 0 || payload_size > sizeof(credential->credential) ||
|
||||
unused_bits > 7) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_PAC, &pac);
|
||||
return rtn;
|
||||
const uint8_t bit_length = payload_size * 8 - unused_bits;
|
||||
if(bit_length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t credential_val = 0;
|
||||
memcpy(&credential_val, payload, payload_size);
|
||||
credential_val = __builtin_bswap64(credential_val);
|
||||
|
||||
credential->bit_length = bit_length;
|
||||
credential->credential = credential_val >> (64 - bit_length);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool seader_unpack_pacs2_bits(Seader* seader, const OCTET_STRING_t* pacs_bits) {
|
||||
SeaderCredential* seader_credential = seader->credential;
|
||||
if(!pacs_bits || !pacs_bits->buf || pacs_bits->size < 2) {
|
||||
FURI_LOG_W(TAG, "Malformed pacs2 bits");
|
||||
return false;
|
||||
}
|
||||
|
||||
seader_log_hex_data(TAG, "PACS2 bits", pacs_bits->buf, pacs_bits->size);
|
||||
|
||||
if(seader_credential->sio[0] == 0x30) {
|
||||
seader_log_hex_data(TAG, "SIO", seader_credential->sio, seader_credential->sio_len);
|
||||
#ifdef ASN1_DEBUG
|
||||
asn_dec_rval_t rval;
|
||||
SIO_t sio = {0};
|
||||
SIO_t* sio_p = &sio;
|
||||
rval = asn_decode(
|
||||
0,
|
||||
ATS_DER,
|
||||
&asn_DEF_SIO,
|
||||
(void**)&sio_p,
|
||||
seader_credential->sio,
|
||||
seader_credential->sio_len);
|
||||
|
||||
if(rval.code == RC_OK) {
|
||||
FURI_LOG_D(TAG, "Decoded SIO");
|
||||
char sioDebug[384] = {0};
|
||||
(&asn_DEF_SIO)->op->print_struct(
|
||||
&asn_DEF_SIO, &sio, 1, seader_print_struct_callback, sioDebug);
|
||||
if(strlen(sioDebug) > 0) {
|
||||
FURI_LOG_D(TAG, "SIO: %s", sioDebug);
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "Failed to decode SIO %d consumed", rval.consumed);
|
||||
}
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_SIO, &sio);
|
||||
#endif
|
||||
}
|
||||
|
||||
const uint8_t unused_bits = pacs_bits->buf[0];
|
||||
const uint8_t* payload = pacs_bits->buf + 1;
|
||||
const size_t payload_size = pacs_bits->size - 1;
|
||||
FURI_LOG_D(TAG, "PACS2 unused_bits=%u payload_size=%zu", unused_bits, payload_size);
|
||||
|
||||
if(!seader_store_pacs_bits(seader_credential, payload, payload_size, unused_bits)) {
|
||||
FURI_LOG_W(TAG, "Failed to store PACS2 bits");
|
||||
return false;
|
||||
}
|
||||
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"credential (%d) %016llx",
|
||||
seader_credential->bit_length,
|
||||
seader_credential->credential);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 800201298106683d052026b6820101
|
||||
@@ -839,7 +822,6 @@ static void seader_abort_active_read(Seader* seader) {
|
||||
}
|
||||
|
||||
bool seader_parse_sam_response2(Seader* seader, SamResponse2_t* samResponse) {
|
||||
uint8_t buffer[10];
|
||||
switch(samResponse->present) {
|
||||
case SamResponse2_PR_pacs:
|
||||
FURI_LOG_I(TAG, "samResponse2 SamResponse2_PR_pacs");
|
||||
@@ -857,14 +839,13 @@ bool seader_parse_sam_response2(Seader* seader, SamResponse2_t* samResponse) {
|
||||
Pacs2_t pacs2 = samResponse->choice.pacs;
|
||||
OCTET_STRING_t* pacs = pacs2.bits;
|
||||
|
||||
buffer[0] = 0x03;
|
||||
buffer[1] = pacs->size & 0xFF;
|
||||
memcpy(buffer + 2, pacs->buf, pacs->size);
|
||||
if(seader_unpack_pacs(seader, buffer, pacs->size + 2)) {
|
||||
if(seader_unpack_pacs2_bits(seader, pacs)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
seader->view_dispatcher, SeaderCustomEventPollerSuccess);
|
||||
seader_sam_set_state(
|
||||
seader, SeaderSamStateIdle, SeaderSamIntentNone, SamCommand_PR_NOTHING);
|
||||
} else {
|
||||
seader_abort_active_read(seader);
|
||||
}
|
||||
break;
|
||||
case SamResponse2_PR_NOTHING:
|
||||
@@ -886,15 +867,7 @@ bool seader_parse_sam_response(Seader* seader, SamResponse_t* samResponse) {
|
||||
switch(seader->sam_state) {
|
||||
case SeaderSamStateConversation:
|
||||
case SeaderSamStateFinishing:
|
||||
if(seader->sam_intent == SeaderSamIntentReadPacs) {
|
||||
FURI_LOG_I(TAG, "samResponse read PACS");
|
||||
if(seader_unpack_pacs(seader, samResponse->buf, samResponse->size)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
seader->view_dispatcher, SeaderCustomEventPollerSuccess);
|
||||
seader_sam_set_state(
|
||||
seader, SeaderSamStateIdle, SeaderSamIntentNone, SamCommand_PR_NOTHING);
|
||||
}
|
||||
} else if(seader->sam_intent == SeaderSamIntentConfig) {
|
||||
if(seader->sam_intent == SeaderSamIntentConfig) {
|
||||
FURI_LOG_I(TAG, "samResponse config");
|
||||
seader_worker->stage = SeaderPollerEventTypeFail;
|
||||
seader_sam_set_state(
|
||||
@@ -921,8 +894,6 @@ bool seader_parse_sam_response(Seader* seader, SamResponse_t* samResponse) {
|
||||
seader_send_process_config_card(seader);
|
||||
} else if(seader->sam_intent == SeaderSamIntentReadPacs2) {
|
||||
seader_send_request_pacs2(seader);
|
||||
} else if(seader->sam_intent == SeaderSamIntentReadPacs) {
|
||||
seader_send_request_pacs(seader);
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "Unexpected detect intent=%d", seader->sam_intent);
|
||||
seader_abort_active_read(seader);
|
||||
@@ -1379,8 +1350,7 @@ void seader_parse_nfc_off(Seader* seader) {
|
||||
|
||||
seader_send_response(seader, &response, ExternalApplicationA, SAMInterface, 0);
|
||||
if(seader->sam_state == SeaderSamStateConversation &&
|
||||
(seader->sam_intent == SeaderSamIntentReadPacs ||
|
||||
seader->sam_intent == SeaderSamIntentReadPacs2 ||
|
||||
(seader->sam_intent == SeaderSamIntentReadPacs2 ||
|
||||
seader->sam_intent == SeaderSamIntentConfig)) {
|
||||
seader_sam_set_state(
|
||||
seader, SeaderSamStateFinishing, seader->sam_intent, seader->samCommand);
|
||||
|
||||
@@ -22,7 +22,6 @@ ErrorResponse ::= SEQUENCE {
|
||||
}
|
||||
|
||||
SamCommand ::= CHOICE {
|
||||
requestPacs [1] RequestPacs,
|
||||
version [2] NULL,
|
||||
cardDetected [13] CardDetected,
|
||||
processSNMPMessage [20] OCTET STRING,
|
||||
|
||||
@@ -110,7 +110,6 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
SeaderSamIntentNone,
|
||||
SeaderSamIntentReadPacs,
|
||||
SeaderSamIntentReadPacs2,
|
||||
SeaderSamIntentConfig,
|
||||
SeaderSamIntentMaintenance,
|
||||
|
||||
Reference in New Issue
Block a user