mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-14 19:53:35 -07:00
MRTD WIP secure messaging
This commit is contained in:
+39
-12
@@ -100,21 +100,29 @@ struct AIDSet AID = {
|
||||
|
||||
bool mrtd_send_apdu(MrtdApplication* app, uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, uint8_t lc, const void* data, int16_t le) {
|
||||
FuriHalNfcTxRxContext* tx_rx = app->tx_rx;
|
||||
size_t idx = 0;
|
||||
|
||||
FURI_LOG_D(TAG, "Send APDU, lc: %d, le: %d", lc, le);
|
||||
|
||||
size_t idx = 0;
|
||||
tx_rx->tx_data[idx++] = cla;
|
||||
tx_rx->tx_data[idx++] = ins;
|
||||
tx_rx->tx_data[idx++] = p1;
|
||||
tx_rx->tx_data[idx++] = p2;
|
||||
if(lc > 0) {
|
||||
tx_rx->tx_data[idx++] = lc;
|
||||
memcpy(tx_rx->tx_data + idx, data, lc);
|
||||
idx += lc;
|
||||
}
|
||||
if(le >= 0) {
|
||||
tx_rx->tx_data[idx++] = le&0xff;
|
||||
if(app->secure_messaging) {
|
||||
FURI_LOG_D(TAG, "Protect APDU");
|
||||
|
||||
app->ssc_long++;
|
||||
idx = mrtd_protect_apdu(cla, ins, p1, p2, lc, data, le, app->ksenc, app->ksmac, app->ssc_long, tx_rx->tx_data);
|
||||
|
||||
} else {
|
||||
tx_rx->tx_data[idx++] = cla;
|
||||
tx_rx->tx_data[idx++] = ins;
|
||||
tx_rx->tx_data[idx++] = p1;
|
||||
tx_rx->tx_data[idx++] = p2;
|
||||
if(lc > 0) {
|
||||
tx_rx->tx_data[idx++] = lc;
|
||||
memcpy(tx_rx->tx_data + idx, data, lc);
|
||||
idx += lc;
|
||||
}
|
||||
if(le >= 0) {
|
||||
tx_rx->tx_data[idx++] = le&0xff;
|
||||
}
|
||||
}
|
||||
|
||||
tx_rx->tx_bits = idx * 8;
|
||||
@@ -208,6 +216,7 @@ size_t mrtd_read_binary(MrtdApplication* app, uint8_t* buffer, size_t bufsize, s
|
||||
|
||||
void mrtd_read_dump(MrtdApplication* app, EFFile file, const char* descr) {
|
||||
FURI_LOG_D(TAG, "Read and dump %s:", descr);
|
||||
|
||||
if(!mrtd_select_file(app, file)) {
|
||||
return;
|
||||
}
|
||||
@@ -258,12 +267,22 @@ void parse_ef_dir(EF_DIR_contents* EF_DIR, const uint8_t* data, size_t length) {
|
||||
}
|
||||
}
|
||||
|
||||
void parse_ef_com(EF_COM_contents* EF_COM, const uint8_t* data, size_t length) {
|
||||
UNUSED(EF_COM); //TODO
|
||||
UNUSED(length); //TODO
|
||||
size_t offset = 0;
|
||||
|
||||
TlvInfo tlv = iso7816_tlv_parse(data + offset);
|
||||
UNUSED(tlv); //TODO
|
||||
}
|
||||
|
||||
//TODO: remove testing function
|
||||
void mrtd_test(MrtdApplication* app, MrtdData* mrtd_data) {
|
||||
FuriHalNfcTxRxContext* tx_rx = app->tx_rx;
|
||||
|
||||
FURI_LOG_D(TAG, "Mrtd Test");
|
||||
mrtd_read_dump(app, EF.ATR, "EF.ATR");
|
||||
mrtd_read_dump(app, EF.COM, "EF.COM");
|
||||
mrtd_read_dump(app, EF.DIR, "EF.DIR");
|
||||
parse_ef_dir(&app->files.EF_DIR, tx_rx->rx_data, tx_rx->rx_bits / 8 - 2); // bits to bytes, and exclude the 2 byte return code
|
||||
mrtd_read_dump(app, EF.CardAccess, "EF.CardAccess");
|
||||
@@ -294,6 +313,12 @@ void mrtd_test(MrtdApplication* app, MrtdData* mrtd_data) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(!mrtd_data->auth_success) {
|
||||
return;
|
||||
}
|
||||
|
||||
mrtd_read_dump(app, EF.COM, "EF.COM");
|
||||
}
|
||||
|
||||
MrtdApplication* mrtd_alloc_init(FuriHalNfcTxRxContext* tx_rx) {
|
||||
@@ -388,5 +413,7 @@ bool mrtd_bac(MrtdApplication* app, MrtdAuthData* auth) {
|
||||
app->ssc_long = mrtd_ssc_from_data(rnd_ic, rnd_ifd);
|
||||
FURI_LOG_D(TAG, "SSC: %01llX", app->ssc_long);
|
||||
|
||||
app->secure_messaging = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -22,12 +22,20 @@ typedef struct {
|
||||
uint8_t applications_count;
|
||||
} EF_DIR_contents;
|
||||
|
||||
typedef struct {
|
||||
uint16_t lds_version;
|
||||
uint16_t unicode_version;
|
||||
//TODO: taglist
|
||||
} EF_COM_contents;
|
||||
|
||||
typedef struct {
|
||||
FuriHalNfcTxRxContext* tx_rx;
|
||||
uint16_t file_offset;
|
||||
uint8_t ksenc[16];
|
||||
uint8_t ksmac[16];
|
||||
uint64_t ssc_long;
|
||||
uint64_t ssc_long; // TODO: rename without _long
|
||||
|
||||
bool secure_messaging;
|
||||
|
||||
struct {
|
||||
EF_DIR_contents EF_DIR;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "mrtd_helpers.h"
|
||||
|
||||
#include <stdio.h> //TODO: remove
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <mbedtls/des.h>
|
||||
@@ -169,6 +170,96 @@ bool mrtd_bac_decrypt_verify(const uint8_t* data, size_t data_length, uint8_t* k
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mrtd_bac_mac_init(mrtd_bac_mac_ctx* ctx, uint8_t key[16]) {
|
||||
mbedtls_des_init(&ctx->des);
|
||||
mbedtls_des_setkey_enc(&ctx->des, key);
|
||||
memset(ctx->mac, 0, 8);
|
||||
ctx->idx_in = 0;
|
||||
memcpy(ctx->key, key, 16);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mrtd_bac_mac_update(mrtd_bac_mac_ctx* ctx, const uint8_t* data, size_t data_length) {
|
||||
size_t data_idx = 0;
|
||||
//uint8_t* xormac = ctx->xormac;
|
||||
|
||||
if(ctx->idx_in != 0) {
|
||||
uint8_t buff_add = 8 - ctx->idx_in;
|
||||
if(data_length < buff_add) {
|
||||
buff_add = data_length;
|
||||
}
|
||||
memcpy(ctx->buffer_in + ctx->idx_in, data, buff_add);
|
||||
ctx->idx_in = (ctx->idx_in + buff_add) % 8;
|
||||
data_idx += buff_add;
|
||||
|
||||
if(ctx->idx_in == 0) { // buffer_in filled
|
||||
for(uint8_t j=0; j<8; ++j) {
|
||||
ctx->xormac[j] = ctx->mac[j] ^ ctx->buffer_in[j];
|
||||
}
|
||||
mbedtls_des_crypt_ecb(&ctx->des, ctx->xormac, ctx->mac);
|
||||
|
||||
printf("DES1: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
ctx->buffer_in[0], ctx->buffer_in[1], ctx->buffer_in[2], ctx->buffer_in[3],
|
||||
ctx->buffer_in[4], ctx->buffer_in[5], ctx->buffer_in[6], ctx->buffer_in[7]);
|
||||
|
||||
//printf("DES1: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
//xormac[0], xormac[1], xormac[2], xormac[3],
|
||||
//xormac[4], xormac[5], xormac[6], xormac[7]);
|
||||
}
|
||||
}
|
||||
|
||||
while(true) {
|
||||
if(data_idx + 8 > data_length) {
|
||||
// Not a full block
|
||||
break;
|
||||
}
|
||||
for(uint8_t j=0; j<8; ++j) {
|
||||
ctx->xormac[j] = ctx->mac[j] ^ data[data_idx++];
|
||||
}
|
||||
|
||||
mbedtls_des_crypt_ecb(&ctx->des, ctx->xormac, ctx->mac);
|
||||
printf("DES1: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
data[data_idx - 8 + 0], data[data_idx - 8 + 1], data[data_idx - 8 + 2], data[data_idx - 8 + 3],
|
||||
data[data_idx - 8 + 4], data[data_idx - 8 + 5], data[data_idx - 8 + 6], data[data_idx - 8 + 7]);
|
||||
|
||||
//printf("DES1: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
//xormac[0], xormac[1], xormac[2], xormac[3],
|
||||
//xormac[4], xormac[5], xormac[6], xormac[7]);
|
||||
}
|
||||
|
||||
if(data_idx < data_length) {
|
||||
ctx->idx_in = data_length - data_idx;
|
||||
memcpy(ctx->buffer_in, data + data_idx, ctx->idx_in);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mrtd_bac_mac_pad(mrtd_bac_mac_ctx* ctx) {
|
||||
memset(ctx->buffer_in + ctx->idx_in, 0x00, 8 - ctx->idx_in);
|
||||
ctx->buffer_in[ctx->idx_in] = 0x80;
|
||||
ctx->idx_in = 8;
|
||||
|
||||
mrtd_bac_mac_update(ctx, NULL, 0); // Force processing the buffer_in
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mrtd_bac_mac_finalize(mrtd_bac_mac_ctx* ctx, uint8_t output[8]) {
|
||||
mrtd_bac_mac_pad(ctx);
|
||||
|
||||
uint8_t tmp[8];
|
||||
mbedtls_des_init(&ctx->des);
|
||||
mbedtls_des_setkey_dec(&ctx->des, ctx->key+8);
|
||||
mbedtls_des_crypt_ecb(&ctx->des, ctx->mac, tmp);
|
||||
|
||||
mbedtls_des_init(&ctx->des);
|
||||
mbedtls_des_setkey_enc(&ctx->des, ctx->key);
|
||||
mbedtls_des_crypt_ecb(&ctx->des, tmp, output);
|
||||
|
||||
mbedtls_des_free(&ctx->des);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mrtd_bac_mac(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t* output) {
|
||||
// MAC
|
||||
uint8_t mac[8];
|
||||
@@ -184,7 +275,11 @@ bool mrtd_bac_mac(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t
|
||||
for(uint8_t j=0; j<8; ++j) {
|
||||
xormac[j] = mac[j] ^ data[i * 8 + j];
|
||||
}
|
||||
|
||||
mbedtls_des_crypt_ecb(&ctx, xormac, mac);
|
||||
printf("DES1: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
xormac[0], xormac[1], xormac[2], xormac[3],
|
||||
xormac[4], xormac[5], xormac[6], xormac[7]);
|
||||
}
|
||||
|
||||
mbedtls_des_init(&ctx);
|
||||
@@ -201,6 +296,7 @@ bool mrtd_bac_mac(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t
|
||||
}
|
||||
|
||||
bool mrtd_bac_padded_mac(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t* output) {
|
||||
//TODO: bufferless padding should be possible with 3DES
|
||||
size_t newlength = ((data_length+8)/8)*8; // TODO: return this value too?
|
||||
uint8_t padded[newlength]; //TODO: input parameter
|
||||
memset(padded, 0, newlength);
|
||||
@@ -214,3 +310,75 @@ bool mrtd_bac_padded_mac(const uint8_t* data, size_t data_length, uint8_t* key,
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t mrtd_protect_apdu(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, uint8_t lc, const void* data, int16_t le, uint8_t* key_enc, uint8_t* key_mac, uint64_t ssc, uint8_t* output) {
|
||||
//TODO: max size on output?
|
||||
size_t idx = 0;
|
||||
|
||||
// CC = MAC( SSC || CmdHeader || DO'87 )
|
||||
mrtd_bac_mac_ctx mac_ctx;
|
||||
mrtd_bac_mac_init(&mac_ctx, key_mac);
|
||||
uint64_t ssc_n = htonll(ssc);
|
||||
mrtd_bac_mac_update(&mac_ctx, (uint8_t*)&ssc_n, 8);
|
||||
|
||||
// Mask cla
|
||||
output[idx++] = cla | 0x0c;
|
||||
output[idx++] = ins;
|
||||
output[idx++] = p1;
|
||||
output[idx++] = p2;
|
||||
|
||||
// Pad Header
|
||||
mrtd_bac_mac_update(&mac_ctx, output, idx);
|
||||
mrtd_bac_mac_pad(&mac_ctx);
|
||||
|
||||
size_t idx_lc = idx;
|
||||
output[idx++] = 0xff; // place holder for Lc
|
||||
|
||||
// Build DO'87
|
||||
// TODO: condition on data presence
|
||||
{
|
||||
size_t newlength = ((lc+8)/8)*8;
|
||||
uint8_t padded[newlength];
|
||||
size_t idx_do87 = idx;
|
||||
|
||||
output[idx++] = 0x87; // Header
|
||||
output[idx++] = newlength + 1; // Length
|
||||
output[idx++] = 0x01; //TODO: check this value
|
||||
|
||||
memset(padded, 0, newlength);
|
||||
memcpy(padded, data, lc);
|
||||
padded[lc] = 0x80;
|
||||
|
||||
mrtd_bac_encrypt(padded, newlength, key_enc, output + idx);
|
||||
idx += newlength;
|
||||
|
||||
mrtd_bac_mac_update(&mac_ctx, output + idx_do87, idx - idx_do87);
|
||||
}
|
||||
|
||||
// Build DO'8E
|
||||
// TODO: conditions?
|
||||
{
|
||||
output[idx++] = 0x8E; // Header
|
||||
output[idx++] = 0x08; // Length
|
||||
|
||||
printf("idx: %d\n", idx);
|
||||
|
||||
uint8_t mac[8];
|
||||
mrtd_bac_mac_finalize(&mac_ctx, output + idx);
|
||||
idx += 8;
|
||||
printf("MAC: ");
|
||||
for(uint8_t i=0; i<8; ++i) {
|
||||
printf("%02X ", mac[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
output[idx_lc] = idx - idx_lc - 1; // Set Lc
|
||||
|
||||
output[idx++] = 0x00;
|
||||
|
||||
if(le) {
|
||||
//TODO: le?
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mbedtls/des.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t year;
|
||||
uint8_t month;
|
||||
@@ -32,6 +34,16 @@ typedef struct {
|
||||
//TODO: PACE
|
||||
} MrtdAuthData;
|
||||
|
||||
typedef struct {
|
||||
mbedtls_des_context des;
|
||||
uint8_t key[16];
|
||||
uint8_t mac[8];
|
||||
uint8_t xormac[8];
|
||||
|
||||
uint8_t buffer_in[8];
|
||||
uint8_t idx_in;
|
||||
} mrtd_bac_mac_ctx;
|
||||
|
||||
uint8_t mrtd_bac_check_digit(const char* input, const uint8_t length);
|
||||
|
||||
//TODO: swap order, all other functions have output last
|
||||
@@ -47,12 +59,21 @@ bool mrtd_bac_encrypt(const uint8_t* data, size_t data_length, uint8_t* key, uin
|
||||
|
||||
bool mrtd_bac_mac(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t* output);
|
||||
|
||||
bool mrtd_bac_mac_init(mrtd_bac_mac_ctx* ctx, uint8_t key[16]);
|
||||
|
||||
bool mrtd_bac_mac_update(mrtd_bac_mac_ctx* ctx, const uint8_t* data, size_t data_length);
|
||||
|
||||
bool mrtd_bac_mac_finalize(mrtd_bac_mac_ctx* ctx, uint8_t output[8]);
|
||||
|
||||
bool mrtd_bac_padded_mac(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t* output);
|
||||
|
||||
bool mrtd_bac_decrypt(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t* output);
|
||||
|
||||
bool mrtd_bac_decrypt_verify(const uint8_t* data, size_t data_length, uint8_t* key_enc, uint8_t* key_mac, uint8_t* output);
|
||||
|
||||
#include <machine/_endian.h>
|
||||
#define htonll(x) ((((uint64_t)__htonl(x)) << 32) + __htonl((x) >> 32))
|
||||
|
||||
static __inline uint64_t mrtd_ssc_from_data(const uint8_t* rnd_ic, const uint8_t* rnd_ifd) {
|
||||
#if _BYTE_ORDER == _LITTLE_ENDIAN
|
||||
return
|
||||
@@ -70,3 +91,5 @@ static __inline uint64_t mrtd_ssc_from_data(const uint8_t* rnd_ic, const uint8_t
|
||||
(*((uint64_t*)(rnd_ifd + 4)) * 0x100000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t mrtd_protect_apdu(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, uint8_t lc, const void* data, int16_t le, uint8_t* key_enc, uint8_t* key_mac, uint64_t ssc, uint8_t* output);
|
||||
|
||||
+81
-4
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "lib/nfc/protocols/mrtd_helpers.h"
|
||||
|
||||
// gcc -o test_mrtd_helpers -Wall -Ilib/mbedtls/include lib/nfc/protocols/mrtd_helpers.c lib/mbedtls/library/sha1.c lib/mbedtls/library/des.c lib/mbedtls/library/platform_util.c test_mrtd_helpers.c
|
||||
// gcc -o test_mrtd_helpers -Wall -Ilib/mbedtls/include -Itoolchain/x86_64-linux/arm-none-eabi/include/ lib/nfc/protocols/mrtd_helpers.c lib/mbedtls/library/sha1.c lib/mbedtls/library/des.c lib/mbedtls/library/platform_util.c test_mrtd_helpers.c
|
||||
|
||||
#define COLOR_RED "\033[0;31m"
|
||||
#define COLOR_GREEN "\033[0;32m"
|
||||
@@ -152,7 +152,7 @@ void test_mrtd_bac_encrypt(uint8_t* data, size_t data_length, uint8_t* key, uint
|
||||
void test_mrtd_bac_padded_mac(uint8_t* data, size_t data_length, uint8_t* key, uint8_t* exp_output, size_t exp_output_length) {
|
||||
uint8_t mac[8];
|
||||
if(!mrtd_bac_padded_mac(data, data_length, key, mac)) {
|
||||
printf("ERROR BAC MAC");
|
||||
printf("ERROR BAC MAC\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -161,6 +161,7 @@ void test_mrtd_bac_padded_mac(uint8_t* data, size_t data_length, uint8_t* key, u
|
||||
print_hex(exp_output, exp_output_length);
|
||||
printf(" is:\n");
|
||||
print_hex(mac, 8);
|
||||
printf(COLOR_RESET "\n");
|
||||
return;
|
||||
} else {
|
||||
printf(COLOR_GREEN "SUCCESS - mrtd_bac_padded_mac output: ");
|
||||
@@ -169,6 +170,45 @@ void test_mrtd_bac_padded_mac(uint8_t* data, size_t data_length, uint8_t* key, u
|
||||
}
|
||||
}
|
||||
|
||||
void test_mrtd_bac_mac_calls(uint8_t* data, size_t data_length, uint8_t* key, uint8_t* exp_output, size_t exp_output_length) {
|
||||
mrtd_bac_mac_ctx ctx;
|
||||
|
||||
for(int break_at=0; break_at<data_length; break_at += 3) {
|
||||
if(!mrtd_bac_mac_init(&ctx, key)) {
|
||||
printf("ERROR mrtd_bac_mac_init (break_at: %d)\n", break_at);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t mac[8];
|
||||
|
||||
if(!mrtd_bac_mac_update(&ctx, data, break_at)) {
|
||||
printf("ERROR mrtd_bac_mac_update 1 (break_at: %d)\n", break_at);
|
||||
}
|
||||
|
||||
if(!mrtd_bac_mac_update(&ctx, data + break_at, data_length - break_at)) {
|
||||
printf("ERROR mrtd_bac_mac_update 2 (break_at: %d)\n", break_at);
|
||||
}
|
||||
|
||||
if(!mrtd_bac_mac_finalize(&ctx, mac)) {
|
||||
printf("ERROR mrtd_bac_mac_finalize (break_at: %d)\n", break_at);
|
||||
return;
|
||||
}
|
||||
|
||||
if(memcmp(exp_output, mac, exp_output_length)) {
|
||||
printf(COLOR_RED "FAILED - mrtd_bac_mac calls (break_at: %d), expected output:\n", break_at);
|
||||
print_hex(exp_output, exp_output_length);
|
||||
printf(" is:\n");
|
||||
print_hex(mac, 8);
|
||||
printf(COLOR_RESET "\n");
|
||||
return;
|
||||
} else {
|
||||
printf(COLOR_GREEN "SUCCESS - mrtd_bac_mac calls (break_at: %d) output: ", break_at);
|
||||
print_hex(mac, 8);
|
||||
printf(COLOR_RESET "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_mrtd_bac_decrypt_verify(const uint8_t* data, size_t data_length, uint8_t* key_enc, uint8_t* key_mac, uint8_t* exp_output, size_t exp_output_length, bool should_verify) {
|
||||
uint8_t buffer[256];
|
||||
|
||||
@@ -202,6 +242,30 @@ void test_mrtd_ssc_from_data(const uint8_t* rnd_ic, const uint8_t* rnd_ifd, uint
|
||||
printf(COLOR_GREEN "SUCCESS - mrtd_ssc_from_data output: %016lx\n" COLOR_RESET, ssc_long);
|
||||
}
|
||||
|
||||
void test_mrtd_protect_apdu(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, uint8_t lc, const void* data, int16_t le, uint8_t* ks_enc, uint8_t* ks_mac, uint64_t ssc, uint8_t* exp_output, size_t exp_output_length) {
|
||||
uint8_t buffer[4096];
|
||||
|
||||
size_t ret = mrtd_protect_apdu(cla, ins, p1, p2, lc, data, le, ks_enc, ks_mac, ssc, buffer);
|
||||
|
||||
if(!ret) {
|
||||
printf(COLOR_RED "FAILED - mrtd_protect_apdu returned an error\n" COLOR_RESET);
|
||||
return;
|
||||
}
|
||||
|
||||
if(memcmp(buffer, exp_output, ret)) {
|
||||
printf(COLOR_RED "FAILED - mrtd_protect_apdu, expected output:\n" COLOR_RESET);
|
||||
print_hex(exp_output, exp_output_length);
|
||||
printf(" is:\n");
|
||||
print_hex(buffer, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
printf(COLOR_GREEN "SUCCESS - mrtd_protect_apdu output: ");
|
||||
print_hex(buffer, ret);
|
||||
printf("\n" COLOR_RESET);
|
||||
//TODO: hexdump
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
test_mrtd_bac_check_digit("D23145890734", 9);
|
||||
test_mrtd_bac_check_digit("340712", 7);
|
||||
@@ -253,6 +317,14 @@ int main(int argc, char** argv) {
|
||||
/*exp_output_size*/ 8
|
||||
);
|
||||
|
||||
test_mrtd_bac_mac_calls(
|
||||
/*input*/ (uint8_t*)"\x72\xC2\x9C\x23\x71\xCC\x9B\xDB\x65\xB7\x79\xB8\xE8\xD3\x7B\x29\xEC\xC1\x54\xAA\x56\xA8\x79\x9F\xAE\x2F\x49\x8F\x76\xED\x92\xF2",
|
||||
/*size*/ 32,
|
||||
/*key*/ (uint8_t*)"\x79\x62\xD9\xEC\xE0\x3D\x1A\xCD\x4C\x76\x08\x9D\xCE\x13\x15\x43",
|
||||
/*exp output*/ (uint8_t*)"\x5F\x14\x48\xEE\xA8\xAD\x90\xA7",
|
||||
/*exp_output_size*/ 8
|
||||
);
|
||||
|
||||
test_mrtd_bac_decrypt_verify(
|
||||
/*input*/ (uint8_t*)"\x46\xB9\x34\x2A\x41\x39\x6C\xD7\x38\x6B\xF5\x80\x31\x04\xD7\xCE\xDC\x12\x2B\x91\x32\x13\x9B\xAF\x2E\xED\xC9\x4E\xE1\x78\x53\x4F\x2F\x2D\x23\x5D\x07\x4D\x74\x49",
|
||||
/*size*/ 40,
|
||||
@@ -265,10 +337,13 @@ int main(int argc, char** argv) {
|
||||
|
||||
//TODO: test that does not verify
|
||||
|
||||
uint8_t* ks_enc = (uint8_t*)"\x97\x9E\xC1\x3B\x1C\xBF\xE9\xDC\xD0\x1A\xB0\xFE\xD3\x07\xEA\xE5";
|
||||
uint8_t* ks_mac = (uint8_t*)"\xF1\xCB\x1F\x1F\xB5\xAD\xF2\x08\x80\x6B\x89\xDC\x57\x9D\xC1\xF8";
|
||||
|
||||
test_mrtd_bac_keys_from_seed(
|
||||
(uint8_t*)"\x00\x36\xD2\x72\xF5\xC3\x50\xAC\xAC\x50\xC3\xF5\x72\xD2\x36\x00",
|
||||
(uint8_t*)"\x97\x9E\xC1\x3B\x1C\xBF\xE9\xDC\xD0\x1A\xB0\xFE\xD3\x07\xEA\xE5",
|
||||
(uint8_t*)"\xF1\xCB\x1F\x1F\xB5\xAD\xF2\x08\x80\x6B\x89\xDC\x57\x9D\xC1\xF8"
|
||||
ks_enc,
|
||||
ks_mac
|
||||
);
|
||||
|
||||
uint8_t* rnd_ic = (uint8_t*)"\x46\x08\xF9\x19\x88\x70\x22\x12";
|
||||
@@ -276,5 +351,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
test_mrtd_ssc_from_data(rnd_ic, rnd_ifd, 0x887022120C06C226);
|
||||
|
||||
test_mrtd_protect_apdu(0x00, 0xA4, 0x02, 0x0C, 0x02, "\x01\x1e", -1, ks_enc, ks_mac, 0x887022120C06C227, (uint8_t*)"\x0C\xA4\x02\x0C\x15\x87\x09\x01\x63\x75\x43\x29\x08\xC0\x44\xF6\x8E\x08\xBF\x8B\x92\xD6\x35\xFF\x24\xF8\x00", 27);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user