mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-21 05:04:46 -07:00
MRTD decrypt RX APDU
This commit is contained in:
@@ -77,28 +77,9 @@ struct AIDSet AID = {
|
|||||||
.AdditionalBiometrics = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x03},
|
.AdditionalBiometrics = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x03},
|
||||||
};
|
};
|
||||||
|
|
||||||
/*bool mrtd_send_apdu(MrtdApplication* app, uint8_t* buffer, size_t length) {
|
|
||||||
FuriHalNfcTxRxContext* tx_rx = app->tx_rx;
|
|
||||||
|
|
||||||
memcpy(tx_rx->tx_data, buffer, length);
|
//TODO: rename to transceive?
|
||||||
tx_rx->tx_bits = length * 8;
|
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, uint8_t* output) {
|
||||||
tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault;
|
|
||||||
|
|
||||||
//TODO: timeout as param?
|
|
||||||
if(furi_hal_nfc_tx_rx(tx_rx, 300)) {
|
|
||||||
mrtd_trace(app);
|
|
||||||
uint16_t ret_code = mrtd_decode_response(tx_rx->rx_data, tx_rx->rx_bits / 8);
|
|
||||||
if(ret_code == 0x9000) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
FURI_LOG_E(TAG, "APDU answer is not 0x9000, but 0x%04X", ret_code);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
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;
|
FuriHalNfcTxRxContext* tx_rx = app->tx_rx;
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
|
|
||||||
@@ -133,16 +114,18 @@ bool mrtd_send_apdu(MrtdApplication* app, uint8_t cla, uint8_t ins, uint8_t p1,
|
|||||||
mrtd_trace(app);
|
mrtd_trace(app);
|
||||||
uint16_t ret_code = mrtd_decode_response(tx_rx->rx_data, tx_rx->rx_bits / 8);
|
uint16_t ret_code = mrtd_decode_response(tx_rx->rx_data, tx_rx->rx_bits / 8);
|
||||||
|
|
||||||
|
if(app->secure_messaging && ret_code == 0x9000) {
|
||||||
|
app->ssc_long++;
|
||||||
|
mrtd_bac_decrypt_verify_sm(tx_rx->rx_data, tx_rx->rx_bits / 8 - 2,
|
||||||
|
app->ksenc, app->ksmac, app->ssc_long, output, &ret_code);
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: handle other return codes?
|
//TODO: handle other return codes?
|
||||||
if(ret_code == 0x9000) {
|
if(ret_code == 0x9000) {
|
||||||
|
if(!app->secure_messaging && le > 0) {
|
||||||
if(app->secure_messaging) {
|
// Secure Messaging sets output while decrypting
|
||||||
//TODO: decrypt and verify
|
memcpy(output, tx_rx->rx_data, le);
|
||||||
app->ssc_long++;
|
|
||||||
|
|
||||||
mrtd_bac_decrypt_verify
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_I(TAG, "APDU answer is not 0x9000, but 0x%04X", ret_code);
|
FURI_LOG_I(TAG, "APDU answer is not 0x9000, but 0x%04X", ret_code);
|
||||||
@@ -168,7 +151,7 @@ bool mrtd_send_apdu(MrtdApplication* app, uint8_t cla, uint8_t ins, uint8_t p1,
|
|||||||
bool mrtd_select_app(MrtdApplication* app, AIDValue aid) {
|
bool mrtd_select_app(MrtdApplication* app, AIDValue aid) {
|
||||||
FURI_LOG_D(TAG, "Send select App: %02X %02X %02X %02X %02X %02X %02X",
|
FURI_LOG_D(TAG, "Send select App: %02X %02X %02X %02X %02X %02X %02X",
|
||||||
aid[0], aid[1], aid[2], aid[3], aid[4], aid[5], aid[6]);
|
aid[0], aid[1], aid[2], aid[3], aid[4], aid[5], aid[6]);
|
||||||
if(!mrtd_send_apdu(app, 0x00, 0xA4, 0x04, 0x0C, 0x07, aid, -1)) {
|
if(!mrtd_send_apdu(app, 0x00, 0xA4, 0x04, 0x0C, 0x07, aid, -1, NULL)) {
|
||||||
FURI_LOG_W(TAG, "Failed select App");
|
FURI_LOG_W(TAG, "Failed select App");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -177,14 +160,11 @@ bool mrtd_select_app(MrtdApplication* app, AIDValue aid) {
|
|||||||
|
|
||||||
bool mrtd_get_challenge(MrtdApplication* app, uint8_t challenge[8]) {
|
bool mrtd_get_challenge(MrtdApplication* app, uint8_t challenge[8]) {
|
||||||
FURI_LOG_D(TAG, "Send Get Challenge");
|
FURI_LOG_D(TAG, "Send Get Challenge");
|
||||||
if(!mrtd_send_apdu(app, 0x00, 0x84, 0x00, 0x00, 0x00, NULL, 0x08)) {
|
if(!mrtd_send_apdu(app, 0x00, 0x84, 0x00, 0x00, 0x00, NULL, 0x08, challenge)) {
|
||||||
FURI_LOG_W(TAG, "Failed get challenge");
|
FURI_LOG_W(TAG, "Failed get challenge");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuriHalNfcTxRxContext* tx_rx = app->tx_rx;
|
|
||||||
memcpy(challenge, tx_rx->rx_data, 8);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,21 +173,18 @@ bool mrtd_external_authenticate(MrtdApplication* app, uint8_t* cmd_data, size_t
|
|||||||
furi_assert(out_size >= 0x28);
|
furi_assert(out_size >= 0x28);
|
||||||
|
|
||||||
FURI_LOG_D(TAG, "Send External Authenticate");
|
FURI_LOG_D(TAG, "Send External Authenticate");
|
||||||
if(!mrtd_send_apdu(app, 0x00, 0x82, 0x00, 0x00, cmd_size, cmd_data, 0x28)) {
|
if(!mrtd_send_apdu(app, 0x00, 0x82, 0x00, 0x00, cmd_size, cmd_data, 0x28, out_data)) {
|
||||||
FURI_LOG_W(TAG, "Failed External Authenticate");
|
FURI_LOG_W(TAG, "Failed External Authenticate");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuriHalNfcTxRxContext* tx_rx = app->tx_rx;
|
|
||||||
memcpy(out_data, tx_rx->rx_data, 0x28);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mrtd_select_file(MrtdApplication* app, EFFile file) {
|
bool mrtd_select_file(MrtdApplication* app, EFFile file) {
|
||||||
uint8_t data[] = {file.file_id >> 8, file.file_id & 0xff};
|
uint8_t data[] = {file.file_id >> 8, file.file_id & 0xff};
|
||||||
FURI_LOG_D(TAG, "Send select EF: 0x%04X", file.file_id);
|
FURI_LOG_D(TAG, "Send select EF: 0x%04X", file.file_id);
|
||||||
if(!mrtd_send_apdu(app, 0x00, 0xA4, 0x02, 0x0C, 0x02, data, -1)) {
|
if(!mrtd_send_apdu(app, 0x00, 0xA4, 0x02, 0x0C, 0x02, data, -1, NULL)) {
|
||||||
FURI_LOG_E(TAG, "Failed select EF 0x%04X", file.file_id);
|
FURI_LOG_E(TAG, "Failed select EF 0x%04X", file.file_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -221,12 +198,12 @@ size_t mrtd_read_binary(MrtdApplication* app, uint8_t* buffer, size_t bufsize, s
|
|||||||
UNUSED(bufsize);
|
UNUSED(bufsize);
|
||||||
// 00 B0 offst -
|
// 00 B0 offst -
|
||||||
FURI_LOG_D(TAG, "Read binary, offset: %d", offset);
|
FURI_LOG_D(TAG, "Read binary, offset: %d", offset);
|
||||||
if(!mrtd_send_apdu(app, 0x00, 0xB0, offset>>8, offset&0xff, 0x00, NULL, 0)) {
|
//TODO: limit reading/buffer fill to max bufsize
|
||||||
|
if(!mrtd_send_apdu(app, 0x00, 0xB0, offset>>8, offset&0xff, 0x00, NULL, 0, buffer)) {
|
||||||
FURI_LOG_E(TAG, "Failed to read");
|
FURI_LOG_E(TAG, "Failed to read");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: copy data to buffer
|
|
||||||
//TODO: return read amount
|
//TODO: return read amount
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -146,12 +146,6 @@ bool mrtd_bac_encrypt(const uint8_t* data, size_t data_length, uint8_t* key, uin
|
|||||||
bool mrtd_bac_decrypt(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) {
|
||||||
uint8_t IV[8] = "\x00\x00\x00\x00\x00\x00\x00\x00";
|
uint8_t IV[8] = "\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||||
|
|
||||||
printf("Decrypt: ");
|
|
||||||
for(uint8_t i=0; i<data_length; ++i) {
|
|
||||||
printf("%02X ", data[i]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
mbedtls_des3_context ctx;
|
mbedtls_des3_context ctx;
|
||||||
mbedtls_des3_init(&ctx);
|
mbedtls_des3_init(&ctx);
|
||||||
mbedtls_des3_set2key_dec(&ctx, key);
|
mbedtls_des3_set2key_dec(&ctx, key);
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ bool mrtd_bac_decrypt(const uint8_t* data, size_t data_length, uint8_t* key, uin
|
|||||||
|
|
||||||
bool mrtd_bac_decrypt_verify(const uint8_t* data, size_t data_length, uint8_t* key_enc, uint8_t* key_mac, 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);
|
||||||
|
|
||||||
|
bool mrtd_bac_decrypt_verify_sm(const uint8_t* data, size_t data_length, uint8_t* key_enc, uint8_t* key_mac, uint64_t ssc, uint8_t* output, uint16_t* ret_code);
|
||||||
|
|
||||||
#include <machine/_endian.h>
|
#include <machine/_endian.h>
|
||||||
#define htonll(x) ((((uint64_t)__htonl(x)) << 32) + __htonl((x) >> 32))
|
#define htonll(x) ((((uint64_t)__htonl(x)) << 32) + __htonl((x) >> 32))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user