mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 18:48:13 -07:00
Merge branch 'master' into bruteforce-smart-mode
This commit is contained in:
commit
8e0e8e2240
1273 changed files with 74746 additions and 17013 deletions
|
@ -22,6 +22,7 @@
|
|||
#include "cmdsmartcard.h"
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
#include "commonutil.h"
|
||||
|
||||
#define CARD_INS_DECRYPT 0x01
|
||||
#define CARD_INS_ENCRYPT 0x02
|
||||
|
@ -35,26 +36,77 @@
|
|||
// look for CardHelper
|
||||
bool IsCardHelperPresent(bool verbose) {
|
||||
|
||||
if (IfPm3Smartcard()) {
|
||||
int resp_len = 0;
|
||||
uint8_t version[] = {0x96, 0x69, 0x00, 0x00, 0x00};
|
||||
uint8_t resp[30] = {0};
|
||||
ExchangeAPDUSC(verbose, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len);
|
||||
if (IfPm3Smartcard() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (resp_len < 8) {
|
||||
return false;
|
||||
}
|
||||
int resp_len = 0;
|
||||
uint8_t version[] = {0x96, 0x69, 0x00, 0x00, 0x00};
|
||||
uint8_t resp[30] = {0};
|
||||
ExchangeAPDUSC(verbose, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len);
|
||||
|
||||
if (strstr("CryptoHelper", (char *)resp) == 0) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Found smart card helper");
|
||||
}
|
||||
return true;
|
||||
if (resp_len < 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strstr("CryptoHelper", (char *)resp) == 0) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Found smart card helper");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsHIDSamPresent(bool verbose) {
|
||||
|
||||
if (IfPm3Smartcard() == false) {
|
||||
PrintAndLogEx(WARNING, "Proxmark3 does not have SMARTCARD support enabled, exiting");
|
||||
return false;
|
||||
}
|
||||
|
||||
// detect SAM
|
||||
smart_card_atr_t card;
|
||||
smart_select(verbose, &card);
|
||||
if (card.atr_len == 0) {
|
||||
PrintAndLogEx(ERR, "Can't get ATR from a smart card");
|
||||
return false;
|
||||
}
|
||||
|
||||
// SAM identification
|
||||
smart_card_atr_t supported[] = {
|
||||
{15, {0x3B, 0x95, 0x96, 0x80, 0xB1, 0xFE, 0x55, 0x1F, 0xC7, 0x47, 0x72, 0x61, 0x63, 0x65, 0x13}},
|
||||
{11, {0x3b, 0x90, 0x96, 0x91, 0x81, 0xb1, 0xfe, 0x55, 0x1f, 0xc7, 0xd4}},
|
||||
};
|
||||
bool found = false;
|
||||
for (int i = 0; i < ARRAYLEN(supported); i++) {
|
||||
if ((card.atr_len == supported[i].atr_len) &&
|
||||
(memcmp(card.atr, supported[i].atr, supported[i].atr_len) == 0)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == false) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(SUCCESS, "Not detecting a SAM");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Suspect some SAMs has version name in the historical bytes
|
||||
uint8_t T0 = card.atr[1];
|
||||
uint8_t K = T0 & 0x0F; // Number of historical bytes
|
||||
if (K > 0 && (K < (card.atr_len - 3)) && verbose) {
|
||||
// Last byte of ATR is CRC and before that we have K bytes of
|
||||
// "historical bytes".
|
||||
// By construction K can't go above 15
|
||||
char sam_name[16] = {0};
|
||||
memcpy(sam_name, &card.atr[card.atr_len - 1 - K], K);
|
||||
PrintAndLogEx(SUCCESS, "SAM (%s) detected", sam_name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) {
|
||||
uint8_t cmd[] = {0x96, ins, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
memcpy(cmd + 5, src, 8);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <ctype.h>
|
||||
#include "common.h"
|
||||
|
||||
bool IsHIDSamPresent(bool verbose);
|
||||
bool IsCardHelperPresent(bool verbose);
|
||||
bool Encrypt(uint8_t *src, uint8_t *dest);
|
||||
bool Decrypt(uint8_t *src, uint8_t *dest);
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
* verifies the magic properties, then stores a formatted string, prefixed by
|
||||
* prefix in dst.
|
||||
*/
|
||||
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_info) {
|
||||
struct version_information_t *v = (struct version_information_t *)version_info;
|
||||
void FormatVersionInformation(char *dst, int len, const char *prefix, const void *version_info) {
|
||||
const struct version_information_t *v = (const struct version_information_t *)version_info;
|
||||
dst[0] = 0;
|
||||
strncat(dst, prefix, len - 1);
|
||||
if (v->magic != VERSION_INFORMATION_MAGIC) {
|
||||
|
@ -53,8 +53,8 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
|
|||
strncat(dst, v->armsrc, len - strlen(dst) - 1);
|
||||
}
|
||||
|
||||
void format_version_information_short(char *dst, int len, void *version_info) {
|
||||
struct version_information_t *v = (struct version_information_t *)version_info;
|
||||
void format_version_information_short(char *dst, int len, const void *version_info) {
|
||||
const struct version_information_t *v = (const struct version_information_t *)version_info;
|
||||
dst[0] = 0;
|
||||
if (v->magic != VERSION_INFORMATION_MAGIC) {
|
||||
strncat(dst, "Missing/Invalid version information", len - strlen(dst) - 1);
|
||||
|
@ -151,7 +151,7 @@ void num_to_bytes(uint64_t n, size_t len, uint8_t *dest) {
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t bytes_to_num(uint8_t *src, size_t len) {
|
||||
uint64_t bytes_to_num(const uint8_t *src, size_t len) {
|
||||
uint64_t num = 0;
|
||||
while (len--) {
|
||||
num = (num << 8) | (*src);
|
||||
|
@ -161,63 +161,255 @@ uint64_t bytes_to_num(uint8_t *src, size_t len) {
|
|||
}
|
||||
|
||||
uint16_t MemLeToUint2byte(const uint8_t *data) {
|
||||
return (data[1] << 8) + data[0];
|
||||
return (uint16_t)(
|
||||
(((uint16_t)(data[1])) << (8 * 1)) +
|
||||
(((uint16_t)(data[0])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint32_t MemLeToUint3byte(const uint8_t *data) {
|
||||
return (data[2] << 16) + (data[1] << 8) + data[0];
|
||||
return (uint32_t)(
|
||||
(((uint32_t)(data[2])) << (8 * 2)) +
|
||||
(((uint32_t)(data[1])) << (8 * 1)) +
|
||||
(((uint32_t)(data[0])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint32_t MemLeToUint4byte(const uint8_t *data) {
|
||||
return (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0];
|
||||
return (uint32_t)(
|
||||
(((uint32_t)(data[3])) << (8 * 3)) +
|
||||
(((uint32_t)(data[2])) << (8 * 2)) +
|
||||
(((uint32_t)(data[1])) << (8 * 1)) +
|
||||
(((uint32_t)(data[0])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t MemLeToUint5byte(const uint8_t *data) {
|
||||
return (uint64_t)(
|
||||
(((uint64_t)(data[4])) << (8 * 4)) +
|
||||
(((uint64_t)(data[3])) << (8 * 3)) +
|
||||
(((uint64_t)(data[2])) << (8 * 2)) +
|
||||
(((uint64_t)(data[1])) << (8 * 1)) +
|
||||
(((uint64_t)(data[0])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t MemLeToUint6byte(const uint8_t *data) {
|
||||
return (uint64_t)(
|
||||
(((uint64_t)(data[5])) << (8 * 5)) +
|
||||
(((uint64_t)(data[4])) << (8 * 4)) +
|
||||
(((uint64_t)(data[3])) << (8 * 3)) +
|
||||
(((uint64_t)(data[2])) << (8 * 2)) +
|
||||
(((uint64_t)(data[1])) << (8 * 1)) +
|
||||
(((uint64_t)(data[0])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t MemLeToUint7byte(const uint8_t *data) {
|
||||
return (uint64_t)(
|
||||
(((uint64_t)(data[6])) << (8 * 6)) +
|
||||
(((uint64_t)(data[5])) << (8 * 5)) +
|
||||
(((uint64_t)(data[4])) << (8 * 4)) +
|
||||
(((uint64_t)(data[3])) << (8 * 3)) +
|
||||
(((uint64_t)(data[2])) << (8 * 2)) +
|
||||
(((uint64_t)(data[1])) << (8 * 1)) +
|
||||
(((uint64_t)(data[0])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t MemLeToUint8byte(const uint8_t *data) {
|
||||
return (uint64_t)(
|
||||
(((uint64_t)(data[7])) << (8 * 7)) +
|
||||
(((uint64_t)(data[6])) << (8 * 6)) +
|
||||
(((uint64_t)(data[5])) << (8 * 5)) +
|
||||
(((uint64_t)(data[4])) << (8 * 4)) +
|
||||
(((uint64_t)(data[3])) << (8 * 3)) +
|
||||
(((uint64_t)(data[2])) << (8 * 2)) +
|
||||
(((uint64_t)(data[1])) << (8 * 1)) +
|
||||
(((uint64_t)(data[0])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint16_t MemBeToUint2byte(const uint8_t *data) {
|
||||
return (data[0] << 8) + data[1];
|
||||
return (uint16_t)(
|
||||
(((uint16_t)(data[0])) << (8 * 1)) +
|
||||
(((uint16_t)(data[1])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint32_t MemBeToUint3byte(const uint8_t *data) {
|
||||
return (data[0] << 16) + (data[1] << 8) + data[2];
|
||||
return (uint32_t)(
|
||||
(((uint32_t)(data[0])) << (8 * 2)) +
|
||||
(((uint32_t)(data[1])) << (8 * 1)) +
|
||||
(((uint32_t)(data[2])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint32_t MemBeToUint4byte(const uint8_t *data) {
|
||||
return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
|
||||
return (uint32_t)(
|
||||
(((uint32_t)(data[0])) << (8 * 3)) +
|
||||
(((uint32_t)(data[1])) << (8 * 2)) +
|
||||
(((uint32_t)(data[2])) << (8 * 1)) +
|
||||
(((uint32_t)(data[3])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t MemBeToUint5byte(const uint8_t *data) {
|
||||
return (uint64_t)(
|
||||
(((uint64_t)(data[0])) << (8 * 4)) +
|
||||
(((uint64_t)(data[1])) << (8 * 3)) +
|
||||
(((uint64_t)(data[2])) << (8 * 2)) +
|
||||
(((uint64_t)(data[3])) << (8 * 1)) +
|
||||
(((uint64_t)(data[4])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t MemBeToUint6byte(const uint8_t *data) {
|
||||
return (uint64_t)(
|
||||
(((uint64_t)(data[0])) << (8 * 5)) +
|
||||
(((uint64_t)(data[1])) << (8 * 4)) +
|
||||
(((uint64_t)(data[2])) << (8 * 3)) +
|
||||
(((uint64_t)(data[3])) << (8 * 2)) +
|
||||
(((uint64_t)(data[4])) << (8 * 1)) +
|
||||
(((uint64_t)(data[5])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t MemBeToUint7byte(const uint8_t *data) {
|
||||
return (uint64_t)(
|
||||
(((uint64_t)(data[0])) << (8 * 6)) +
|
||||
(((uint64_t)(data[1])) << (8 * 5)) +
|
||||
(((uint64_t)(data[2])) << (8 * 4)) +
|
||||
(((uint64_t)(data[3])) << (8 * 3)) +
|
||||
(((uint64_t)(data[4])) << (8 * 2)) +
|
||||
(((uint64_t)(data[5])) << (8 * 1)) +
|
||||
(((uint64_t)(data[6])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t MemBeToUint8byte(const uint8_t *data) {
|
||||
return (uint64_t)(
|
||||
(((uint64_t)(data[0])) << (8 * 7)) +
|
||||
(((uint64_t)(data[1])) << (8 * 6)) +
|
||||
(((uint64_t)(data[2])) << (8 * 5)) +
|
||||
(((uint64_t)(data[3])) << (8 * 4)) +
|
||||
(((uint64_t)(data[4])) << (8 * 3)) +
|
||||
(((uint64_t)(data[5])) << (8 * 2)) +
|
||||
(((uint64_t)(data[6])) << (8 * 1)) +
|
||||
(((uint64_t)(data[7])) << (8 * 0))
|
||||
);
|
||||
}
|
||||
|
||||
void Uint2byteToMemLe(uint8_t *data, uint16_t value) {
|
||||
data[1] = (value >> 8) & 0xff;
|
||||
data[0] = value & 0xff;
|
||||
data[0] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint3byteToMemLe(uint8_t *data, uint32_t value) {
|
||||
data[2] = (value >> 16) & 0xff;
|
||||
data[1] = (value >> 8) & 0xff;
|
||||
data[0] = value & 0xff;
|
||||
data[0] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint4byteToMemLe(uint8_t *data, uint32_t value) {
|
||||
data[3] = (value >> 24) & 0xff;
|
||||
data[2] = (value >> 16) & 0xff;
|
||||
data[1] = (value >> 8) & 0xff;
|
||||
data[0] = value & 0xff;
|
||||
data[0] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[3] = (uint8_t)((value >> (8 * 3)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint5byteToMemLe(uint8_t *data, uint64_t value) {
|
||||
data[0] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[3] = (uint8_t)((value >> (8 * 3)) & 0xffu);
|
||||
data[4] = (uint8_t)((value >> (8 * 4)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint6byteToMemLe(uint8_t *data, uint64_t value) {
|
||||
data[0] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[3] = (uint8_t)((value >> (8 * 3)) & 0xffu);
|
||||
data[4] = (uint8_t)((value >> (8 * 4)) & 0xffu);
|
||||
data[5] = (uint8_t)((value >> (8 * 5)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint7byteToMemLe(uint8_t *data, uint64_t value) {
|
||||
data[0] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[3] = (uint8_t)((value >> (8 * 3)) & 0xffu);
|
||||
data[4] = (uint8_t)((value >> (8 * 4)) & 0xffu);
|
||||
data[5] = (uint8_t)((value >> (8 * 5)) & 0xffu);
|
||||
data[6] = (uint8_t)((value >> (8 * 6)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint8byteToMemLe(uint8_t *data, uint64_t value) {
|
||||
data[0] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[3] = (uint8_t)((value >> (8 * 3)) & 0xffu);
|
||||
data[4] = (uint8_t)((value >> (8 * 4)) & 0xffu);
|
||||
data[5] = (uint8_t)((value >> (8 * 5)) & 0xffu);
|
||||
data[6] = (uint8_t)((value >> (8 * 6)) & 0xffu);
|
||||
data[7] = (uint8_t)((value >> (8 * 7)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint2byteToMemBe(uint8_t *data, uint16_t value) {
|
||||
data[0] = (value >> 8) & 0xff;
|
||||
data[1] = value & 0xff;
|
||||
data[0] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint3byteToMemBe(uint8_t *data, uint32_t value) {
|
||||
data[0] = (value >> 16) & 0xff;
|
||||
data[1] = (value >> 8) & 0xff;
|
||||
data[2] = value & 0xff;
|
||||
data[0] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint4byteToMemBe(uint8_t *data, uint32_t value) {
|
||||
data[0] = (value >> 24) & 0xff;
|
||||
data[1] = (value >> 16) & 0xff;
|
||||
data[2] = (value >> 8) & 0xff;
|
||||
data[3] = value & 0xff;
|
||||
data[0] = (uint8_t)((value >> (8 * 3)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[3] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint5byteToMemBe(uint8_t *data, uint64_t value) {
|
||||
data[0] = (uint8_t)((value >> (8 * 4)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 3)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[3] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[4] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint6byteToMemBe(uint8_t *data, uint64_t value) {
|
||||
data[0] = (uint8_t)((value >> (8 * 5)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 4)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 3)) & 0xffu);
|
||||
data[3] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[4] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[5] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint7byteToMemBe(uint8_t *data, uint64_t value) {
|
||||
data[0] = (uint8_t)((value >> (8 * 6)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 5)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 4)) & 0xffu);
|
||||
data[3] = (uint8_t)((value >> (8 * 3)) & 0xffu);
|
||||
data[4] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[5] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[6] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
}
|
||||
|
||||
void Uint8byteToMemBe(uint8_t *data, uint64_t value) {
|
||||
data[0] = (uint8_t)((value >> (8 * 7)) & 0xffu);
|
||||
data[1] = (uint8_t)((value >> (8 * 6)) & 0xffu);
|
||||
data[2] = (uint8_t)((value >> (8 * 5)) & 0xffu);
|
||||
data[3] = (uint8_t)((value >> (8 * 4)) & 0xffu);
|
||||
data[4] = (uint8_t)((value >> (8 * 3)) & 0xffu);
|
||||
data[5] = (uint8_t)((value >> (8 * 2)) & 0xffu);
|
||||
data[6] = (uint8_t)((value >> (8 * 1)) & 0xffu);
|
||||
data[7] = (uint8_t)((value >> (8 * 0)) & 0xffu);
|
||||
}
|
||||
|
||||
// RotateLeft - Ultralight, Desfire
|
||||
|
@ -293,3 +485,45 @@ void reverse_array_copy(const uint8_t *src, int src_len, uint8_t *dest) {
|
|||
dest[i] = src[(src_len - 1) - i];
|
||||
}
|
||||
}
|
||||
|
||||
static int hexchar_to_dec(char ch) {
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
return ch - '0';
|
||||
}
|
||||
if (ch >= 'a' && ch <= 'f') {
|
||||
return ch - 'a' + 10;
|
||||
}
|
||||
if (ch >= 'A' && ch <= 'F') {
|
||||
return ch - 'A' + 10;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// no spaces allowed for input hex string
|
||||
bool hexstr_to_byte_array(const char *hexstr, uint8_t *d, size_t *n) {
|
||||
|
||||
size_t hexstr_len = strlen(hexstr);
|
||||
if (hexstr_len & 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*n = (hexstr_len >> 1);
|
||||
|
||||
for (int i = 0; i < *n; i++) {
|
||||
|
||||
char c1 = *hexstr++;
|
||||
char c2 = *hexstr++;
|
||||
|
||||
if (c1 == '\0' || c2 == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
int b = (hexchar_to_dec(c1) << 4) | hexchar_to_dec(c2);
|
||||
if (b < 0) {
|
||||
// Error: invalid hex character
|
||||
return false;
|
||||
}
|
||||
d[i] = (uint8_t) b;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -50,8 +50,8 @@
|
|||
#endif
|
||||
|
||||
extern struct version_information_t g_version_information;
|
||||
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_info);
|
||||
void format_version_information_short(char *dst, int len, void *version_info);
|
||||
void FormatVersionInformation(char *dst, int len, const char *prefix, const void *version_info);
|
||||
void format_version_information_short(char *dst, int len, const void *version_info);
|
||||
|
||||
uint32_t reflect(uint32_t v, int b); // used in crc.c ...
|
||||
uint8_t reflect8(uint8_t b); // dedicated 8bit reversal
|
||||
|
@ -59,21 +59,40 @@ uint16_t reflect16(uint16_t b); // dedicated 16bit reversal
|
|||
uint32_t reflect32(uint32_t b); // dedicated 32bit reversal
|
||||
|
||||
void num_to_bytes(uint64_t n, size_t len, uint8_t *dest);
|
||||
uint64_t bytes_to_num(uint8_t *src, size_t len);
|
||||
uint64_t bytes_to_num(const uint8_t *src, size_t len);
|
||||
|
||||
// LE and BE to/from memory
|
||||
uint16_t MemLeToUint2byte(const uint8_t *data);
|
||||
uint32_t MemLeToUint3byte(const uint8_t *data);
|
||||
uint32_t MemLeToUint4byte(const uint8_t *data);
|
||||
uint64_t MemLeToUint5byte(const uint8_t *data);
|
||||
uint64_t MemLeToUint6byte(const uint8_t *data);
|
||||
uint64_t MemLeToUint7byte(const uint8_t *data);
|
||||
uint64_t MemLeToUint8byte(const uint8_t *data);
|
||||
|
||||
uint16_t MemBeToUint2byte(const uint8_t *data);
|
||||
uint32_t MemBeToUint3byte(const uint8_t *data);
|
||||
uint32_t MemBeToUint4byte(const uint8_t *data);
|
||||
uint64_t MemBeToUint5byte(const uint8_t *data);
|
||||
uint64_t MemBeToUint6byte(const uint8_t *data);
|
||||
uint64_t MemBeToUint7byte(const uint8_t *data);
|
||||
uint64_t MemBeToUint8byte(const uint8_t *data);
|
||||
|
||||
void Uint2byteToMemLe(uint8_t *data, uint16_t value);
|
||||
void Uint3byteToMemLe(uint8_t *data, uint32_t value);
|
||||
void Uint4byteToMemLe(uint8_t *data, uint32_t value);
|
||||
void Uint5byteToMemLe(uint8_t *data, uint64_t value);
|
||||
void Uint6byteToMemLe(uint8_t *data, uint64_t value);
|
||||
void Uint7byteToMemLe(uint8_t *data, uint64_t value);
|
||||
void Uint8byteToMemLe(uint8_t *data, uint64_t value);
|
||||
|
||||
void Uint2byteToMemBe(uint8_t *data, uint16_t value);
|
||||
void Uint3byteToMemBe(uint8_t *data, uint32_t value);
|
||||
void Uint4byteToMemBe(uint8_t *data, uint32_t value);
|
||||
void Uint5byteToMemBe(uint8_t *data, uint64_t value);
|
||||
void Uint6byteToMemBe(uint8_t *data, uint64_t value);
|
||||
void Uint7byteToMemBe(uint8_t *data, uint64_t value);
|
||||
void Uint8byteToMemBe(uint8_t *data, uint64_t value);
|
||||
|
||||
// rotate left byte array
|
||||
void rol(uint8_t *data, const size_t len);
|
||||
|
@ -90,4 +109,5 @@ uint16_t get_sw(const uint8_t *d, uint16_t n);
|
|||
void reverse_array(uint8_t *d, size_t n);
|
||||
void reverse_array_copy(const uint8_t *src, int src_len, uint8_t *dest);
|
||||
|
||||
bool hexstr_to_byte_array(const char *hexstr, uint8_t *d, size_t *n);
|
||||
#endif
|
||||
|
|
|
@ -3,10 +3,10 @@ CRAPTO1
|
|||
Provides a set of library functions which aid the verification
|
||||
of crypto1 weaknesses.
|
||||
|
||||
In short a partial implementation of:
|
||||
In short a partial implementation of:
|
||||
Dismantling MIFARE Classic
|
||||
URL: http://www.sos.cs.ru.nl/applications/rfid/2008-esorics.pdf
|
||||
Flavio D. Garcia, Gerhard de Koning Gans, Ruben Muijrers,
|
||||
Flavio D. Garcia, Gerhard de Koning Gans, Ruben Muijrers,
|
||||
Peter van Rossum, Roel Verdult, Ronny Wichers Schreur, Bart Jacobs
|
||||
Institute for Computing and Information Sciences,
|
||||
Radboud University Nijmegen, The Netherlands
|
||||
|
|
|
@ -42,10 +42,14 @@ void init_table(CrcType_t crctype) {
|
|||
case CRC_15693:
|
||||
case CRC_ICLASS:
|
||||
case CRC_CRYPTORF:
|
||||
case CRC_KERMIT:
|
||||
generate_table(CRC16_POLY_CCITT, true);
|
||||
break;
|
||||
case CRC_FELICA:
|
||||
case CRC_XMODEM:
|
||||
case CRC_CCITT:
|
||||
case CRC_11784:
|
||||
case CRC_PHILIPS:
|
||||
generate_table(CRC16_POLY_CCITT, false);
|
||||
break;
|
||||
case CRC_LEGIC:
|
||||
|
@ -54,15 +58,6 @@ void init_table(CrcType_t crctype) {
|
|||
case CRC_LEGIC_16:
|
||||
generate_table(CRC16_POLY_LEGIC_16, true);
|
||||
break;
|
||||
case CRC_CCITT:
|
||||
generate_table(CRC16_POLY_CCITT, false);
|
||||
break;
|
||||
case CRC_KERMIT:
|
||||
generate_table(CRC16_POLY_CCITT, true);
|
||||
break;
|
||||
case CRC_11784:
|
||||
generate_table(CRC16_POLY_CCITT, false);
|
||||
break;
|
||||
case CRC_NONE:
|
||||
crc_table_init = false;
|
||||
current_crc_type = CRC_NONE;
|
||||
|
@ -210,6 +205,9 @@ void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8
|
|||
case CRC_LEGIC_16:
|
||||
// TODO
|
||||
return;
|
||||
case CRC_PHILIPS:
|
||||
crc = crc16_philips(d, n);
|
||||
break;
|
||||
case CRC_NONE:
|
||||
return;
|
||||
}
|
||||
|
@ -244,6 +242,8 @@ uint16_t Crc16ex(CrcType_t ct, const uint8_t *d, size_t n) {
|
|||
case CRC_LEGIC_16:
|
||||
// TODO
|
||||
return 0;
|
||||
case CRC_PHILIPS:
|
||||
return crc16_philips(d, n);
|
||||
case CRC_NONE:
|
||||
default:
|
||||
break;
|
||||
|
@ -290,6 +290,8 @@ bool check_crc(CrcType_t ct, const uint8_t *d, size_t n) {
|
|||
case CRC_LEGIC_16:
|
||||
// TODO
|
||||
return false;
|
||||
case CRC_PHILIPS:
|
||||
return (crc16_philips(d, n) == 0);
|
||||
case CRC_NONE:
|
||||
default:
|
||||
break;
|
||||
|
@ -350,3 +352,6 @@ uint16_t crc16_legic(uint8_t const *d, size_t n, uint8_t uidcrc) {
|
|||
return crc16_fast(d, n, initial, true, false);
|
||||
}
|
||||
|
||||
uint16_t crc16_philips(uint8_t const *d, size_t n) {
|
||||
return crc16_fast(d, n, 0x49A3, false, false);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ typedef enum {
|
|||
CRC_KERMIT,
|
||||
CRC_XMODEM,
|
||||
CRC_CRYPTORF,
|
||||
CRC_PHILIPS,
|
||||
} CrcType_t;
|
||||
|
||||
uint16_t update_crc16_ex(uint16_t crc, uint8_t c, uint16_t polynomial);
|
||||
|
@ -78,6 +79,9 @@ uint16_t crc16_iclass(uint8_t const *d, size_t n);
|
|||
// ie: uidcrc = 0x78 then initial_value == 0x7878
|
||||
uint16_t crc16_legic(uint8_t const *d, size_t n, uint8_t uidcrc);
|
||||
|
||||
// Calculate CRC-16/ Philips.
|
||||
uint16_t crc16_philips(uint8_t const *d, size_t n);
|
||||
|
||||
// table implementation
|
||||
void init_table(CrcType_t crctype);
|
||||
void reset_table(void);
|
||||
|
|
|
@ -26,5 +26,7 @@ const struct version_information_t SECTVERSINFO g_version_information = {
|
|||
1, /* version 1 */
|
||||
0, /* version information not present */
|
||||
2, /* cleanliness couldn't be determined */
|
||||
/* Remaining fields: zero */
|
||||
"Iceman/master/unknown",
|
||||
"1970-01-01 00:00:00",
|
||||
"no sha256"
|
||||
};
|
||||
|
|
|
@ -173,7 +173,7 @@ uint32_t ul_ev1_pwdgenD(const uint8_t *uid) {
|
|||
|
||||
// AIR purifier Xiaomi
|
||||
uint32_t ul_ev1_pwdgenE(const uint8_t *uid) {
|
||||
uint8_t hash[20];
|
||||
uint8_t hash[20] = {0};
|
||||
mbedtls_sha1(uid, 7, hash);
|
||||
uint32_t pwd = 0;
|
||||
pwd |= (hash[ hash[0] % 20 ]) << 24 ;
|
||||
|
@ -185,7 +185,7 @@ uint32_t ul_ev1_pwdgenE(const uint8_t *uid) {
|
|||
|
||||
// NDEF tools format password generator
|
||||
uint32_t ul_ev1_pwdgenF(const uint8_t *uid) {
|
||||
uint8_t hash[16];
|
||||
uint8_t hash[16] = {0};;
|
||||
mbedtls_md5(uid, 7, hash);
|
||||
uint32_t pwd = 0;
|
||||
pwd |= hash[0] << 24;
|
||||
|
@ -195,6 +195,20 @@ uint32_t ul_ev1_pwdgenF(const uint8_t *uid) {
|
|||
return pwd;
|
||||
}
|
||||
|
||||
// Solution from @atc1441
|
||||
// https://gist.github.com/atc1441/41af75048e4c22af1f5f0d4c1d94bb56
|
||||
// Philips Sonicare toothbrush NFC head
|
||||
uint32_t ul_ev1_pwdgenG(const uint8_t *uid, const uint8_t *mfg) {
|
||||
|
||||
init_table(CRC_PHILIPS);
|
||||
// UID
|
||||
uint32_t crc1 = crc16_philips(uid, 7);
|
||||
// MFG string
|
||||
uint32_t crc2 = crc16_fast(mfg, 10, crc1, false, false);
|
||||
|
||||
return (BSWAP_16(crc2) << 16 | BSWAP_16(crc1));
|
||||
}
|
||||
|
||||
// pack generation for algo 1-3
|
||||
uint16_t ul_ev1_packgenA(const uint8_t *uid) {
|
||||
uint16_t pack = (uid[0] ^ uid[1] ^ uid[2]) << 8 | (uid[2] ^ 8);
|
||||
|
@ -224,13 +238,26 @@ uint16_t ul_ev1_packgenD(const uint8_t *uid) {
|
|||
p ^= 0x5555;
|
||||
return BSWAP_16(p & 0xFFFF);
|
||||
}
|
||||
|
||||
uint16_t ul_ev1_packgenE(const uint8_t *uid) {
|
||||
|
||||
uint32_t pwd = ul_ev1_pwdgenE(uid);
|
||||
return (0xAD << 8 | ((pwd >> 24) & 0xFF));
|
||||
}
|
||||
|
||||
uint16_t ul_ev1_packgenG(const uint8_t *uid, const uint8_t *mfg) {
|
||||
init_table(CRC_PHILIPS);
|
||||
// UID
|
||||
uint32_t crc1 = crc16_philips(uid, 7);
|
||||
// MFG string
|
||||
uint32_t crc2 = crc16_fast(mfg, 10, crc1, false, false);
|
||||
// PWD
|
||||
uint32_t pwd = (BSWAP_16(crc2) << 16 | BSWAP_16(crc1));
|
||||
|
||||
uint8_t pb[4];
|
||||
num_to_bytes(pwd, 4, pb);
|
||||
return BSWAP_16(crc16_fast(pb, 4, crc2, false, false));
|
||||
}
|
||||
|
||||
|
||||
// default shims
|
||||
uint32_t ul_ev1_pwdgen_def(const uint8_t *uid) {
|
||||
|
@ -299,10 +326,41 @@ int mfc_algo_yale_all(uint8_t *uid, uint8_t *keys) {
|
|||
int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) {
|
||||
if (sector > 15) return PM3_EINVARG;
|
||||
if (key == NULL) return PM3_EINVARG;
|
||||
if (keytype > 2) return PM3_EINVARG;
|
||||
*key = 0;
|
||||
|
||||
if (keytype == 0 && sector == 2) {
|
||||
*key = 0xFFFFFFFFFFFF;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
if (keytype == 0 && sector == 1) {
|
||||
*key = 0x2a2c13cc242a;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
if (keytype == 0) {
|
||||
uint64_t lut[16] = {
|
||||
0xf057b39ee3d8ULL, 0x969d954ac157ULL, 0x8f43580d2c9dULL, 0xffcce0050c43ULL,
|
||||
0x341b15a690ccULL, 0x89585612e71bULL, 0xbb74b0953658ULL, 0xfb97f84b5b74ULL,
|
||||
0xc9d188359f92ULL, 0x8f92e97f5897ULL, 0x166ca2b09fd1ULL, 0x27dd93101c6cULL,
|
||||
0xda3e3fd649ddULL, 0x58dded078e3eULL, 0x5cd005cfd907ULL, 0x118dd00187d0ULL
|
||||
};
|
||||
|
||||
uint8_t h = ((uid[3] >> 4) & 0xF);
|
||||
h += ((uid[2] >> 4) & 0xF);
|
||||
h += uid[0] & 0xF;
|
||||
|
||||
uint64_t m = lut[h & 0xF];
|
||||
|
||||
uint64_t id = (bytes_to_num(uid, 4) << 8);
|
||||
|
||||
*key = (h + (id + m + ((uint64_t)h << 40ULL))) & 0xFFFFFFFFFFFFULL;
|
||||
|
||||
} else {
|
||||
*key = 0xFFFFFFFFFFFF;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys) {
|
||||
if (keys == NULL) return PM3_EINVARG;
|
||||
|
||||
|
@ -522,7 +580,7 @@ int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint3
|
|||
|
||||
int mfc_generate4b_nuid(uint8_t *uid, uint8_t *nuid) {
|
||||
uint16_t crc;
|
||||
uint8_t b1, b2;
|
||||
uint8_t b1 = 0, b2 = 0;
|
||||
|
||||
compute_crc(CRC_14443_A, uid, 3, &b1, &b2);
|
||||
nuid[0] = (b2 & 0xE0) | 0xF;
|
||||
|
@ -556,7 +614,7 @@ int mfc_algo_touch_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *
|
|||
|
||||
int generator_selftest(void) {
|
||||
#ifndef ON_DEVICE
|
||||
#define NUM_OF_TEST 8
|
||||
#define NUM_OF_TEST 10
|
||||
|
||||
PrintAndLogEx(INFO, "PWD / KEY generator selftest");
|
||||
PrintAndLogEx(INFO, "----------------------------");
|
||||
|
@ -569,64 +627,81 @@ int generator_selftest(void) {
|
|||
if (success)
|
||||
testresult++;
|
||||
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid1, 7), pwd1, success ? "OK" : "->8432EB17<-");
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid1, 7), pwd1, success ? _GREEN_("ok") : "->8432EB17<-");
|
||||
|
||||
uint8_t uid2[] = {0x04, 0x1f, 0x98, 0xea, 0x1e, 0x3e, 0x81};
|
||||
uint32_t pwd2 = ul_ev1_pwdgenB(uid2);
|
||||
success = (pwd2 == 0x5fd37eca);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid2, 7), pwd2, success ? "OK" : "->5fd37eca<--");
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid2, 7), pwd2, success ? _GREEN_("ok") : "->5fd37eca<--");
|
||||
|
||||
uint8_t uid3[] = {0x04, 0x62, 0xB6, 0x8A, 0xB4, 0x42, 0x80};
|
||||
uint32_t pwd3 = ul_ev1_pwdgenC(uid3);
|
||||
success = (pwd3 == 0x5a349515);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid3, 7), pwd3, success ? "OK" : "->5a349515<--");
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid3, 7), pwd3, success ? _GREEN_("ok") : "->5a349515<--");
|
||||
|
||||
uint8_t uid4[] = {0x04, 0xC5, 0xDF, 0x4A, 0x6D, 0x51, 0x80};
|
||||
uint32_t pwd4 = ul_ev1_pwdgenD(uid4);
|
||||
success = (pwd4 == 0x72B1EC61);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid4, 7), pwd4, success ? "OK" : "->72B1EC61<--");
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid4, 7), pwd4, success ? _GREEN_("ok") : "->72B1EC61<--");
|
||||
|
||||
uint8_t uid5[] = {0x04, 0xA0, 0x3C, 0xAA, 0x1E, 0x70, 0x80};
|
||||
uint32_t pwd5 = ul_ev1_pwdgenE(uid5);
|
||||
success = (pwd5 == 0xCD91AFCC);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid5, 7), pwd5, success ? "OK" : "->CD91AFCC<--");
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid5, 7), pwd5, success ? _GREEN_("ok") : "->CD91AFCC<--");
|
||||
|
||||
uint8_t uid6[] = {0x04, 0x77, 0x42, 0xAB, 0xEF, 0x42, 0x70};
|
||||
uint32_t pwd6 = ul_ev1_pwdgenF(uid6);
|
||||
success = (pwd6 == 0xA9C4C3C0);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid6, 7), pwd6, success ? "OK" : "->A9C4C3C0<--");
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid6, 7), pwd6, success ? _GREEN_("ok") : "->A9C4C3C0<--");
|
||||
|
||||
uint8_t uid7[] = {0x04, 0x0D, 0x4B, 0x5A, 0xC5, 0x71, 0x81};
|
||||
uint8_t mfg[] = {0x32, 0x31, 0x30, 0x36, 0x32, 0x38, 0x20, 0x35, 0x32, 0x4D};
|
||||
uint32_t pwd7 = ul_ev1_pwdgenG(uid7, mfg);
|
||||
success = (pwd7 == 0xFBCFACC1);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %08X - %s", sprint_hex(uid7, 7), pwd7, success ? _GREEN_("ok") : "->FBCFACC1<--");
|
||||
|
||||
|
||||
// uint8_t uid5[] = {0x11, 0x22, 0x33, 0x44};
|
||||
// uint64_t key1 = mfc_algo_a(uid5);
|
||||
// success = (key1 == 0xD1E2AA68E39A);
|
||||
// PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid5, 4), key1, success ? "OK" : "->D1E2AA68E39A<--");
|
||||
// PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid5, 4), key1, success ? _GREEN_("ok") : "->D1E2AA68E39A<--");
|
||||
|
||||
uint8_t uid7[] = {0x74, 0x57, 0xCA, 0xA9};
|
||||
uint64_t key7 = 0;
|
||||
mfc_algo_sky_one(uid7, 15, 0, &key7);
|
||||
success = (key7 == 0x82c7e64bc565);
|
||||
uint8_t uid8[] = {0x74, 0x57, 0xCA, 0xA9};
|
||||
uint64_t key8 = 0;
|
||||
mfc_algo_sky_one(uid8, 15, 0, &key8);
|
||||
success = (key8 == 0x82c7e64bc565);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid7, 4), key7, success ? "OK" : "->82C7E64BC565<--");
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIx64" - %s", sprint_hex(uid8, 4), key8, success ? _GREEN_("ok") : "->82C7E64BC565<--");
|
||||
|
||||
// MFC SAFLOK
|
||||
uint8_t uid9[] = {0x11, 0x22, 0x33, 0x44};
|
||||
uint64_t key9 = 0;
|
||||
mfc_algo_saflok_one(uid9, 0, 0, &key9);
|
||||
success = (key9 == 0xD1E2AA68E39A);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "UID | %s | %"PRIX64" - %s", sprint_hex(uid9, 4), key9, success ? _GREEN_("ok") : _RED_(">> D1E2AA68E39A <<"));
|
||||
|
||||
uint32_t lf_id = lf_t55xx_white_pwdgen(0x00000080);
|
||||
success = (lf_id == 0x00018383);
|
||||
if (success)
|
||||
testresult++;
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "ID | 0x00000080 | %08"PRIx32 " - %s", lf_id, success ? "OK" : "->00018383<--");
|
||||
PrintAndLogEx(success ? SUCCESS : WARNING, "ID | 0x00000080 | %08"PRIx32 " - %s", lf_id, success ? _GREEN_("ok") : "->00018383<--");
|
||||
|
||||
PrintAndLogEx(SUCCESS, "------------------- Selftest %s", (testresult == NUM_OF_TEST) ? "OK" : "fail");
|
||||
PrintAndLogEx(SUCCESS, "------------------- Selftest %s", (testresult == NUM_OF_TEST) ? _GREEN_("ok") : _RED_("fail"));
|
||||
|
||||
#endif
|
||||
return PM3_SUCCESS;
|
||||
|
|
|
@ -28,6 +28,7 @@ uint32_t ul_ev1_pwdgenC(const uint8_t *uid);
|
|||
uint32_t ul_ev1_pwdgenD(const uint8_t *uid);
|
||||
uint32_t ul_ev1_pwdgenE(const uint8_t *uid);
|
||||
uint32_t ul_ev1_pwdgenF(const uint8_t *uid);
|
||||
uint32_t ul_ev1_pwdgenG(const uint8_t *uid, const uint8_t *mfg);
|
||||
|
||||
uint16_t ul_ev1_packgen_def(const uint8_t *uid);
|
||||
uint16_t ul_ev1_packgenA(const uint8_t *uid);
|
||||
|
@ -35,6 +36,7 @@ uint16_t ul_ev1_packgenB(const uint8_t *uid);
|
|||
uint16_t ul_ev1_packgenC(const uint8_t *uid);
|
||||
uint16_t ul_ev1_packgenD(const uint8_t *uid);
|
||||
uint16_t ul_ev1_packgenE(const uint8_t *uid);
|
||||
uint16_t ul_ev1_packgenG(const uint8_t *uid, const uint8_t *mfg);
|
||||
|
||||
uint32_t ul_c_otpgenA(const uint8_t *uid);
|
||||
|
||||
|
|
|
@ -53,8 +53,8 @@
|
|||
// **********************************************************************************************
|
||||
// ---------------------------------Utilities Section--------------------------------------------
|
||||
// **********************************************************************************************
|
||||
#define LOWEST_DEFAULT_CLOCK 32
|
||||
#define FSK_PSK_THRESHOLD 123
|
||||
#define LOWEST_DEFAULT_CLOCK 32
|
||||
#define FSK_PSK_THRESHOLD 123
|
||||
|
||||
//to allow debug print calls when used not on dev
|
||||
|
||||
|
@ -268,12 +268,20 @@ static size_t removeEm410xParity(uint8_t *bits, size_t startIdx, bool isLong, bo
|
|||
*validLong = false;
|
||||
uint8_t bLen = isLong ? 110 : 55;
|
||||
uint16_t parityCol[4] = { 0, 0, 0, 0 };
|
||||
|
||||
for (int word = 0; word < bLen; word += 5) {
|
||||
for (int bit = 0; bit < 5; bit++) {
|
||||
if (word + bit >= bLen) break;
|
||||
|
||||
if (word + bit >= bLen) {
|
||||
break;
|
||||
}
|
||||
|
||||
parityWd = (parityWd << 1) | bits[startIdx + word + bit];
|
||||
if ((word <= 50) && (bit < 4))
|
||||
|
||||
if ((word <= 50) && (bit < 4)) {
|
||||
parityCol[bit] = (parityCol[bit] << 1) | bits[startIdx + word + bit];
|
||||
}
|
||||
|
||||
bits[bitCnt++] = (bits[startIdx + word + bit]);
|
||||
}
|
||||
if (word + 5 > bLen) break;
|
||||
|
@ -293,12 +301,15 @@ static size_t removeEm410xParity(uint8_t *bits, size_t startIdx, bool isLong, bo
|
|||
if (!isLong && validRowParitySkipColP && validColParity) {
|
||||
*validShort = true;
|
||||
}
|
||||
|
||||
if (isLong && validRowParity) {
|
||||
*validLong = true;
|
||||
}
|
||||
|
||||
if (isLong && validRowParitySkipColP && validColParity) {
|
||||
*validShortExtended = true;
|
||||
}
|
||||
|
||||
if (*validShort || *validShortExtended || *validLong) {
|
||||
return bitCnt;
|
||||
} else {
|
||||
|
@ -425,10 +436,10 @@ static size_t findModStart(const uint8_t *src, size_t size, uint8_t expWaveSize)
|
|||
}
|
||||
|
||||
static int getClosestClock(int testclk) {
|
||||
const uint16_t clocks[] = {8, 16, 32, 40, 50, 64, 100, 128, 256, 384};
|
||||
const uint8_t limit[] = {1, 2, 4, 4, 5, 8, 8, 8, 8, 8};
|
||||
const uint16_t clocks[] = {8, 16, 32, 40, 50, 64, 100, 128, 256, 272, 384};
|
||||
const uint8_t limit[] = {1, 2, 4, 4, 5, 8, 8, 8, 8, 24, 24};
|
||||
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
for (uint8_t i = 0; i < ARRAYLEN(clocks); i++) {
|
||||
if (testclk >= clocks[i] - limit[i] && testclk <= clocks[i] + limit[i])
|
||||
return clocks[i];
|
||||
}
|
||||
|
@ -602,7 +613,7 @@ bool DetectCleanAskWave(const uint8_t *dest, size_t size, uint8_t high, uint8_t
|
|||
// based on count of low to low
|
||||
int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clock) {
|
||||
size_t i = 100;
|
||||
size_t minClk = 512;
|
||||
size_t minClk = 768;
|
||||
uint16_t shortestWaveIdx = 0;
|
||||
|
||||
// get to first full low to prime loop and skip incomplete first pulse
|
||||
|
@ -611,11 +622,11 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo
|
|||
|
||||
if (i == size)
|
||||
return -1;
|
||||
if (size < 512)
|
||||
if (size < 768)
|
||||
return -2;
|
||||
|
||||
// clock, numoftimes, first idx
|
||||
uint16_t tmpclk[10][3] = {
|
||||
uint16_t tmpclk[11][3] = {
|
||||
{8, 0, 0},
|
||||
{16, 0, 0},
|
||||
{32, 0, 0},
|
||||
|
@ -625,11 +636,12 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo
|
|||
{100, 0, 0},
|
||||
{128, 0, 0},
|
||||
{256, 0, 0},
|
||||
{272, 0, 0},
|
||||
{384, 0, 0},
|
||||
};
|
||||
|
||||
// loop through all samples (well, we don't want to go out-of-bounds)
|
||||
while (i < (size - 512)) {
|
||||
while (i < (size - 768)) {
|
||||
// measure from low to low
|
||||
size_t startwave = i;
|
||||
|
||||
|
@ -644,7 +656,7 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo
|
|||
|
||||
int foo = getClosestClock(minClk);
|
||||
if (foo > 0) {
|
||||
for (uint8_t j = 0; j < 10; j++) {
|
||||
for (uint8_t j = 0; j < 11; j++) {
|
||||
if (tmpclk[j][0] == foo) {
|
||||
tmpclk[j][1]++;
|
||||
|
||||
|
@ -658,8 +670,17 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo
|
|||
}
|
||||
|
||||
// find the clock with most hits and it the first index it was encountered.
|
||||
int possible_clks = 0;
|
||||
for (uint8_t j = 0; j < 11; j++) {
|
||||
if (tmpclk[j][1] > 0) {
|
||||
possible_clks++;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t second_shortest = 0;
|
||||
int second = 0;
|
||||
int max = 0;
|
||||
for (uint8_t j = 0; j < 10; j++) {
|
||||
for (int j = 10; j > -1; j--) {
|
||||
if (g_debugMode == 2) {
|
||||
prnt("DEBUG, ASK, clocks %u | hits %u | idx %u"
|
||||
, tmpclk[j][0]
|
||||
|
@ -667,13 +688,23 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo
|
|||
, tmpclk[j][2]
|
||||
);
|
||||
}
|
||||
|
||||
if (max < tmpclk[j][1]) {
|
||||
second = *clock;
|
||||
second_shortest = shortestWaveIdx;
|
||||
|
||||
*clock = tmpclk[j][0];
|
||||
shortestWaveIdx = tmpclk[j][2];
|
||||
max = tmpclk[j][1];
|
||||
}
|
||||
}
|
||||
|
||||
// ASK clock 8 is very rare and usually gives us false positives
|
||||
if (possible_clks > 1 && *clock == 8) {
|
||||
*clock = second;
|
||||
shortestWaveIdx = second_shortest;
|
||||
}
|
||||
|
||||
if (*clock == 0)
|
||||
return -1;
|
||||
|
||||
|
@ -701,9 +732,9 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) {
|
|||
}
|
||||
|
||||
size_t i = 1;
|
||||
uint8_t num_clks = 9;
|
||||
uint8_t num_clks = 10;
|
||||
// first 255 value pos0 is placeholder for user inputed clock.
|
||||
uint16_t clk[] = {255, 8, 16, 32, 40, 50, 64, 100, 128, 255};
|
||||
uint16_t clk[] = {255, 8, 16, 32, 40, 50, 64, 100, 128, 255, 272};
|
||||
|
||||
// sometimes there is a strange end wave - filter out this
|
||||
size -= 60;
|
||||
|
@ -744,8 +775,8 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) {
|
|||
|
||||
uint8_t clkCnt, tol;
|
||||
size_t j = 0;
|
||||
uint16_t bestErr[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000};
|
||||
uint8_t bestStart[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint16_t bestErr[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000};
|
||||
uint8_t bestStart[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
size_t errCnt, arrLoc, loopEnd;
|
||||
|
||||
if (found_clk) {
|
||||
|
@ -884,11 +915,11 @@ int DetectStrongNRZClk(const uint8_t *dest, size_t size, int peak, int low, bool
|
|||
// detect nrz clock by reading #peaks vs no peaks(or errors)
|
||||
int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx) {
|
||||
size_t i = 0;
|
||||
uint8_t clk[] = {8, 16, 32, 40, 50, 64, 100, 128, 255};
|
||||
uint16_t clk[] = {8, 16, 32, 40, 50, 64, 100, 128, 255, 272, 384};
|
||||
size_t loopCnt = 4096; //don't need to loop through entire array...
|
||||
|
||||
//if we already have a valid clock quit
|
||||
for (; i < 8; ++i)
|
||||
for (; i < ARRAYLEN(clk); ++i)
|
||||
if (clk[i] == clock) return clock;
|
||||
|
||||
if (size < 20) return 0;
|
||||
|
@ -915,7 +946,7 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx)
|
|||
uint8_t tol = 0;
|
||||
uint16_t smplCnt = 0;
|
||||
int16_t peakcnt = 0;
|
||||
int16_t peaksdet[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int16_t peaksdet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint16_t minPeak = 255;
|
||||
bool firstpeak = true;
|
||||
//test for large clipped waves - ignore first peak
|
||||
|
@ -938,10 +969,10 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx)
|
|||
bool errBitHigh = 0, bitHigh = 0, lastPeakHigh = 0;
|
||||
uint8_t ignoreCnt = 0, ignoreWindow = 4;
|
||||
int lastBit = 0;
|
||||
size_t bestStart[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
size_t bestStart[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
peakcnt = 0;
|
||||
//test each valid clock from smallest to greatest to see which lines up
|
||||
for (clkCnt = 0; clkCnt < 8; ++clkCnt) {
|
||||
for (clkCnt = 0; clkCnt < ARRAYLEN(bestStart); ++clkCnt) {
|
||||
//ignore clocks smaller than smallest peak
|
||||
if (clk[clkCnt] < minPeak - (clk[clkCnt] / 4)) continue;
|
||||
//try lining up the peaks by moving starting point (try first 256)
|
||||
|
@ -994,7 +1025,7 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx)
|
|||
}
|
||||
|
||||
uint8_t best = 0;
|
||||
for (int m = 7; m > 0; m--) {
|
||||
for (int m = ARRAYLEN(peaksdet) - 1; m >= 0; m--) {
|
||||
if ((peaksdet[m] >= (peaksdet[best] - 1)) && (peaksdet[m] <= peaksdet[best] + 1) && lowestTransition) {
|
||||
if (clk[m] > (lowestTransition - (clk[m] / 8)) && clk[m] < (lowestTransition + (clk[m] / 8))) {
|
||||
best = m;
|
||||
|
@ -1087,10 +1118,12 @@ uint16_t countFC(const uint8_t *bits, size_t size, bool fskAdj) {
|
|||
fcH = fcLens[best2];
|
||||
fcL = fcLens[best1];
|
||||
}
|
||||
/*
|
||||
if ((size - 180) / fcH / 3 > fcCnts[best1] + fcCnts[best2]) {
|
||||
if (g_debugMode == 2) prnt("DEBUG countfc: fc is too large: %zu > %u. Not psk or fsk", (size - 180) / fcH / 3, fcCnts[best1] + fcCnts[best2]);
|
||||
return 0; //lots of waves not psk or fsk
|
||||
}
|
||||
*/
|
||||
// TODO: take top 3 answers and compare to known Field clocks to get top 2
|
||||
|
||||
uint16_t fcs = (((uint16_t)fcH) << 8) | fcL;
|
||||
|
@ -1101,8 +1134,8 @@ uint16_t countFC(const uint8_t *bits, size_t size, bool fskAdj) {
|
|||
// detect psk clock by reading each phase shift
|
||||
// a phase shift is determined by measuring the sample length of each wave
|
||||
int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShift, uint8_t *curPhase, uint8_t *fc) {
|
||||
uint8_t clk[] = {255, 16, 32, 40, 50, 64, 100, 128, 255}; //255 is not a valid clock
|
||||
uint16_t loopCnt = 4096; //don't need to loop through entire array...
|
||||
uint16_t clk[] = {255, 16, 32, 40, 50, 64, 100, 128, 256, 272, 384}; // 255 is not a valid clock
|
||||
uint16_t loopCnt = 4096; // don't need to loop through entire array...
|
||||
|
||||
if (size < 160 + 20) return 0;
|
||||
// size must be larger than 20 here, and 160 later on.
|
||||
|
@ -1123,8 +1156,8 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif
|
|||
|
||||
uint8_t clkCnt;
|
||||
uint16_t waveLenCnt, fullWaveLen = 0;
|
||||
uint16_t bestErr[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000};
|
||||
uint16_t peaksdet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint16_t bestErr[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000};
|
||||
uint16_t peaksdet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
//find start of modulating data in trace
|
||||
size_t i = findModStart(dest, size, *fc);
|
||||
|
@ -1146,7 +1179,7 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif
|
|||
}
|
||||
|
||||
//test each valid clock from greatest to smallest to see which lines up
|
||||
for (clkCnt = 7; clkCnt >= 1 ; clkCnt--) {
|
||||
for (clkCnt = 9; clkCnt >= 1 ; clkCnt--) {
|
||||
uint8_t tol = *fc / 2;
|
||||
size_t lastClkBit = firstFullWave; //set end of wave as clock align
|
||||
size_t waveStart = 0;
|
||||
|
@ -1186,8 +1219,8 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif
|
|||
}
|
||||
//all tested with errors
|
||||
//return the highest clk with the most peaks found
|
||||
uint8_t best = 7;
|
||||
for (i = 7; i >= 1; i--) {
|
||||
uint8_t best = 9;
|
||||
for (i = 9; i >= 1; i--) {
|
||||
if (peaksdet[i] > peaksdet[best])
|
||||
best = i;
|
||||
|
||||
|
@ -1463,7 +1496,7 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s
|
|||
static int millerRawDecode(uint8_t *bits, size_t *size, int invert) {
|
||||
if (*size < 16) return -1;
|
||||
|
||||
uint16_t MaxBits = 512, errCnt = 0;
|
||||
uint16_t MaxBits = MAX_DEMODULATION_BITS, errCnt = 0;
|
||||
size_t i, bitCnt = 0;
|
||||
uint8_t alignCnt = 0, curBit = bits[0], alignedIdx = 0, halfClkErr = 0;
|
||||
|
||||
|
@ -1507,7 +1540,7 @@ int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert) {
|
|||
uint16_t bitnum = 0;
|
||||
uint16_t errCnt = 0;
|
||||
size_t i = *offset;
|
||||
uint16_t maxbits = 512;
|
||||
uint16_t maxbits = MAX_DEMODULATION_BITS;
|
||||
|
||||
//check for phase change faults - skip one sample if faulty
|
||||
bool offsetA = true, offsetB = true;
|
||||
|
@ -1547,7 +1580,7 @@ uint16_t manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alig
|
|||
if (*size < 16) return 0xFFFF;
|
||||
|
||||
int errCnt = 0, bestErr = 1000;
|
||||
uint16_t bitnum = 0, maxBits = 512, bestRun = 0;
|
||||
uint16_t bitnum = 0, maxBits = MAX_DEMODULATION_BITS, bestRun = 0;
|
||||
size_t i;
|
||||
|
||||
//find correct start position [alignment]
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
// ignore first x samples of the buffer
|
||||
#define SIGNAL_IGNORE_FIRST_SAMPLES 10
|
||||
|
||||
// Max number of bits when demodulating a signal
|
||||
#define MAX_DEMODULATION_BITS 4096
|
||||
|
||||
// generic
|
||||
typedef struct {
|
||||
int low;
|
||||
|
|
|
@ -21,7 +21,10 @@ MYSRCS = \
|
|||
cipher.c \
|
||||
cmac.c \
|
||||
des.c \
|
||||
ecc_point_compression.c \
|
||||
ecdh.c \
|
||||
ecdsa.c \
|
||||
gcm.c \
|
||||
md.c \
|
||||
md5.c \
|
||||
oid.c \
|
||||
|
@ -43,7 +46,8 @@ MYSRCS = \
|
|||
threading.c \
|
||||
x509.c \
|
||||
x509_crl.c \
|
||||
x509_crt.c
|
||||
x509_crt.c \
|
||||
net_sockets.c
|
||||
|
||||
LIB_A = libmbedtls.a
|
||||
|
||||
|
|
|
@ -2811,7 +2811,7 @@
|
|||
* This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other
|
||||
* requisites are enabled as well.
|
||||
*/
|
||||
//#define MBEDTLS_GCM_C
|
||||
#define MBEDTLS_GCM_C
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_HAVEGE_C
|
||||
|
@ -2979,7 +2979,7 @@
|
|||
*
|
||||
* This module provides networking routines.
|
||||
*/
|
||||
//#define MBEDTLS_NET_C
|
||||
#define MBEDTLS_NET_C
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_OID_C
|
||||
|
|
130
common/mbedtls/ecc_point_compression.c
Normal file
130
common/mbedtls/ecc_point_compression.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Not original to the mbedtls library. Taken from
|
||||
* https://github.com/mwarning/mbedtls_ecp_compression
|
||||
* to solve mbedtls' lack of support for elliptic point
|
||||
* compression and decompression
|
||||
*
|
||||
* Released under CC0 1.0 Universal License
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is all about mbedtls_ecp_decompress() and mbedtls_ecp_compress()
|
||||
*
|
||||
* Perform X25519 / Curve25519 point compression and decompression for mbedtls.
|
||||
* As of mbedtls 2.5.1, mbedtls does not support decompression yet.
|
||||
*
|
||||
*/
|
||||
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
|
||||
#include "ecc_point_compression.h"
|
||||
|
||||
int mbedtls_ecp_decompress(
|
||||
const mbedtls_ecp_group *grp,
|
||||
const unsigned char *input, size_t ilen,
|
||||
unsigned char *output, size_t *olen, size_t osize
|
||||
) {
|
||||
int ret;
|
||||
size_t plen;
|
||||
mbedtls_mpi r;
|
||||
mbedtls_mpi x;
|
||||
mbedtls_mpi n;
|
||||
|
||||
plen = mbedtls_mpi_size(&grp->P);
|
||||
|
||||
*olen = 2 * plen + 1;
|
||||
|
||||
if (osize < *olen)
|
||||
return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL);
|
||||
|
||||
if (ilen != plen + 1)
|
||||
return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
|
||||
|
||||
if (input[0] != 0x02 && input[0] != 0x03)
|
||||
return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
|
||||
|
||||
// output will consist of 0x04|X|Y
|
||||
memcpy(output, input, ilen);
|
||||
output[0] = 0x04;
|
||||
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&x);
|
||||
mbedtls_mpi_init(&n);
|
||||
|
||||
// x <= input
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&x, input + 1, plen));
|
||||
|
||||
// r = x^2
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&r, &x, &x));
|
||||
|
||||
// r = x^2 + a
|
||||
if (grp->A.p == NULL) {
|
||||
// Special case where a is -3
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&r, &r, 3));
|
||||
} else {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&r, &r, &grp->A));
|
||||
}
|
||||
|
||||
// r = x^3 + ax
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&r, &r, &x));
|
||||
|
||||
// r = x^3 + ax + b
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&r, &r, &grp->B));
|
||||
|
||||
// Calculate square root of r over finite field P:
|
||||
// r = sqrt(x^3 + ax + b) = (x^3 + ax + b) ^ ((P + 1) / 4) (mod P)
|
||||
|
||||
// n = P + 1
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&n, &grp->P, 1));
|
||||
|
||||
// n = (P + 1) / 4
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&n, 2));
|
||||
|
||||
// r ^ ((P + 1) / 4) (mod p)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&r, &r, &n, &grp->P, NULL));
|
||||
|
||||
// Select solution that has the correct "sign" (equals odd/even solution in finite group)
|
||||
if ((input[0] == 0x03) != mbedtls_mpi_get_bit(&r, 0)) {
|
||||
// r = p - r
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&r, &grp->P, &r));
|
||||
}
|
||||
|
||||
// y => output
|
||||
ret = mbedtls_mpi_write_binary(&r, output + 1 + plen, plen);
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_mpi_free(&x);
|
||||
mbedtls_mpi_free(&n);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int mbedtls_ecp_compress(
|
||||
const mbedtls_ecp_group *grp,
|
||||
const unsigned char *input, size_t ilen,
|
||||
unsigned char *output, size_t *olen, size_t osize
|
||||
) {
|
||||
size_t plen;
|
||||
|
||||
plen = mbedtls_mpi_size(&grp->P);
|
||||
|
||||
*olen = plen + 1;
|
||||
|
||||
if (osize < *olen)
|
||||
return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL);
|
||||
|
||||
if (ilen != 2 * plen + 1)
|
||||
return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
|
||||
|
||||
if (input[0] != 0x04)
|
||||
return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
|
||||
|
||||
// output will consist of 0x0?|X
|
||||
memcpy(output, input, *olen);
|
||||
|
||||
// Encode even/odd of Y into first byte (either 0x02 or 0x03)
|
||||
output[0] = 0x02 + (input[2 * plen] & 1);
|
||||
|
||||
return (0);
|
||||
}
|
32
common/mbedtls/ecc_point_compression.h
Normal file
32
common/mbedtls/ecc_point_compression.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Not original to the mbedtls library. Taken from
|
||||
* https://github.com/mwarning/mbedtls_ecp_compression
|
||||
* to solve mbedtls' lack of support for elliptic point
|
||||
* compression and decompression
|
||||
*
|
||||
* Released under CC0 1.0 Universal License
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is all about mbedtls_ecp_decompress() and mbedtls_ecp_compress()
|
||||
*
|
||||
* Perform X25519 / Curve25519 point compression and decompression for mbedtls.
|
||||
* As of mbedtls 2.5.1, mbedtls does not support decompression yet.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mbedtls/ecp.h"
|
||||
|
||||
int mbedtls_ecp_decompress(
|
||||
const mbedtls_ecp_group *grp,
|
||||
const unsigned char *input, size_t ilen,
|
||||
unsigned char *output, size_t *olen, size_t osize
|
||||
);
|
||||
|
||||
int mbedtls_ecp_compress(
|
||||
const mbedtls_ecp_group *grp,
|
||||
const unsigned char *input, size_t ilen,
|
||||
unsigned char *output, size_t *olen, size_t osize
|
||||
);
|
Loading…
Add table
Add a link
Reference in a new issue