Author Topic: Quansheng UV5 (new 2024 V5.00.03) wont allow FW change or chirp. Any Clues?  (Read 15885 times)

0 Members and 2 Guests are viewing this topic.

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
It seems to me that there is some initialization of the aes module in the bootloader code.
Because the aes registers simply do not respond via debug.

did you called AES_Init?

Maybe there is needs to enable clock for AES module in SYSCON.

Try this:
Code: [Select]
SYSCON_DEV_CLK_GATE |= DEV_CLK_GATE_AES_CLK_GATE;

// SYSCON defs
#define SYSCON_BASE             0x40000000
#define SYSCON_CLK_SEL          (*(volatile uint32_t *)(SYSCON_BASE + 0x0000))
#define SYSCON_DIV_CLK_GATE     (*(volatile uint32_t *)(SYSCON_BASE + 0x0004))
#define SYSCON_DEV_CLK_GATE     (*(volatile uint32_t *)(SYSCON_BASE + 0x0008))
#define SYSCON_RC_FREQ_DELTA    (*(volatile uint32_t *)(SYSCON_BASE + 0x0078))
#define SYSCON_VREF_VOLT_DELTA  (*(volatile uint32_t *)(SYSCON_BASE + 0x007c))
#define SYSCON_CHIP_ID0         (*(volatile uint32_t *)(SYSCON_BASE + 0x0080))
#define SYSCON_CHIP_ID1         (*(volatile uint32_t *)(SYSCON_BASE + 0x0084))
#define SYSCON_CHIP_ID2         (*(volatile uint32_t *)(SYSCON_BASE + 0x0088))
#define SYSCON_CHIP_ID3         (*(volatile uint32_t *)(SYSCON_BASE + 0x008c))
#define SYSCON_PLL_CTRL         (*(volatile uint32_t *)(SYSCON_BASE + 0x0180))
#define SYSCON_PLL_ST           (*(volatile uint32_t *)(SYSCON_BASE + 0x0184))

#define DEV_CLK_GATE_AES_CLK_GATE   (1 << 28)

But if you're doing it just after reset with no init at all, it also may need to configure clock.
Needs to find initialization.
See dp32g030 datasheet for SYSCON registers description.

In particular, the work with the 0x40000000 register is interesting. It seems to me that something similar is at offset 0x628. I am bad at decompiling. Therefore, this is only an assumption.

No, it looks like UART1 init:
Code: [Select]
@ arm-none-eabi-objdump -D -b binary -marm --start-address=0x628 --stop-address=0x6cd -Mforce-thumb bootloader.bin

     628: b510      push {r4, lr}
     62a: 2001      movs r0, #1
     62c: 0780      lsls r0, r0, #30
     62e: 6881      ldr r1, [r0, #8]
     630: 2280      movs r2, #128 @ 0x80
     632: 4311      orrs r1, r2
     634: 6081      str r1, [r0, #8]
     636: 4c1c      ldr r4, [pc, #112] @ (0x6a8)   @ r4 = 0x4006B800   // UART1_CTRL
     638: 6820      ldr r0, [r4, #0]
     63a: 0840      lsrs r0, r0, #1
     63c: 0040      lsls r0, r0, #1
     63e: 6020      str r0, [r4, #0]
     640: 481a      ldr r0, [pc, #104] @ (0x6ac)   @ r0 = 0x40000040   // 0x40000040+0x38=0x40000078
     642: 6b81      ldr r1, [r0, #56] @ 0x38      @ r1 = SYSCON->RC_FREQ_DELTA;
     644: 4a1a      ldr r2, [pc, #104] @ (0x6b0)   @ r2 = 0x02DC6C00
     646: 0048      lsls r0, r1, #1
     648: 0b00      lsrs r0, r0, #12
     64a: 0fc9      lsrs r1, r1, #31
     64c: d001      beq.n 0x652
     64e: 1880      adds r0, r0, r2
     650: e000      b.n 0x654
     652: 1a10      subs r0, r2, r0
     654: 4917      ldr r1, [pc, #92] @ (0x6b4)   @ r1 = 0x0000988D
     656: f7ff fd67 bl 0x128
     65a: 6060      str r0, [r4, #4]
     65c: 200e      movs r0, #14
     65e: 6020      str r0, [r4, #0]
     660: 2004      movs r0, #4
     662: 6220      str r0, [r4, #32]
     664: 2200      movs r2, #0
     666: 61e2      str r2, [r4, #28]
     668: 20c7      movs r0, #199 @ 0xc7
     66a: 61a0      str r0, [r4, #24]
     66c: 6122      str r2, [r4, #16]
     66e: 4812      ldr r0, [pc, #72] @ (0x6b8)   @ r0 = 0x40001000   // DMA_CTR
     670: 6801      ldr r1, [r0, #0]
     672: 0849      lsrs r1, r1, #1
     674: 0049      lsls r1, r1, #1
     676: 6001      str r1, [r0, #0]
     678: 4b0b      ldr r3, [pc, #44] @ (0x6a8)
     67a: 4910      ldr r1, [pc, #64] @ (0x6bc)   @ r1 = 0x40001100   // DMA_CH0CTR
     67c: 330c      adds r3, #12
     67e: 608b      str r3, [r1, #8]
     680: 4b0f      ldr r3, [pc, #60] @ (0x6c0)   @ r3 = 0x20000324
     682: 60cb      str r3, [r1, #12]
     684: 23ff      movs r3, #255 @ 0xff
     686: 3311      adds r3, #17
     688: 604b      str r3, [r1, #4]
     68a: 6042      str r2, [r0, #4]
     68c: 4a0d      ldr r2, [pc, #52] @ (0x6c4)   @ r2 = 0x00000F0F
     68e: 6082      str r2, [r0, #8]
     690: 4a0d      ldr r2, [pc, #52] @ (0x6c8)   @ r2 = 0x00006FFF
     692: 600a      str r2, [r1, #0]
     694: 2120      movs r1, #32
     696: 6161      str r1, [r4, #20]
     698: 6802      ldr r2, [r0, #0]
     69a: 2101      movs r1, #1
     69c: 430a      orrs r2, r1
     69e: 6002      str r2, [r0, #0]
     6a0: 6820      ldr r0, [r4, #0]
     6a2: 4308      orrs r0, r1
     6a4: 6020      str r0, [r4, #0]
     6a6: bd10      pop {r4, pc}
     6a8: b800      DCD 0x4006B800
     6aa: 4006     
     6ac: 0040      DCD 0x40000040
     6ae: 4000     
     6b0: 6c00        DCD 0x02DC6C00
     6b2: 02dc     
     6b4: 988d      DCD 0x0000988D
     6b6: 0000     
     6b8: 1000      DCD 0x40001000
     6ba: 4000     
     6bc: 1100        DCD 0x40001100
     6be: 4000
     6c0: 0324        DCD 0x20000324
     6c2: 2000
     6c4: 0f0f        DCD 0x00000F0F
     6c6: 0000
     6c8: 6fff        DCD 0x00006FFF
     6ca: 0000
« Last Edit: August 16, 2024, 09:25:58 pm by radiolistener »
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
here is some identified functions in the bootloader 5:
Code: [Select]
address => identified function

0x154 => memcpy([r0]void *dest, [r1]const void *src, [r2]size_t n)
0x19c => ReadUInt32LE([r0]uint8_t* pdata)
0x1e0 => erase flash page?
0x1ec => write flash page?
0x21c => AES_ProcessBlock128([r0]uint32_t* src, [r1]uint32_t* dst);
0x254 => AES_KDF([r0]uint8_t* buffer) // fill buffer with a new key
0x27c => ProcessPacket() // process received packet
0x2a8 => ProcessPacket_057d([r0]uint8_t* packet_ptr) // setFlashVersionReq
0x30c => ProcessPacket_0578([r0]uint8_t* packet_ptr) // writeNvramReq?
0x338 => ProcessPacket_057b([r0]uint8_t* packet_ptr) // writeFlashPageReq
0x480 => SendPacket_057c([r0]uint32_t sequenceId, [r1]uint16_t chunkNumber, [r2]uint8_t errorCode) // writeFlashPageAck
0x4f0 => AES_Init([r0]uint32_t mode, [r1]uint32_t* key, [r2]uint32_t* iv) // mode: 0=encrypt;1=kdf;2=decrypt;3=kdf&decrypt
0x818 => UartSendBuffer([r0]uint8_t* buffer, [r1]uint32_t length)   // send raw buffer
0x838 => SendPacket(byte* buffer, int length)  // encrypt, envelope and send packet

RAM at offset 0x20000314 structure:
Code: [Select]
typedef struct {
     uint8_t  State;                    // u8  @ offset 0
     uint8_t  IsFlashWriteEnabled;      // u8  @ offset 1
     uint16_t ChunkNumber;              // u16 @ offset 2
     uint16_t ChunkCount;               // u16 @ offset 4
     uint32_t SequenceId;               // u32 @ offset 8
} RAM314_T;
« Last Edit: August 16, 2024, 10:30:50 pm by radiolistener »
 

Offline ruslik064

  • Contributor
  • Posts: 30
  • Country: ru
I wrote this function in the debugger.
Code: [Select]
proc uv_aes_init {} {
set status [read_memory 0x400BD000 32 1]
echo [format "read cr register before gate set %08b." $status]

write_memory 0x40000008 32 {0x18000085} ;# DEV_CLK_GATE register set (from offset 904 bootcode)
set status2 [read_memory 0x40000008 32 1]
echo [format "dev_clk_gate set %08b." $status2]

write_memory 0x400BD000 32 0x28 ;# AES CR set mode
set status [read_memory 0x400BD000 32 1]
echo [format "read cr register after gate set and set mode %08b." $status]


write_memory 0x400BD01c 32 0xe16e0d29 ;#keyr3
write_memory 0x400BD018 32 0xe0c83418 ;#keyr2
write_memory 0x400BD014 32 0x987f9433 ;#keyr1
write_memory 0x400BD010 32 0xf5ff620e ;#keyr0

write_memory 0x400BD02c 32 0x14b7a2be ;#iv3
write_memory 0x400BD028 32 0x0223e259 ;#iv2
write_memory 0x400BD024 32 0xb2066d88 ;#iv1
write_memory 0x400BD020 32 0x86977e36 ;#iv0


set keyr0 [read_memory 0x400BD010 32 1]
echo [format "keyr0 before 0x%08x." $keyr0]
set keyr1 [read_memory 0x400BD014 32 1]
echo [format "keyr1 before 0x%08x." $keyr1]
set keyr2 [read_memory 0x400BD018 32 1]
echo [format "keyr2 before 0x%08x." $keyr2]
set keyr3 [read_memory 0x400BD01c 32 1]
echo [format "keyr3 before 0x%08x." $keyr3]

set sr [read_memory 0x400BD004 32 1]
echo [format "sr before aes enable %08b." $sr]

write_memory 0x400BD000 32 0x29 ;# AES CR enable [expr {[read_memory 0x400BD000 32 1] | (1 << 0)}]

set sr [read_memory 0x400BD004 32 1]
echo [format "sr after aes enable %08b." $sr]

set keyr0 [read_memory 0x400BD010 32 1]
echo [format "keyr0  after 0x%08x." $keyr0]
set keyr1 [read_memory 0x400BD014 32 1]
echo [format "keyr1  after 0x%08x." $keyr1]
set keyr2 [read_memory 0x400BD018 32 1]
echo [format "keyr2  after 0x%08x." $keyr2]
set keyr3 [read_memory 0x400BD01c 32 1]
echo [format "keyr3  after 0x%08x." $keyr3]

}

As a result, the DEV_CLK_GATE register configuration is required. After that, aes began to respond.

Code: [Select]
[DP32G0xx.cpu] halted due to debug-request, current mode: Handler HardFault
xPSR: 0xc1000003 pc: 0xfffffffe msp: 0xffffffd8
read cr register before gate set 00000000.
dev_clk_gate set 11000000000000000000010000101.
read cr register after gate set and set mode 00101000.
keyr0 before 0xf5ff620e.
keyr1 before 0x987f9433.
keyr2 before 0xe0c83418.
keyr3 before 0xe16e0d29.
sr before aes enable 00000000.
sr after aes enable 00000001.
keyr0  after 0xcb0ccb1c.
keyr1  after 0xf0717ef3.
keyr2  after 0x03ad3804.
keyr3  after 0xb6945a2e.
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Here is the output of this function in openocd. If this is correct and useful I can write the rest. The kdf function itself only reads the contents after init? I am also interested in what happens in the bootloader at offset 904. I took the value of the dev_clk_gate register from there.
 
The following users thanked this post: radiolistener

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
Here is the output of this function in openocd. If this is correct and useful I can write the rest.

yes, it is useful, but needs time to extract data into usable format.  :)

The kdf function itself only reads the contents after init?

yes, AES_KDF(uint32_t* buffer) function just waits for CCF flag in AES->SR register and then reads new key from AES->KEYRx registers. Then it set CCFC flag in AES->CR register. Note that AES_KDF function expects that you initialized AES module in KDF mode (2).

By the way, you can call existing code from bootloader. For example, just load memory pointer to the RAM buffer into R0 reg and then call 0x254. It should fill the RAM buffer with a new key with original bootloader code.

I am also interested in what happens in the bootloader at offset 904. I took the value of the dev_clk_gate register from there.

I am also interested in what happens in the bootloader at offset 904. I took the value of the dev_clk_gate register from there.

Yes, you're right, previously I didn't notice to instruction at 0x90e, it seems the place where the clocks are initialized.  :)
The rest of code seems not interesting, it just initialize GPIO, UART, sends bootloader version to UART, receive command packet and process it.

Here is the code, there are possible mistakes in comments, I didn't dig it deep:
Code: [Select]
@ arm-none-eabi-objdump -D -b binary -marm --start-address=0x904 --stop-address=0x9e4 -Mforce-thumb bootloader.bin
bootloader.bin:     file format binary


Disassembly of section .data:

00000904 <.data+0x904>:
     904: b5f8      push {r3, r4, r5, r6, r7, lr}
     906: f7ff ffd7 bl 0x8b8
     90a: 482a      ldr r0, [pc, #168] @ (0x9b4)       @ r0 = 0x18000085
     90c: 0781      lsls r1, r0, #30                 @ r1 = (uint8_t*)0x40000000;    // SYSCON
     90e: 6088      str r0, [r1, #8]                    @ *(uint32_t*)&r1[8] = r0;      // *(*uint32_t*)0x40000008 = 0x18000085;  // SYSCON->DEV_CLK_GATE = AES_CLK_GATE | CRC_CLK_GATE | UART1_CLK_GATE | GPIOC_CLK_GATE | GPIOA_CLK_GATE;
     910: f7ff fe6c bl 0x5ec                           @ call_05ec();      // init PORTCON (PORTB_SEL1 &= 0xF0FF0FFF; etc)
     914: f7ff fe4e bl 0x5b4                           @ call_05b4();      // init GPIO output state
     918: f7ff fe42 bl 0x5a0                           @ call_05a0();      // init CRC
     91c: f7ff fe84 bl 0x628                           @ call_0628();      // init UART1
     920: 4825      ldr r0, [pc, #148] @ (0x9b8)       @ r0 = 0x20001324
     922: f7ff fe19 bl 0x558                           @ call_0558(r0);    // fill buffer (r0) with SYSCON_CHIP_ID0-3
     926: 4825      ldr r0, [pc, #148] @ (0x9bc)       @ r0 = 0x40060000   // GPIOA
     928: 6800      ldr r0, [r0, #0]
     92a: 4c25      ldr r4, [pc, #148] @ (0x9c0)       @ r4 = 0x40061000   // GPIOC
     92c: 06c0      lsls r0, r0, #27
     92e: 0f80      lsrs r0, r0, #30
     930: 4f24      ldr r7, [pc, #144] @ (0x9c4)       @ r7 = 0x00030D40
     932: 4d25      ldr r5, [pc, #148] @ (0x9c8)       @ r5 = 0x20000314   // ram0314 pointer
     934: 2803      cmp r0, #3
     936: d10c      bne.n 0x952                       @ if (ram0314->u8_0 != 3) goto 0x952;
     938: 6820      ldr r0, [r4, #0]
     93a: 0680      lsls r0, r0, #26
     93c: d409      bmi.n 0x952
     93e: 4638      mov r0, r7
     940: f7ff fdf8 bl 0x534                           @ call_0534()   // ??? nops
     944: 6820      ldr r0, [r4, #0]
     946: 0680      lsls r0, r0, #26
     948: d403      bmi.n 0x952
     94a: 2001      movs r0, #1
     94c: 7028      strb r0, [r5, #0]
     94e: 2008      movs r0, #8
     950: 6020      str r0, [r4, #0]
     952: 210c      movs r1, #12
     954: 481d      ldr r0, [pc, #116] @ (0x9cc)       @ r0 = 0x00000BF0;  // "5.00.01"
     956: f7ff ff5f bl 0x818                           @ UartSendBuffer(r0);
     95a: 2102      movs r1, #2
     95c: a01c      add r0, pc, #112 @ (adr r0, 0x9d0)   @ r0 = 0x09d0;  // "\r\n"   
     95e: f7ff ff5b bl 0x818                           @ UartSendBuffer(r0);
     962: 7828      ldrb r0, [r5, #0]
     964: 4e1b      ldr r6, [pc, #108] @ (0x9d4)       @ r6 = 0x000186A0
     966: 2801      cmp r0, #1
     968: d111      bne.n 0x98e
     96a: f7ff feaf bl 0x6cc                           @ call_06cc()   // probably receive the raw packet, decypt and extract from envelope
     96e: 2800      cmp r0, #0
     970: d101      bne.n 0x976
     972: f7ff fc83 bl 0x27c                           @ ProcessPacket()
     976: 7828      ldrb r0, [r5, #0]
     978: 2801      cmp r0, #1
     97a: d00f      beq.n 0x99c
     97c: 2802      cmp r0, #2
     97e: d014      beq.n 0x9aa
     980: 2803      cmp r0, #3
     982: d1f2      bne.n 0x96a
     984: 2000      movs r0, #0
     986: 6020      str r0, [r4, #0]
     988: 4813      ldr r0, [pc, #76] @ (0x9d8)       @ r0 = 0x000493E0
     98a: f7ff fdd3 bl 0x534
     98e: 4630      mov r0, r6
     990: f7ff fdd0 bl 0x534
     994: f7ff fc3c bl 0x210
     998: 2000      movs r0, #0
     99a: bdf8      pop {r3, r4, r5, r6, r7, pc}
     99c: 4638      mov r0, r7
     99e: f7ff fdc9 bl 0x534
     9a2: f7ff fd7d bl 0x4a0
     9a6: 4630      mov r0, r6
     9a8: e000      b.n 0x9ac
     9aa: 480c      ldr r0, [pc, #48] @ (0x9dc)       @ r0 = 0x00002710
     9ac: f7ff fdc2 bl 0x534
     9b0: e7db      b.n 0x96a

     9b2: 0000      movs r0, r0
     
     9b4: 0085      DCD     0x18000085
     9b6: 1800
     9b8: 1324      DCD     0x20001324
     9ba: 2000
     9bc: 0000      DCD     0x40060000
     9be: 4006
     9c0: 1000      DCD     0x40061000
     9c2: 4006
     9c4: 0d40      DCD     0x00030D40
     9c6: 0003
     9c8: 0314      DCD     0x20000314
     9ca: 2000
     9cc: 0bf0      DCD     0x00000BF0
     9ce: 0000
     9d0: 0a0d      .asciz  "\r\n"
     9d2: 0000      .byte   0
     9d4: 86a0      DCD     0x000186A0
     9d6: 0001
     9d8: 93e0      DCD     0x000493E0
     9da: 0004
     9dc: 2710      DCD     0x00002710
     9de: 0000
     9e0: 6c16
     9e2: e614

At a glance  *(*uint32_t*)0x40000008 = 0x18000085; is
Code: [Select]
SYSCON->DEV_CLK_GATE = AES_CLK_GATE | CRC_CLK_GATE | UART1_CLK_GATE | GPIOC_CLK_GATE | GPIOA_CLK_GATE;

so, this is where clock initialization happens.  :)
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
I wrote test script, it uses existing code of bootloader v5, can you run it on the radio with bootloader v5 and share results?

It expects that the radio has bootloader v5 in the memory, it won't work with other bootloader.

I'm not familiar with openocd, so there is possible mistakes.
Especially, I'm not sure on how to properly execute subroutine and return to the debugger, if it don't works, try to load reg lr 0xFFFFFFF9 before each call.

Code: [Select]
proc test_aes {} {
    # Stack init
    reg sp 0x20001738 ;# value taken from bootloader 5 vector table
   
    # Clocks init
    write_memory 0x40000008 32 {0x18000085} ;# AES, CRC, UART1, GPIOC, GPIOA clocks enabled
    set dev_clk_gate [read_memory 0x40000008 32 1]
    echo [format "DEV_CLK_GATE set: 0x%08x." $dev_clk_gate]

    # Fill key and iv buffers
    write_memory 0x20000000 8 {0xe1 0x6e 0x0d 0x29 0xe0 0xc8 0x34 0x18 0x98 0x7f 0x94 0x33 0xf5 0xff 0x62 0x0e}
    write_memory 0x20000010 8 {0x14 0xb7 0xa2 0xbe 0x02 0x23 0xe2 0x59 0xb2 0x06 0x6d 0x88 0x86 0x97 0x7e 0x36}

    # call 0x4f0 => AES_Init(1, key, iv);
    reg r0 1
    reg r1 0x20000000 ;# Address of the key
    reg r2 0x20000010 ;# Address of the IV
    reg pc 0x4f0
    resume
    echo "AES_Init(1, key, iv) completed..."


    # call 0x254 => AES_KDF(key2);
    reg r0 0x20000020 ;# Address for the key2
    reg pc 0x254
    resume
    echo "AES_KDF(key2) completed..."

    # Dump 16 bytes from the key2 array
    echo "Dump key2:"
    # dump_image key2_dump.bin 0x20000020 16
    mdw 0x20000020 4

    # call 0x4f0 => AES_Init(2, key2, iv);
    reg r0 2
    reg r1 0x20000020 ;# Address of the key2
    reg r2 0x20000010 ;# Address of the IV
    reg pc 0x4f0
    resume
    echo "AES_Init(2, key2, iv) completed..."

    # call 0x21c => AES_ProcessBlock128(key, data);
    reg r0 0x20000000 ;# Address of the original key
    reg r1 0x20000030 ;# Address for the encrypted data
    reg pc 0x21c
    resume
    echo "AES_ProcessBlock128(key, data) completed..."

    # Dump 16 bytes from the data array
    echo "Dump data:"
    # dump_image data_dump.bin 0x20000030 16
    mdw 0x20000030 4
   
    dump_image full_dump.bin 0x20000000 64
}

it should write full_dump.bin file, share it with script output.
This file should contains (key, iv, key2, data) vectors. In total 64 bytes.
key2 is KDF result for key 0 and data is AES decrypt result for key data with (key2,iv) key and can be used for encryption testing.

To be clear, here is C code that I wanted to execute:
Code: [Select]
void testCode() {
    SYSCON_DEV_CLK_GATE = AES_CLK_GATE | CRC_CLK_GATE | UART1_CLK_GATE | GPIOC_CLK_GATE | GPIOA_CLK_GATE;

    uint8_t key[16] = { 0xe1,0x6e,0x0d,0x29,0xe0,0xc8,0x34,0x18,0x98,0x7f,0x94,0x33,0xf5,0xff,0x62,0x0e }; // key 00
    uint8_t  iv[16] = { 0x14,0xb7,0xa2,0xbe,0x02,0x23,0xe2,0x59,0xb2,0x06,0x6d,0x88,0x86,0x97,0x7e,0x36 }; //  iv 00

    AES_Init(1, key, iv);       // r0=1;r1=key;r2=iv;bl 0x4f0
    uint8_t key2[16];
    AES_KDF(key2);              // r0=key2;bl 0x254

    // *** dump 16 bytes from key2 array ***

    AES_Init(2, key2, iv);      // r0=2;r1=key2;r2=iv;bl 0x4f0
    uint8_t data[16];
    AES_ProcessBlock128(key, data); // r0=key;r1=data;bl 0x21c

    // ***dump 16 bytes from data array***     
}
« Last Edit: August 20, 2024, 10:58:35 am by radiolistener »
 

Offline ruslik064

  • Contributor
  • Posts: 30
  • Country: ru
The syntax of openocd differs from what you wrote. But the most interesting thing is not this. Nobody talked about it, but the station with boot v5 does not want to connect to the debugger. For what reason I do not know. That is why I work with the debugger on the old boot. In this regard, I cannot run this code inside. I will try to hook the debugger again, of course, but previous attempts did not lead to success.
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
The syntax of openocd differs from what you wrote.

I tried to ask chatgpt to rewrite C code to openocd script, the result was ugly so I rewrote it using syntax that he provided. I don't have configured environment, so cannot test.

If it don't works then chatgpt give me a wrong syntax, this is not surprise, it often doing such mistakes.
What is the error?

Nobody talked about it, but the station with boot v5 does not want to connect to the debugger. For what reason I do not know.

probably swd pins are disabled in bootloader v5 at startup, but then its interesting question how it was obtained from the chip
« Last Edit: August 21, 2024, 11:14:14 am by radiolistener »
 

Offline ruslik064

  • Contributor
  • Posts: 30
  • Country: ru
Quote
probably swd pins are disabled in bootloader v5 at startup, but then its interesting question how it was obtained from the chip
  :)

Got it with jlink programmer. I can flash or read anything in the chip (nvram boot rom) without any problems. The bootloader for jlink is written.
Code: [Select]
set_reg {r0 1}
    set_reg {r1 0x20000000} ;# Address of the key
    set_reg {r2 0x20000010} ;# Address of the IV
    set_reg {pc 0x4f0}
    resume
    echo "AES_Init(1, key, iv) completed..."

the code there is approximately like this. I think the differences are visible.

https://openocd.org/doc/html/General-Commands.html description
« Last Edit: August 21, 2024, 11:26:53 am by ruslik064 »
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
Got it with jlink programmer. I can flash or read anything in the chip (nvram boot rom) without any problems. The bootloader for jlink is written.

is it works on a radio with bootloader v5?

Here is fixed script, does it works?
Code: [Select]
proc test_aes {} {
    # Stack init
    set_reg { sp 0x20001738 } ;# value taken from bootloader 5 vector table
   
    # Clocks init
    write_memory 0x40000008 32 {0x18000085} ;# AES, CRC, UART1, GPIOC, GPIOA clocks enabled
    set dev_clk_gate [read_memory 0x40000008 32 1]
    echo [format "DEV_CLK_GATE set: 0x%08x." $dev_clk_gate]

    # Fill key and iv buffers
    write_memory 0x20000000 8 {0xe1 0x6e 0x0d 0x29 0xe0 0xc8 0x34 0x18 0x98 0x7f 0x94 0x33 0xf5 0xff 0x62 0x0e}
    write_memory 0x20000010 8 {0x14 0xb7 0xa2 0xbe 0x02 0x23 0xe2 0x59 0xb2 0x06 0x6d 0x88 0x86 0x97 0x7e 0x36}

    # call 0x4f0 => AES_Init(1, key, iv);
    set_reg { r0 1 }
    set_reg { r1 0x20000000 }       ;# Address of the key
    set_reg { r2 0x20000010 }       ;# Address of the IV
    set_reg { pc 0x4f0 }
    resume
    echo "AES_Init(1, key, iv) completed..."


    # call 0x254 => AES_KDF(key2);
    set_reg { r0 0x20000020 }       ;# Address for the key2
    set_reg { pc 0x254 }
    resume
    echo "AES_KDF(key2) completed..."

    # Dump 16 bytes from the key2 array
    echo "Dump key2:"
    mdw 0x20000020 4

    # call 0x4f0 => AES_Init(2, key2, iv);
    set_reg { r0 2 }
    set_reg { r1 0x20000020 }       ;# Address of the key2
    set_reg { r2 0x20000010 }       ;# Address of the IV
    set_reg { pc 0x4f0 }
    resume
    echo "AES_Init(2, key2, iv) completed..."

    # call 0x21c => AES_ProcessBlock128(key, data);
    set_reg { r0 0x20000000 }       ;# Address of the original key
    set_reg { r1 0x20000030 }       ;# Address for the encrypted data
    set_reg { pc 0x21c }
    resume
    echo "AES_ProcessBlock128(key, data) completed..."

    # Dump 16 bytes from the data array
    echo "Dump data:"
    mdw 0x20000030 4
   
    # Full memory dump (key,iv,key2,data)
    echo "Full dump key,iv,key2,data:"
    dump_image full_dump.bin 0x20000000 64
}
« Last Edit: August 21, 2024, 01:17:08 pm by radiolistener »
 

Offline ruslik064

  • Contributor
  • Posts: 30
  • Country: ru
No, I couldn't run it with bootloader 5. ST-link doesn't connect to stations when bootloader 5 is flashed in it. :-//

I need to think about it
« Last Edit: August 21, 2024, 12:11:01 pm by ruslik064 »
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
At a glance these procedures use relative addresses, so it looks movable.
You can write their code into RAM and execute from RAM.

Here is script which don't depends on bootloader code, you can run it on a radio with bootloader v2:
Code: [Select]
proc test_aes {} {
    # Stack init
    set_reg { sp 0x20001738 } ;# value taken from bootloader 5 vector table

    # Create AES_Init in RAM [0x4f0..0x534]
    write_memory 0x200004f0 8 {
0x10 0xB5 0x0F 0x4B 0x1C 0x68 0x64 0x08 0x64 0x00 0x1C 0x60 0xC0 0x00 0x20 0x24
0x20 0x43 0x18 0x60 0x08 0x68 0xD8 0x61 0x48 0x68 0x98 0x61 0x88 0x68 0x58 0x61
0xC8 0x68 0x18 0x61 0x10 0x68 0xD8 0x62 0x50 0x68 0x98 0x62 0x90 0x68 0x58 0x62
0xD0 0x68 0x18 0x62 0x18 0x68 0x01 0x21 0x08 0x43 0x18 0x60 0x10 0xBD 0x00 0x00
0x00 0xD0 0x0B 0x40   
    }
    # Create AES_ProcessBlock128 [0x21c..254]
    write_memory 0x2000021c 8 {
0x0C 0x4A 0x03 0x68 0x93 0x60 0x43 0x68 0x93 0x60 0x83 0x68 0x93 0x60 0xC0 0x68
0x90 0x60 0x50 0x68 0xC0 0x07 0xFC 0xD0 0xD0 0x68 0x08 0x60 0xD0 0x68 0x48 0x60
0xD0 0x68 0x88 0x60 0xD0 0x68 0xC8 0x60 0x10 0x68 0x80 0x21 0x08 0x43 0x10 0x60
0x70 0x47 0x00 0x00 0x00 0xD0 0x0B 0x40
    }
    # Create AES_KDF in RAM [0x254..0x27c]
    write_memory 0x20000254 8 {
0x08 0x49 0x4A 0x68 0xD2 0x07 0xFC 0xD0 0xCA 0x69 0x02 0x60 0x8A 0x69 0x42 0x60
0x4A 0x69 0x82 0x60 0x0A 0x69 0xC2 0x60 0x08 0x68 0x80 0x22 0x10 0x43 0x08 0x60
0x70 0x47 0x00 0x00 0x00 0xD0 0x0B 0x40
    }

    # Clocks init
    write_memory 0x40000008 32 {0x18000085} ;# AES, CRC, UART1, GPIOC, GPIOA clocks enabled
    set dev_clk_gate [read_memory 0x40000008 32 1]
    echo [format "DEV_CLK_GATE set: 0x%08x." $dev_clk_gate]

    # Fill key and iv buffers
    write_memory 0x20000000 8 {0xe1 0x6e 0x0d 0x29 0xe0 0xc8 0x34 0x18 0x98 0x7f 0x94 0x33 0xf5 0xff 0x62 0x0e}
    write_memory 0x20000010 8 {0x14 0xb7 0xa2 0xbe 0x02 0x23 0xe2 0x59 0xb2 0x06 0x6d 0x88 0x86 0x97 0x7e 0x36}

    # call 0x4f0 => AES_Init(1, key, iv);
    set_reg { r0 1 }
    set_reg { r1 0x20000000 }       ;# Address of the key
    set_reg { r2 0x20000010 }       ;# Address of the IV
    set_reg { pc 0x200004f0 }
    resume
    echo "AES_Init(1, key, iv) completed..."

    # call 0x254 => AES_KDF(key2);
    set_reg { r0 0x20000020 }       ;# Address for the key2
    set_reg { pc 0x20000254 }
    resume
    echo "AES_KDF(key2) completed..."

    # Dump 16 bytes from the key2 array
    echo "Dump key2:"
    mdw 0x20000020 4

    # call 0x4f0 => AES_Init(2, key2, iv);
    set_reg { r0 2 }
    set_reg { r1 0x20000020 }       ;# Address of the key2
    set_reg { r2 0x20000010 }       ;# Address of the IV
    set_reg { pc 0x200004f0 }
    resume
    echo "AES_Init(2, key2, iv) completed..."

    # call 0x21c => AES_ProcessBlock128(key, data);
    set_reg { r0 0x20000000 }       ;# Address of the original key
    set_reg { r1 0x20000030 }       ;# Address for the encrypted data
    set_reg { pc 0x2000021c }
    resume
    echo "AES_ProcessBlock128(key, data) completed..."

    # Dump 16 bytes from the data array
    echo "Dump data:"
    mdw 0x20000030 4
   
    # Full memory dump (key,iv,key2,data)
    echo "Full dump (key,iv,key2,data) to full_dump.bin..."
    dump_image full_dump.bin 0x20000000 64
    echo "Done"
}

I'm not sure if resume is correct way to call the procedure and continue script when it returns.
If this way don't works and it still continue to run, try to add this command before each resume:
Code: [Select]
set_reg { lr 0xFFFFFFF9 }
It will load return address 0xFFFFFFF9 which should trigger exception and return to debugger.
I expect it should stop the code after return and continue to execute script. Needs to test it.

« Last Edit: August 21, 2024, 01:59:19 pm by radiolistener »
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
just installed openocd and tested it on STM32G431.

Previous script has mistake, it don't wait for procedure exit.

Here is fixed script:
Code: [Select]
proc callSub {addr} {
    bp 0x00000000 2 hw
    reg lr 0x00000001
    reg pc $addr
    resume
    wait_halt
    rbp 0x00000000
}

proc test_aes {} {
    # Create AES_Init in RAM [0x4f0..0x534]
    write_memory 0x200004f0 8 {
0x10 0xB5 0x0F 0x4B 0x1C 0x68 0x64 0x08 0x64 0x00 0x1C 0x60 0xC0 0x00 0x20 0x24
0x20 0x43 0x18 0x60 0x08 0x68 0xD8 0x61 0x48 0x68 0x98 0x61 0x88 0x68 0x58 0x61
0xC8 0x68 0x18 0x61 0x10 0x68 0xD8 0x62 0x50 0x68 0x98 0x62 0x90 0x68 0x58 0x62
0xD0 0x68 0x18 0x62 0x18 0x68 0x01 0x21 0x08 0x43 0x18 0x60 0x10 0xBD 0x00 0x00
0x00 0xD0 0x0B 0x40   
    }
    # Create AES_ProcessBlock128 [0x21c..254]
    write_memory 0x2000021c 8 {
0x0C 0x4A 0x03 0x68 0x93 0x60 0x43 0x68 0x93 0x60 0x83 0x68 0x93 0x60 0xC0 0x68
0x90 0x60 0x50 0x68 0xC0 0x07 0xFC 0xD0 0xD0 0x68 0x08 0x60 0xD0 0x68 0x48 0x60
0xD0 0x68 0x88 0x60 0xD0 0x68 0xC8 0x60 0x10 0x68 0x80 0x21 0x08 0x43 0x10 0x60
0x70 0x47 0x00 0x00 0x00 0xD0 0x0B 0x40
    }
    # Create AES_KDF in RAM [0x254..0x27c]
    write_memory 0x20000254 8 {
0x08 0x49 0x4A 0x68 0xD2 0x07 0xFC 0xD0 0xCA 0x69 0x02 0x60 0x8A 0x69 0x42 0x60
0x4A 0x69 0x82 0x60 0x0A 0x69 0xC2 0x60 0x08 0x68 0x80 0x22 0x10 0x43 0x08 0x60
0x70 0x47 0x00 0x00 0x00 0xD0 0x0B 0x40
    }


    # Stack init
    set_reg { sp 0x20001738 } ;# value taken from bootloader 5 vector table

    # Clocks init
    write_memory 0x40000008 32 {0x18000085} ;# AES, CRC, UART1, GPIOC, GPIOA clocks enabled
    set dev_clk_gate [read_memory 0x40000008 32 1]
    echo [format "DEV_CLK_GATE set: 0x%08x." $dev_clk_gate]

    # Fill key and iv buffers
    write_memory 0x20000000 8 {0xe1 0x6e 0x0d 0x29 0xe0 0xc8 0x34 0x18 0x98 0x7f 0x94 0x33 0xf5 0xff 0x62 0x0e}
    write_memory 0x20000010 8 {0x14 0xb7 0xa2 0xbe 0x02 0x23 0xe2 0x59 0xb2 0x06 0x6d 0x88 0x86 0x97 0x7e 0x36}

    # call 0x4f0 => AES_Init(1, key, iv);
    set_reg { r0 1 }
    set_reg { r1 0x20000000 }       ;# Address of the key
    set_reg { r2 0x20000010 }       ;# Address of the IV
    callSub 0x200004f0
    echo "AES_Init(1, key, iv) completed..."


    # call 0x254 => AES_KDF(key2);
    set_reg { r0 0x20000020 }       ;# Address for the key2
    callSub 0x20000254
    echo "AES_KDF(key2) completed..."

    # Dump 16 bytes from the key2 array
    set dumpKey2 [read_memory 0x20000020 8 16]
    echo "Dump key2: $dumpKey2"

    # call 0x4f0 => AES_Init(2, key2, iv);
    set_reg { r0 2 }
    set_reg { r1 0x20000020 }       ;# Address of the key2
    set_reg { r2 0x20000010 }       ;# Address of the IV
    callSub 0x200004f0
    echo "AES_Init(2, key2, iv) completed..."

    # call 0x21c => AES_ProcessBlock128(key, data);
    set_reg { r0 0x20000000 }       ;# Address of the original key
    set_reg { r1 0x20000030 }       ;# Address for the encrypted data
    callSub 0x2000021c
    echo "AES_ProcessBlock128(key, data) completed..."

    # Dump 16 bytes from the data array
    set dumpData [read_memory 0x20000020 8 16]
    echo "Dump data: $dumpData"
   
    # Full memory dump (key,iv,key2,data)
    echo "Full dump (key,iv,key2,data) to full_dump.bin..."
    dump_image full_dump.bin 0x20000000 64
    echo "Done"
}

it should work.
In order to call procedure and return to the script, I'm set breakpoint and return address to 0. So the MCU will raise breakpoint after return.
Tested on STM32G431.


Currently I don't have uv-k5 with connected swd. Needs to wait.

If someone can run it on UV-K5, please share result. It don't depends on bootloader, can be run on v2.
« Last Edit: August 21, 2024, 09:09:03 pm by radiolistener »
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
just tried to solder stlinkv2 to swd pins, but can't connect.
For some unknown reason stlinkv2 don't see it.

Do you use stlinkv2? Can you share config file for openocd?
 

Offline ruslik064

  • Contributor
  • Posts: 30
  • Country: ru
 

Offline ruslik064

  • Contributor
  • Posts: 30
  • Country: ru
something happened
Code: [Select]
[DP32G0xx.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x21000000 pc: 0x00000412 msp: 0x200015c0
DEV_CLK_GATE set: 0x18000085.
[DP32G0xx.cpu] halted due to breakpoint, current mode: Thread
xPSR: 0x01000000 pc: 00000000 msp: 0x20001738
AES_Init(1, key, iv) completed...
[DP32G0xx.cpu] halted due to breakpoint, current mode: Thread
xPSR: 0x01000000 pc: 00000000 msp: 0x20001738
AES_KDF(key2) completed...
Dump key2: 0xbb 0xda 0xd9 0xde 0x1b 0xa1 0x8b 0x2e 0xa8 0x88 0x3b 0xbc 0xa0 0xfc 0x75 0x6f
[DP32G0xx.cpu] halted due to breakpoint, current mode: Thread
xPSR: 0x01000000 pc: 00000000 msp: 0x20001738
AES_Init(2, key2, iv) completed...
[DP32G0xx.cpu] halted due to breakpoint, current mode: Thread
xPSR: 0x01000000 pc: 00000000 msp: 0x20001738
AES_ProcessBlock128(key, data) completed...
Dump data: 0xbb 0xda 0xd9 0xde 0x1b 0xa1 0x8b 0x2e 0xa8 0x88 0x3b 0xbc 0xa0 0xfc 0x75 0x6f
Full dump (key,iv,key2,data) to full_dump.bin...
Done

ran with v2 bootloader.
but I think this is wrong. or just dump data is read from the same place as key2
« Last Edit: August 22, 2024, 06:54:09 am by ruslik064 »
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
something happened
ran with v2 bootloader.

Thanks. At a glance looks good, as expected.

but I think this is wrong.

I see that data dump is the same as key2 dump in the log, this is really wrong.

But it appears there is mistake in my script:
Code: [Select]
set dumpData [read_memory 0x20000020 8 16]
should be
Code: [Select]
set dumpData [read_memory 0x20000030 8 16]
So actually my script printing key2 instead of data and this is the reason why its the same.
But there is full_dump.bin and it contains data array, it shows that the data is:
Code: [Select]
28 B8 03 BF 42 AA C4 B9 EC 38 39 3F 35 15 A7 9E

Here is fixed script:
Code: [Select]
proc callSub {addr} {
    bp 0x00000000 2 hw
    reg lr 0x00000001
    reg pc $addr
    resume
    wait_halt
    rbp 0x00000000
}

proc test_aes {} {
    # Create AES_Init in RAM [0x4f0..0x534]
    write_memory 0x200004f0 8 {
0x10 0xB5 0x0F 0x4B 0x1C 0x68 0x64 0x08 0x64 0x00 0x1C 0x60 0xC0 0x00 0x20 0x24
0x20 0x43 0x18 0x60 0x08 0x68 0xD8 0x61 0x48 0x68 0x98 0x61 0x88 0x68 0x58 0x61
0xC8 0x68 0x18 0x61 0x10 0x68 0xD8 0x62 0x50 0x68 0x98 0x62 0x90 0x68 0x58 0x62
0xD0 0x68 0x18 0x62 0x18 0x68 0x01 0x21 0x08 0x43 0x18 0x60 0x10 0xBD 0x00 0x00
0x00 0xD0 0x0B 0x40   
    }
    # Create AES_ProcessBlock128 [0x21c..254]
    write_memory 0x2000021c 8 {
0x0C 0x4A 0x03 0x68 0x93 0x60 0x43 0x68 0x93 0x60 0x83 0x68 0x93 0x60 0xC0 0x68
0x90 0x60 0x50 0x68 0xC0 0x07 0xFC 0xD0 0xD0 0x68 0x08 0x60 0xD0 0x68 0x48 0x60
0xD0 0x68 0x88 0x60 0xD0 0x68 0xC8 0x60 0x10 0x68 0x80 0x21 0x08 0x43 0x10 0x60
0x70 0x47 0x00 0x00 0x00 0xD0 0x0B 0x40
    }
    # Create AES_KDF in RAM [0x254..0x27c]
    write_memory 0x20000254 8 {
0x08 0x49 0x4A 0x68 0xD2 0x07 0xFC 0xD0 0xCA 0x69 0x02 0x60 0x8A 0x69 0x42 0x60
0x4A 0x69 0x82 0x60 0x0A 0x69 0xC2 0x60 0x08 0x68 0x80 0x22 0x10 0x43 0x08 0x60
0x70 0x47 0x00 0x00 0x00 0xD0 0x0B 0x40
    }


    # Stack init
    set_reg { sp 0x20001738 } ;# value taken from bootloader 5 vector table

    # Clocks init
    write_memory 0x40000008 32 {0x18000085} ;# AES, CRC, UART1, GPIOC, GPIOA clocks enabled
    set dev_clk_gate [read_memory 0x40000008 32 1]
    echo [format "DEV_CLK_GATE set: 0x%08x." $dev_clk_gate]

    # Fill key and iv buffers
    write_memory 0x20000000 8 {0xe1 0x6e 0x0d 0x29 0xe0 0xc8 0x34 0x18 0x98 0x7f 0x94 0x33 0xf5 0xff 0x62 0x0e}
    write_memory 0x20000010 8 {0x14 0xb7 0xa2 0xbe 0x02 0x23 0xe2 0x59 0xb2 0x06 0x6d 0x88 0x86 0x97 0x7e 0x36}

    # call 0x4f0 => AES_Init(1, key, iv);
    set_reg { r0 1 }
    set_reg { r1 0x20000000 }       ;# Address of the key
    set_reg { r2 0x20000010 }       ;# Address of the IV
    callSub 0x200004f0
    echo "AES_Init(1, key, iv) completed..."


    # call 0x254 => AES_KDF(key2);
    set_reg { r0 0x20000020 }       ;# Address for the key2
    callSub 0x20000254
    echo "AES_KDF(key2) completed..."

    # Dump 16 bytes from the key2 array
    set dumpKey2 [read_memory 0x20000020 8 16]
    echo "Dump key2: $dumpKey2"

    # call 0x4f0 => AES_Init(2, key2, iv);
    set_reg { r0 2 }
    set_reg { r1 0x20000020 }       ;# Address of the key2
    set_reg { r2 0x20000010 }       ;# Address of the IV
    callSub 0x200004f0
    echo "AES_Init(2, key2, iv) completed..."

    # call 0x21c => AES_ProcessBlock128(key, data);
    set_reg { r0 0x20000000 }       ;# Address of the original key
    set_reg { r1 0x20000030 }       ;# Address for the encrypted data
    callSub 0x2000021c
    echo "AES_ProcessBlock128(key, data) completed..."

    # Dump 16 bytes from the data array
    set dumpData [read_memory 0x20000030 8 16]
    echo "Dump data: $dumpData"
   
    # Full memory dump (key,iv,key2,data)
    echo "Full dump (key,iv,key2,data) to full_dump.bin..."
    dump_image full_dump.bin 0x20000000 64
    echo "Done"
}

it should print
Code: [Select]
28 B8 03 BF 42 AA C4 B9 EC 38 39 3F 35 15 A7 9E
It appears now we have pre-computed key for (key,iv) pair #0 and decrypt test vector, so I can test encryption. Needs some time to analyze it.
 

Offline ruslik064

  • Contributor
  • Posts: 30
  • Country: ru
Well, the script error doesn't affect the final dump then. Ok, let's wait for news. If you need anything, I'm here.
 

Offline ruslik064

  • Contributor
  • Posts: 30
  • Country: ru
I also forgot to say. There is some kind of check in the original firmware. Thus, firmware of old versions below 5 does not work on new stations. And firmware of version 5 does not work on old stations either. The firmware compares something with nvram, apparently. And this algorithm has been changed in the new ones. However, modified ones like fagci work on any stations, apparently this check has been removed there.
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
Something strange here with AES module on dp32g030.

Here is input vectors:
Code: [Select]
key=bbdad9de1ba18b2ea8883bbca0fc756f
iv= 14b7a2be0223e259b2066d8886977e36
cipher=e16e0d29e0c83418987f9433f5ff620e

dp32g030 AES module decrypt produce this output:
Code: [Select]
plain=28b803bf42aac4b9ec38393f3515a79e

But proper AES-128 CBC should be
Code: [Select]
plain=ae91cade4b788b1f5bbd5bc72767d792

May be there is some inconsistency with byte order or word order for key or message, but I tried different variations and don't found matches...

I'm not sure. Is it possible that the chip installed on UV-K5 has AES module which uses some different encryption algorithm, not AES-128 CBC? This is very strange, because datasheet says that it uses AES-128 CBC.


I'm not sure, may be there is some mistake in the AES test script. Can you run it again, does it shows the same results?

Also try to add sleep 1000 after clock enable. May be AES module needs some time to properly initialize at clock startup. Does it change results?
« Last Edit: August 22, 2024, 09:19:45 am by radiolistener »
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
I took openocd from here as a basis
https://github.com/Lar-Sen/Quansheng_UV-K5_Kitchen/tree/main/unbrick-toolkit

I'm tried the same configs, but unfortunately it don't detects chip on my UV-K5:
Code: [Select]
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : clock speed 960 kHz
Info : STLINK V2J37S7 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.217930
Error: init mode failed (unable to connect to the target)

With STM32F431 openocd works ok, so I think there is some issue with SWD on my radio. I tried also on second uv-k5 which is defective (broken UART RX line), but it appears that it also cannot be detected with SWD.
« Last Edit: August 22, 2024, 09:34:07 am by radiolistener »
 

Offline ruslik064

  • Contributor
  • Posts: 30
  • Country: ru
If you have boot v2. Try to put the station into boot mode first and then connect.I'll look at the script later while I'm a bit busy.
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
If you have boot v2. Try to put the station into boot mode first and then connect.I'll look at the script later while I'm a bit busy.

Yeah, it's connected from bootloader!  :)
So, it seems that firmware disables SWD pins after startup. I think using RESET pin can help to connect to the chip with bootloader v5.
 

Offline ruslik064

  • Contributor
  • Posts: 30
  • Country: ru
I think it is necessary to introduce checks at each stage before and after the execution of functions. To see what was actually written into the registers, etc.
 

Offline darkspr1te

  • Frequent Contributor
  • **
  • Posts: 359
  • Country: zm
I also have been reversing this in ghidra,
attached are some of my findings




darkspr1te





 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 4054
  • Country: ua
some good news, I can reproduce AES module encrypt operation, it needs to use reversed byte order. So, it uses AES-128 CBC.
With decrypt operation there is something strange, hope it also related with byte order. Needs to analyze more.
 
The following users thanked this post: ruslik064


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf