mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 23:36:31 +08:00
import mbedtls ecc point (de)compression extension and use
This commit is contained in:
parent
59aa95fa6e
commit
44f2e253d8
|
@ -10,6 +10,7 @@ add_library(pm3rrg_rdv4_mbedtls STATIC
|
||||||
../../common/mbedtls/error.c
|
../../common/mbedtls/error.c
|
||||||
../../common/mbedtls/ecp.c
|
../../common/mbedtls/ecp.c
|
||||||
../../common/mbedtls/ecdh.c
|
../../common/mbedtls/ecdh.c
|
||||||
|
../../common/mbedtls/ecc_point_compression.c
|
||||||
../../common/mbedtls/ecp_curves.c
|
../../common/mbedtls/ecp_curves.c
|
||||||
../../common/mbedtls/certs.c
|
../../common/mbedtls/certs.c
|
||||||
../../common/mbedtls/camellia.c
|
../../common/mbedtls/camellia.c
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "mbedtls/ecp.h"
|
#include "mbedtls/ecp.h"
|
||||||
#include "mbedtls/bignum.h"
|
#include "mbedtls/bignum.h"
|
||||||
#include "mbedtls/ecdh.h"
|
#include "mbedtls/ecdh.h"
|
||||||
|
#include "mbedtls/ecc_point_compression.h"
|
||||||
|
|
||||||
uint8_t ecpData[] = { 0x6a, 0x01, 0x00, 0x00, 0x04 };
|
uint8_t ecpData[] = { 0x6a, 0x01, 0x00, 0x00, 0x04 };
|
||||||
uint8_t aid[] = { 0x4f, 0x53, 0x45, 0x2e, 0x56, 0x41, 0x53, 0x2e, 0x30, 0x31 };
|
uint8_t aid[] = { 0x4f, 0x53, 0x45, 0x2e, 0x56, 0x41, 0x53, 0x2e, 0x30, 0x31 };
|
||||||
|
@ -187,9 +188,7 @@ static int LoadReaderPrivateKey(uint8_t *buf, size_t bufLen, mbedtls_ecp_keypair
|
||||||
|
|
||||||
tlvdb_free(derRoot);
|
tlvdb_free(derRoot);
|
||||||
|
|
||||||
if (mbedtls_mpi_read_binary(&privKey->Q.X, pubkeyCoordsTlv->value + 2, 32)
|
if (mbedtls_ecp_point_read_binary(&privKey->grp, &privKey->Q, pubkeyCoordsTlv->value + 1, 65)) {
|
||||||
|| mbedtls_mpi_read_binary(&privKey->Q.Y, pubkeyCoordsTlv->value + 34, 32)
|
|
||||||
|| mbedtls_mpi_lset(&privKey->Q.Z, 1)) {
|
|
||||||
PrintAndLogEx(FAILED, "Failed to read in public key coordinates");
|
PrintAndLogEx(FAILED, "Failed to read in public key coordinates");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -216,9 +215,20 @@ static int GetPrivateKeyHint(mbedtls_ecp_keypair *privKey, uint8_t *keyHint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int LoadMobileEphemeralKey(uint8_t *xcoordBuf, mbedtls_ecp_keypair *pubKey) {
|
static int LoadMobileEphemeralKey(uint8_t *xcoordBuf, mbedtls_ecp_keypair *pubKey) {
|
||||||
if (mbedtls_mpi_read_binary(&pubKey->Q.X, xcoordBuf, 32)) {
|
uint8_t compressedEcKey[33] = {0};
|
||||||
|
compressedEcKey[0] = 0x02;
|
||||||
|
memcpy(compressedEcKey + 1, xcoordBuf, 32);
|
||||||
|
|
||||||
|
uint8_t decompressedEcKey[65] = {0};
|
||||||
|
size_t decompressedEcKeyLen = 0;
|
||||||
|
if (mbedtls_ecp_decompress(&pubKey->grp, compressedEcKey, sizeof(compressedEcKey), decompressedEcKey, &decompressedEcKeyLen, sizeof(decompressedEcKey))) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mbedtls_ecp_point_read_binary(&pubKey->grp, &pubKey->Q, decompressedEcKey, decompressedEcKeyLen)) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,6 +410,65 @@ static int CmdVASReader(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdVASDecrypt(const char *Cmd) {
|
static int CmdVASDecrypt(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "nfc vas decrypt",
|
||||||
|
"Decrypt a previously captured cryptogram",
|
||||||
|
"nfc vas reader -p pass.com.example.ticket -k ./priv.key -> select pass and decrypt with priv.key\nnfc vas reader --url https://example.com -> URL Only mode");
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_str0("p", NULL, "<pid>", "pass type id"),
|
||||||
|
arg_str0("k", NULL, "<key>", "path to terminal private key"),
|
||||||
|
arg_str0(NULL, NULL, "<hex>", "cryptogram to decrypt"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
struct arg_str *passTypeIdArg = arg_get_str(ctx, 1);
|
||||||
|
int passTypeIdLen = arg_get_str_len(ctx, 1);
|
||||||
|
uint8_t pidHash[32] = {0};
|
||||||
|
sha256hash((uint8_t *) passTypeIdArg->sval[0], passTypeIdLen, pidHash);
|
||||||
|
|
||||||
|
uint8_t cryptogram[120] = {0};
|
||||||
|
int cryptogramLen = 0;
|
||||||
|
CLIGetHexWithReturn(ctx, 3, cryptogram, &cryptogramLen);
|
||||||
|
|
||||||
|
struct arg_str *keyPathArg = arg_get_str(ctx, 2);
|
||||||
|
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");
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *keyData = NULL;
|
||||||
|
size_t keyDataLen = 0;
|
||||||
|
if (loadFile_safe(keyPathArg->sval[0], "", (void **)&keyData, &keyDataLen) != PM3_SUCCESS) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_ecp_keypair privKey;
|
||||||
|
mbedtls_ecp_keypair_init(&privKey);
|
||||||
|
|
||||||
|
if (LoadReaderPrivateKey(keyData, keyDataLen, &privKey) != PM3_SUCCESS) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
mbedtls_ecp_keypair_free(&privKey);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t message[64] = {0};
|
||||||
|
size_t messageLen = 0;
|
||||||
|
uint8_t timestamp[4] = {0};
|
||||||
|
|
||||||
|
if (DecryptVASCryptogram(cryptogram, cryptogramLen, &privKey, message, &messageLen, timestamp) != PM3_SUCCESS) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
mbedtls_ecp_keypair_free(&privKey);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
mbedtls_ecp_keypair_free(&privKey);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,7 +481,7 @@ static int CmdHelp(const char *Cmd);
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"--------", CmdHelp, AlwaysAvailable, "----------- " _CYAN_("Value Added Service") " -----------"},
|
{"--------", CmdHelp, AlwaysAvailable, "----------- " _CYAN_("Value Added Service") " -----------"},
|
||||||
{"reader", CmdVASReader, IfPm3Iso14443a, "Read and decrypt VAS message"},
|
{"reader", CmdVASReader, IfPm3Iso14443a, "Read and decrypt VAS message"},
|
||||||
{"decrypt", CmdVASDecrypt, AlwaysAvailable, "Decrypt a VAS cryptogram"},
|
{"decrypt", CmdVASDecrypt, AlwaysAvailable, "Decrypt a previously captured VAS cryptogram"},
|
||||||
{"sim", CmdVASSim, IfPm3Iso14443a, "Simulate a VAS mobile credential"},
|
{"sim", CmdVASSim, IfPm3Iso14443a, "Simulate a VAS mobile credential"},
|
||||||
{"--------", CmdHelp, AlwaysAvailable, "----------------- " _CYAN_("General") " -----------------"},
|
{"--------", CmdHelp, AlwaysAvailable, "----------------- " _CYAN_("General") " -----------------"},
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
|
|
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…
Reference in a new issue