From 789bdbf457ab39b32cb49eb7717b30f7ae40476c Mon Sep 17 00:00:00 2001 From: cfif Date: Wed, 28 Jan 2026 14:48:17 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MainModesArbiter.c | 2 +- MainModesArbiter_InitStage.c | 4 +- NAMI.c | 136 +++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 NAMI.c diff --git a/MainModesArbiter.c b/MainModesArbiter.c index a07ecc1..b39b2d0 100644 --- a/MainModesArbiter.c +++ b/MainModesArbiter.c @@ -59,7 +59,7 @@ static _Noreturn void Mma_Thread(tMma *env) { SystemDelayMs(1000); - ModelTask_StartThread(&env->ModelTask); +// ModelTask_StartThread(&env->ModelTask); /* diff --git a/MainModesArbiter_InitStage.c b/MainModesArbiter_InitStage.c index 06c7695..339dcf7 100644 --- a/MainModesArbiter_InitStage.c +++ b/MainModesArbiter_InitStage.c @@ -79,10 +79,10 @@ static void Mma_InitSubSystems(tMma *env) { CanSerialPortCanUds_Start(&env->canUds); CanSpamReceiver_Init(&env->canSpamReceiver, &env->canPorts->Can0_IO); - CanSpamReceiver_StartThread(&env->canSpamReceiver); +// CanSpamReceiver_StartThread(&env->canSpamReceiver); CanSpamTransmitter_Init(&env->canSpamTransmitter, &env->canPorts->Can0_IO); - CanSpamTransmitter_StartThread(&env->canSpamTransmitter); +// CanSpamTransmitter_StartThread(&env->canSpamTransmitter); tLinData *linData = Lin0_Init(GetLin0CallbackHandler); Lin_0_Init(&env->linTaskActuator0, linData, &env->linPorts->lin0_Io, &env->slog.logger); diff --git a/NAMI.c b/NAMI.c new file mode 100644 index 0000000..7a4b76f --- /dev/null +++ b/NAMI.c @@ -0,0 +1,136 @@ +// +// Created by cfif on 28.01.2026. +// +#include +#include + +/** + * CCU Secure Access Algorithm + * Реализация алгоритма генерации ключа по seed для диагностического доступа + * Согласно спецификации NAMI UMP vehicle, версия 1.1 + */ + +/* Позиции битов коэффициентов в seed */ +#define COEFF1_POS 20 /* Направление сдвига (0 - влево, 1 - вправо) */ +#define COEFF2_POS 7 /* Старший бит количества сдвигов */ +#define COEFF3_POS 11 /* */ +#define COEFF4_POS 5 /* */ +#define COEFF5_POS 8 /* Младший бит количества сдвигов */ +#define COEFF6_POS 22 /* Старший бит операции инверсии */ +#define COEFF7_POS 1 /* Младший бит операции инверсии */ +#define COEFF8_POS 21 /* Старший бит побитовой операции */ +#define COEFF9_POS 6 /* Младший бит побитовой операции */ + +/* Позиции битов для инверсии */ +#define INV_A_BITS ((1U << 6) | (1U << 15) | (1U << 17)) +#define INV_B_BITS ((1U << 11) | (1U << 9) | (1U << 16)) +#define INV_C_BITS ((1U << 7) | (1U << 10) | (1U << 13) | (1U << 4)) + +/** + * Извлечение бита из значения + * position: 0 = младший бит (LSB), 31 = старший бит (MSB) + */ +static inline uint32_t extract_bit(uint32_t value, int position) +{ + return (value >> position) & 1U; +} + +/** + * Циклический сдвиг вправо (rotation) + */ +static inline uint32_t rotate_right(uint32_t value, int bits) +{ + bits = bits % 32; + if (bits == 0) return value; + return (value >> bits) | (value << (32 - bits)); +} + +/** + * Циклический сдвиг влево (rotation) + */ +static inline uint32_t rotate_left(uint32_t value, int bits) +{ + bits = bits % 32; + if (bits == 0) return value; + return (value << bits) | (value >> (32 - bits)); +} + +/** + * Генерация 32-битного ключа из 32-битного seed + * + * Параметры: + * seed - случайное значение от ECU (32 бита) + * + * Возвращает: + * 32-битный ключ для ответа ECU + */ +uint32_t generate_key(uint32_t seed) +{ + /* Извлечение коэффициентов из seed */ + uint32_t coeff1 = extract_bit(seed, COEFF1_POS); /* Направление сдвига */ + + /* Коэффициенты 2-5: количество циклических сдвигов (coeff2 - старший бит) */ + uint32_t coeff2 = extract_bit(seed, COEFF2_POS); + uint32_t coeff3 = extract_bit(seed, COEFF3_POS); + uint32_t coeff4 = extract_bit(seed, COEFF4_POS); + uint32_t coeff5 = extract_bit(seed, COEFF5_POS); + uint32_t num_shifts = (coeff2 << 3) | (coeff3 << 2) | (coeff4 << 1) | coeff5; + + /* Коэффициенты 6-7: выбор операции инверсии (coeff6 - старший бит) */ + uint32_t coeff6 = extract_bit(seed, COEFF6_POS); + uint32_t coeff7 = extract_bit(seed, COEFF7_POS); + uint32_t inversion_op = (coeff6 << 1) | coeff7; + + /* Коэффициенты 8-9: побитовая операция (coeff8 - старший бит) */ + uint32_t coeff8 = extract_bit(seed, COEFF8_POS); + uint32_t coeff9 = extract_bit(seed, COEFF9_POS); + uint32_t bitwise_op = (coeff8 << 1) | coeff9; + + /* Шаг 1: Вычисление intermediate 1 (циклический сдвиг) */ + uint32_t intermediate1; + if (coeff1 == 0) { + intermediate1 = rotate_left(seed, num_shifts); + } else { + intermediate1 = rotate_right(seed, num_shifts); + } + + /* Шаг 2: Вычисление intermediate 2 (инверсия битов) */ + uint32_t intermediate2 = intermediate1; + + switch (inversion_op) { + case 1: /* Операция A: инвертировать биты 6, 15, 17 */ + intermediate2 ^= INV_A_BITS; + break; + case 2: /* Операция B: инвертировать биты 11, 9, 16 */ + intermediate2 ^= INV_B_BITS; + break; + case 3: /* Операция C: инвертировать биты 7, 10, 13, 4 */ + intermediate2 ^= INV_C_BITS; + break; + case 0: /* Нет инверсии */ + default: + break; + } + + /* Шаг 3: Вычисление финального ключа (побитовая операция) */ + uint32_t key; + switch (bitwise_op) { + case 0: /* Key = intermediate value */ + key = intermediate2; + break; + case 1: /* Key = seed AND intermediate value */ + key = seed & intermediate2; + break; + case 2: /* Key = seed XOR intermediate value */ + key = seed ^ intermediate2; + break; + case 3: /* Key = seed OR intermediate value */ + key = seed | intermediate2; + break; + default: + key = intermediate2; + break; + } + + return key; +} \ No newline at end of file