reworked the logic and params a bit

This commit is contained in:
iceman1001 2023-07-09 15:26:05 +02:00
commit a49fdbda0d

View file

@ -390,177 +390,169 @@ static int VASReader(uint8_t *pidHash, const char *url, size_t urlLen, uint8_t *
static int CmdVASReader(const char *Cmd) { static int CmdVASReader(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf vas reader", CLIParserInit(&ctx, "hf vas reader",
"Read and decrypt VAS message", "Read and decrypt Value Added Services (VAS) message",
"hf vas reader -p pass.com.example.ticket -k client/resources/vas_priv.key -> select pass and decrypt with priv.key\n" "hf vas reader --url https://example.com -> URL Only mode\n"
"hf vas reader --url https://example.com -> URL Only mode" "hf vas reader --pid pass.com.passkit.pksamples.nfcdemo -f vas_privkey.der -@\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str0("p", NULL, "<pid>", "pass type id"), arg_str0(NULL, "pid", "<str>", "PID, pass type id"),
arg_str0("k", NULL, "<key>", "path to terminal private key"), arg_str0("f", "file", "<fn>", "path to terminal private key file"),
arg_str0(NULL, "url", "<url>", "a URL to provide to the mobile device"), arg_str0(NULL, "url", "<str>", "a URL to provide to the mobile device"),
arg_lit0("@", NULL, "continuous mode"), arg_lit0("@", NULL, "continuous mode"),
arg_lit0("v", "verbose", "log additional information"), arg_lit0("v", "verbose", "log additional information"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
struct arg_str *passTypeIdArg = arg_get_str(ctx, 1); int pidlen = 0;
int passTypeIdLen = arg_get_str_len(ctx, 1); char pid[512] = {0};
uint8_t pidHash[32] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)pid, 512, &pidlen);
sha256hash((uint8_t *) passTypeIdArg->sval[0], passTypeIdLen, pidHash);
struct arg_str *keyPathArg = arg_get_str(ctx, 2); int keyfnlen = 0;
int keyPathLen = arg_get_str_len(ctx, 2); char keyfn[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)keyfn, FILE_PATH_SIZE, &keyfnlen);
if (keyPathLen == 0 && passTypeIdLen > 0) { if (keyfnlen == 0 && pidlen > 0) {
PrintAndLogEx(FAILED, "Must provide path to terminal private key if a pass type id is provided"); PrintAndLogEx(FAILED, "Must provide path to terminal private key if a pass type id is provided");
CLIParserFree(ctx); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
uint8_t *keyData = NULL; int urllen = 0;
size_t keyDataLen = 0; char url[512] = {0};
if (loadFile_safe(keyPathArg->sval[0], "", (void **)&keyData, &keyDataLen) != PM3_SUCCESS) { CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)url, 512, &urllen);
CLIParserFree(ctx);
return PM3_EINVARG; bool continuous = arg_get_lit(ctx, 4);
bool verbose = arg_get_lit(ctx, 5);
CLIParserFree(ctx);
// santity checks
uint8_t *key_data = NULL;
size_t key_datalen = 0;
if (loadFile_safe(keyfn, "", (void **)&key_data, &key_datalen) != PM3_SUCCESS) {
return PM3_EFILE;
} }
mbedtls_ecp_keypair privKey; mbedtls_ecp_keypair privKey;
mbedtls_ecp_keypair_init(&privKey); mbedtls_ecp_keypair_init(&privKey);
if (LoadReaderPrivateKey(keyData, keyDataLen, &privKey) != PM3_SUCCESS) { if (LoadReaderPrivateKey(key_data, key_datalen, &privKey) != PM3_SUCCESS) {
CLIParserFree(ctx); free(key_data);
mbedtls_ecp_keypair_free(&privKey); mbedtls_ecp_keypair_free(&privKey);
return PM3_EINVARG; return PM3_ESOFT;
} }
free(key_data);
free(keyData); PrintAndLogEx(INFO, "Requesting pass type id... " _GREEN_("%s"), sprint_ascii((uint8_t *) pid, pidlen));
struct arg_str *urlArg = arg_get_str(ctx, 3);
int urlLen = arg_get_str_len(ctx, 3);
const char *url = NULL;
if (urlLen > 0) {
url = urlArg->sval[0];
}
bool continuous = arg_get_lit(ctx, 4);
bool verbose = arg_get_lit(ctx, 5);
PrintAndLogEx(INFO, "Requesting pass type id: %s", sprint_ascii((uint8_t *) passTypeIdArg->sval[0], passTypeIdLen));
if (continuous) { if (continuous) {
PrintAndLogEx(INFO, "Press " _GREEN_("Enter") " to exit"); PrintAndLogEx(INFO, "Press " _GREEN_("Enter") " to exit");
} }
uint8_t pidhash[32] = {0};
sha256hash((uint8_t *) pid, pidlen, pidhash);
size_t clen = 0;
size_t mlen = 0;
uint8_t cryptogram[120] = {0}; uint8_t cryptogram[120] = {0};
size_t cryptogramLen = 0; uint8_t msg[64] = {0};
int readerErr = -1; uint32_t timestamp = 0;
int res = PM3_SUCCESS;
do { do {
readerErr = VASReader(passTypeIdLen > 0 ? pidHash : NULL, url, urlLen, cryptogram, &cryptogramLen, verbose); if (continuous && kbd_enter_pressed()) {
if (readerErr == 0 || kbd_enter_pressed()) {
break; break;
} }
msleep(200); res = VASReader( (pidlen > 0) ? pidhash : NULL, url, urllen, cryptogram, &clen, verbose);
if (res == PM3_SUCCESS) {
res = DecryptVASCryptogram(pidhash, cryptogram, clen, &privKey, msg, &mlen, &timestamp);
if (res == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "Timestamp... " _YELLOW_("%d") " (secs since Jan 1, 2001)", timestamp);
PrintAndLogEx(SUCCESS, "Message..... " _YELLOW_("%s"), sprint_ascii(msg, mlen));
// extra sleep after successfull read
if (continuous) {
msleep(3000);
}
}
}
msleep(300);
} while (continuous); } while (continuous);
if (readerErr) {
CLIParserFree(ctx);
mbedtls_ecp_keypair_free(&privKey);
return PM3_EINVARG;
}
uint8_t message[64] = {0};
size_t messageLen = 0;
uint32_t timestamp = 0;
if (DecryptVASCryptogram(pidHash, cryptogram, cryptogramLen, &privKey, message, &messageLen, &timestamp) != PM3_SUCCESS) {
CLIParserFree(ctx);
mbedtls_ecp_keypair_free(&privKey);
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "Message: %s", sprint_ascii(message, messageLen));
PrintAndLogEx(SUCCESS, "Timestamp: %d (secs since Jan 1, 2001)", timestamp);
CLIParserFree(ctx);
mbedtls_ecp_keypair_free(&privKey); mbedtls_ecp_keypair_free(&privKey);
return PM3_SUCCESS; return res;
} }
static int CmdVASDecrypt(const char *Cmd) { static int CmdVASDecrypt(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf vas decrypt", CLIParserInit(&ctx, "hf vas decrypt",
"Decrypt a previously captured cryptogram", "Decrypt a previously captured cryptogram",
"hf vas reader -p pass.com.example.ticket -k client/resources/vas_priv.key -> select pass and decrypt with priv.key\n" "hf vas decrypt --pid pass.com.passkit.pksamples.nfcdemo -f vas_privkey.der -d 00000000\n"
"hf vas reader --url https://example.com -> URL Only mode"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str0("p", NULL, "<pid>", "pass type id"), arg_str0(NULL, "pid", "<str>", "PID, pass type id"),
arg_str0("k", NULL, "<key>", "path to terminal private key"), arg_str0("f", "file", "<fn>", "path to terminal private key file"),
arg_str0(NULL, NULL, "<hex>", "cryptogram to decrypt"), arg_str0("d", "data", "<hex>", "cryptogram to decrypt"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
struct arg_str *passTypeIdArg = arg_get_str(ctx, 1); int pidlen = 0;
int passTypeIdLen = arg_get_str_len(ctx, 1); char pid[512] = {0};
uint8_t pidHash[32] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)pid, 512, &pidlen);
sha256hash((uint8_t *) passTypeIdArg->sval[0], passTypeIdLen, pidHash);
uint8_t cryptogram[120] = {0}; int keyfnlen = 0;
int cryptogramLen = 0; char keyfn[FILE_PATH_SIZE] = {0};
CLIGetHexWithReturn(ctx, 3, cryptogram, &cryptogramLen); CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)keyfn, FILE_PATH_SIZE, &keyfnlen);
struct arg_str *keyPathArg = arg_get_str(ctx, 2); if (keyfnlen == 0 && pidlen > 0) {
int keyPathLen = arg_get_str_len(ctx, 2);
if (keyPathLen == 0 && passTypeIdLen > 0) {
PrintAndLogEx(FAILED, "Must provide path to terminal private key if a pass type id is provided"); PrintAndLogEx(FAILED, "Must provide path to terminal private key if a pass type id is provided");
CLIParserFree(ctx); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
uint8_t *keyData = NULL; int clen = 0;
size_t keyDataLen = 0; uint8_t cryptogram[120] = {0};
if (loadFile_safe(keyPathArg->sval[0], "", (void **)&keyData, &keyDataLen) != PM3_SUCCESS) { CLIGetHexWithReturn(ctx, 3, cryptogram, &clen);
CLIParserFree(ctx); CLIParserFree(ctx);
return PM3_EINVARG;
// santity checks
uint8_t *key_data = NULL;
size_t key_datalen = 0;
if (loadFile_safe(keyfn, "", (void **)&key_data, &key_datalen) != PM3_SUCCESS) {
return PM3_EFILE;
} }
mbedtls_ecp_keypair privKey; mbedtls_ecp_keypair privKey;
mbedtls_ecp_keypair_init(&privKey); mbedtls_ecp_keypair_init(&privKey);
if (LoadReaderPrivateKey(keyData, keyDataLen, &privKey) != PM3_SUCCESS) { if (LoadReaderPrivateKey(key_data, key_datalen, &privKey) != PM3_SUCCESS) {
CLIParserFree(ctx); free(key_data);
mbedtls_ecp_keypair_free(&privKey); mbedtls_ecp_keypair_free(&privKey);
return PM3_EINVARG; return PM3_EFILE;
} }
free(key_data);
free(keyData); uint8_t pidhash[32] = {0};
sha256hash((uint8_t *) pid, pidlen, pidhash);
uint8_t message[64] = {0}; size_t mlen = 0;
size_t messageLen = 0; uint8_t msg[64] = {0};
uint32_t timestamp = 0; uint32_t timestamp = 0;
if (DecryptVASCryptogram(pidHash, cryptogram, cryptogramLen, &privKey, message, &messageLen, &timestamp) != PM3_SUCCESS) { int res = DecryptVASCryptogram(pidhash, cryptogram, clen, &privKey, msg, &mlen, &timestamp);
CLIParserFree(ctx); if (res == PM3_SUCCESS) {
mbedtls_ecp_keypair_free(&privKey); PrintAndLogEx(SUCCESS, "Timestamp... " _YELLOW_("%d") " (secs since Jan 1, 2001)", timestamp);
return PM3_EINVARG; PrintAndLogEx(SUCCESS, "Message..... " _YELLOW_("%s"), sprint_ascii(msg, mlen));
} }
PrintAndLogEx(SUCCESS, "Message: %s", sprint_ascii(message, messageLen));
PrintAndLogEx(SUCCESS, "Timestamp: %d (secs since Jan 1, 2001)", timestamp);
CLIParserFree(ctx);
mbedtls_ecp_keypair_free(&privKey); mbedtls_ecp_keypair_free(&privKey);
return PM3_SUCCESS; return res;
} }
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);