From 38d0ba12f9bb242c758ccf7fc0a2b2055973b301 Mon Sep 17 00:00:00 2001 From: kormax <3392860+kormax@users.noreply.github.com> Date: Wed, 25 Mar 2026 17:15:27 +0200 Subject: [PATCH] Move '--aidsearch' matching to regex --- client/resources/aidlist.json | 6 +++--- client/src/aidsearch.c | 25 ++----------------------- doc/aidlist.md | 4 ++-- 3 files changed, 7 insertions(+), 28 deletions(-) diff --git a/client/resources/aidlist.json b/client/resources/aidlist.json index eb337dbf8..b884d3179 100644 --- a/client/resources/aidlist.json +++ b/client/resources/aidlist.json @@ -2222,7 +2222,7 @@ "Name": "Apple VAS (OSE.VAS.01)", "Description": "Apple VAS", "Type": "loyalty", - "ResponseContains": "50084170706c65506179" + "ResponseRegex": ".*50084170706c65506179.*9000$" }, { "AID": "4F53452E5641532E3031", @@ -2231,7 +2231,7 @@ "Name": "Google Smart Tap (OSE.VAS.01)", "Description": "Google Smart Tap", "Type": "loyalty", - "ResponseContains": "500a416e64726f6964506179" + "ResponseRegex": ".*500a416e64726f6964506179.*9000$" }, { "AID": "4F53452E5641532E3031", @@ -2240,7 +2240,7 @@ "Name": "Samsung VAS (OSE.VAS.01)", "Description": "Samsung VAS", "Type": "loyalty", - "ResponseContains": "500d53616d73756e6757616c6c6574" + "ResponseRegex": ".*500d53616d73756e6757616c6c6574.*9000$" }, { "AID": "A000000476D0000101", diff --git a/client/src/aidsearch.c b/client/src/aidsearch.c index 65810c0b6..60d2af202 100644 --- a/client/src/aidsearch.c +++ b/client/src/aidsearch.c @@ -112,27 +112,6 @@ static bool aidCompare(const char *aidlarge, const char *aidsmall) { return false; } -static bool ResponseContainsMatch(const char *needle, const char *text) { - if (needle == NULL || text == NULL || needle[0] == '\0' || text[0] == '\0') { - return false; - } - - char *needle_lc = str_dup(needle); - char *text_lc = str_dup(text); - if (needle_lc == NULL || text_lc == NULL) { - free(needle_lc); - free(text_lc); - return false; - } - - str_lower(needle_lc); - str_lower(text_lc); - bool matched = (strstr(text_lc, needle_lc) != NULL); - free(needle_lc); - free(text_lc); - return matched; -} - bool AIDGetFromElm(json_t *data, uint8_t *aid, size_t aidmaxlen, int *aidlen) { *aidlen = 0; const char *hexaid = jsonStrGet(data, "AID"); @@ -245,8 +224,8 @@ int PrintAIDDescriptionEx(json_t *xroot, char *aid, const uint8_t *response, siz } if (response_hex != NULL) { - const char *response_contains = jsonStrGet(data, "ResponseContains"); - if (response_contains && ResponseContainsMatch(response_contains, response_hex)) { + const char *response_regex = jsonStrGet(data, "ResponseRegex"); + if (response_regex && str_regex_match_case_insensitive(response_regex, response_hex)) { contains_elm = data; } } diff --git a/doc/aidlist.md b/doc/aidlist.md index 800644a4b..0ffaf0f17 100644 --- a/doc/aidlist.md +++ b/doc/aidlist.md @@ -16,7 +16,7 @@ Each entry in `client/resources/aidlist.json` must contain all of the fields bel - `Type`: High-level category tag (for example `transport`, `emv`, `gp`, `pacs`, `ndef`). ## Optional fields -- `ResponseContains`: Case-insensitive hex substring matched against the APDU SELECT response (encoded as hex without separators). Use this field when multiple protocols share the same AID and can be distinguished by response content. +- `ResponseRegex`: Case-insensitive regex matched against the APDU SELECT response encoded as hex without separators. Current regex subset supports `^`, `$`, `.`, `*`, and `\` escape. Use this field when multiple protocols share the same AID and can be distinguished by response content. Example: ```json @@ -39,6 +39,6 @@ Response-disambiguation example: "Name": "Google Smart Tap (OSE.VAS.01)", "Description": "Google Smart Tap", "Type": "loyalty", - "ResponseContains": "500a416e64726f6964506179" + "ResponseRegex": ".*500a416e64726f6964506179.*9000$" } ```