diff --git a/Makefile b/Makefile index 51c8c4d..24fe08f 100755 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ OBJS += external/printf/printf.o # Drivers OBJS += driver/adc.o +OBJS += driver/aes.o OBJS += driver/backlight.o OBJS += driver/bk1080.o OBJS += driver/bk4819.o diff --git a/app/uart.c b/app/uart.c index 15d5d91..a32da43 100644 --- a/app/uart.c +++ b/app/uart.c @@ -17,13 +17,18 @@ #include #include "app/fm.h" #include "app/uart.h" +#include "board.h" #include "bsp/dp32g030/dma.h" #include "bsp/dp32g030/gpio.h" +#include "driver/aes.h" +#include "driver/bk4819.h" #include "driver/crc.h" #include "driver/eeprom.h" #include "driver/gpio.h" #include "driver/uart.h" +#include "functions.h" #include "misc.h" +#include "settings.h" #include "sram-overlay.h" #define DMA_INDEX(x, y) (((x) + (y)) % sizeof(UART_DMA_Buffer)) @@ -38,27 +43,20 @@ typedef struct { uint16_t ID; } Footer_t; -static const uint8_t Obfuscation[16] = { 0x16, 0x6C, 0x14, 0xE6, 0x2E, 0x91, 0x0D, 0x40, 0x21, 0x35, 0xD5, 0x40, 0x13, 0x03, 0xE9, 0x80 }; - -static union { - uint8_t Buffer[256]; - struct { - Header_t Header; - uint8_t Data[252]; - }; -} UART_Command; - typedef struct { Header_t Header; uint32_t Timestamp; } CMD_0514_t; typedef struct { - char Version[16]; - bool bHasCustomAesKey; - bool bIsInLockScreen; - uint8_t Padding[2]; - uint32_t Random[4]; + Header_t Header; + struct { + char Version[16]; + bool bHasCustomAesKey; + bool bIsInLockScreen; + uint8_t Padding[2]; + uint32_t Challenge[4]; + } Data; } REPLY_0514_t; typedef struct { @@ -70,12 +68,77 @@ typedef struct { } CMD_051B_t; typedef struct { - uint16_t Offset; - uint8_t Size; - uint8_t Padding; - uint8_t Data[128]; + Header_t Header; + struct { + uint16_t Offset; + uint8_t Size; + uint8_t Padding; + uint8_t Data[128]; + } Data; } REPLY_051B_t; +typedef struct { + Header_t Header; + uint16_t Offset; + uint8_t Size; + bool bAllowPassword; + uint32_t Timestamp; + uint8_t Data[0]; +} CMD_051D_t; + +typedef struct { + Header_t Header; + struct { + uint16_t Offset; + } Data; +} REPLY_051D_t; + +typedef struct { + Header_t Header; + struct { + uint16_t RSSI; + uint8_t ExNoiseIndicator; + uint8_t GlitchIndicator; + } Data; +} REPLY_0527_t; + +typedef struct { + Header_t Header; + struct { + uint16_t Voltage; + uint16_t Current; + } Data; +} REPLY_0529_t; + +typedef struct { + Header_t Header; + uint32_t Response[4]; +} CMD_052D_t; + +typedef struct { + Header_t Header; + struct { + bool bIsLocked; + uint8_t Padding[3]; + } Data; +} REPLY_052D_t; + +typedef struct { + Header_t Header; + uint32_t Timestamp; +} CMD_052F_t; + +static const uint8_t Obfuscation[16] = { 0x16, 0x6C, 0x14, 0xE6, 0x2E, 0x91, 0x0D, 0x40, 0x21, 0x35, 0xD5, 0x40, 0x13, 0x03, 0xE9, 0x80 }; + +static union { + uint8_t Buffer[256]; + struct { + Header_t Header; + uint8_t Data[252]; + }; +} UART_Command; + +static uint32_t Timestamp; static uint16_t gUART_WriteIndex; static bool bIsEncrypted; @@ -109,41 +172,61 @@ static void SendReply(void *pReply, uint16_t Size) UART_Send(&Footer, sizeof(Footer)); } -static void CMD_0514(const uint8_t *pBuffer) +static void SendVersion(void) { - //const CMD_0514_t *pCmd = (const CMD_0514_t *)pBuffer; - struct { - Header_t Header; - REPLY_0514_t Data; - } Reply; - - //gCmd_Timestamp = Read_U32((byte *)&pCmd->Timestamp); - gFmRadioCountdown = 4; - GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BACKLIGHT); + REPLY_0514_t Reply; Reply.Header.ID = 0x0515; Reply.Header.Size = sizeof(Reply.Data); strcpy(Reply.Data.Version, "Open Edition FW"); Reply.Data.bHasCustomAesKey = bHasCustomAesKey; Reply.Data.bIsInLockScreen = bIsInLockScreen; - Reply.Data.Random[0] = 0x11111111; - Reply.Data.Random[1] = 0x22222222; - Reply.Data.Random[2] = 0x33333333; - Reply.Data.Random[3] = 0x44444444; + Reply.Data.Challenge[0] = gChallenge[0]; + Reply.Data.Challenge[1] = gChallenge[1]; + Reply.Data.Challenge[2] = gChallenge[2]; + Reply.Data.Challenge[3] = gChallenge[3]; SendReply(&Reply, sizeof(Reply)); } +static bool IsBadChallenge(const uint32_t *pKey, const uint32_t *pIn, const uint32_t *pResponse) +{ + uint8_t i; + uint32_t IV[4]; + + IV[0] = 0; + IV[1] = 0; + IV[2] = 0; + IV[3] = 0; + AES_Encrypt(pKey, IV, pIn, IV, true); + for (i = 0; i < 4; i++) { + if (IV[i] != pResponse[i]) { + return true; + } + } + + return false; +} + +static void CMD_0514(const uint8_t *pBuffer) +{ + const CMD_0514_t *pCmd = (const CMD_0514_t *)pBuffer; + + Timestamp = pCmd->Timestamp; + gFmRadioCountdown = 4; + GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BACKLIGHT); + SendVersion(); +} + static void CMD_051B(const uint8_t *pBuffer) { const CMD_051B_t *pCmd = (const CMD_051B_t *)pBuffer; - struct { - Header_t Header; - REPLY_051B_t Data; - } Reply; + REPLY_051B_t Reply; bool bLocked = false; - // if (pCmd->Timestamp != gTimestamp) return; + if (pCmd->Timestamp != Timestamp) { + return; + } gFmRadioCountdown = 4; memset(&Reply, 0, sizeof(Reply)); @@ -163,6 +246,136 @@ static void CMD_051B(const uint8_t *pBuffer) SendReply(&Reply, pCmd->Size + 8); } +static void CMD_051D(const uint8_t *pBuffer) +{ + const CMD_051D_t *pCmd = (const CMD_051D_t *)pBuffer; + REPLY_051D_t Reply; + bool bReloadEeprom; + bool bIsLocked; + + if (pCmd->Timestamp != Timestamp) { + return; + } + + bReloadEeprom = false; + + gFmRadioCountdown = 4; + Reply.Header.ID = 0x051E; + Reply.Header.Size = sizeof(Reply.Data); + Reply.Data.Offset = pCmd->Offset; + + bIsLocked = bHasCustomAesKey; + if (bHasCustomAesKey) { + bIsLocked = gIsLocked; + } + + if (!bIsLocked) { + uint16_t i; + + for (i = 0; i < (pCmd->Size / 8U); i++) { + uint16_t Offset = pCmd->Offset + (i * 8U); + + if (Offset >= 0x0F30 && Offset < 0x0F40) { + if (!gIsLocked) { + bReloadEeprom = true; + } + } + + if ((Offset < 0x0E98 || Offset >= 0x0EA0) || !bIsInLockScreen || pCmd->bAllowPassword) { + EEPROM_WriteBuffer(Offset, &pCmd->Data[i * 8U]); + } + } + + if (bReloadEeprom) { + BOARD_EEPROM_Init(); + } + } + + SendReply(&Reply, sizeof(Reply)); +} + +static void CMD_0527(void) +{ + REPLY_0527_t Reply; + + Reply.Header.ID = 0x0528; + Reply.Header.Size = sizeof(Reply.Data); + Reply.Data.RSSI = BK4819_GetRegister(BK4819_REG_67) & 0x01FF; + Reply.Data.ExNoiseIndicator = BK4819_GetRegister(BK4819_REG_65) & 0x007F; + Reply.Data.GlitchIndicator = BK4819_GetRegister(BK4819_REG_63); + + SendReply(&Reply, sizeof(Reply)); +} + +static void CMD_0529(void) +{ + REPLY_0529_t Reply; + + Reply.Header.ID = 0x52A; + Reply.Header.Size = sizeof(Reply.Data); + // Original doesn't actually send current! + BOARD_ADC_GetBatteryInfo(&Reply.Data.Voltage, &Reply.Data.Current); + SendReply(&Reply, sizeof(Reply)); +} + +static void CMD_052D(const uint8_t *pBuffer) +{ + const CMD_052D_t *pCmd = (const CMD_052D_t *)pBuffer; + REPLY_052D_t Reply; + bool bIsLocked; + + gFmRadioCountdown = 4; + Reply.Header.ID = 0x052E; + Reply.Header.Size = sizeof(Reply.Data); + + bIsLocked = bHasCustomAesKey; + + if (!bIsLocked) { + bIsLocked = IsBadChallenge(gCustomAesKey, gChallenge, pCmd->Response); + } + if (!bIsLocked) { + bIsLocked = IsBadChallenge(gDefaultAesKey, gChallenge, pCmd->Response); + if (bIsLocked) { + gTryCount++; + } + } + if (gTryCount < 3) { + if (!bIsLocked) { + gTryCount = 0; + } + } else { + gTryCount = 3; + bIsLocked = true; + } + gIsLocked = bIsLocked; + Reply.Data.bIsLocked = bIsLocked; + SendReply(&Reply, sizeof(Reply)); +} + +static void CMD_052F(const uint8_t *pBuffer) +{ + const CMD_052F_t *pCmd = (const CMD_052F_t *)pBuffer; + + gEeprom.DUAL_WATCH = DUAL_WATCH_OFF; + gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF; + gEeprom.RX_CHANNEL = 0; + gEeprom.DTMF_SIDE_TONE = false; + gEeprom.VfoInfo[0].FrequencyReverse = false; + gEeprom.VfoInfo[0].pCurrent = &gEeprom.VfoInfo[0].ConfigRX; + gEeprom.VfoInfo[0].pReverse = &gEeprom.VfoInfo[0].ConfigTX; + gEeprom.VfoInfo[0].FREQUENCY_DEVIATION_SETTING = FREQUENCY_DEVIATION_OFF; + gEeprom.VfoInfo[0].DTMF_PTT_ID_TX_MODE = PTT_ID_OFF; + gEeprom.VfoInfo[0].DTMF_DECODING_ENABLE = false; + gIsNoaaMode = false; + if (gCurrentFunction == FUNCTION_POWER_SAVE) { + FUNCTION_Select(FUNCTION_0); + } + Timestamp = pCmd->Timestamp; + GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BACKLIGHT); + + SendVersion(); +} + bool UART_IsCommandAvailable(void) { uint16_t DmaLength; @@ -259,12 +472,6 @@ bool UART_IsCommandAvailable(void) void UART_HandleCommand(void) { switch (UART_Command.Header.ID) { - case 0x0527: - break; - - case 0x051D: - break; - case 0x0514: CMD_0514(UART_Command.Buffer); break; @@ -273,19 +480,32 @@ void UART_HandleCommand(void) CMD_051B(UART_Command.Buffer); break; + case 0x051D: + CMD_051D(UART_Command.Buffer); + break; + case 0x051F: + // Not implementing non-authentic command break; case 0x0521: + // Not implementing non-authentic command + break; + + case 0x0527: + CMD_0527(); break; case 0x0529: + CMD_0529(); break; case 0x052D: + CMD_052D(UART_Command.Buffer); break; case 0x052F: + CMD_052F(UART_Command.Buffer); break; case 0x05DD: diff --git a/board.c b/board.c index c0591d9..25cd4f9 100644 --- a/board.c +++ b/board.c @@ -751,10 +751,10 @@ void BOARD_EEPROM_Init(void) EEPROM_ReadBuffer(0x0D60, gMR_ChannelAttributes, 207); // 0F30..0F3F - EEPROM_ReadBuffer(0x0F30, gCustomPasswordKey, 16); + EEPROM_ReadBuffer(0x0F30, gCustomAesKey, 16); for (i = 0; i < 4; i++) { - if (gCustomPasswordKey[i] != 0xFFFFFFFFU) { + if (gCustomAesKey[i] != 0xFFFFFFFFU) { bHasCustomAesKey = true; return; } diff --git a/driver/bk4819-regs.h b/driver/bk4819-regs.h index fcabd2d..9a55052 100644 --- a/driver/bk4819-regs.h +++ b/driver/bk4819-regs.h @@ -72,7 +72,9 @@ enum BK4819_REGISTER_t { BK4819_REG_5C = 0x5CU, BK4819_REG_5D = 0x5DU, BK4819_REG_5F = 0x5FU, + BK4819_REG_63 = 0x63U, BK4819_REG_64 = 0x64U, + BK4819_REG_65 = 0x65U, BK4819_REG_67 = 0x67U, BK4819_REG_68 = 0x68U, BK4819_REG_69 = 0x69U, diff --git a/misc.c b/misc.c index d90083e..fea713e 100644 --- a/misc.c +++ b/misc.c @@ -29,9 +29,17 @@ uint8_t gSetting_F_LOCK; bool gSetting_ScrambleEnable; uint8_t gSetting_F_LOCK; -uint32_t gCustomPasswordKey[4]; +const uint32_t gDefaultAesKey[4] = { + 0x4AA5CC60, + 0x0312CC5F, + 0xFFD2DABB, + 0x6BBA7F92, +}; +uint32_t gCustomAesKey[4]; bool bHasCustomAesKey; +uint32_t gChallenge[4]; +uint8_t gTryCount; uint8_t gEEPROM_1EC0_0[8]; uint8_t gEEPROM_1EC0_1[8]; diff --git a/misc.h b/misc.h index 92e6982..c26a3f9 100644 --- a/misc.h +++ b/misc.h @@ -59,9 +59,11 @@ extern uint8_t gSetting_F_LOCK; extern bool gSetting_ScrambleEnable; extern uint8_t gSetting_F_LOCK; -extern uint32_t gCustomPasswordKey[4]; - +extern const uint32_t gDefaultAesKey[4]; +extern uint32_t gCustomAesKey[4]; extern bool bHasCustomAesKey; +extern uint32_t gChallenge[4]; +extern uint8_t gTryCount; extern uint8_t gEEPROM_1EC0_0[8]; extern uint8_t gEEPROM_1EC0_1[8];