mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 12:42:30 +04:00
Merge pull request #898 from mishamyte/feature/ul-c-try-auth-with-default-pass
[NFC]: Ultralight C. Attempt of authentication with default key
This commit is contained in:
@@ -445,6 +445,8 @@ static NfcCommand mf_ultralight_poller_handler_auth(MfUltralightPoller* instance
|
||||
static NfcCommand mf_ultralight_poller_handler_auth_ultralight_c(MfUltralightPoller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
FURI_LOG_D(TAG, "MfulC auth");
|
||||
|
||||
do {
|
||||
if(mf_ultralight_support_feature(
|
||||
instance->feature_set, MfUltralightFeatureSupportAuthenticate)) {
|
||||
instance->mfu_event.type = MfUltralightPollerEventTypeAuthRequest;
|
||||
@@ -453,35 +455,25 @@ static NfcCommand mf_ultralight_poller_handler_auth_ultralight_c(MfUltralightPol
|
||||
if(!instance->mfu_event.data->auth_context.skip_auth) {
|
||||
FURI_LOG_D(TAG, "Trying to authenticate with 3des key");
|
||||
instance->auth_context.tdes_key = instance->mfu_event.data->auth_context.tdes_key;
|
||||
do {
|
||||
uint8_t output[MF_ULTRALIGHT_C_AUTH_DATA_SIZE];
|
||||
uint8_t RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0};
|
||||
furi_hal_random_fill_buf(RndA, sizeof(RndA));
|
||||
instance->error = mf_ultralight_poller_authenticate_start(instance, RndA, output);
|
||||
if(instance->error != MfUltralightErrorNone) break;
|
||||
instance->error =
|
||||
mf_ultralight_poller_auth_tdes(instance, &instance->auth_context);
|
||||
|
||||
uint8_t decoded_shifted_RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0};
|
||||
const uint8_t* RndB = output + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET;
|
||||
instance->error = mf_ultralight_poller_authenticate_end(
|
||||
instance, RndB, output, decoded_shifted_RndA);
|
||||
if(instance->error != MfUltralightErrorNone) break;
|
||||
|
||||
mf_ultralight_3des_shift_data(RndA);
|
||||
instance->auth_context.auth_success =
|
||||
(memcmp(RndA, decoded_shifted_RndA, sizeof(decoded_shifted_RndA)) == 0);
|
||||
|
||||
if(instance->auth_context.auth_success) {
|
||||
if(instance->error == MfUltralightErrorNone &&
|
||||
instance->auth_context.auth_success) {
|
||||
FURI_LOG_D(TAG, "Auth success");
|
||||
}
|
||||
} while(false);
|
||||
|
||||
if(instance->error != MfUltralightErrorNone || !instance->auth_context.auth_success) {
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "Auth failed");
|
||||
iso14443_3a_poller_halt(instance->iso14443_3a_poller);
|
||||
}
|
||||
} else {
|
||||
// We assume here that it is card read without explicitly provided key
|
||||
// So we try to auth with default one
|
||||
instance->state = MfUltralightPollerStateTryDefaultMfulCKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
instance->state = MfUltralightPollerStateReadPages;
|
||||
} while(false);
|
||||
|
||||
return command;
|
||||
}
|
||||
@@ -578,6 +570,40 @@ static NfcCommand mf_ultralight_poller_handler_try_default_pass(MfUltralightPoll
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
mf_ultralight_poller_handler_try_default_ultralight_c_key(MfUltralightPoller* instance) {
|
||||
do {
|
||||
if(!mf_ultralight_support_feature(
|
||||
instance->feature_set, MfUltralightFeatureSupportAuthenticate)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(instance->auth_context.auth_success) {
|
||||
break;
|
||||
}
|
||||
|
||||
FURI_LOG_D(TAG, "Trying authentication with default 3DES key");
|
||||
|
||||
memcpy(
|
||||
&instance->auth_context.tdes_key.data,
|
||||
MF_ULTRALIGHT_C_DEFAULT_KEY,
|
||||
MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE);
|
||||
|
||||
instance->error = mf_ultralight_poller_auth_tdes(instance, &instance->auth_context);
|
||||
|
||||
if(instance->error == MfUltralightErrorNone && instance->auth_context.auth_success) {
|
||||
FURI_LOG_D(TAG, "Default 3DES key detected");
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "Authentication attempt with default 3DES key failed");
|
||||
iso14443_3a_poller_halt(instance->iso14443_3a_poller);
|
||||
}
|
||||
|
||||
} while(false);
|
||||
|
||||
instance->state = MfUltralightPollerStateReadPages;
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
mf_ultralight_poller_handler_check_mfuc_auth_status(MfUltralightPoller* instance) {
|
||||
instance->state = MfUltralightPollerStateReadSuccess;
|
||||
@@ -742,6 +768,8 @@ static const MfUltralightPollerReadHandler
|
||||
mf_ultralight_poller_handler_read_tearing_flags,
|
||||
[MfUltralightPollerStateAuth] = mf_ultralight_poller_handler_auth,
|
||||
[MfUltralightPollerStateTryDefaultPass] = mf_ultralight_poller_handler_try_default_pass,
|
||||
[MfUltralightPollerStateTryDefaultMfulCKey] =
|
||||
mf_ultralight_poller_handler_try_default_ultralight_c_key,
|
||||
[MfUltralightPollerStateCheckMfulCAuthStatus] =
|
||||
mf_ultralight_poller_handler_check_mfuc_auth_status,
|
||||
[MfUltralightPollerStateAuthMfulC] = mf_ultralight_poller_handler_auth_ultralight_c,
|
||||
|
||||
@@ -81,6 +81,19 @@ MfUltralightError mf_ultralight_poller_auth_pwd(
|
||||
MfUltralightPoller* instance,
|
||||
MfUltralightPollerAuthContext* data);
|
||||
|
||||
/**
|
||||
* @brief Perform 3DES authentication with key.
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in, out] data pointer to the authentication context.
|
||||
* @return MfUltralightErrorNone on success, an error code on failure.
|
||||
*/
|
||||
MfUltralightError mf_ultralight_poller_auth_tdes(
|
||||
MfUltralightPoller* instance,
|
||||
MfUltralightPollerAuthContext* data);
|
||||
|
||||
/**
|
||||
* @brief Start authentication procedure.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "mf_ultralight_poller_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define TAG "MfUltralightPoller"
|
||||
|
||||
@@ -62,6 +63,38 @@ MfUltralightError mf_ultralight_poller_auth_pwd(
|
||||
return ret;
|
||||
}
|
||||
|
||||
MfUltralightError mf_ultralight_poller_auth_tdes(
|
||||
MfUltralightPoller* instance,
|
||||
MfUltralightPollerAuthContext* data) {
|
||||
furi_check(instance);
|
||||
furi_check(data);
|
||||
|
||||
MfUltralightError ret = MfUltralightErrorNone;
|
||||
|
||||
uint8_t output[MF_ULTRALIGHT_C_AUTH_DATA_SIZE];
|
||||
uint8_t RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0};
|
||||
furi_hal_random_fill_buf(RndA, sizeof(RndA));
|
||||
|
||||
ret = mf_ultralight_poller_authenticate_start(instance, RndA, output);
|
||||
|
||||
if(ret != MfUltralightErrorNone) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t decoded_shifted_RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0};
|
||||
const uint8_t* RndB = output + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET;
|
||||
ret = mf_ultralight_poller_authenticate_end(instance, RndB, output, decoded_shifted_RndA);
|
||||
|
||||
if(ret != MfUltralightErrorNone) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
mf_ultralight_3des_shift_data(RndA);
|
||||
data->auth_success = (memcmp(RndA, decoded_shifted_RndA, sizeof(decoded_shifted_RndA)) == 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static MfUltralightError mf_ultralight_poller_send_authenticate_cmd(
|
||||
MfUltralightPoller* instance,
|
||||
const uint8_t* cmd,
|
||||
@@ -134,7 +167,7 @@ MfUltralightError mf_ultralight_poller_authenticate_start(
|
||||
uint8_t* RndB = output + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET;
|
||||
mf_ultralight_3des_decrypt(
|
||||
&instance->des_context,
|
||||
instance->mfu_event.data->auth_context.tdes_key.data,
|
||||
instance->auth_context.tdes_key.data,
|
||||
iv,
|
||||
encRndB,
|
||||
sizeof(encRndB),
|
||||
@@ -145,7 +178,7 @@ MfUltralightError mf_ultralight_poller_authenticate_start(
|
||||
|
||||
mf_ultralight_3des_encrypt(
|
||||
&instance->des_context,
|
||||
instance->mfu_event.data->auth_context.tdes_key.data,
|
||||
instance->auth_context.tdes_key.data,
|
||||
encRndB,
|
||||
output,
|
||||
MF_ULTRALIGHT_C_AUTH_DATA_SIZE,
|
||||
@@ -179,7 +212,7 @@ MfUltralightError mf_ultralight_poller_authenticate_end(
|
||||
|
||||
mf_ultralight_3des_decrypt(
|
||||
&instance->des_context,
|
||||
instance->mfu_event.data->auth_context.tdes_key.data,
|
||||
instance->auth_context.tdes_key.data,
|
||||
RndB,
|
||||
bit_buffer_get_data(instance->rx_buffer) + 1,
|
||||
MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE,
|
||||
|
||||
@@ -59,6 +59,7 @@ typedef enum {
|
||||
MfUltralightPollerStateAuthMfulC,
|
||||
MfUltralightPollerStateReadPages,
|
||||
MfUltralightPollerStateTryDefaultPass,
|
||||
MfUltralightPollerStateTryDefaultMfulCKey,
|
||||
MfUltralightPollerStateCheckMfulCAuthStatus,
|
||||
MfUltralightPollerStateReadFailed,
|
||||
MfUltralightPollerStateReadSuccess,
|
||||
|
||||
@@ -2741,6 +2741,7 @@ Function,+,mf_ultralight_is_equal,_Bool,"const MfUltralightData*, const MfUltral
|
||||
Function,+,mf_ultralight_is_page_pwd_or_pack,_Bool,"MfUltralightType, uint16_t"
|
||||
Function,+,mf_ultralight_load,_Bool,"MfUltralightData*, FlipperFormat*, uint32_t"
|
||||
Function,+,mf_ultralight_poller_auth_pwd,MfUltralightError,"MfUltralightPoller*, MfUltralightPollerAuthContext*"
|
||||
Function,+,mf_ultralight_poller_auth_tdes,MfUltralightError,"MfUltralightPoller*, MfUltralightPollerAuthContext*"
|
||||
Function,+,mf_ultralight_poller_authenticate_end,MfUltralightError,"MfUltralightPoller*, const uint8_t*, const uint8_t*, uint8_t*"
|
||||
Function,+,mf_ultralight_poller_authenticate_start,MfUltralightError,"MfUltralightPoller*, const uint8_t*, uint8_t*"
|
||||
Function,+,mf_ultralight_poller_read_counter,MfUltralightError,"MfUltralightPoller*, uint8_t, MfUltralightCounter*"
|
||||
|
||||
|
Reference in New Issue
Block a user