mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-03-29 06:19:53 +00:00
Merge pull request #3156 from cindersocket/fix-3041
Fixes RfidResearchGroup/proxmark3#3041
This commit is contained in:
@@ -3982,24 +3982,71 @@ static int CmdQRcode(const char *Cmd) {
|
||||
CLIParserInit(&ctx, "data qrcode",
|
||||
"Generate a QR code with the input data",
|
||||
"data qrcode -f <filename>\n"
|
||||
"data qrcode -d 123456789\n"
|
||||
"data qrcode -d 0123456789\n"
|
||||
"data qrcode -d AABBCCDD --ascii\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("a", "ascii", "Render with ASCII-safe characters"),
|
||||
arg_str0("f", "file", "<fn>", "Specify a filename"),
|
||||
arg_str0("d", "data", "<hex>", "message as hex bytes"),
|
||||
arg_str0("d", "data", "<hex>", "message as a single hex byte string"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
bool ascii = arg_get_lit(ctx, 1);
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = { 0 };
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
|
||||
int dlen = 0;
|
||||
char data[1024] = { 0 };
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)data, sizeof(data), &dlen);
|
||||
uint8_t data[512] = { 0 };
|
||||
int data_arg_len = 0;
|
||||
char data_arg[1024] = { 0 };
|
||||
struct arg_str *data_arg_str = arg_get_str(ctx, 3);
|
||||
int data_count = data_arg_str->count;
|
||||
|
||||
if (data_count > 1) {
|
||||
CLIParserFree(ctx);
|
||||
PrintAndLogEx(ERR, "QR data accepts exactly one -d value. Use a single contiguous hex string and encode spaces as 20.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (data_count == 1) {
|
||||
if (CLIParamStrToBuf(data_arg_str, (uint8_t *)data_arg, sizeof(data_arg), &data_arg_len) != 0) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (strpbrk(data_arg, " \t") != NULL) {
|
||||
CLIParserFree(ctx);
|
||||
PrintAndLogEx(ERR, "QR data must be one contiguous hex string. Spaces are not supported; encode a space byte as 20.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
for (int i = 0; i < data_arg_len; i++) {
|
||||
if (isxdigit((unsigned char)data_arg[i]) == 0) {
|
||||
CLIParserFree(ctx);
|
||||
PrintAndLogEx(ERR, "QR data must contain only hex characters 0-9, a-f, or A-F.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (data_arg_len & 1) {
|
||||
CLIParserFree(ctx);
|
||||
PrintAndLogEx(ERR, "QR data must contain an even number of hex digits.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
dlen = hex_to_bytes(data_arg, data, sizeof(data));
|
||||
if (dlen < 0) {
|
||||
CLIParserFree(ctx);
|
||||
PrintAndLogEx(ERR, "QR data must be valid hex bytes.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (fnlen && dlen) {
|
||||
@@ -4028,17 +4075,27 @@ static int CmdQRcode(const char *Cmd) {
|
||||
}
|
||||
|
||||
if (dlen) {
|
||||
int8_t smallest_version = qrcode_getMinVersionForBytes(dlen, ECC_LOW);
|
||||
if (smallest_version < 1) {
|
||||
PrintAndLogEx(ERR, "QR data is too large to fit in a supported QR code.");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// calc size of input data to get the correct
|
||||
int smallest_version = (dlen + 17) / 20;
|
||||
uint8_t qr_arr[qrcode_getBufferSize(smallest_version)];
|
||||
qrcode_initText(&qrcode, qr_arr, smallest_version, ECC_LOW, (char *) data);
|
||||
if (qrcode_initBytes(&qrcode, qr_arr, smallest_version, ECC_LOW, data, dlen) < 0) {
|
||||
PrintAndLogEx(ERR, "Failed to encode QR data.");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
qrcode_print_matrix_utf8(&qrcode);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
qrcode_print_matrix_utf8_2x2(&qrcode);
|
||||
if (ascii) {
|
||||
qrcode_print_matrix_ascii(&qrcode);
|
||||
} else {
|
||||
qrcode_print_matrix_utf8(&qrcode);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
qrcode_print_matrix_utf8_2x2(&qrcode);
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -793,6 +793,34 @@ uint16_t qrcode_getBufferSize(uint8_t version) {
|
||||
return bb_getGridSizeBytes(4 * version + 17);
|
||||
}
|
||||
|
||||
int8_t qrcode_getMinVersionForBytes(uint16_t length, uint8_t ecc) {
|
||||
if (ecc > ECC_HIGH) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t eccFormatBits = (ECC_FORMAT_BITS >> (2 * ecc)) & 0x03;
|
||||
|
||||
#if LOCK_VERSION == 0
|
||||
for (uint8_t version = 1; version <= 40; version++) {
|
||||
uint16_t moduleCount = NUM_RAW_DATA_MODULES[version - 1];
|
||||
uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits][version - 1];
|
||||
uint32_t requiredBits = 4 + getModeBits(version, MODE_BYTE) + ((uint32_t)length * 8);
|
||||
|
||||
if (requiredBits <= ((uint32_t)dataCapacity * 8)) {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
#else
|
||||
uint8_t version = LOCK_VERSION;
|
||||
uint16_t moduleCount = NUM_RAW_DATA_MODULES;
|
||||
uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits];
|
||||
uint32_t requiredBits = 4 + getModeBits(version, MODE_BYTE) + ((uint32_t)length * 8);
|
||||
return (requiredBits <= ((uint32_t)dataCapacity * 8)) ? version : -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// @TODO: Return error if data is too big.
|
||||
int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length) {
|
||||
uint8_t size = version * 4 + 17;
|
||||
@@ -885,6 +913,15 @@ bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y) {
|
||||
return (qrcode->modules[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0;
|
||||
}
|
||||
|
||||
void qrcode_print_matrix_ascii(QRCode *q) {
|
||||
for (uint8_t y = 0; y < q->size; y++) {
|
||||
for (uint8_t x = 0; x < q->size; x++) {
|
||||
PrintAndLogEx(NORMAL, "%s" NOLF, qrcode_getModule(q, x, y) ? "##" : " ");
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
}
|
||||
|
||||
void qrcode_print_matrix_utf8(QRCode *q) {
|
||||
|
||||
// UTF-8 block characters for better resolution
|
||||
|
||||
@@ -73,11 +73,13 @@ extern "C" {
|
||||
|
||||
|
||||
uint16_t qrcode_getBufferSize(uint8_t version);
|
||||
int8_t qrcode_getMinVersionForBytes(uint16_t length, uint8_t ecc);
|
||||
|
||||
int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data);
|
||||
int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length);
|
||||
|
||||
bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y);
|
||||
void qrcode_print_matrix_ascii(QRCode *q);
|
||||
void qrcode_print_matrix_utf8(QRCode *q);
|
||||
void qrcode_print_matrix_utf8_2x2(QRCode *q);
|
||||
|
||||
|
||||
@@ -462,6 +462,11 @@ while true; do
|
||||
if ! CheckExecute "reveng readline test" "$CLIENTBIN -c 'reveng -h;reveng -D'" "CRC-64/GO-ISO"; then break; fi
|
||||
if ! CheckExecute "reveng -g test" "$CLIENTBIN -c 'reveng -g abda202c'" "CRC-16/ISO-IEC-14443-3-A"; then break; fi
|
||||
if ! CheckExecute "reveng -w test" "$CLIENTBIN -c 'reveng -w 8 -s 01020304e3 010204039d'" "CRC-8/SMBUS"; then break; fi
|
||||
if ! CheckExecute "data qrcode ascii test" "$CLIENTBIN -c 'data qrcode -d aa --ascii'" "##"; then break; fi
|
||||
if ! CheckExecute "data qrcode repeated -d" "$CLIENTBIN -c 'data qrcode -d aa -d bb' 2>&1" "excess option -d\\|--data"; then break; fi
|
||||
if ! CheckExecute "data qrcode invalid hex" "$CLIENTBIN -c 'data qrcode -d zz' 2>&1" "QR data must contain only hex characters"; then break; fi
|
||||
if ! CheckExecute "data qrcode odd hex" "$CLIENTBIN -c 'data qrcode -d a' 2>&1" "QR data must contain an even number of hex digits"; then break; fi
|
||||
if ! CheckExecute "data qrcode spaced hex" "$CLIENTBIN -c 'data qrcode -d \"aa bb\"' 2>&1" "Spaces are not supported; encode a space byte as 20"; then break; fi
|
||||
if ! CheckExecute "mfu pwdgen test" "$CLIENTBIN -c 'hf mfu pwdgen --test'" "Selftest ok"; then break; fi
|
||||
if ! CheckExecute "mfu keygen test" "$CLIENTBIN -c 'hf mfu keygen --uid 11223344556677'" "80 B1 C2 71 D8 A0"; then break; fi
|
||||
if ! CheckExecute "jooki encode test" "$CLIENTBIN -c 'hf jooki encode --test'" "04 28 F4 DA F0 4A 81 \( ok \)"; then break; fi
|
||||
|
||||
Reference in New Issue
Block a user