Quansheng UV5 (new 2024 V5.00.03) wont allow FW change or chirp. Any Clues? - Page 1
Forum section: electronics / rf-microwave

author: minsik
author_rank: Contributor
timestamp: July 01, 2024, 01:41:42 pm
content: Hi guys.This is a recent 2024 new Quansheng UV5 (new 2024 V5.00.03) which wont allow FW change or chirp. Any Clues?Goes into FW mode, then they complain there was a problem and wont proceed. Seems version 5.00.03 returns something other than expected bytes when trying to even use chirp. It complains the version is wrong and wont proceed. any clues how to update the firmware to say egzumer or use chirp with this newest radio. Looks the same as one I purchased earlier and yet that works fine. This one all black and yet other wise is labeled UV-5R PLUS Output power = 8W. (hmmmm) FCC ID-xbpuv-k5.Used K5prog to backup ok. Trying to use K5prog to upload firmware this is what happens.------------------------------------------------------------listening for firmware update mode packet ..sending k5_hello ..firmware version: '5.00.03'has custom AES key: nois in lock screen: nochallenge: 05 DD 4F 4F------------------------------------------------------------obviously the change in supplied firmware is different from previous.Surely people are starting to see these around??

author: radiolistener
author_rank: Super Contributor
timestamp: July 01, 2024, 03:05:11 pm
content: Can you please try my tool for fw update and share the log file with communication details if it reject fw update or eeprom read/write?https://github.com/qrp73/K5TOOL/releases/tag/v1.4I would like to see log files for the following commands, it will help to understand what is going on:Code:k5tool -rebootk5tool -rdee 0x0000 0x2000 eeprom-0000-2000.rawk5tool -wree 0x0000 eeprom-0000-2000.rawk5tool -wrflash <firmware filename>Each k5tool execution replaces previous log file, old log file is moved to the file with .bak extension, the old file with .bak extension is removed. So copy log file after each command. The log file appears in the current folder.If your system has several serial ports, it may require to specify which serial port is connected to the radio, just add -port option:On Windows:Code:k5tool.exe -port COM3 -rebootOn Linux:Code:./k5tool -port /dev/ttyUSB0 -rebootThe commandCode:k5tool -rebootjust reads firmware version then reboot the radio and read bootloader version.The commandCode:k5tool -rdee 0x0000 0x2000 eeprom-0000-2000.rawreads full eeprom backup.The commandCode:k5tool -wree 0x0000 eeprom-0000-2000.rawwrites eeprom backup file to the radioThe commandCode:k5tool -wrflash <firmware filename>uploads new firmware to the radio. It expects official firmware format (packed and encrypted).If you're want to upload raw (upacked and decrypted) firmware image, it can be done withCode:k5tool -wrflashraw 2.01.32 <firmware filename>where 2.01.32 is the version string which will be send to the radio to unlock firmware write.But note, there is no way to check if raw firmware is valid and not corrupted. It's better to use official firmware format, because it allows CRC checksum check.

author: ftg
author_rank: Frequent Contributor
timestamp: July 02, 2024, 02:19:28 pm
content: It seems that in V5 the firmware image format the bootlaoder in the radio accepts seems to have changed.I'd ask on the UVK5-Dev Telegram group, as others are also working on that V5 firmware issue.I have a new one enroute, so we'll see if it also has V5 firmware and if SWD is still accessible enough to dump the firmware.

author: radiolistener
author_rank: Super Contributor
timestamp: July 02, 2024, 02:32:24 pm
content: it's impossible to say what is going on without logs.Technically the firmware version doesn't affect ability to update firmware, because firmware update is performed from bootloader which is not a part of firmware and remains unchanged. But if there is new bootloader it's possible, that it can break existing firmware update tools.You can check bootloader version with:Code:./k5tool -rebootFor example, I got new UV-K5 and it cannot accept firmware update. k5prog shows some strange incorrect response. And detailed investigation shows that the radio just sends bootloader beacon packet, but unable to listen for incoming packets from PC. k5prog just thought that echo is a response from UV-K5. I discovered it with my k5tool. So, it seems like RX line on my new UV-K5 is broken, probably defective chip.This is the reason why I wrote k5tool - to get ability to see detailed communication log in order to investigate issues.The log of k5tool contains full communication details, include raw sent/received data in hex, decrypted hex data and human-readable parsed packets. So you can see all details what is sent and what is received and can understand what happens.In addition k5tool allows to convert firmware from packed to unpacked format and from unpacked to packed format and also it has UV-K5 bootloader simulator mode for testing other UV-K5 firmware update software (in simulator mode it also writes the same detailed communication log).

author: ftg
author_rank: Frequent Contributor
timestamp: July 02, 2024, 02:47:49 pm
content: On telegram the current consensus seems to be that the packing format for the firmware has changed.It is hoped that it is not AES instead the previous XOR.AES is not out of the question, as the factory firmware update tool and the firmwares apparently support it. Just that it was not used.

author: radiolistener
author_rank: Super Contributor
timestamp: July 02, 2024, 02:56:40 pm
content: Quote from: ftg on July 02, 2024, 02:47:49 pmin this case it should not affect ability to upload firmware from existing firmware images, because old UV-K5 uses plain upload format and unpacking is done on firmware update tool side. It just makes it harder to decrypt the new official firmware file images.From my point of view, it may be due to defective radio or it may be due to they changed bootloader version and now it requires different packets format.In any case it's impossible to decide what is going on without the log file.

author: ftg
author_rank: Frequent Contributor
timestamp: July 02, 2024, 02:59:58 pm
content: It absolutely does affect uploading old firmware images if V5 is deliberately not backwards compatible.Even the V4 firmware was not available from the vendor site when it started shipping, it was dumped from radios.So the old update tool with old firmwares not being compatible wiht the new V5 firmware makes sense.And yeah, it is not possible to go much further without a device at hand or logfiles.Additionally, I do have one UV-K5(where the programming connector was damaged by a faulty cable and that one now also refuses to program.I'll have to solder in some wires for more reliable updates in it.

author: radiolistener
author_rank: Super Contributor
timestamp: July 02, 2024, 05:17:52 pm
content: Quote from: ftg on July 02, 2024, 02:59:58 pmif you upload V5 firmware (taken with SWD for example) into old radio, it will not stop accepting old firmwares, because firmware is accepted with bootloader, not by firmware. When you update firmware it don't touch bootloader which remains on the top part of memory (above address 0xf000). The new firmware is flashed from bootloader code, not from firmware code.So, this issue is definitely not related with firmware version. It may be related with a new bootloader version, which will break support for official firmware update tool either. Or it may be related with some UART defect on the radio. Or it may be related with version signature which is send to unlock firmware write.There are possible many issues. In order to find what is going on exactly, there is needs to capture log files taken on problematic radio.It appears that broken UART on a new UV-K5 radio happens very often. I suspect that probably someone tried to connect bad accessory to the radio (with high voltage or something like that, it may be some headset or programming cable) and it damage UART RX line on the radio. Then they return the radio back and seller selling it again to a new buyer. And since it happens very often, probably there is probably present some bad accessory for the radio, which damage UV-K5 accessory port and many peoples catch in that issue.Another possible issue is production defects.So, if you're get new UV-K5, it's mandatory to test it's accessory port, there is a high risk that you get returned radio with damaged accessory port.

author: ftg
author_rank: Frequent Contributor
timestamp: July 03, 2024, 07:10:31 am
content: The only information we have about the new firmware running on the device is that it reports V5.00.03 as it's version.The bootloader was likely also updated by the factory.Radios that shipped with V5 firmware not being updatable nor flashable with the current tooling is not an isolated incident.

author: radiolistener
author_rank: Super Contributor
timestamp: July 03, 2024, 04:49:43 pm
content: what is the version of bootloader on problematic device?

author: A.Z.
author_rank: Super Contributor
timestamp: July 03, 2024, 05:00:19 pm
content: @radiolistenerjust an idea, add to your tool an option, say --logappend which will force it to append to the current log instead of overwriting it, I think it may be useful

author: Vadym
author_rank: Newbie
timestamp: July 04, 2024, 08:26:05 am
content: Hello @radiolistener.It would be very helpful if your K5TOOL will support firmware's read feature.I raised issue for feature at GitHub,https://github.com/qrp73/K5TOOL/issues/2Thank you for K5TOOL

author: radiolistener
author_rank: Super Contributor
timestamp: July 04, 2024, 09:18:34 am
content: Quote from: Vadym on July 04, 2024, 08:26:05 amThere is no way to read it with known bootloader packets.Technically it is possible to make modded firmware which will support packet to do it, but since it needs to upload such modded firmware to the radio, there is no sense to read it back.

author: ftg
author_rank: Frequent Contributor
timestamp: July 11, 2024, 12:58:23 pm
content: Just received my "new" UV-K5(8 ) and based on initial testing the programming connector in is bad.As received it was incredibly stiff and did not accept the programming cable.Had to push in a more robust 3.5mm connector to it a few times for it to loosen up and allow the programming cable to properly bottom out.k5prog-win just showed this in endless flood in programming mode:K5TOOL gave this as a response to hello:And the same for attempted reboot:I'll try it with an additional cable later today and see if it was just my cheap programming cable or something else.If it does not work with the other style cable either, I'll solder in an USB UART direct to the MCU UART pins and see how things work then.

author: radiolistener
author_rank: Super Contributor
timestamp: July 11, 2024, 01:49:44 pm
content: Quote from: ftg on July 11, 2024, 12:58:23 pmDid you tried it when radio was turned on in a usual mode? I'm asking because your screenshot shows that the radio sends bootloader beacon packet which happens when radio in bootloader mode (turn on with pressed key to get LED on).-hello and -reboot commands should be send in a normal mode (when radio is working), it will not works in bootloader mode.The bootloader mode is intended to upload firmware. And since your radio reports bootloader 2.00.06, it should works ok to upload firmware. This is standerd version of bootloader. If serial port is not broken of course...It shows error, just because you're trying to send hello packet when the radio is staying in the bootloader mode.When the radio is in bootloader mode, it supports only -wrflash and -wrflashraw commands.In order to use -hello and other commands, you're needs to disconnect the cable, power on the radio in usual mode and then connect cable.Before flashing new firmware, take full eeprom backup, because custom firmware may modify some calibration data. You can read eeprom backup when radio is in usual working mode (not bootloader mode when LED is on and nothing on the display).Bootloader mode => -wrflash and -wrflashraw commands onlyNormal mode => -hello, -rdee, -wree, -rdadc, and other commands, but NOT -wrflash and -wrflashraw.

author: A.Z.
author_rank: Super Contributor
timestamp: July 11, 2024, 02:30:07 pm
content: Won't it be useful to add a "sniffer" function to k5tool so that it will be able to detect if the beacon mode is active ?

author: radiolistener
author_rank: Super Contributor
timestamp: July 12, 2024, 03:02:09 am
content: Quote from: A.Z. on July 11, 2024, 02:30:07 pmJust released v1.5:https://github.com/qrp73/K5TOOL/releases/tag/v1.5Now you can list available serial ports:Code:$ ./k5tool -port/dev/ttyS0/dev/ttyUSB0Added -sniffer command, it works in read only mode, it just monitor serial port communication and prints decoded packets to console.Also added -parse and -parse-plain commands it get hex data as argument, parse it and prints decoded packets to console.-parse is used for packets with envelope (encoded)-parse-plain is used for a plain packets without envelope (decoded)for example:Code:$ ./k5tool -parse abcd2800036930e66bd657156c7087606533c7b2246c14e62e910d402135d5401303e980166c14e62e910d40decadcba48 bytesrx: abcd2800036930e66bd657156c7087606533c7b2246c14e62e910d402135d5401303e980166c14e62e910d40decadcbaRX: 1505240045475a554d45522076302e32320000000000000000000000000000000000000000000000recv PacketHelloAck {HdrSize=36Version="EGZUMER v0.22"HasCustomAesKey=0IsPasswordLocked=0Padding=0x00Padding=0x00Challenge=0x00000000Challenge=0x00000000Challenge=0x00000000Challenge=0x00000000}Done$ ./k5tool -parse-plain 1505240045475a554d45522076302e3232000000000000000000000000000000000000000000000040 bytesRX: 1505240045475a554d45522076302e32320000000000000000000000000000000000000000000000recv PacketHelloAck {HdrSize=36Version="EGZUMER v0.22"HasCustomAesKey=0IsPasswordLocked=0Padding=0x00Padding=0x00Challenge=0x00000000Challenge=0x00000000Challenge=0x00000000Challenge=0x00000000}Done

author: ftg
author_rank: Frequent Contributor
timestamp: July 12, 2024, 08:07:42 am
content: Quote from: radiolistener on July 11, 2024, 01:49:44 pmYou were entirely correct and this was user error on my part.Both the cable and radio port worked fine.Flashed latest IJV firmware to the radio successfully with K5TOOL.Nice to have an additional tool in the arsenal.This also confirms that my 6/2024 stickered radio does not have the new V5 firmware.The serial number might also point towards week 26 of 2024 as the manufacturing date, which would be in June and correspond with the sticker.So still waiting to encounter a unit with V5 firmware so that I can dump the FW and bootlaoder with SWD, assuming it still works.Edit:Forgot to mention that K5TOOL annoyingly seems to default to /dev/ttyS0 on linux, not /dev/ttyUSB0.It's a minor annoyance, but an annoyance it is.

author: A.Z.
author_rank: Super Contributor
timestamp: July 12, 2024, 09:12:51 am
content: Quote from: radiolistener on July 12, 2024, 03:02:09 amThank you, another suggestion, let's say you change the "Logger" code this way (note: AIR CODE !)Code:static Logger(bool bAppend){try{FileMode fm = Filemode.Create;const string fileName = "K5TOOL.log";if (File.Exists(fileName)){if (bAppend){fm = FileMode.Append;} else {var fileNameBak = fileName + ".bak";if (File.Exists(fileNameBak))File.Delete(fileNameBak);File.Move(fileName, fileNameBak);}}_stream = new FileStream(fileName, fm, FileAccess.ReadWrite, FileShare.Read);_stream.Seek(0, SeekOrigin.End);LogToFile(string.Format("====[UTC:{0:yyyy-MM-ddTHH:mm:ss}]{1}",DateTime.UtcNow,new string('=', 80-4-25)));}catch (Exception ex){Error(ex);}}and then add a new parameter "-keeplog" to the tool, when such a parameter is specified the constructor "bAppend" flag is set to True, otherwise it will be False, such a mod would allow to keep the log in case one wants to run the tool several times in a row to perform some checks, that way the output will go to a single log w/o overwrite (append to existing log)

author: radiolistener
author_rank: Super Contributor
timestamp: July 13, 2024, 01:07:22 am
content: Quote from: ftg on July 12, 2024, 08:07:42 amThis is strange, it just use the last one from the port list reported by OS.So, it expects that the last connected device should be used as default.At least I think that it should work in that way.It appears that your system reports ports in reverse or random order.Could you please run k5tool with empty -port option? It should show port list in the order reported from the OS:Code:$ ./k5tool -port/dev/ttyS0/dev/ttyUSB0Added fix to prefer /dev/ttyUSB* devices as default. Try it, let me know if it works. The fix is alreadypushedto git source code.

author: eXisten
author_rank: Contributor
timestamp: July 20, 2024, 05:08:13 am
content: Hello!I got a new radio on monday (Quansheng UV5R Plus - interesting, because my unit has a USB charging port and I don't think it should) and unfortunately I am not able to change the firmware. All the methods I know don't work. I managed to make a copy of the configuration and calibration files, program the channels via CPS (CHIRP reports an unsupported version - 5.00.05).K5TOOL reading shows:firmware 5.00.05bootloader 5.00.01I don't know what to do - i guess, i can only wait for a solution...Regards - Rob.

author: radiolistener
author_rank: Super Contributor
timestamp: July 20, 2024, 08:51:29 am
content: Quote from: eXisten on July 20, 2024, 05:08:13 amCan you please share k5tool log file taken when you're trying to upload firmware?

author: eXisten
author_rank: Contributor
timestamp: July 20, 2024, 08:59:18 am
content: Sure, is it about this data?====[UTC:2024-07-20T08:57:43]=================================================== Opening COM7 rx: abcd24006c6934e62f930f463d66850a24441690856c9de61bbf3d700f05e4403b0fe980166c14c6ffffdcba RX: 7a052000010202061c53504a3747ff1093008900352e30302e303100280c000000000020 recv Packet {HdrId=0x057aHdrSize=0x0020Data=010202061c53504a3747ff1093008900352e30302e303100280c000000000020} Unexpected response Packet {HdrId=0x057aHdrSize=0x0020Data=010202061c53504a3747ff1093008900352e30302e303100280c000000000020

author: radiolistener
author_rank: Super Contributor
timestamp: July 20, 2024, 10:43:09 am
content: yes, thanks. It shows that they changed bootloader to version 5.00.01 which uses different packets. Needs some time to to research it.Did you tried official flasher tool?I can build new test flasher version that supports this new bootloader packet, but it needs to be tested and, there is no guarantee that it can work because there is possible other changes that we don't know. There is possibility that it can brick the radio and it will require to wait for new bootloader support in flasher tools to unbrick it. Can you agree to test it?

author: eXisten
author_rank: Contributor
timestamp: July 20, 2024, 01:54:35 pm
content: Yes, I tried - with no effect. When you click the "connect" button, the "update" field turns off and cannot be used.Would I agree to test your tool? Hmm, tempting, but still risky - the question is how muchThis requires deep considerationAny way, I will be grateful for sharing any new information regarding work on figuring out the new bootloaderRegards - Rob.

author: radiolistener
author_rank: Super Contributor
timestamp: July 20, 2024, 02:26:40 pm
content: At a glance a new bootloader beacon packet looks exactly the same as the old one, it just use different id. So, I can add support for this packet in a test version of the tool and it can start upload firmware with old packets. In that way we can bypass this step.But it is unknown how the new bootloader will react on old packets for flashing. Since official flasher don't supports it, there is no way to check it. It is possible that it can accept old packets and flashing will be ok. But on the other hand it can reject it and in that case it should fail with no flashing and it should not affect the radio.But there is some minor risk that sending old packets in response to the new bootloader beacon may be incorrectly interpreted in the new bootloader with unpredictable results... At worse case it may leads to incorrect firmware overwrite, so the radio will be bricked and may not start after that and will require to use new flasher which supports new bootloader (which is not available at this time) to restore it.Unfortunately it is unknown when a new flasher which supports new bootloader will be available and there is some small risk that it will be never available (it means that such new radio with bootloader 5.00.01 will never support firmware upgrade, this looks highly unlikely, but still possible). So, if radio will be bricked it may needs to wait for a new flasher tool version which will have support for a new bootloader.I already implemented test version of the tool, so if someone agree to test it on a new radio with bootloader 5.00.01, with take into account that there is some risk to brick it, just let me know.

author: eXisten
author_rank: Contributor
timestamp: July 20, 2024, 08:08:13 pm
content: The conclusion is that you still have to wait - but either with a working radio or with a broken oneWell, there's no fun without risk!I hope that in the event of a failure I will be able to count on further assistance?If so, I still have questions:1. What firmware do you recommend for testing?2. Should I perform a full reset on my device before flashing?3. Assuming the operation is successful (I hope), what effect will this have on the ability to program the radio using CHIRP or PSCPS?

author: radiolistener
author_rank: Super Contributor
timestamp: July 21, 2024, 06:31:23 am
content: Yes, we're needs to wait until someone who has radio with new bootloader will test it and there is no guarantee that it will works and will not brick the radio. But it's better to test it on one device and share results to other, so other peoples will know if it works or not and can avoid unnecessary risk of bricking the radio. If it will be tested by many peoples and it will brick the radio, it leads to a lot of bricked radio and it will be a stupid way...I estimate the risk is not high, and if I had a radio with a new bootloader, I would test it without hesitation. The price of the radio is 15-20 USD and you don't lose it, you can use its component as replacement part for other radio (battery, charger, enclosure, antenna, PCB with all working elements include display, etc). And you can fix its firmware later, when new bootloader will be supported in a new flasher tools. So, I don't see there a big lose.I expect that if it don't supports old flash write packet, it just will fail on first write packet and it don't brick the radio.But there is some risk that it can brick the radio, and there is needs to be ready for that, this is why I don't share the test tool with new protocol support and will share it to the one people who understand it and is ready for that. If there is no such people, we're needs to wait when some other people will get the radio with new bootloader and will do research how it's new bootloader works. There is no other way...By the way. Did you tried to read EEPROM from the radio with new firmware 5.00.05?If it don't works, can you share k5tool log file for -rdee command?Note: EEPROM read should be executed when radio is working in normal mode, not bootloader

author: radiolistener
author_rank: Super Contributor
timestamp: July 21, 2024, 07:00:40 am
content: Quote from: eXisten on July 20, 2024, 08:08:13 pmIt don't matters, I recommend to use official firmware for the first test, to minimize risk with bugs in custom firmware.For exampleRT590_v2.01.32_publish.bin, this is the best official firmware from my opinion.The only thing that needs to be done before upload new firmware is to read full eeprom backup and keep that file. Later, it can help to restore original calibrations and settings if it will be broken with custom firmware.Quote from: eXisten on July 20, 2024, 08:08:13 pmYou can do, but it don't matters.Quote from: eXisten on July 20, 2024, 08:08:13 pmIf you upload official firmware and it will works ok, it will be supported in software like CHIRP or PSCPS the same as it was worked before for old radio.PS: before testing there is a sense to check if PCB hardware is the same as for old UV-K5 radio. If it uses new PCB hardware, there is high risk that old firmware will be incompatible... Can you share photo of PCB?

author: eXisten
author_rank: Contributor
timestamp: July 21, 2024, 11:07:17 am
content: Yes, E5TOOL reads EEPROM correctly.Here is a photo of the PCB:https://zapodaj.net/plik-qym6AWJa0Z

author: radiolistener
author_rank: Super Contributor
timestamp: July 21, 2024, 01:32:32 pm
content: pcb has the same version as old uv-k5 and looks the same, so it should work ok with old firmware.Since read eeprom works ok, it looks that the only change is bootloader.So there is a chance that it can support old flash write packet. Needs to test it.If it fails then this new bootloader uses new write packet, and needs further reverse engineering.Here is patch file which add support for a new bootloader beacon packet for K5TOOL source code. If someone can accept possible risk of bricking device, please test if this patch helps to upload firmware to the radio with a new bootloader 5.00.01 and write here message if it works or not. Please share log file if it fails.

author: eXisten
author_rank: Contributor
timestamp: July 21, 2024, 04:27:02 pm
content: What should I do with this file?

author: radiolistener
author_rank: Super Contributor
timestamp: July 22, 2024, 03:30:06 pm
content: Quote from: eXisten on July 21, 2024, 04:27:02 pmyou can apply it to source code, compile and test it.Well, here istestversion of k5tool which supports new bootloader beacon packet, it uses old flash write packets, so it's unknown if new bootloader supports it. There is a risk that it may not work on a radio with new bootloader 5 (or higher) and it include risk that it may brick the radio, because no one tested it with new bootloader radio.Use it at your own risk.This test version also includes some minor fixed for write packet structure to be compatible with original flasher software, it will be committed soon to git-hub.If you test it on a radio with new bootloader, please let me know if it works and share the log file.

author: Chris79
author_rank: Newbie
timestamp: July 22, 2024, 06:56:10 pm
content: I've given it a go, but no luck. Here's the log attached.Not bricked though. Just an endless beacon loop.

author: eXisten
author_rank: Contributor
timestamp: July 22, 2024, 09:46:14 pm
content: Same for me. Nothing came of it, but the radio is aliveWhen I tried to load the Egzumer mod, it went into a loop - I had to close the terminal window.Quote

author: radiolistener
author_rank: Super Contributor
timestamp: July 22, 2024, 09:49:12 pm
content: Quote from: Chris79 on July 22, 2024, 06:56:10 pmThanks a lot.I see two possible reasons:1) The new bootloader don't want to accept firmware version 3.2) Developer of bootloader just removed old write unlock packet and replaced it with a new one.To clarify which one we have, could you please test firmware update with manually specified fake version, for example 5.00.07?Here is how to do it.You're needs to unpack firmware and then flash it with -wrflashraw command and fake 5.00.07 version to unlock write:Code:$ ./k5tool -unpack RT590_v2.01.32_publish.binCRC check passed...Version: 2.01.32Write RT590_v2.01.32_publish-2.01.32.raw...Done$ ./k5tool -wrflashraw 5.00.07 RT590_v2.01.32_publish-2.01.32.rawLet me know the result.If it don't helps, then it means that the new bootloader don't allow old write unlock packet. In that case we're needs to wait for official firmware updater or when someone can obtain firmware from the chip and disassemble it...

author: radiolistener
author_rank: Super Contributor
timestamp: July 22, 2024, 09:53:55 pm
content: Quote from: eXisten on July 22, 2024, 09:46:14 pmThanks. egzumer firmware has version started from *, but bootloader still don't accept it.We're needs to try to specify version 5 manually, if it don't helps, then the new bootloader wants a different way to unlock flash write...

author: Chris79
author_rank: Newbie
timestamp: July 22, 2024, 10:32:16 pm
content: Attempted to unpack and flash with V3.No success. Same beacon loop again.

author: radiolistener
author_rank: Super Contributor
timestamp: July 22, 2024, 10:57:36 pm
content: Quote from: Chris79 on July 22, 2024, 10:32:16 pmThanks, it means that manufacturer removed old flash write packet support from the new bootloader. We're needs to wait for official updater tool to get more info.I updated K5TOOL to v1.6:https://github.com/qrp73/K5TOOL/releases/tag/v1.6It has fixed bootloader packets structure added error details for flash write operation, also this version prefers USB serial ports on linux.And this version has a check for bootloader 5. For bootloader 5 this version will show not supported error.

author: eXisten
author_rank: Contributor
timestamp: July 23, 2024, 07:16:46 am
content: Quote from: radiolistener on July 22, 2024, 09:53:55 pmWhere does this "*" come from?

author: radiolistener
author_rank: Super Contributor
timestamp: July 23, 2024, 07:36:16 am
content: Quote from: eXisten on July 23, 2024, 07:16:46 amfrom version string. It is packed with firmware image.When you do firmware unpack this version string is displayed here:Code:$ ./k5tool -unpack RT590_v2.01.32_publish.binCRC check passed...Version: 2.01.32When you do firmware pack, you're needs to provide that version string

author: radiolistener
author_rank: Super Contributor
timestamp: July 23, 2024, 07:45:21 am
content: Quote from: Chris79 on July 22, 2024, 06:56:10 pmDo you use classic UV-K5 model, or some clone?

author: Chris79
author_rank: Newbie
timestamp: July 23, 2024, 01:49:40 pm
content: It's one of the new Quansheng UV-5R Plus models. Looks a little like a Baofeng, but system is Quansheng*Also has a usb charging port, which the original Quansheng UV-5R Plus models didn't have.

author: eXisten
author_rank: Contributor
timestamp: July 24, 2024, 06:36:15 am
content: I have an identical one! Mine also has a USB charging port (which wasn't there before)Well, we just have to wait until someone comes up with something.

author: Chris79
author_rank: Newbie
timestamp: July 25, 2024, 05:39:54 pm
content: Just for comparison, I ordered and have just received another UV-5R Plus from Ali Express at the grand total of £4.37 delivered.This time, I received one of the non-USB ones.Here are side by side photos, the usb one (with newer firmware) on the left in each photo. (I've erased the serial numbers from the photos).There is a distinct difference with the smaller connector (mic input?) on the newer model, which is different from all other uv-K5 radios. I also noticed that the usb one shows a "usb connected" icon (2 pin plug) on screen too when the flashing cable is attached and the radio switched on, which the non-usb doesn't, which maybe suggests something is physically different with how the usb port is wired up?This one flashed fine, as expected.There is reference to a USB and non-USB radio in the manual too.

author: ftg
author_rank: Frequent Contributor
timestamp: August 07, 2024, 07:11:44 am
content: I can as well confirm that the Quansheng UV-5R Plus with USB-C charging has version 5 firmware and bootloader.There has been some preliminiary reversing by tunas1337 that points towards at least the firmware upload commands being changed.The firmware was graciously dumped by UB4C and is also attached below.It is also mirrored here:https://prkele.prk.tky.fi/~ftg/images/uvk5/qz_uv-5r_plus_ver5fw/fw_dump_from_UB4C/If any of you want something tested on the physical hardware, do let me know.

author: radiolistener
author_rank: Super Contributor
timestamp: August 07, 2024, 08:38:48 pm
content: Quote from: ftg on August 07, 2024, 07:11:44 amThanks a lot.At a glance, not only upload command is changed, but also responses.Do you have the same dump for an old bootloader 2.00.06?It will helps to reverse.

author: radiolistener
author_rank: Super Contributor
timestamp: August 08, 2024, 12:52:05 am
content: Some findings. The new bootloader supports 3 commands:Code:$ arm-none-eabi-objdump -D -b binary -marm --start-address=0x27c --stop-address=0x2a8 -Mforce-thumb bootloader.bin27c:b510push{r4, lr}27e:4809ldrr0, [pc, #36]@ (0x2a4) @ r0 = 0x20000B24;// packet_ptr = pointer to unpacked packet280:22afmovsr2, #175@ 0xaf @ r2 = 0x00af282:8801ldrhr1, [r0, #0] @ r1 = *(short*)&packet_ptr;// packet id284:00d2lslsr2, r2, #3 @ r2 = r2 << 3 = 0x0578;286:1a89subsr1, r1, r2 @ r1 = r1-r2;288:d006beq.n0x298 @ [if (r1==0x0578) { call 0x30c; return; }]28a:2903cmpr1, #328c:d007beq.n0x29e @ [if (r1==0x057b) { call 0x338; return; }]28e:2905cmpr1, #5290:d101bne.n0x296 @ [if (r1==0x057d) { call 0x2a8; return; }]292:f000 f809bl0x2a8296:bd10pop{r4, pc}298:f000 f838bl0x30c29c:bd10pop{r4, pc}29e:f000 f84bbl0x3382a2:bd10pop{r4, pc}2a4:0b24lsrsr4, r4, #122a6:2000movsr0, #0It seems that the new packet id=0x057d is a new flash unlock command it is processed with procedure at address 0x2a8.This procedure checks if a first letter of version string is '*' or equals to the first letter of bootloader version string "5.00.01" (0x0bf0 offset) and ignores packet if it don't equals:Code:$ arm-none-eabi-objdump -D -b binary -marm --start-address=0x2a8 --stop-address=0x30c -Mforce-thumb bootloader.bin2a8:b510push{r4, lr}2aa:7d01ldrbr1, [r0, #20] @ r1 = (byte)packet_ptr;2ac:b08csubsp, #48@ 0x30 @ sp -= 48; // alloc 48 bytes on stack2ae:2910cmpr1, #162b0:d224bcs.n0x2fc @ if (r1 >= 16) return;2b2:4a13ldrr2, [pc, #76]@ (0x300) @ r2 = 0x0BF0; // pointer to string "5.00.01"2b4:7900ldrbr0, [r0, #4] @ r0 = (byte)packet_ptr; // first letter of version string2b6:7812ldrbr2, [r2, #0] @ r2 = '5';2b8:4290cmpr0, r22ba:d001beq.n0x2c02bc:282acmpr0, #42@ 0x2a2be:d11dbne.n0x2fc @ if (r0!=r2 && r0!='*') return;2c0:4a10ldrr2, [pc, #64]@ (0x304) @ r2 = 0x20000314; // ptrVars2c2:2001movsr0, #1 @ r0 = 1;2c4:7050strbr0, [r2, #1] @ r2 = (byte)r0;// IsWriteEnable = 1;2c6:4810ldrr0, [pc, #64]@ (0x308) @ r0 = 0x09f0; // ptr to bootloader area at 0x09f0 offset2c8:0149lslsr1, r1, #5 @ r1 = r1 << 5;2ca:1809addsr1, r1, r0 @ r1 += r0; // r1 = (byte)packet_ptr * 0x20 + 0x09f0;2cc:460cmovr4, r1 @ r4 = r1;2ce:2210movsr2, #16 @ r2 = 16;2d0:a804addr0, sp, #16 @ r0 = sp+16;2d2:f7ff ff3fbl0x154 @ call 0x154; // memcpy(r0, r1, r2);2d6:4621movr1, r4 @ r1 = r4;2d8:3110addsr1, #16 @ r1 += 16;2da:2210movsr2, #16 @ r2 = 16;2dc:4668movr0, sp @ r0 = sp;2de:f7ff ff39bl0x154 @ call 0x154; // memcpy(r0, r1, r2);2e2:466amovr2, sp @ r2 = sp;2e4:a904addr1, sp, #16 @ r1 = sp+16;2e6:2001movsr0, #1 @ r0 = 1;2e8:f000 f902bl0x4f0 @ call 0x4f0;2ec:a808addr0, sp, #32 @ r0 = sp+32;2ee:f7ff ffb1bl0x254 @ call 0x254;2f2:466amovr2, sp @ r2 = sp;2f4:a908addr1, sp, #32 @ r1 = sp+32;2f6:2002movsr0, #2 @ r0 = 2;2f8:f000 f8fabl0x4f0 @ call 0x4f02fc:b00caddsp, #48@ 0x30 @ sp += 48; // free 48 bytes on stack2fe:bd10pop{r4, pc} @ return;300:0bf0lsrsr0, r6, #15302:0000movsr0, r0304:0314lslsr4, r2, #12306:2000movsr0, #0308:09f0lsrsr0, r6, #730a:0000movsr0, r0But there is a new unknown byte field after 16 bytes of version string signature. The procedure rejects packet if this byte is >= 0x10. If this field is less than 0x10, then it calculates ptr = byte * 0x20 + 0x09F0. It appears like pointer to bootloader area which starts at 0x09f0 offset. Then it doing some manipulation with it. Needs time to discover it more deep...Let me know if you discover more details.

author: radiolistener
author_rank: Super Contributor
timestamp: August 08, 2024, 06:43:01 am
content: The new write flash packet has id=0x057b.The procedure which process this packet starts at 0x0338 offset, it get argument packet_ptr passed through r0.Code:arm-none-eabi-objdump -D -b binary -marm --start-address=0x338 --stop-address=0x464 -Mforce-thumb bootloader.bin338:b5f8push{r3, r4, r5, r6, r7, lr}33a:4c46ldrr4, [pc, #280]@ (0x454) @ r4 = 0x2000031433c:4605movr5, r0 @ r5 = packet_ptr33e:7860ldrbr0, [r4, #1] @ r0 = (byte)r4; // r0=IsWriteEnabled;340:2801cmpr0, #1342:d005beq.n0x350 @ if (!IsWriteEnabled) { call_0480(0, 1, 0); return; }344:2100movsr1, #0346:2201movsr2, #1348:4608movr0, r134a:f000 f899bl0x48034e:bdf8pop{r3, r4, r5, r6, r7, pc}350:7a68ldrbr0, [r5, #9] @ r0 = (byte)packet_ptr; // r0=chunkNumber.hi;352:7a29ldrbr1, [r5, #8] @ r1 = (byte)packet_ptr; // r1=chunkNumber.lo;354:0200lslsr0, r0, #8 @ r0 <<= 8;356:4308orrsr0, r1 @ r0 |= r1; // r0 = chunkNumber;358:d01cbeq.n0x394 @ if (r0 != 0) goto 0x394;35a:7820ldrbr0, [r4, #0] @ r0 = (byte)r4; // some variable35c:2802cmpr0, #235e:d1f6bne.n0x34e360:483dldrr0, [pc, #244]@ (0x458)362:6801ldrr1, [r0, #0]364:2208movsr2, #8366:4051eorsr1, r2368:6001strr1, [r0, #0]36a:7a68ldrbr0, [r5, #9]36c:7a29ldrbr1, [r5, #8]36e:0200lslsr0, r0, #8370:4308orrsr0, r1372:8861ldrhr1, [r4, #2]374:1c49addsr1, r1, #1376:4288cmpr0, r1378:d105bne.n0x38637a:1d28addsr0, r5, #437c:f7ff ff0ebl0x19c380:68a1ldrr1, [r4, #8]382:4288cmpr0, r1384:d021beq.n0x3ca386:2100movsr1, #0388:2201movsr2, #138a:4608movr0, r138c:f000 f878bl0x480390:2001movsr0, #1392:e05db.n0x450394:1d28addsr0, r5, #4396:f7ff ff01bl0x19c39a:60a0strr0, [r4, #8]39c:7ae8ldrbr0, [r5, #11]39e:7aa9ldrbr1, [r5, #10]3a0:0200lslsr0, r0, #83a2:4308orrsr0, r13a4:80a0strhr0, [r4, #4]3a6:2000movsr0, #03a8:8060strhr0, [r4, #2]3aa:2002movsr0, #23ac:7020strbr0, [r4, #0]3ae:2778movsr7, #120@ 0x783b0:b672cpsidi3b2:2600movsr6, #03b4:2001movsr0, #13b6:0271lslsr1, r6, #93b8:0300lslsr0, r0, #123ba:1808addsr0, r1, r03bc:f7ff ff10bl0x1e03c0:1c76addsr6, r6, #13c2:b2b6uxthr6, r63c4:42becmpr6, r73c6:d3f5bcc.n0x3b43c8:b662cpsiei3ca:22ffmovsr2, #255@ 0xff3cc:4629movr1, r53ce:3201addsr2, #13d0:3110addsr1, #163d2:4822ldrr0, [pc, #136]@ (0x45c)3d4:f7ff febebl0x1543d8:4920ldrr1, [pc, #128]@ (0x45c)3da:2000movsr0, #03dc:0082lslsr2, r0, #23de:588bldrr3, [r1, r2]3e0:1c40addsr0, r0, #13e2:ba1brevr3, r33e4:b280uxthr0, r03e6:508bstrr3, [r1, r2]3e8:2840cmpr0, #64@ 0x403ea:d3f7bcc.n0x3dc3ec:4f1cldrr7, [pc, #112]@ (0x460)3ee:2600movsr6, #03f0:0130lslsr0, r6, #43f2:4a1aldrr2, [pc, #104]@ (0x45c)3f4:19c1addsr1, r0, r73f6:1880addsr0, r0, r23f8:f7ff ff10bl0x21c3fc:1c76addsr6, r6, #13fe:b2b6uxthr6, r6400:2e10cmpr6, #16402:d3f5bcc.n0x3f0404:2000movsr0, #0406:0082lslsr2, r0, #2408:58b9ldrr1, [r7, r2]40a:1c40addsr0, r0, #140c:ba09revr1, r140e:b280uxthr0, r0410:50b9strr1, [r7, r2]412:2840cmpr0, #64@ 0x40414:d3f7bcc.n0x406416:b672cpsidi418:7a68ldrbr0, [r5, #9]41a:7a29ldrbr1, [r5, #8]41c:0200lslsr0, r0, #841e:4308orrsr0, r1420:0201lslsr1, r0, #8422:2001movsr0, #1424:0300lslsr0, r0, #12426:1808addsr0, r1, r0428:2240movsr2, #64@ 0x4042a:490dldrr1, [pc, #52]@ (0x460)42c:f7ff fedebl0x1ec430:b662cpsiei432:7a68ldrbr0, [r5, #9]434:7a2aldrbr2, [r5, #8]436:0201lslsr1, r0, #8438:4311orrsr1, r243a:8061strhr1, [r4, #2]43c:2200movsr2, #043e:68a0ldrr0, [r4, #8]440:f000 f81ebl0x480444:8860ldrhr0, [r4, #2]446:88a1ldrhr1, [r4, #4]448:1c40addsr0, r0, #144a:4288cmpr0, r144c:d187bne.n0x35e44e:2003movsr0, #3450:7020strbr0, [r4, #0]452:bdf8pop{r3, r4, r5, r6, r7, pc}454:0314lslsr4, r2, #12456:2000movsr0, #0458:1000asrsr0, r0, #3245a:4006andsr6, r045c:1124asrsr4, r4, #445e:2000movsr0, #0460:0f24lsrsr4, r4, #28462:2000movsr0, #0Preliminary structure looks the same as for old packet 0x0519. But needs more detailed check.It looks like the only thing that needs to be changed for bootloader v5 is just to replace packet id for version packet 0x057d (instead of 0x0530) and for write packet 0x057b (instead of 0x0519) and add byte field at the end of version packet. The meaning of this field still unclear, but it should be < 0x10.Also it looks that the new write packet 0x057b possible uses some kind of firmware decryption, see this code:Code:3ca:22ffmovsr2, #255@ 0xff @ r2 = 255;3cc:4629movr1, r5 @ r1 = r5;3ce:3201addsr2, #1 @ r2 += 1;3d0:3110addsr1, #16 @ r1 += 16;3d2:4822ldrr0, [pc, #136]@ (0x45c) @ r0 = 0x20001124;3d4:f7ff febebl0x154 @ memcpy(r0, r1, r2);3d8:4920ldrr1, [pc, #128]@ (0x45c) @ r1 = 0x20001124;3da:2000movsr0, #0 @ r0 = 0;3dc:0082lslsr2, r0, #2 @ r2 = r0 << 2;3de:588bldrr3, [r1, r2] @ r3 = *(uint32_t)(r1+r2);3e0:1c40addsr0, r0, #1 @ r0 += 1;3e2:ba1brevr3, r33e4:b280uxthr0, r03e6:508bstrr3, [r1, r2]3e8:2840cmpr0, #64@ 0x403ea:d3f7bcc.n0x3dc3ec:4f1cldrr7, [pc, #112]@ (0x460)3ee:2600movsr6, #03f0:0130lslsr0, r6, #43f2:4a1aldrr2, [pc, #104]@ (0x45c)3f4:19c1addsr1, r0, r73f6:1880addsr0, r0, r23f8:f7ff ff10bl0x21c3fc:1c76addsr6, r6, #13fe:b2b6uxthr6, r6400:2e10cmpr6, #16402:d3f5bcc.n0x3f0404:2000movsr0, #0406:0082lslsr2, r0, #2408:58b9ldrr1, [r7, r2]40a:1c40addsr0, r0, #140c:ba09revr1, r140e:b280uxthr0, r0410:50b9strr1, [r7, r2]412:2840cmpr0, #64@ 0x40414:d3f7bcc.n0x406I'm not sure what is going on here, needs to analyze it more deep.PS: this is my first experience with ARM assembly code analysis, so it's not easy to read it, because I'm used to assembler of other processors. ARM assembly code looks like an explosion in a pasta factory

author: radiolistener
author_rank: Super Contributor
timestamp: August 08, 2024, 08:22:43 am
content: The response for write flash packet for bootloader 5 is exactly the same as for bootloader 2.The only difference is id=0x057c (instead of 0x051a). The structure is exactly the same:Code:$ arm-none-eabi-objdump -D -b binary -marm --start-address=0x480 --stop-address=0x4a1 -Mforce-thumb bootloader.bin@ SendPacket_057c(uint32_t sequenceId, uint16_t chunkNumber, uint8_t errorCode)480:b53epush{r1, r2, r3, r4, r5, lr}482:4c06ldrr4, [pc, #24]@ (0x49c) @ r4 = 0x057C;484:466bmovr3, sp @ r3 = sp;486:801cstrhr4, [r3, #0] @ r3 = (uint16_t)r4;488:2408movsr4, #848a:805cstrhr4, [r3, #2] @ r3 = (uint16_t)8;48c:9001strr0, [sp, #4] @ sp = (uint32_t)sequenceId;48e:8119strhr1, [r3, #8] @ r3 = (uint16_t)chunkNumber;490:729astrbr2, [r3, #10] @ r3 = (uint8_t)errorCode;492:210cmovsr1, #12494:4668movr0, sp496:f000 f9cfbl0x838 @ SendPacket(sp, 12);49a:bd3epop{r1, r2, r3, r4, r5, pc} @ return;49c:057clslsr4, r7, #2149e:0000movsr0, r0

author: radiolistener
author_rank: Super Contributor
timestamp: August 09, 2024, 02:53:18 am
content: some new findings. It seems that the new bootloader 5 really expects encrypted firmware image.Here is a fragment of ProcessPacket_057b function (it handles flash write packet):Code:3d2:4822ldrr0, [pc, #136]@ (0x45c) @ r0 = (uint8_t*)0x20001124;3d4:f7ff febebl0x154 @ memcpy(0x20001124, packet_ptr->flashData, 0x100);3d8:4920ldrr1, [pc, #128]@ (0x45c) @ r1 = (uint8_t*)0x20001124;3da:2000movsr0, #0 @ r0 = 0;@ do {3dc:0082lslsr2, r0, #2 @ r2 = r0 << 2;3de:588bldrr3, [r1, r2] @ r3 = *(uint32_t*)&r1;3e0:1c40addsr0, r0, #1 @ r0 += 1;3e2:ba1brevr3, r3 @ r3 = bswap_32(r3);3e4:b280uxthr0, r0 @ r0 = (uint16_t)r0;3e6:508bstrr3, [r1, r2] @ *(uint32_t*)&r1 = r33e8:2840cmpr0, #64@ 0x403ea:d3f7bcc.n0x3dc @ } while (r0 < 64);3ec:4f1cldrr7, [pc, #112]@ (0x460) @ r7 = 0x20000F24;3ee:2600movsr6, #0 @ r6 = 0;@ do {3f0:0130lslsr0, r6, #4 @ r0 = r6 << 4;3f2:4a1aldrr2, [pc, #104]@ (0x45c) @ r2 = 0x20001124;3f4:19c1addsr1, r0, r7 @ r1 = r0 + r7;3f6:1880addsr0, r0, r2 @ r0 = r0 + r2;3f8:f7ff ff10bl0x21c @ DecryptBlock128(0x20001124 + r6*16, 0x20000F24 + r6*16);3fc:1c76addsr6, r6, #1 @ r6 += 1;3fe:b2b6uxthr6, r6 @ r6 = (uint16_t)r6;400:2e10cmpr6, #16402:d3f5bcc.n0x3f0 @ } while (r6 < 16);404:2000movsr0, #0 @ r0 = 0;@ do {406:0082lslsr2, r0, #2 @ r2 = r0 << 2;408:58b9ldrr1, [r7, r2] @ r1 = *(uint32_t*)&r7;40a:1c40addsr0, r0, #1 @ r0 += 1;40c:ba09revr1, r1 @ r1 = bswap_32(r1);40e:b280uxthr0, r0 @ r0 = (uint16_t)r0;410:50b9strr1, [r7, r2] @ *(uint32_t*)&r7 = r1;412:2840cmpr0, #64@ 0x40414:d3f7bcc.n0x406 @ } while (r0 < 64);416:b672cpsidi @ DisableIRQ();418:7a68ldrbr0, [r5, #9] @ r0 = (uint8_t)packet_ptr;// r0=packet_ptr->chunkNumber.hi;41a:7a29ldrbr1, [r5, #8] @ r1 = (uint8_t)packet_ptr;// r1=packet_ptr->chunkNumber.lo;41c:0200lslsr0, r0, #8 @ r0 <<= 8;41e:4308orrsr0, r1 @ r0 |= r1; // r0=packet_ptr->chunkNumber;420:0201lslsr1, r0, #8 @ r1 = r0 << 8; // r1=packet_ptr->chunkNumber * 0x100;422:2001movsr0, #1 @ r0 = 1;424:0300lslsr0, r0, #12 @ r0 <<= 12;426:1808addsr0, r1, r0 @ r0 = r1 + r0;428:2240movsr2, #64@ 0x40 @ r2 = 64;42a:490dldrr1, [pc, #52]@ (0x460) @ r1 = 0x20000F24;42c:f7ff fedebl0x1ec @ call_thumb_200001bc(0x1000 + packet_ptr->chunkNumber * 0x100, 0x20000F24, 64); // write flash page???430:b662cpsiei @ EnableIRQ();As you can see, it calls the function at address 0x21c. I name it DecryptBlock128, because it looks like using some hardware cryptographic module to decrypt 128 bits of data:Code:@ arm-none-eabi-objdump -D -b binary -marm --start-address=0x21c --stop-address=0x254 -Mforce-thumb bootloader.bin@ DecryptBlock128(r0, r1)0000021c <.data+0x21c>:21c:4a0cldrr2, [pc, #48]@ (0x250) @ r2 = 0x400BD000;21e:6803ldrr3, [r0, #0]220:6093strr3, [r2, #8] @ *(uint32_t*)&r2 = *(uint32_t*)&r0222:6843ldrr3, [r0, #4]224:6093strr3, [r2, #8] @ *(uint32_t*)&r2 = *(uint32_t*)&r0226:6883ldrr3, [r0, #8]228:6093strr3, [r2, #8] @ *(uint32_t*)&r2 = *(uint32_t*)&r022a:68c0ldrr0, [r0, #12]22c:6090strr0, [r2, #8] @ *(uint32_t*)&r2 = *(uint32_t*)&r0@ do {22e:6850ldrr0, [r2, #4] @ r0 = *(uint32_t*)&r2;230:07c0lslsr0, r0, #31 @ r0 <<= 31;232:d0fcbeq.n0x22e @ } while (r0==0);234:68d0ldrr0, [r2, #12]236:6008strr0, [r1, #0] @ *(uint32_t*)&r1 = *(uint32_t*)&r2;238:68d0ldrr0, [r2, #12]23a:6048strr0, [r1, #4] @ *(uint32_t*)&r1 = *(uint32_t*)&r2;23c:68d0ldrr0, [r2, #12]23e:6088strr0, [r1, #8] @ *(uint32_t*)&r1 = *(uint32_t*)&r2;240:68d0ldrr0, [r2, #12]242:60c8strr0, [r1, #12] @ *(uint32_t*)&r1 = *(uint32_t*)&r2;244:6810ldrr0, [r2, #0] @ r0 = *(uint32_t*)&r2;246:2180movsr1, #128@ 0x80248:4308orrsr0, r124a:6010strr0, [r2, #0] @ *(uint32_t*)&r2 = *(uint32_t*)&r2 | 0x80;24c:4770bxlr @ return24e:0000250:d000DCD 0x400BD000252:400bManually decompiled version:Code:void DecryptBlock128(uint32_t* src, uint32_t* dst) {uint32_t* reg_base = 0x400BD000;reg_base = src;reg_base = src;reg_base = src;reg_base = src;while ((reg_base & 1)==0) { }dst = reg_base;dst = reg_base;dst = reg_base;dst = reg_base;reg_base = reg_base | 0x80;}As you can see, it sends data to some hardware unit with base address 0x400BD000 then waits for completion and reads data back.And now it's more clear what meaning the new byte field in the version packet. It selects one of 16 keys stored in the bootloader at address 0x09f0, each key is 32 bytes length (256 bit).Here is the code of ProcessPacket_057d function which process version packet:Code:@ arm-none-eabi-objdump -D -b binary -marm --start-address=0x2a8 --stop-address=0x30c -Mforce-thumb bootloader.bin@ ProcessPacket_057d(uint8_t* packet_ptr)000002a8 <.data+0x2a8>:2a8:b510push{r4, lr}2aa:7d01ldrbr1, [r0, #20] @ r1 = (uint8_t)packet_ptr;2ac:b08csubsp, #48@ 0x30 @ sp -= 48; // alloc 48 bytes on stack2ae:2910cmpr1, #162b0:d224bcs.n0x2fc @ if (r1 >= 16) return;2b2:4a13ldrr2, [pc, #76]@ (0x300) @ r2 = 0x0BF0; // pointer to string "5.00.01"2b4:7900ldrbr0, [r0, #4] @ r0 = (uint8_t)packet_ptr; // first letter of version string2b6:7812ldrbr2, [r2, #0] @ r2 = '5';2b8:4290cmpr0, r22ba:d001beq.n0x2c02bc:282acmpr0, #42@ 0x2a2be:d11dbne.n0x2fc @ if (r0!=r2 && r0!='*') return;2c0:4a10ldrr2, [pc, #64]@ (0x304) @ r2 = (uint8_t*)0x20000314; // ram3142c2:2001movsr0, #1 @ r0 = 1;2c4:7050strbr0, [r2, #1] @ *(uint8_t*)&r2 = r0; // ram314->IsFlashWriteEnable = 1;2c6:4810ldrr0, [pc, #64]@ (0x308) @ r0 = 0x09f0; // ptr to bootloader area at 0x09f0 offset2c8:0149lslsr1, r1, #5 @ r1 = r1 << 5;2ca:1809addsr1, r1, r0 @ r1 += r0; // r1 = (byte)packet_ptr * 0x20 + 0x09f0;2cc:460cmovr4, r1 @ r4 = r1;2ce:2210movsr2, #16 @ r2 = 16;2d0:a804addr0, sp, #16 @ r0 = sp+16;2d2:f7ff ff3fbl0x154 @ memcpy(r0, r1, r2);2d6:4621movr1, r4 @ r1 = r4;2d8:3110addsr1, #16 @ r1 += 16;2da:2210movsr2, #16 @ r2 = 16;2dc:4668movr0, sp @ r0 = sp;2de:f7ff ff39bl0x154 @ memcpy(r0, r1, r2);2e2:466amovr2, sp @ r2 = sp;2e4:a904addr1, sp, #16 @ r1 = sp+16;2e6:2001movsr0, #1 @ r0 = 1;2e8:f000 f902bl0x4f0 @ call_4f0(r0, r1, r2);2ec:a808addr0, sp, #32 @ r0 = sp+32;2ee:f7ff ffb1bl0x254 @ call_254(r0);2f2:466amovr2, sp @ r2 = sp;2f4:a908addr1, sp, #32 @ r1 = sp+32;2f6:2002movsr0, #2 @ r0 = 2;2f8:f000 f8fabl0x4f0 @ call_4f0(r0, r1, r2);2fc:b00caddsp, #48@ 0x30 @ sp += 48; // free 48 bytes on stack2fe:bd10pop{r4, pc} @ return;300:0bf0DCD 0x00000BF0302:0000304:0314DCD 0x20000314306:2000308:09f0DCD 0x000009f030a:0000Manually decompiled version:Code:void ProcessPacket_057d(uint8_t* packet_ptr) {uint8_t keyNumber = packet_ptr;if (keyNumber >= 16) {return;}uint8_t version = packet_ptr;if (version != '5' && version != '*') {return;}RAM314_T* ram314 = (RAM314_T*)0x20000314; // Pointer to ram314ram314->IsFlashWriteEnable = 1; // ram314->u8_1uint8_t* keyBase = (uint8_t*)0x09f0;uint8_t* keyPtr = keyBase + (keyNumber << 5);uint8_t stack;memcpy(stack + 16, keyPtr, 16);memcpy(stack, keyPtr + 16, 16);call_4f0(1, stack + 16, stack);call_254(stack + 32);call_4f0(2, stack + 32, stack);}And the function call_4f0() uses the same base address 0x400BD000 as DecryptBlock128():Code:@ arm-none-eabi-objdump -D -b binary -marm --start-address=0x4f0 --stop-address=0x534 -Mforce-thumb bootloader.bin > FUN_000004f0.s@ call_4f0(uint32_t v, uint32_t* key1, uint32_t* key2)000004f0 <.data+0x4f0>:4f0:b510push{r4, lr}4f2:4b0fldrr3, [pc, #60]@ (0x530) @ r3 = 0x400BD000;4f4:681cldrr4, [r3, #0] @ r4 = *(uint32_t*)&r3;4f6:0864lsrsr4, r4, #1 @ r4 >>= 1;4f8:0064lslsr4, r4, #1 @ r4 <<= 1;4fa:601cstrr4, [r3, #0] @ *(uint32_t*)&r3 = r4;4fc:00c0lslsr0, r0, #3 @ r0 <<= 3;4fe:2420movsr4, #32 @ r4 = 32;500:4320orrsr0, r4 @ r0 |= r4; // r0 = (r0 << 3) | 0x20;502:6018strr0, [r3, #0] @ *(uint32_t*)&r3 = r0;504:6808ldrr0, [r1, #0]506:61d8strr0, [r3, #28] @ *(uint32_t*)&r3 = *(uint32_t*)&r1;508:6848ldrr0, [r1, #4]50a:6198strr0, [r3, #24] @ *(uint32_t*)&r3 = *(uint32_t*)&r1;50c:6888ldrr0, [r1, #8]50e:6158strr0, [r3, #20] @ *(uint32_t*)&r3 = *(uint32_t*)&r1;510:68c8ldrr0, [r1, #12]512:6118strr0, [r3, #16] @ *(uint32_t*)&r3 = *(uint32_t*)&r1;514:6810ldrr0, [r2, #0]516:62d8strr0, [r3, #44]@ 0x2c @ *(uint32_t*)&r3 = *(uint32_t*)&r2;518:6850ldrr0, [r2, #4]51a:6298strr0, [r3, #40]@ 0x28 @ *(uint32_t*)&r3 = *(uint32_t*)&r2;51c:6890ldrr0, [r2, #8]51e:6258strr0, [r3, #36]@ 0x24 @ *(uint32_t*)&r3 = *(uint32_t*)&r2;520:68d0ldrr0, [r2, #12]522:6218strr0, [r3, #32] @ *(uint32_t*)&r3 = *(uint32_t*)&r2;524:6818ldrr0, [r3, #0]526:2101movsr1, #1528:4308orrsr0, r152a:6018strr0, [r3, #0] @ *(uint32_t*)&r3 = *(uint32_t*)&r3 | 1;52c:bd10pop{r4, pc}52e:0000530:d000 DCD 0x400BD000532:400bManually decompiled version:Code:void call_4f0(uint32_t v, uint32_t* key1, uint32_t* key2) {uint32_t* reg_base = 0x400BD000;reg_base &= ~1;reg_base = (v << 3) | 0x20;reg_base = key1;reg_base = key1;reg_base = key1;reg_base = key1;reg_base = key2;reg_base = key2;reg_base = key2;reg_base = key2;reg_base = reg_base | 1;}so it seems like this function setting the decryption key for hardware cryptographic module.Does anyone know what is the module with base address 0x400BD000? What encryption algorithm it uses? AES 256?

author: radiolistener
author_rank: Super Contributor
timestamp: August 09, 2024, 04:59:11 am
content: Yes, this is AES hardware accelerator module:DP32G030 datasheet:https://github.com/amnemonic/Quansheng_UV-K5_Firmware/raw/main/hardware/DP32G030/DP32G030_Chinese_Datasheet.7zNow needs to understand how it works...With datasheet in Chinese language this is not easy

author: Chris79
author_rank: Newbie
timestamp: August 09, 2024, 08:09:49 am
content: I've translated it using the Google translate app. I hope this helps.

author: eXisten
author_rank: Contributor
timestamp: August 09, 2024, 08:19:17 am
content: I translated the entire PDF (DP32G030 datasheet) - it is in parts. Division by page numbers in file names.If necessary, the conceptual diagrams would have to be translated separately - as Chris79 did.Will it be useful?Here is the link to the translated files:https://megawrzuta.pl/filesgroup/1bd474fe6c9b35ba396863752269c59f.html

author: radiolistener
author_rank: Super Contributor
timestamp: August 09, 2024, 08:37:41 am
content: Here is reconstructed code for version packet handler and AES_ProcessBlock128 (previous name DecryptBlock128):Code:#define AES_BASE 0x400BD000#define AES_CR (*(volatile uint32_t *)(AES_BASE + 0x0000))#define AES_SR (*(volatile uint32_t *)(AES_BASE + 0x0004))#define AES_DINR (*(volatile uint32_t *)(AES_BASE + 0x0008))#define AES_DOUTR (*(volatile uint32_t *)(AES_BASE + 0x000C))#define AES_KEYR0 (*(volatile uint32_t *)(AES_BASE + 0x0010))#define AES_KEYR1 (*(volatile uint32_t *)(AES_BASE + 0x0014))#define AES_KEYR2 (*(volatile uint32_t *)(AES_BASE + 0x0018))#define AES_KEYR3 (*(volatile uint32_t *)(AES_BASE + 0x001C))#define AES_IVR0 (*(volatile uint32_t *)(AES_BASE + 0x0020))#define AES_IVR1 (*(volatile uint32_t *)(AES_BASE + 0x0024))#define AES_IVR2 (*(volatile uint32_t *)(AES_BASE + 0x0028))#define AES_IVR3 (*(volatile uint32_t *)(AES_BASE + 0x002C))#define AES_CR_EN (1 << 0)#define AES_CR_CCFC (1 << 7)#define AES_SR_CCF (1 << 0)#define AES_CR_CHMOD_ECB (0 << 5)#define AES_CR_CHMOD_CBC (1 << 5)#define AES_CR_CHMOD_CTR (2 << 5)#define AES_MODE_ENCRYPT 0#define AES_MODE_KEY 1#define AES_MODE_DECRYPT 2#define AES_MODE_KEYNDECRYPT 3typedef struct {uint8_t u8_0; // u8 @ offset 0 // stateuint8_t IsFlashWriteEnabled; // u8 @ offset 1uint16_t ChunkNumber; // u16 @ offset 2uint16_t ChunkCount; // u16 @ offset 4uint32_t SequenceId; // u32 @ offset 8} RAM314_T;// 0x057d version packet for bootloader v5// It works the same as 0x0530 version packet for bootloader v2,// but 0x057d packet has additional byte field to select one of 16 decryption keys hardcoded in bootloader at offset 0x09f0.// When PC sends this version packet to the radio, the radio initialize AES module with decryption key.// This key will be used to decrypt firmware content with AES_ProcessBlock128 function.void ProcessPacket_057d(uint8_t* packet_ptr) {uint8_t keyNumber = packet_ptr;if (keyNumber >= 16) {return;}uint8_t version = packet_ptr;if (version != '5' && version != '*') {return;}RAM314_T* ram314 = (RAM314_T*)0x20000314; // Pointer to ram314ram314->IsFlashWriteEnable = 1; // ram314->u8_1uint8_t* keyBase = (uint8_t*)0x09f0; // pointer to keys table (see 0x09f0 offset in bootloader.bin)uint8_t* keyPtr = keyBase + (keyNumber << 5);uint8_t key;uint8_t iv;uint8_t key2;memcpy(key, keyPtr, 16);memcpy(iv, (keyPtr + 16), 16);AES_Init(AES_MODE_KEY, key, iv);AES_GenerateDerivedKey(key2Buf);AES_Init(AES_MODE_DECRYPT, key2, iv);}void AES_Init(uint32_t mode, uint32_t* key, uint32_t* iv) {AES_CR &= ~AES_CR_EN;AES_CR = (mode << 3) | AES_CR_CHMOD_CBC;AES_KEYR3 = key;AES_KEYR2 = key;AES_KEYR1 = key;AES_KEYR0 = key;AES_IVR3 = iv;AES_IVR2 = iv;AES_IVR1 = iv;AES_IVR0 = iv;AES_CR |= AES_CR_EN;}void AES_GenerateDerivedKey(uint32_t* buffer) {while ((AES_SR & AES_SR_CCF)==0) { }buffer = AES_KEYR3;buffer = AES_KEYR2;buffer = AES_KEYR1;buffer = AES_KEYR0;AES_CR |= AES_CR_CCFC;}void AES_ProcessBlock128(uint32_t* src, uint32_t* dst) {AES_DINR = src;AES_DINR = src;AES_DINR = src;AES_DINR = src;while ((AES_SR & AES_SR_CCF)==0) { }dst = AES_DOUTR;dst = AES_DOUTR;dst = AES_DOUTR;dst = AES_DOUTR;AES_CR |= AES_CR_CCFC;}

author: radiolistener
author_rank: Super Contributor
timestamp: August 09, 2024, 10:31:38 am
content: Unfortunately I'm not sure how AES KEY_DERIVATION mode works on DP32G030.I need to know how it works in order to generate exactly the same key.Probably it just encode empty buffer with zeros with key and IV, but I'm not sure...Can someone help to find the information?Maybe someone can run the test code with OpenOCD?Here is the test code:Code:void testCode() {uint8_t key;uint8_t iv;uint8_t key2;for (var i=0; i < 16; i++) {key = i;iv = i^2;}AES_Init(1, key, iv);AES_GenerateDerivedKey(key2);for(;;); // stop here and dump key2 content}void AES_Init(uint32_t mode, uint32_t* key, uint32_t* iv) {AES_CR &= ~AES_CR_EN;AES_CR = (mode << 3) | AES_CR_CHMOD_CBC;AES_KEYR3 = key;AES_KEYR2 = key;AES_KEYR1 = key;AES_KEYR0 = key;AES_IVR3 = iv;AES_IVR2 = iv;AES_IVR1 = iv;AES_IVR0 = iv;AES_CR |= AES_CR_EN;}void AES_GenerateDerivedKey(uint32_t* buffer) {while ((AES_SR & AES_SR_CCF)==0) { }buffer = AES_KEYR3;buffer = AES_KEYR2;buffer = AES_KEYR1;buffer = AES_KEYR0;AES_CR |= AES_CR_CCFC;}

author: Tunas1337
author_rank: Newbie
timestamp: August 09, 2024, 11:40:33 am
content: Hi radiolistener,I made an account to reply. Check 0x9e0 (XOR key, unchanged), 9f0, and I think a00. The latter two are AES IV and key, I can't remember which was which. From my analysis, AES is not used, only the command IDs got switched. 578, 57b and 57d.

author: radiolistener
author_rank: Super Contributor
timestamp: August 09, 2024, 12:33:25 pm
content: Quote from: Tunas1337 on August 09, 2024, 11:40:33 amThis is strange, here is my analysis of procedure ProcessPacket_057b at offset 0x338:Code:@ arm-none-eabi-objdump -D -b binary -marm --start-address=0x338 --stop-address=0x464 -Mforce-thumb bootloader.bintypedef struct {uint8_t u8_0; // u8 @ offset 0 // stateuint8_t IsFlashWriteEnabled; // u8 @ offset 1uint16_t ChunkNumber; // u16 @ offset 2uint16_t ChunkCount; // u16 @ offset 4uint32_t SequenceId; // u32 @ offset 8} RAM314_T;@ // WriteFlashPageReq@ ProcessPacket_057b(uint8_t* packet_ptr)00000338 <.data+0x338>:338:b5f8push{r3, r4, r5, r6, r7, lr}33a:4c46ldrr4, [pc, #280]@ (0x454) @ r4 = (uint8_t*)0x20000314; // ram0314 pointer33c:4605movr5, r0 @ r5 = r0; // r5=packet_ptr;33e:7860ldrbr0, [r4, #1] @ r0 = *(uint8_t*)&r4; // r0=ram0314->IsFlashWriteEnabled;340:2801cmpr0, #1342:d005beq.n0x350 @ if (!ram0314->IsFlashWriteEnabled) { SendPacket_057c(0, 0, 1); return; }344:2100movsr1, #0346:2201movsr2, #1348:4608movr0, r134a:f000 f899bl0x48034e:bdf8pop{r3, r4, r5, r6, r7, pc}350:7a68ldrbr0, [r5, #9] @ r0 = (uint8_t)packet_ptr; // r0=packet_ptr->chunkNumber.hi;352:7a29ldrbr1, [r5, #8] @ r1 = (uint8_t)packet_ptr; // r1=packet_ptr->chunkNumber.lo;354:0200lslsr0, r0, #8 @ r0 <<= 8;356:4308orrsr0, r1 @ r0 |= r1; // r0=packet_ptr->chunkNumber;358:d01cbeq.n0x394 @ if (r0 == 0) goto 0x394;35a:7820ldrbr0, [r4, #0] @ r0 = *(uint8_t*)&r4; // r0 = ram0314->u8_0;35c:2802cmpr0, #235e:d1f6bne.n0x34e @ if (r0 != 2) return;360:483dldrr0, [pc, #244]@ (0x458) @ r0 = (uint8_t*)0x40061000; // ???watchdog reg???362:6801ldrr1, [r0, #0] @ r1 = *(uint32_t*)r0;364:2208movsr2, #8 @ r2 = 8;366:4051eorsr1, r2 @ r1 ^= r2;368:6001strr1, [r0, #0] @ *(uint32_t*)r0 = r1;36a:7a68ldrbr0, [r5, #9] @ r0 = (uint8_t)packet_ptr;// r0=packet_ptr->chunkNumber.hi;36c:7a29ldrbr1, [r5, #8] @ r1 = (uint8_t)packet_ptr;// r1=packet_ptr->chunkNumber.lo;36e:0200lslsr0, r0, #8 @ r0 <<= 8;370:4308orrsr0, r1 @ r0 |= r1; // r0=packet_ptr->chunkNumber;372:8861ldrhr1, [r4, #2] @ r1 = &(uint16_t*)&r4; // r1 = ram0314->ChunkNumber;374:1c49addsr1, r1, #1 @ r1 += 1;376:4288cmpr0, r1378:d105bne.n0x386 @ if (r0 != r1) goto 0x386;37a:1d28addsr0, r5, #4 @ r0 = r5+4;37c:f7ff ff0ebl0x19c @ r0 = ReadUInt32LE(packet_ptr+4); // r0 = packet_ptr->sequenceId;380:68a1ldrr1, [r4, #8] @ r1 = *(uint32_t*)&r4; // r1 = ram0314->SequenceId;382:4288cmpr0, r1384:d021beq.n0x3ca @ if (r0 == r1) goto 0x3ca;386:2100movsr1, #0388:2201movsr2, #138a:4608movr0, r138c:f000 f878bl0x480 @ SendPacket_057c(0, 0, 1);390:2001movsr0, #1 @ *(uint8_t*)&r4 = 1; // ram0314->u8_0 = 1;392:e05db.n0x450 @ return;@394:1d28addsr0, r5, #4 @ r0 = r5 + 4;396:f7ff ff01bl0x19c @ r0 = ReadUInt32LE(packet_ptr+4); // r0 = packet_ptr->sequenceId;39a:60a0strr0, [r4, #8] @ *(uint32_t*)&r4 = r0; // ram0314->SequenceId = packet_ptr->sequenceId;39c:7ae8ldrbr0, [r5, #11] @ r0 = (byte)packet_ptr; // r0=packet_ptr->chunkCount.hi;39e:7aa9ldrbr1, [r5, #10] @ r1 = (byte)packet_ptr; // r0=packet_ptr->chunkCount.lo;3a0:0200lslsr0, r0, #8 @ r0 <<= 8;3a2:4308orrsr0, r1 @ r0 |= r1; // r0 = packet_ptr->chunkCount;3a4:80a0strhr0, [r4, #4] @ *(uint16_t*)&r4 = r0; // ram0314->ChunkCount = packet_ptr->chunkCount;3a6:2000movsr0, #03a8:8060strhr0, [r4, #2] @ *(uint16_t*)&r4 = 0; // ram0314->ChunkNumber = 0;3aa:2002movsr0, #23ac:7020strbr0, [r4, #0] @ *(uint8_t*)&r4 = 2; // ram0314->u8_0 = 2;3ae:2778movsr7, #120@ 0x78 @ r7 = 1203b0:b672cpsidi @ __disable_irq();3b2:2600movsr6, #0 @ r6 = 0;@ do {3b4:2001movsr0, #1 @ r0 = 1;3b6:0271lslsr1, r6, #9 @ r1 = r6 << 9; // r1 = r6 * 0x200;3b8:0300lslsr0, r0, #12 @ r0 <<= 12; // r0 = 1<<12 = 0x1000;3ba:1808addsr0, r1, r0 @ r0 = r1 + r0;3bc:f7ff ff10bl0x1e0 @ call_thumb_200000dc(0x1000 + r6 * 0x200); // erase flash page???3c0:1c76addsr6, r6, #1 @ r6 += 1;3c2:b2b6uxthr6, r6 @ r6 = (uint16_t)r6;3c4:42becmpr6, r73c6:d3f5bcc.n0x3b4 @ } while (r6 < r7)3c8:b662cpsiei @ __enable_irq();3ca:22ffmovsr2, #255@ 0xff @ r2 = 255;3cc:4629movr1, r5 @ r1 = r5;3ce:3201addsr2, #1 @ r2 += 1;3d0:3110addsr1, #16 @ r1 += 16;3d2:4822ldrr0, [pc, #136]@ (0x45c) @ r0 = (uint8_t*)0x20001124;3d4:f7ff febebl0x154 @ memcpy(0x20001124, packet_ptr->flashData, 0x100);3d8:4920ldrr1, [pc, #128]@ (0x45c) @ r1 = (uint8_t*)0x20001124;3da:2000movsr0, #0 @ r0 = 0;@ do {3dc:0082lslsr2, r0, #2 @ r2 = r0 << 2;3de:588bldrr3, [r1, r2] @ r3 = *(uint32_t*)&r1;3e0:1c40addsr0, r0, #1 @ r0 += 1;3e2:ba1brevr3, r3 @ r3 = bswap_32(r3);3e4:b280uxthr0, r0 @ r0 = (uint16_t)r0;3e6:508bstrr3, [r1, r2] @ *(uint32_t*)&r1 = r33e8:2840cmpr0, #64@ 0x403ea:d3f7bcc.n0x3dc @ } while (r0 < 64);3ec:4f1cldrr7, [pc, #112]@ (0x460) @ r7 = 0x20000F24;3ee:2600movsr6, #0 @ r6 = 0;@ do {3f0:0130lslsr0, r6, #4 @ r0 = r6 << 4;3f2:4a1aldrr2, [pc, #104]@ (0x45c) @ r2 = 0x20001124;3f4:19c1addsr1, r0, r7 @ r1 = r0 + r7;3f6:1880addsr0, r0, r2 @ r0 = r0 + r2;3f8:f7ff ff10bl0x21c @ AES_ProcessBlock128(0x20001124 + r6*16, 0x20000F24 + r6*16);3fc:1c76addsr6, r6, #1 @ r6 += 1;3fe:b2b6uxthr6, r6 @ r6 = (uint16_t)r6;400:2e10cmpr6, #16402:d3f5bcc.n0x3f0 @ } while (r6 < 16);404:2000movsr0, #0 @ r0 = 0;@ do {406:0082lslsr2, r0, #2 @ r2 = r0 << 2;408:58b9ldrr1, [r7, r2] @ r1 = *(uint32_t*)&r7;40a:1c40addsr0, r0, #1 @ r0 += 1;40c:ba09revr1, r1 @ r1 = bswap_32(r1);40e:b280uxthr0, r0 @ r0 = (uint16_t)r0;410:50b9strr1, [r7, r2] @ *(uint32_t*)&r7 = r1;412:2840cmpr0, #64@ 0x40414:d3f7bcc.n0x406 @ } while (r0 < 64);416:b672cpsidi @ __disable_irq();418:7a68ldrbr0, [r5, #9] @ r0 = (uint8_t)packet_ptr;// r0=packet_ptr->chunkNumber.hi;41a:7a29ldrbr1, [r5, #8] @ r1 = (uint8_t)packet_ptr;// r1=packet_ptr->chunkNumber.lo;41c:0200lslsr0, r0, #8 @ r0 <<= 8;41e:4308orrsr0, r1 @ r0 |= r1; // r0=packet_ptr->chunkNumber;420:0201lslsr1, r0, #8 @ r1 = r0 << 8; // r1=packet_ptr->chunkNumber * 0x100;422:2001movsr0, #1 @ r0 = 1;424:0300lslsr0, r0, #12 @ r0 <<= 12;426:1808addsr0, r1, r0 @ r0 = r1 + r0;428:2240movsr2, #64@ 0x40 @ r2 = 64;42a:490dldrr1, [pc, #52]@ (0x460) @ r1 = 0x20000F24;42c:f7ff fedebl0x1ec @ call_thumb_200001bc(0x1000 + packet_ptr->chunkNumber * 0x100, 0x20000F24, 64); // write flash page???430:b662cpsiei @ __enable_irq();432:7a68ldrbr0, [r5, #9] @ r0 = (uint8_t)packet_ptr;// r0=packet_ptr->chunkNumber.hi;434:7a2aldrbr2, [r5, #8] @ r2 = (uint8_t)packet_ptr;// r1=packet_ptr->chunkNumber.lo;436:0201lslsr1, r0, #8 @ r1 = r0 << 8;438:4311orrsr1, r2 @ r1 |= r2; // r1=packet_ptr->chunkNumber;43a:8061strhr1, [r4, #2] @ *(uint16_t*)&r4 = r1; // ram0314->ChunkNumber = packet_ptr->chunkNumber;43c:2200movsr2, #0 @ r2 = 0;43e:68a0ldrr0, [r4, #8] @ r0 = *(uint32_t*)&r4; // r0 = ram0314->SequenceId;440:f000 f81ebl0x480 @ SendPacket_057c(ram0314->SequenceId, packet_ptr->chunkNumber, 0)444:8860ldrhr0, [r4, #2] @ r0 = *(uint16_t*)&r4; // r0 = ram0314->ChunkNumber;446:88a1ldrhr1, [r4, #4] @ r1 = *(uint16_t*)&r4; // r1 = ram0314->ChunkCount;448:1c40addsr0, r0, #1 @ r0 += 1;44a:4288cmpr0, r144c:d187bne.n0x35e @ if (r0 != r1) return;44e:2003movsr0, #3 @ r0 = 3;450:7020strbr0, [r4, #0] @ *(uint8_t*)&r4 = r0; // ram0314->u8_0 = 3;452:bdf8pop{r3, r4, r5, r6, r7, pc} @ return;454:0314DCD 0x20000314456:2000458:1000DCD 0x4006100045a:400645c:1124DCD 0x2000112445e:2000460:0f24DCD 0x20000F24462:2000look at this fragment:Code:// copy flash data from packet to RAM@0x200011243d2:4822ldrr0, [pc, #136]@ (0x45c) @ r0 = (uint8_t*)0x20001124;3d4:f7ff febebl0x154 @ memcpy(0x20001124, packet_ptr->flashData, 0x100);3d8:4920ldrr1, [pc, #128]@ (0x45c) @ r1 = (uint8_t*)0x20001124;3da:2000movsr0, #0 @ r0 = 0;// reverse bytes (bswap_32) for every u32 word at RAM@0x20001124@ do {3dc:0082lslsr2, r0, #2 @ r2 = r0 << 2;3de:588bldrr3, [r1, r2] @ r3 = *(uint32_t*)&r1;3e0:1c40addsr0, r0, #1 @ r0 += 1;3e2:ba1brevr3, r3 @ r3 = bswap_32(r3);3e4:b280uxthr0, r0 @ r0 = (uint16_t)r0;3e6:508bstrr3, [r1, r2] @ *(uint32_t*)&r1 = r33e8:2840cmpr0, #64@ 0x403ea:d3f7bcc.n0x3dc @ } while (r0 < 64);3ec:4f1cldrr7, [pc, #112]@ (0x460) @ r7 = 0x20000F24;3ee:2600movsr6, #0 @ r6 = 0;// AES decrypt with 128 bit (16 bytes) blocks from RAM@0x20001124 to RAM@0x20000F24@ do {3f0:0130lslsr0, r6, #4 @ r0 = r6 << 4;3f2:4a1aldrr2, [pc, #104]@ (0x45c) @ r2 = 0x20001124;3f4:19c1addsr1, r0, r7 @ r1 = r0 + r7;3f6:1880addsr0, r0, r2 @ r0 = r0 + r2;3f8:f7ff ff10bl0x21c @ AES_ProcessBlock128(0x20001124 + r6*16, 0x20000F24 + r6*16);3fc:1c76addsr6, r6, #1 @ r6 += 1;3fe:b2b6uxthr6, r6 @ r6 = (uint16_t)r6;400:2e10cmpr6, #16402:d3f5bcc.n0x3f0 @ } while (r6 < 16);404:2000movsr0, #0 @ r0 = 0;// reverse bytes for every u32 word at RAM@0x20000F24@ do {406:0082lslsr2, r0, #2 @ r2 = r0 << 2;408:58b9ldrr1, [r7, r2] @ r1 = *(uint32_t*)&r7;40a:1c40addsr0, r0, #1 @ r0 += 1;40c:ba09revr1, r1 @ r1 = bswap_32(r1);40e:b280uxthr0, r0 @ r0 = (uint16_t)r0;410:50b9strr1, [r7, r2] @ *(uint32_t*)&r7 = r1;412:2840cmpr0, #64@ 0x40414:d3f7bcc.n0x406 @ } while (r0 < 64);// flash write decrypted data from RAM@0x20000F24416:b672cpsidi @ __disable_irq();418:7a68ldrbr0, [r5, #9] @ r0 = (uint8_t)packet_ptr;// r0=packet_ptr->chunkNumber.hi;41a:7a29ldrbr1, [r5, #8] @ r1 = (uint8_t)packet_ptr;// r1=packet_ptr->chunkNumber.lo;41c:0200lslsr0, r0, #8 @ r0 <<= 8;41e:4308orrsr0, r1 @ r0 |= r1; // r0=packet_ptr->chunkNumber;420:0201lslsr1, r0, #8 @ r1 = r0 << 8; // r1=packet_ptr->chunkNumber * 0x100;422:2001movsr0, #1 @ r0 = 1;424:0300lslsr0, r0, #12 @ r0 <<= 12;426:1808addsr0, r1, r0 @ r0 = r1 + r0;428:2240movsr2, #64@ 0x40 @ r2 = 64;42a:490dldrr1, [pc, #52]@ (0x460) @ r1 = 0x20000F24;42c:f7ff fedebl0x1ec @ call_thumb_200001bc(0x1000 + packet_ptr->chunkNumber * 0x100, 0x20000F24, 64); // write flash page???430:b662cpsiei @ __enable_irq();As you can see it definitely uses AES decryption...Did you tried it?I suspect it will write broken firmware image if you upload it with a new packet 0x057b with no AES encryption. So the radio won't boot.There is need to encrypt flash image with AES CBC. But we need to generate the key in the same way as DP32G030 doing it. But I'm not sure - what happens when you initialize AES module with key and IV in mode 1 (keygen)?Does it just encrypt a buffer with zeros or how does it get the key?I need test result for known key and IV to understand what it doing exactly.Maybe there is an answer in the DP32G030 datasheet, but it is in Chinese, so it's hard to find something...I'm ready to make test version of k5tool to upload firmware with using AES encryption on bootloader 5, but I'm not sure if my assumption is correct that DP32G030 AES module just encrypts zeros to generate new key. If my assumption is incorrect, it may generate wrong key and brick the radio.This is why it will be great if someone can upload test code under debugger and dump the key result for known key, iv pair. It will helps to test the code before testing it on the real radio.Unfortunately I don't have UV-K5 with bootloader 5 and asking someone with version 5 to try upload with test code may lead to brick with high probability and asking to test different code changes may take too long time. So, I want to make sure that I see all things, before propose to test upload firmware on v5.

author: eXisten
author_rank: Contributor
timestamp: August 09, 2024, 01:25:22 pm
content: QuoteTake a look 5 posts above - it might be useful...?

author: zrq
author_rank: Frequent Contributor
timestamp: August 09, 2024, 09:47:06 pm
content: AES_CR: AES control registerAES_SR: AES state registerAES_DINR: AES data input registerAES_DOUTR: AES data output registerAES_KEYR?: AES key register ?AES_IVR?: AES IV register?Let me know if there is anything else I can help as a native speaker. I can translate the section 5.25 of the datasheet in the weekend if it helps.Quote from: radiolistener on August 09, 2024, 04:59:11 am

author: radiolistener
author_rank: Super Contributor
timestamp: August 09, 2024, 11:19:25 pm
content: Quote from: eXisten on August 09, 2024, 01:25:22 pmThanks, what I'm looking for is "Key derivation" procedure. Unfortunately the datasheet just explain the sequence on how to do it with hardware AES module. This sequence is already reconstructed from the code.The question is how hardware AES module generates the key (generation algorithm).In order to generate it on PC, I need to know how it works in the hardware. But unfortunately the datasheet don't explain this...There are different AES KDF (Key Derivation Function) exists, but they all are not a part of AES standard and it's unknown which one is used in DP32G030 hardware AES module.So, this is where I stuck.In other words, here is the code which generates key on hardware AES module:Code:uint8_t key = ...;uint8_t iv = ...;AES_Init(1, key, iv);uint8_t key2;AES_GenerateDerivedKey(key2);Original (key, iv) pair is known. But I don't know how to generate key2 on PC, because this is done on DP32G030 hardware AES module and I don't have ability to test it.If you can run this code on DP32G030 and share some test vectors (inputkey,ivand outputkey2content), it will help a lot.The functions source code is here:Code:#define AES_BASE 0x400BD000#define AES_CR (*(volatile uint32_t *)(AES_BASE + 0x0000))#define AES_SR (*(volatile uint32_t *)(AES_BASE + 0x0004))#define AES_KEYR0 (*(volatile uint32_t *)(AES_BASE + 0x0010))#define AES_KEYR1 (*(volatile uint32_t *)(AES_BASE + 0x0014))#define AES_KEYR2 (*(volatile uint32_t *)(AES_BASE + 0x0018))#define AES_KEYR3 (*(volatile uint32_t *)(AES_BASE + 0x001C))#define AES_IVR0 (*(volatile uint32_t *)(AES_BASE + 0x0020))#define AES_IVR1 (*(volatile uint32_t *)(AES_BASE + 0x0024))#define AES_IVR2 (*(volatile uint32_t *)(AES_BASE + 0x0028))#define AES_IVR3 (*(volatile uint32_t *)(AES_BASE + 0x002C))#define AES_CR_EN (1 << 0)#define AES_CR_CHMOD_CBC (1 << 5)#define AES_CR_CCFC (1 << 7)#define AES_SR_CCF (1 << 0)void AES_Init(uint32_t mode, uint32_t* key, uint32_t* iv) {AES_CR &= ~AES_CR_EN;AES_CR = (mode << 3) | AES_CR_CHMOD_CBC;AES_KEYR3 = key;AES_KEYR2 = key;AES_KEYR1 = key;AES_KEYR0 = key;AES_IVR3 = iv;AES_IVR2 = iv;AES_IVR1 = iv;AES_IVR0 = iv;AES_CR |= AES_CR_EN;}void AES_GenerateDerivedKey(uint32_t* buffer) {while ((AES_SR & AES_SR_CCF)==0) { }buffer = AES_KEYR3;buffer = AES_KEYR2;buffer = AES_KEYR1;buffer = AES_KEYR0;AES_CR |= AES_CR_CCFC;}Unfortunately I don't have radio with bootloader 5 to test it. And don't have configured environment to use in-circuit debugging to run the test code and get test vector with known (key,iv) pair and generated key result, it can help to implement proper encryption. I bought second UV-K5 for experiments, but got broken one with damaged serial port, now things are going worse and I don't have ability to buy a new one.PS: if someone tried to update firmware with a new packet id=0x057b but without AES encrypted image and the radio is bricked. Let me know, I can provide you with several encrypted firmware images for testing, it can help to unbrick the radio and helps to get proper way to generate AES key.Also if someone has a dump with bootloader v2, please share it. Since I have radio with bootloader v2, I'm interesting to play with its bootloader.

author: radiolistener
author_rank: Super Contributor
timestamp: August 09, 2024, 11:34:52 pm
content: Also if someone has access to in-circuit debugging and if it will be hard to reconstruct the algorithm of key generation used in hardware, we can get pre-computed keys for (key,iv) pairs in bootloader 5 and use pre-computed keys on PC to encrypt the firmware image. There is needs access to DP32G030 debugger to get pre-computed keys.

author: radiolistener
author_rank: Super Contributor
timestamp: August 10, 2024, 01:04:39 am
content: In short, currently there is need the dump of key2 for this code executed on DP32G030:Code:uint8_t key = { 0xe1,0x6e,0x0d,0x29,0xe0,0xc8,0x34,0x18,0x98,0x7f,0x94,0x33,0xf5,0xff,0x62,0x0e }; // key 00uint8_t iv = { 0x14,0xb7,0xa2,0xbe,0x02,0x23,0xe2,0x59,0xb2,0x06,0x6d,0x88,0x86,0x97,0x7e,0x36 }; // iv 00AES_Init(1, key, iv);uint8_t key2;AES_KDF(key2);// ***dump of key2 needed***// ===functions code===#define AES_BASE 0x400BD000#define AES_CR (*(volatile uint32_t *)(AES_BASE + 0x0000))#define AES_SR (*(volatile uint32_t *)(AES_BASE + 0x0004))#define AES_KEYR0 (*(volatile uint32_t *)(AES_BASE + 0x0010))#define AES_KEYR1 (*(volatile uint32_t *)(AES_BASE + 0x0014))#define AES_KEYR2 (*(volatile uint32_t *)(AES_BASE + 0x0018))#define AES_KEYR3 (*(volatile uint32_t *)(AES_BASE + 0x001C))#define AES_IVR0 (*(volatile uint32_t *)(AES_BASE + 0x0020))#define AES_IVR1 (*(volatile uint32_t *)(AES_BASE + 0x0024))#define AES_IVR2 (*(volatile uint32_t *)(AES_BASE + 0x0028))#define AES_IVR3 (*(volatile uint32_t *)(AES_BASE + 0x002C))#define AES_CR_EN (1 << 0)#define AES_CR_CHMOD_CBC (1 << 5)#define AES_CR_CCFC (1 << 7)#define AES_SR_CCF (1 << 0)void AES_Init(uint32_t mode, uint32_t* key, uint32_t* iv) {AES_CR &= ~AES_CR_EN;AES_CR = (mode << 3) | AES_CR_CHMOD_CBC;AES_KEYR3 = key;AES_KEYR2 = key;AES_KEYR1 = key;AES_KEYR0 = key;AES_IVR3 = iv;AES_IVR2 = iv;AES_IVR1 = iv;AES_IVR0 = iv;AES_CR |= AES_CR_EN;}void AES_KDF(uint32_t* buffer) {while ((AES_SR & AES_SR_CCF)==0) { }buffer = AES_KEYR3;buffer = AES_KEYR2;buffer = AES_KEYR1;buffer = AES_KEYR0;AES_CR |= AES_CR_CCFC;}This dump is pre-computed key for keyNumber=0, which can be used to encrypt firmware for bootloader v5.It allows to implement upload firmware with bootloader v5.Can someone help to obtain that dump?

author: ruslik064
author_rank: Contributor
timestamp: August 10, 2024, 05:44:55 am
content: As an option. Rewrite the bootloader code to output keys and upload it to the station. I haven't heard of a debugger for dp32g030. We can upload a corrected boot to the station if necessary. And the bootv2 dump is freely available on the Internet.

author: radiolistener
author_rank: Super Contributor
timestamp: August 10, 2024, 06:35:37 am
content: it can be executed as a part of custom firmware and print 16 hex values on the display, but I don't have working environment to compile it and test. So, if someone working on custom firmware it will not be so hard to test it.Getting this pre-computed key allows to use existing bootloader v5.Here is updated test code, I added calculation for decrypt test vector, I need dump of thesekey2anddataarray content, it allows to test all things offline.Code:uint8_t key = { 0xe1,0x6e,0x0d,0x29,0xe0,0xc8,0x34,0x18,0x98,0x7f,0x94,0x33,0xf5,0xff,0x62,0x0e }; // key 00uint8_t iv = { 0x14,0xb7,0xa2,0xbe,0x02,0x23,0xe2,0x59,0xb2,0x06,0x6d,0x88,0x86,0x97,0x7e,0x36 }; // iv 00AES_Init(1, key, iv);uint8_t key2;AES_KDF(key2);// *** dump 16 bytes from key2 array ***AES_Init(2, key2, iv);uint8_t data;AES_ProcessBlock128(key, data);// ***dump 16 bytes from data array***// ===functions code===#define AES_BASE 0x400BD000#define AES_CR (*(volatile uint32_t *)(AES_BASE + 0x0000))#define AES_SR (*(volatile uint32_t *)(AES_BASE + 0x0004))#define AES_DINR (*(volatile uint32_t *)(AES_BASE + 0x0008))#define AES_DOUTR (*(volatile uint32_t *)(AES_BASE + 0x000C))#define AES_KEYR0 (*(volatile uint32_t *)(AES_BASE + 0x0010))#define AES_KEYR1 (*(volatile uint32_t *)(AES_BASE + 0x0014))#define AES_KEYR2 (*(volatile uint32_t *)(AES_BASE + 0x0018))#define AES_KEYR3 (*(volatile uint32_t *)(AES_BASE + 0x001C))#define AES_IVR0 (*(volatile uint32_t *)(AES_BASE + 0x0020))#define AES_IVR1 (*(volatile uint32_t *)(AES_BASE + 0x0024))#define AES_IVR2 (*(volatile uint32_t *)(AES_BASE + 0x0028))#define AES_IVR3 (*(volatile uint32_t *)(AES_BASE + 0x002C))#define AES_CR_EN (1 << 0)#define AES_CR_CHMOD_CBC (1 << 5)#define AES_CR_CCFC (1 << 7)#define AES_SR_CCF (1 << 0)void AES_Init(uint32_t mode, uint32_t* key, uint32_t* iv) {AES_CR &= ~AES_CR_EN;AES_CR = (mode << 3) | AES_CR_CHMOD_CBC;AES_KEYR3 = key;AES_KEYR2 = key;AES_KEYR1 = key;AES_KEYR0 = key;AES_IVR3 = iv;AES_IVR2 = iv;AES_IVR1 = iv;AES_IVR0 = iv;AES_CR |= AES_CR_EN;}void AES_KDF(uint32_t* buffer) {while ((AES_SR & AES_SR_CCF)==0) { }buffer = AES_KEYR3;buffer = AES_KEYR2;buffer = AES_KEYR1;buffer = AES_KEYR0;AES_CR |= AES_CR_CCFC;}void AES_ProcessBlock128(uint32_t* src, uint32_t* dst) {AES_DINR = src;AES_DINR = src;AES_DINR = src;AES_DINR = src;while ((AES_SR & AES_SR_CCF)==0) { }dst = AES_DOUTR;dst = AES_DOUTR;dst = AES_DOUTR;dst = AES_DOUTR;AES_CR |= AES_CR_CCFC;}PS: The new K5TOOL code with support for bootloader v5 protocol is almost complete. I will commit it soon on github.The only thing that needs to be implemented is to add pre-computed key and test it on decrypt test vector to make sure that all things works the same as on MCU.

author: radiolistener
author_rank: Super Contributor
timestamp: August 10, 2024, 07:56:15 am
content: Quote from: ruslik064 on August 10, 2024, 05:44:55 amJustfound. I have no idea why I didn't seen it before, because this site in my favorite list and I downloaded firmware from itNow I'm going to play with bootloader v2

author: radiolistener
author_rank: Super Contributor
timestamp: August 10, 2024, 11:51:56 pm
content: Just compared bootloader v2 code with bootloader v5 and can confirm my previous analysis is correct, there are 2 significant difference:1) setVersion packet for v5 has additional code to initialize AES key2) writeFlash packet for v5 has additional code which apply AES decrypt before flashing the dataAs I said before, I stuck with key generation algorithm which is used in bootloader v5, it uses KDF function of hardware AES module. There is need to find the algorithm which is used for KDF in DP32G030 AES module. Alternative solution is to use pre-computed key. Both ways need to run a test code on the MCU (see code in my previous messages).It can be done on any UV-K5 radio with OpenOCD or with custom made firmware.Currently I have no ready to use environment with custom firmware and didn't tried to use SWD. If someone can help to run the test code on DP32G030 and get the result dump it helps to add support for bootloader v5 in flasher tools.I have ST-LINKv2, can someone help with info on proper connect to SWD pins of UV-K5 and configs for DP32G030?I found some message on internet that pin 2=SWDIO and pin 3=SWCLK, is this correct?

author: ruslik064
author_rank: Contributor
timestamp: August 11, 2024, 06:43:30 am
content: Yeah 1-3.3.v 2-io 3-clk 4-gnd

author: ruslik064
author_rank: Contributor
timestamp: August 13, 2024, 11:29:31 am
content: As I understand, to run this code through Openocd, need to convert it to the Openocd config file format. And there the code differs from standard C.

author: radiolistener
author_rank: Super Contributor
timestamp: August 13, 2024, 11:46:23 am
content: Quote from: ruslik064 on August 13, 2024, 11:29:31 amI didn't worked with openocd yet, so I cannot help with it.Technically I have st-linkv2 which I using for stm32 and I have uv-k5, so I can do it myself, but it needs time to get all things together and configure it.Quote from: ruslik064 on August 13, 2024, 11:29:31 amthe test code should be compiled with C compiler with no issue. Which line is problematic?

author: ruslik064
author_rank: Contributor
timestamp: August 13, 2024, 12:00:29 pm
content: I haven't tried compiling the code. I meant that as I see it, the essence of the code is pure work with the controller registers. This can be done through openocd using its commands. Only the format of the configuration file is a little unclear to me in the area of ​​describing variables. For example, look at the openocd config for uvk5 on github. There are some commands describing the algorithm for recording, for example, a microcontroller.

author: ruslik064
author_rank: Contributor
timestamp: August 13, 2024, 12:06:11 pm
content: I made a test stand with openocd and a connected board.

author: radiolistener
author_rank: Super Contributor
timestamp: August 13, 2024, 12:13:16 pm
content: Quote from: ruslik064 on August 13, 2024, 12:00:29 pmtechnically yes you can try to do it from debugger with no code compilation, but I'm not sure if it can properly process loading accelerator registers.Quote from: ruslik064 on August 13, 2024, 12:00:29 pmCan you give the link?

author: ruslik064
author_rank: Contributor
timestamp: August 13, 2024, 12:17:05 pm
content: still there

author: ruslik064
author_rank: Contributor
timestamp: August 16, 2024, 11:50:32 am
content: 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. 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.

author: radiolistener
author_rank: Super Contributor
timestamp: August 16, 2024, 08:12:43 pm
content: Quote from: ruslik064 on August 16, 2024, 11:50:32 amdid you called AES_Init?Maybe there is needs to enable clock for AES module in SYSCON.Try this:Code: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.Quote from: ruslik064 on August 16, 2024, 11:50:32 amNo, it looks like UART1 init:Code:@ arm-none-eabi-objdump -D -b binary -marm --start-address=0x628 --stop-address=0x6cd -Mforce-thumb bootloader.bin628:b510push{r4, lr}62a:2001movsr0, #162c:0780lslsr0, r0, #3062e:6881ldrr1, [r0, #8]630:2280movsr2, #128@ 0x80632:4311orrsr1, r2634:6081strr1, [r0, #8]636:4c1cldrr4, [pc, #112]@ (0x6a8) @ r4 = 0x4006B800 // UART1_CTRL638:6820ldrr0, [r4, #0]63a:0840lsrsr0, r0, #163c:0040lslsr0, r0, #163e:6020strr0, [r4, #0]640:481aldrr0, [pc, #104]@ (0x6ac) @ r0 = 0x40000040 // 0x40000040+0x38=0x40000078642:6b81ldrr1, [r0, #56]@ 0x38 @ r1 = SYSCON->RC_FREQ_DELTA;644:4a1aldrr2, [pc, #104]@ (0x6b0) @ r2 = 0x02DC6C00646:0048lslsr0, r1, #1648:0b00lsrsr0, r0, #1264a:0fc9lsrsr1, r1, #3164c:d001beq.n0x65264e:1880addsr0, r0, r2650:e000b.n0x654652:1a10subsr0, r2, r0654:4917ldrr1, [pc, #92]@ (0x6b4) @ r1 = 0x0000988D656:f7ff fd67bl0x12865a:6060strr0, [r4, #4]65c:200emovsr0, #1465e:6020strr0, [r4, #0]660:2004movsr0, #4662:6220strr0, [r4, #32]664:2200movsr2, #0666:61e2strr2, [r4, #28]668:20c7movsr0, #199@ 0xc766a:61a0strr0, [r4, #24]66c:6122strr2, [r4, #16]66e:4812ldrr0, [pc, #72]@ (0x6b8) @ r0 = 0x40001000 // DMA_CTR670:6801ldrr1, [r0, #0]672:0849lsrsr1, r1, #1674:0049lslsr1, r1, #1676:6001strr1, [r0, #0]678:4b0bldrr3, [pc, #44]@ (0x6a8)67a:4910ldrr1, [pc, #64]@ (0x6bc) @ r1 = 0x40001100 // DMA_CH0CTR67c:330caddsr3, #1267e:608bstrr3, [r1, #8]680:4b0fldrr3, [pc, #60]@ (0x6c0) @ r3 = 0x20000324682:60cbstrr3, [r1, #12]684:23ffmovsr3, #255@ 0xff686:3311addsr3, #17688:604bstrr3, [r1, #4]68a:6042strr2, [r0, #4]68c:4a0dldrr2, [pc, #52]@ (0x6c4) @ r2 = 0x00000F0F68e:6082strr2, [r0, #8]690:4a0dldrr2, [pc, #52]@ (0x6c8) @ r2 = 0x00006FFF692:600astrr2, [r1, #0]694:2120movsr1, #32696:6161strr1, [r4, #20]698:6802ldrr2, [r0, #0]69a:2101movsr1, #169c:430aorrsr2, r169e:6002strr2, [r0, #0]6a0:6820ldrr0, [r4, #0]6a2:4308orrsr0, r16a4:6020strr0, [r4, #0]6a6:bd10pop{r4, pc}6a8:b800DCD 0x4006B8006aa:40066ac:0040DCD 0x400000406ae:40006b0:6c00 DCD 0x02DC6C006b2:02dc6b4:988dDCD 0x0000988D6b6:00006b8:1000DCD 0x400010006ba:40006bc:1100 DCD 0x400011006be:40006c0:0324 DCD 0x200003246c2:20006c4:0f0f DCD 0x00000F0F6c6:00006c8:6fff DCD 0x00006FFF6ca:0000

author: radiolistener
author_rank: Super Contributor
timestamp: August 16, 2024, 09:52:47 pm
content: here is some identified functions in the bootloader 5:Code:address => identified function0x154 => memcpy(void *dest, const void *src, size_t n)0x19c => ReadUInt32LE(uint8_t* pdata)0x1e0 => erase flash page?0x1ec => write flash page?0x21c => AES_ProcessBlock128(uint32_t* src, uint32_t* dst);0x254 => AES_KDF(uint8_t* buffer) // fill buffer with a new key0x27c => ProcessPacket() // process received packet0x2a8 => ProcessPacket_057d(uint8_t* packet_ptr) // setFlashVersionReq0x30c => ProcessPacket_0578(uint8_t* packet_ptr) // writeNvramReq?0x338 => ProcessPacket_057b(uint8_t* packet_ptr) // writeFlashPageReq0x480 => SendPacket_057c(uint32_t sequenceId, uint16_t chunkNumber, uint8_t errorCode) // writeFlashPageAck0x4f0 => AES_Init(uint32_t mode, uint32_t* key, uint32_t* iv) // mode: 0=encrypt;1=kdf;2=decrypt;3=kdf&decrypt0x818 => UartSendBuffer(uint8_t* buffer, uint32_t length) // send raw buffer0x838 => SendPacket(byte* buffer, int length) // encrypt, envelope and send packetRAM at offset 0x20000314 structure:Code:typedef struct {uint8_t State; // u8 @ offset 0uint8_t IsFlashWriteEnabled; // u8 @ offset 1uint16_t ChunkNumber; // u16 @ offset 2uint16_t ChunkCount; // u16 @ offset 4uint32_t SequenceId; // u32 @ offset 8} RAM314_T;

author: ruslik064
author_rank: Contributor
timestamp: August 19, 2024, 11:44:51 am
content: I wrote this function in the debugger.Code: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 modeset status [read_memory 0x400BD000 32 1]echo [format "read cr register after gate set and set mode %08b." $status]write_memory 0x400BD01c 32 0xe16e0d29 ;#keyr3write_memory 0x400BD018 32 0xe0c83418 ;#keyr2write_memory 0x400BD014 32 0x987f9433 ;#keyr1write_memory 0x400BD010 32 0xf5ff620e ;#keyr0write_memory 0x400BD02c 32 0x14b7a2be ;#iv3write_memory 0x400BD028 32 0x0223e259 ;#iv2write_memory 0x400BD024 32 0xb2066d88 ;#iv1write_memory 0x400BD020 32 0x86977e36 ;#iv0set 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:[DP32G0xx.cpu] halted due to debug-request, current mode: Handler HardFaultxPSR: 0xc1000003 pc: 0xfffffffe msp: 0xffffffd8read 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 connectionsInfo : Listening on port 4444 for telnet connectionsHere 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.

author: radiolistener
author_rank: Super Contributor
timestamp: August 19, 2024, 02:05:36 pm
content: Quote from: ruslik064 on August 19, 2024, 11:44:51 amyes, it is useful, but needs time to extract data into usable format.Quote from: ruslik064 on August 19, 2024, 11:44:51 amyes,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.Quote from: ruslik064 on August 19, 2024, 11:44:51 amQuote from: ruslik064 on August 19, 2024, 11:44:51 amYes, 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:@ arm-none-eabi-objdump -D -b binary -marm --start-address=0x904 --stop-address=0x9e4 -Mforce-thumb bootloader.binbootloader.bin: file format binaryDisassembly of section .data:00000904 <.data+0x904>:904:b5f8push{r3, r4, r5, r6, r7, lr}906:f7ff ffd7bl0x8b890a:482aldrr0, [pc, #168]@ (0x9b4) @ r0 = 0x1800008590c:0781lslsr1, r0, #30 @ r1 = (uint8_t*)0x40000000; // SYSCON90e:6088strr0, [r1, #8] @ *(uint32_t*)&r1 = 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 fe6cbl0x5ec @ call_05ec(); // init PORTCON (PORTB_SEL1 &= 0xF0FF0FFF; etc)914:f7ff fe4ebl0x5b4 @ call_05b4(); // init GPIO output state918:f7ff fe42bl0x5a0 @ call_05a0(); // init CRC91c:f7ff fe84bl0x628 @ call_0628(); // init UART1920:4825ldrr0, [pc, #148]@ (0x9b8) @ r0 = 0x20001324922:f7ff fe19bl0x558 @ call_0558(r0); // fill buffer (r0) with SYSCON_CHIP_ID0-3926:4825ldrr0, [pc, #148]@ (0x9bc) @ r0 = 0x40060000 // GPIOA928:6800ldrr0, [r0, #0]92a:4c25ldrr4, [pc, #148]@ (0x9c0) @ r4 = 0x40061000 // GPIOC92c:06c0lslsr0, r0, #2792e:0f80lsrsr0, r0, #30930:4f24ldrr7, [pc, #144]@ (0x9c4) @ r7 = 0x00030D40932:4d25ldrr5, [pc, #148]@ (0x9c8) @ r5 = 0x20000314 // ram0314 pointer934:2803cmpr0, #3936:d10cbne.n0x952 @ if (ram0314->u8_0 != 3) goto 0x952;938:6820ldrr0, [r4, #0]93a:0680lslsr0, r0, #2693c:d409bmi.n0x95293e:4638movr0, r7940:f7ff fdf8bl0x534 @ call_0534() // ??? nops944:6820ldrr0, [r4, #0]946:0680lslsr0, r0, #26948:d403bmi.n0x95294a:2001movsr0, #194c:7028strbr0, [r5, #0]94e:2008movsr0, #8950:6020strr0, [r4, #0]952:210cmovsr1, #12954:481dldrr0, [pc, #116]@ (0x9cc) @ r0 = 0x00000BF0; // "5.00.01"956:f7ff ff5fbl0x818 @ UartSendBuffer(r0);95a:2102movsr1, #295c:a01caddr0, pc, #112@ (adr r0, 0x9d0) @ r0 = 0x09d0; // "\r\n"95e:f7ff ff5bbl0x818 @ UartSendBuffer(r0);962:7828ldrbr0, [r5, #0]964:4e1bldrr6, [pc, #108]@ (0x9d4) @ r6 = 0x000186A0966:2801cmpr0, #1968:d111bne.n0x98e96a:f7ff feafbl0x6cc @ call_06cc() // probably receive the raw packet, decypt and extract from envelope96e:2800cmpr0, #0970:d101bne.n0x976972:f7ff fc83bl0x27c @ ProcessPacket()976:7828ldrbr0, [r5, #0]978:2801cmpr0, #197a:d00fbeq.n0x99c97c:2802cmpr0, #297e:d014beq.n0x9aa980:2803cmpr0, #3982:d1f2bne.n0x96a984:2000movsr0, #0986:6020strr0, [r4, #0]988:4813ldrr0, [pc, #76]@ (0x9d8) @ r0 = 0x000493E098a:f7ff fdd3bl0x53498e:4630movr0, r6990:f7ff fdd0bl0x534994:f7ff fc3cbl0x210998:2000movsr0, #099a:bdf8pop{r3, r4, r5, r6, r7, pc}99c:4638movr0, r799e:f7ff fdc9bl0x5349a2:f7ff fd7dbl0x4a09a6:4630movr0, r69a8:e000b.n0x9ac9aa:480cldrr0, [pc, #48]@ (0x9dc) @ r0 = 0x000027109ac:f7ff fdc2bl0x5349b0:e7dbb.n0x96a9b2:0000movsr0, r09b4:0085DCD 0x180000859b6:18009b8:1324DCD 0x200013249ba:20009bc:0000DCD 0x400600009be:40069c0:1000DCD 0x400610009c2:40069c4:0d40DCD 0x00030D409c6:00039c8:0314DCD 0x200003149ca:20009cc:0bf0DCD 0x00000BF09ce:00009d0:0a0d.asciz "\r\n"9d2:0000.byte 09d4:86a0DCD 0x000186A09d6:00019d8:93e0DCD 0x000493E09da:00049dc:2710DCD 0x000027109de:00009e0:6c169e2:e614At a glance *(*uint32_t*)0x40000008 = 0x18000085; isCode: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.

author: radiolistener
author_rank: Super Contributor
timestamp: August 19, 2024, 02:12:34 pm
content: 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:proc test_aes {} {# Stack initreg sp 0x20001738 ;# value taken from bootloader 5 vector table# Clocks initwrite_memory 0x40000008 32 {0x18000085} ;# AES, CRC, UART1, GPIOC, GPIOA clocks enabledset dev_clk_gate [read_memory 0x40000008 32 1]echo [format "DEV_CLK_GATE set: 0x%08x." $dev_clk_gate]# Fill key and iv bufferswrite_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 1reg r1 0x20000000 ;# Address of the keyreg r2 0x20000010 ;# Address of the IVreg pc 0x4f0resumeecho "AES_Init(1, key, iv) completed..."# call 0x254 => AES_KDF(key2);reg r0 0x20000020 ;# Address for the key2reg pc 0x254resumeecho "AES_KDF(key2) completed..."# Dump 16 bytes from the key2 arrayecho "Dump key2:"# dump_image key2_dump.bin 0x20000020 16mdw 0x20000020 4# call 0x4f0 => AES_Init(2, key2, iv);reg r0 2reg r1 0x20000020 ;# Address of the key2reg r2 0x20000010 ;# Address of the IVreg pc 0x4f0resumeecho "AES_Init(2, key2, iv) completed..."# call 0x21c => AES_ProcessBlock128(key, data);reg r0 0x20000000 ;# Address of the original keyreg r1 0x20000030 ;# Address for the encrypted datareg pc 0x21cresumeecho "AES_ProcessBlock128(key, data) completed..."# Dump 16 bytes from the data arrayecho "Dump data:"# dump_image data_dump.bin 0x20000030 16mdw 0x20000030 4dump_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:void testCode() {SYSCON_DEV_CLK_GATE = AES_CLK_GATE | CRC_CLK_GATE | UART1_CLK_GATE | GPIOC_CLK_GATE | GPIOA_CLK_GATE;uint8_t key = { 0xe1,0x6e,0x0d,0x29,0xe0,0xc8,0x34,0x18,0x98,0x7f,0x94,0x33,0xf5,0xff,0x62,0x0e }; // key 00uint8_t iv = { 0x14,0xb7,0xa2,0xbe,0x02,0x23,0xe2,0x59,0xb2,0x06,0x6d,0x88,0x86,0x97,0x7e,0x36 }; // iv 00AES_Init(1, key, iv); // r0=1;r1=key;r2=iv;bl 0x4f0uint8_t key2;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 0x4f0uint8_t data;AES_ProcessBlock128(key, data); // r0=key;r1=data;bl 0x21c// ***dump 16 bytes from data array***}

author: ruslik064
author_rank: Contributor
timestamp: August 21, 2024, 10:33:09 am
content: 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.

author: radiolistener
author_rank: Super Contributor
timestamp: August 21, 2024, 11:02:56 am
content: Quote from: ruslik064 on August 21, 2024, 10:33:09 amI 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?Quote from: ruslik064 on August 21, 2024, 10:33:09 amprobably swd pins are disabled in bootloader v5 at startup, but then its interesting question how it was obtained from the chip

author: ruslik064
author_rank: Contributor
timestamp: August 21, 2024, 11:23:31 am
content: QuoteGot 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:set_reg {r0 1}set_reg {r1 0x20000000} ;# Address of the keyset_reg {r2 0x20000010} ;# Address of the IVset_reg {pc 0x4f0}resumeecho "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.htmldescription

author: radiolistener
author_rank: Super Contributor
timestamp: August 21, 2024, 11:56:29 am
content: Quote from: ruslik064 on August 21, 2024, 11:23:31 amis it works on a radio with bootloader v5?Here is fixed script, does it works?Code:proc test_aes {} {# Stack initset_reg { sp 0x20001738 } ;# value taken from bootloader 5 vector table# Clocks initwrite_memory 0x40000008 32 {0x18000085} ;# AES, CRC, UART1, GPIOC, GPIOA clocks enabledset dev_clk_gate [read_memory 0x40000008 32 1]echo [format "DEV_CLK_GATE set: 0x%08x." $dev_clk_gate]# Fill key and iv bufferswrite_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 keyset_reg { r2 0x20000010 } ;# Address of the IVset_reg { pc 0x4f0 }resumeecho "AES_Init(1, key, iv) completed..."# call 0x254 => AES_KDF(key2);set_reg { r0 0x20000020 } ;# Address for the key2set_reg { pc 0x254 }resumeecho "AES_KDF(key2) completed..."# Dump 16 bytes from the key2 arrayecho "Dump key2:"mdw 0x20000020 4# call 0x4f0 => AES_Init(2, key2, iv);set_reg { r0 2 }set_reg { r1 0x20000020 } ;# Address of the key2set_reg { r2 0x20000010 } ;# Address of the IVset_reg { pc 0x4f0 }resumeecho "AES_Init(2, key2, iv) completed..."# call 0x21c => AES_ProcessBlock128(key, data);set_reg { r0 0x20000000 } ;# Address of the original keyset_reg { r1 0x20000030 } ;# Address for the encrypted dataset_reg { pc 0x21c }resumeecho "AES_ProcessBlock128(key, data) completed..."# Dump 16 bytes from the data arrayecho "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}

author: ruslik064
author_rank: Contributor
timestamp: August 21, 2024, 12:07:01 pm
content: 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

author: radiolistener
author_rank: Super Contributor
timestamp: August 21, 2024, 01:46:43 pm
content: 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:proc test_aes {} {# Stack initset_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 0x240x20 0x43 0x18 0x60 0x08 0x68 0xD8 0x61 0x48 0x68 0x98 0x61 0x88 0x68 0x58 0x610xC8 0x68 0x18 0x61 0x10 0x68 0xD8 0x62 0x50 0x68 0x98 0x62 0x90 0x68 0x58 0x620xD0 0x68 0x18 0x62 0x18 0x68 0x01 0x21 0x08 0x43 0x18 0x60 0x10 0xBD 0x00 0x000x00 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 0x680x90 0x60 0x50 0x68 0xC0 0x07 0xFC 0xD0 0xD0 0x68 0x08 0x60 0xD0 0x68 0x48 0x600xD0 0x68 0x88 0x60 0xD0 0x68 0xC8 0x60 0x10 0x68 0x80 0x21 0x08 0x43 0x10 0x600x70 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 0x600x4A 0x69 0x82 0x60 0x0A 0x69 0xC2 0x60 0x08 0x68 0x80 0x22 0x10 0x43 0x08 0x600x70 0x47 0x00 0x00 0x00 0xD0 0x0B 0x40}# Clocks initwrite_memory 0x40000008 32 {0x18000085} ;# AES, CRC, UART1, GPIOC, GPIOA clocks enabledset dev_clk_gate [read_memory 0x40000008 32 1]echo [format "DEV_CLK_GATE set: 0x%08x." $dev_clk_gate]# Fill key and iv bufferswrite_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 keyset_reg { r2 0x20000010 } ;# Address of the IVset_reg { pc 0x200004f0 }resumeecho "AES_Init(1, key, iv) completed..."# call 0x254 => AES_KDF(key2);set_reg { r0 0x20000020 } ;# Address for the key2set_reg { pc 0x20000254 }resumeecho "AES_KDF(key2) completed..."# Dump 16 bytes from the key2 arrayecho "Dump key2:"mdw 0x20000020 4# call 0x4f0 => AES_Init(2, key2, iv);set_reg { r0 2 }set_reg { r1 0x20000020 } ;# Address of the key2set_reg { r2 0x20000010 } ;# Address of the IVset_reg { pc 0x200004f0 }resumeecho "AES_Init(2, key2, iv) completed..."# call 0x21c => AES_ProcessBlock128(key, data);set_reg { r0 0x20000000 } ;# Address of the original keyset_reg { r1 0x20000030 } ;# Address for the encrypted dataset_reg { pc 0x2000021c }resumeecho "AES_ProcessBlock128(key, data) completed..."# Dump 16 bytes from the data arrayecho "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 64echo "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: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.

author: radiolistener
author_rank: Super Contributor
timestamp: August 21, 2024, 05:05:37 pm
content: just installed openocd and tested it on STM32G431.Previous script has mistake, it don't wait for procedure exit.Here is fixed script:Code:proc callSub {addr} {bp 0x00000000 2 hwreg lr 0x00000001reg pc $addrresumewait_haltrbp 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 0x240x20 0x43 0x18 0x60 0x08 0x68 0xD8 0x61 0x48 0x68 0x98 0x61 0x88 0x68 0x58 0x610xC8 0x68 0x18 0x61 0x10 0x68 0xD8 0x62 0x50 0x68 0x98 0x62 0x90 0x68 0x58 0x620xD0 0x68 0x18 0x62 0x18 0x68 0x01 0x21 0x08 0x43 0x18 0x60 0x10 0xBD 0x00 0x000x00 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 0x680x90 0x60 0x50 0x68 0xC0 0x07 0xFC 0xD0 0xD0 0x68 0x08 0x60 0xD0 0x68 0x48 0x600xD0 0x68 0x88 0x60 0xD0 0x68 0xC8 0x60 0x10 0x68 0x80 0x21 0x08 0x43 0x10 0x600x70 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 0x600x4A 0x69 0x82 0x60 0x0A 0x69 0xC2 0x60 0x08 0x68 0x80 0x22 0x10 0x43 0x08 0x600x70 0x47 0x00 0x00 0x00 0xD0 0x0B 0x40}# Stack initset_reg { sp 0x20001738 } ;# value taken from bootloader 5 vector table# Clocks initwrite_memory 0x40000008 32 {0x18000085} ;# AES, CRC, UART1, GPIOC, GPIOA clocks enabledset dev_clk_gate [read_memory 0x40000008 32 1]echo [format "DEV_CLK_GATE set: 0x%08x." $dev_clk_gate]# Fill key and iv bufferswrite_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 keyset_reg { r2 0x20000010 } ;# Address of the IVcallSub 0x200004f0echo "AES_Init(1, key, iv) completed..."# call 0x254 => AES_KDF(key2);set_reg { r0 0x20000020 } ;# Address for the key2callSub 0x20000254echo "AES_KDF(key2) completed..."# Dump 16 bytes from the key2 arrayset 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 key2set_reg { r2 0x20000010 } ;# Address of the IVcallSub 0x200004f0echo "AES_Init(2, key2, iv) completed..."# call 0x21c => AES_ProcessBlock128(key, data);set_reg { r0 0x20000000 } ;# Address of the original keyset_reg { r1 0x20000030 } ;# Address for the encrypted datacallSub 0x2000021cecho "AES_ProcessBlock128(key, data) completed..."# Dump 16 bytes from the data arrayset 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 64echo "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.

author: radiolistener
author_rank: Super Contributor
timestamp: August 21, 2024, 08:56:23 pm
content: 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?

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 06:11:57 am
content: I took openocd from here as a basishttps://github.com/Lar-Sen/Quansheng_UV-K5_Kitchen/tree/main/unbrick-toolkit

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 06:25:22 am
content: something happenedCode:[DP32G0xx.cpu] halted due to debug-request, current mode: ThreadxPSR: 0x21000000 pc: 0x00000412 msp: 0x200015c0DEV_CLK_GATE set: 0x18000085.[DP32G0xx.cpu] halted due to breakpoint, current mode: ThreadxPSR: 0x01000000 pc: 00000000 msp: 0x20001738AES_Init(1, key, iv) completed...[DP32G0xx.cpu] halted due to breakpoint, current mode: ThreadxPSR: 0x01000000 pc: 00000000 msp: 0x20001738AES_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: ThreadxPSR: 0x01000000 pc: 00000000 msp: 0x20001738AES_Init(2, key2, iv) completed...[DP32G0xx.cpu] halted due to breakpoint, current mode: ThreadxPSR: 0x01000000 pc: 00000000 msp: 0x20001738AES_ProcessBlock128(key, data) completed...Dump data: 0xbb 0xda 0xd9 0xde 0x1b 0xa1 0x8b 0x2e 0xa8 0x88 0x3b 0xbc 0xa0 0xfc 0x75 0x6fFull dump (key,iv,key2,data) to full_dump.bin...Doneran with v2 bootloader.but I think this is wrong. or just dump data is read from the same place as key2

author: radiolistener
author_rank: Super Contributor
timestamp: August 22, 2024, 07:03:30 am
content: Quote from: ruslik064 on August 22, 2024, 06:25:22 amThanks. At a glance looks good, as expected.Quote from: ruslik064 on August 22, 2024, 06:25:22 amI 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:set dumpData [read_memory 0x20000020 8 16]should beCode: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:28 B8 03 BF 42 AA C4 B9 EC 38 39 3F 35 15 A7 9EHere is fixed script:Code:proc callSub {addr} {bp 0x00000000 2 hwreg lr 0x00000001reg pc $addrresumewait_haltrbp 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 0x240x20 0x43 0x18 0x60 0x08 0x68 0xD8 0x61 0x48 0x68 0x98 0x61 0x88 0x68 0x58 0x610xC8 0x68 0x18 0x61 0x10 0x68 0xD8 0x62 0x50 0x68 0x98 0x62 0x90 0x68 0x58 0x620xD0 0x68 0x18 0x62 0x18 0x68 0x01 0x21 0x08 0x43 0x18 0x60 0x10 0xBD 0x00 0x000x00 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 0x680x90 0x60 0x50 0x68 0xC0 0x07 0xFC 0xD0 0xD0 0x68 0x08 0x60 0xD0 0x68 0x48 0x600xD0 0x68 0x88 0x60 0xD0 0x68 0xC8 0x60 0x10 0x68 0x80 0x21 0x08 0x43 0x10 0x600x70 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 0x600x4A 0x69 0x82 0x60 0x0A 0x69 0xC2 0x60 0x08 0x68 0x80 0x22 0x10 0x43 0x08 0x600x70 0x47 0x00 0x00 0x00 0xD0 0x0B 0x40}# Stack initset_reg { sp 0x20001738 } ;# value taken from bootloader 5 vector table# Clocks initwrite_memory 0x40000008 32 {0x18000085} ;# AES, CRC, UART1, GPIOC, GPIOA clocks enabledset dev_clk_gate [read_memory 0x40000008 32 1]echo [format "DEV_CLK_GATE set: 0x%08x." $dev_clk_gate]# Fill key and iv bufferswrite_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 keyset_reg { r2 0x20000010 } ;# Address of the IVcallSub 0x200004f0echo "AES_Init(1, key, iv) completed..."# call 0x254 => AES_KDF(key2);set_reg { r0 0x20000020 } ;# Address for the key2callSub 0x20000254echo "AES_KDF(key2) completed..."# Dump 16 bytes from the key2 arrayset 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 key2set_reg { r2 0x20000010 } ;# Address of the IVcallSub 0x200004f0echo "AES_Init(2, key2, iv) completed..."# call 0x21c => AES_ProcessBlock128(key, data);set_reg { r0 0x20000000 } ;# Address of the original keyset_reg { r1 0x20000030 } ;# Address for the encrypted datacallSub 0x2000021cecho "AES_ProcessBlock128(key, data) completed..."# Dump 16 bytes from the data arrayset 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 64echo "Done"}it should printCode:28 B8 03 BF 42 AA C4 B9 EC 38 39 3F 35 15 A7 9EIt 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.

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 07:05:42 am
content: Well, the script error doesn't affect the final dump then. Ok, let's wait for news. If you need anything, I'm here.

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 07:14:12 am
content: 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.

author: radiolistener
author_rank: Super Contributor
timestamp: August 22, 2024, 09:00:15 am
content: Something strange here with AES module on dp32g030.Here is input vectors:Code:key=bbdad9de1ba18b2ea8883bbca0fc756fiv= 14b7a2be0223e259b2066d8886977e36cipher=e16e0d29e0c83418987f9433f5ff620edp32g030 AES module decrypt produce this output:Code:plain=28b803bf42aac4b9ec38393f3515a79eBut proper AES-128 CBC should beCode:plain=ae91cade4b788b1f5bbd5bc72767d792May 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?

author: radiolistener
author_rank: Super Contributor
timestamp: August 22, 2024, 09:24:42 am
content: Quote from: ruslik064 on August 22, 2024, 06:11:57 amI'm tried the same configs, but unfortunately it don't detects chip on my UV-K5:Code:Open On-Chip Debugger 0.12.0Licensed under GNU GPL v2For bug reports, readhttp://openocd.org/doc/doxygen/bugs.htmlInfo : 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/SWDInfo : clock speed 960 kHzInfo : STLINK V2J37S7 (API v2) VID:PID 0483:3748Info : Target voltage: 3.217930Error: 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.

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 09:34:02 am
content: 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.

author: radiolistener
author_rank: Super Contributor
timestamp: August 22, 2024, 09:43:42 am
content: Quote from: ruslik064 on August 22, 2024, 09:34:02 amYeah, 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.

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 10:16:13 am
content: 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.

author: darkspr1te
author_rank: Frequent Contributor
timestamp: August 22, 2024, 10:22:11 am
content: I also have been reversing this in ghidra,attached are some of my findingsdarkspr1te

author: radiolistener
author_rank: Super Contributor
timestamp: August 22, 2024, 11:35:43 am
content: 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.

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 12:08:21 pm
content: As far as I understood from the manual, you need to write data into the data register 4 times in a row.QuoteIn general, all of this needs to be translated.

author: radiolistener
author_rank: Super Contributor
timestamp: August 22, 2024, 12:38:09 pm
content: It appears that AES_Init and AES_Process128 functions working with data where each 32-bit word is reversed (reversed byte order).So, this is the reason why ProcessPacket_057b() doing byte reverse for every 32-bit word before decrypt and after decrypt.According to my tests, mode 0 works as classic AES-128 CBC encrypt and mode 3 works as classic AES-128 CBC decrypt.But bootloader v5 uses mode 2 for decrypt. Previously I thought that this is classic AES-128 CBC decrypt, but it isn't. It don't match to AES-128 CBC decrypt and and don't match to AES-128 CBC encrypt. I'm not sure what is this mode and how it works?

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 01:16:22 pm
content: This?Quote Encryption/decryption using the AES Rijndael block cipher algorithm

author: radiolistener
author_rank: Super Contributor
timestamp: August 22, 2024, 01:43:09 pm
content: Quote from: ruslik064 on August 22, 2024, 01:16:22 pmYes. When configured to use CBC:00: Mode 1: Encryption => Works as classic AES-128 CBC encryption11: Mode 4: Key derivation + decryption => Works as classic AES-128 CBC decryption10: Mode 3: Decryption => the results is different than AES-128 CBC. What is this?Here is example vector for "10: Mode 3: Decryption" (all data has 32-bit words with reversed bytes):key: 00000000000000000000000000000000iv: 00000000000000000000000000000000plain: 00000000000000000000000000000000cipher: EFA4AA0CE22B35957B4C88B24429146Awhile classic AES-128 CBC decryption should produce this vector:key: 00000000000000000000000000000000iv: 00000000000000000000000000000000plain: 00000000000000000000000000000000cipher: 100F0F143D22B511177758793AECD9FF

author: radiolistener
author_rank: Super Contributor
timestamp: August 22, 2024, 02:22:45 pm
content: Preliminary using mode 1 (kdf) and then mode 2 (decrypt) is the same as using mode 3 (kdf+decrypt)...It passed some test cases, but needs to test it more deep.If this true, then it simply uses usual AES-128 CBC with reversed bytes in 32-bit words, with nothing unusual.Pair (key,iv) for decrytpion and encryption is taken from bootloader table by it's number.And since ProcessPacket_057b already has byte order reverse before and after decryption, there is no need to reverse byte order. Just encrypt firmware with classic AES-128 CBC.So, it looks like implementing firmware encryption is pretty easy, but needs to check all things more deep.

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 02:37:57 pm
content: If necessary, I can test the flash on the 5th boot. Without fear of killing the station. I can always flash it with a programmer.

author: radiolistener
author_rank: Super Contributor
timestamp: August 22, 2024, 05:15:28 pm
content: Quote from: ruslik064 on August 22, 2024, 02:37:57 pmThanks, here is test version for bootloader v5.I tested it on simulator, but still not sure that there is no mistake.I added confirmation on startup, it needs to type "yes" in console, otherwise it will exit.WARNING: this is a test version of K5TOOL which is never tested on bootloader v5.There is a high risk to brick the radio. Don't use it if you don't understand the risk and don't understand how to restore radio!UPDATE: it seems there is mistake in this test version, so I removed it to avoid unwanted further bricks. See discussion below.

author: darkspr1te
author_rank: Frequent Contributor
timestamp: August 22, 2024, 06:46:58 pm
content: @radiolistenerI have a pre v5 bootloader, can i flash via swd the v5 and is there any thing i need to back up ?i've not opened my radio yet by I enjoy arm debugging and have already broken the aes128 for ActSafety A600 (software aes128 based on stm's DFU aes at chip release)and autophix OM127 aes128 ( based on cm aes date unknown )so i want to have a crack at re writing this bootloader,darkspr1te

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 06:57:07 pm
content: I'll test it tomorrow. But explain what to give it to boot? I have a dump of 5 firmware. Or are we trying to upload, for example, fagci?

author: ruslik064
author_rank: Contributor
timestamp: August 22, 2024, 07:23:34 pm
content: QuoteDon't do anything yet. You need to understand if what is written works. It's not worth risking without having recovery methods. The path we've taken is long. Don't torture yourself yet. The dump taken from the station and the beginning of this topic took a lot of time. You shouldn't kill your stations if you don't understand what you're doing.QuoteYou can, but it's unlikely that you'll come back)

author: radiolistener
author_rank: Super Contributor
timestamp: August 22, 2024, 07:55:27 pm
content: Quote from: ruslik064 on August 22, 2024, 06:57:07 pmI think anything that can work. If custom firmware don't works due to some config/nvram compatibility issue, you can flash firmware v5, the tool supports raw firmware format with command -wrflashraw, but there is no crc check for raw firmware, so if you use -wrflashraw, then make sure you're using correct image (in plain format as is, with no encryption and no version header).Since there is version check in the bootloader, you're needs to specify * or 5 as version parameter, otherwise bootloader v5 will not accept the firmware.So, if you try to flash custom firmware from packed image with version 2 in the header, the bootloader v5 will reject it.It needs to unpack the firmware and then use -wrflashraw with manual version 5 or * parameter.

author: ruslik064
author_rank: Contributor
timestamp: August 23, 2024, 06:57:57 am
content: Programming on 5 bootloader is successful. But the station does not start. I read the dump after programming, there is a mess.Quote

author: ruslik064
author_rank: Contributor
timestamp: August 23, 2024, 07:08:30 am
content: Are we trying to upload a clean, unencrypted aes dump to the station? Is the dump encrypted before flashing?

author: radiolistener
author_rank: Super Contributor
timestamp: August 23, 2024, 10:26:54 am
content: hm... yes, if you see "Using ProtocolV5", it sends encrypted firmware. But there is possible mistake with byte order for keys, because there is mess with byte order and word order in bootloader code. But at a glance it should be ok according to my tests with openocd.I'm not sure why output ends at 1b00..1c00. It should be ef00..f000.Is this is a full output?Can you read firmware dump with openocd? Does it match with image which you upload?If yes, and it ends with ef00..f000 and Done message, then upload firmware looks good.There is also possible incompatibility with eeprom/nvram content which can block firmware from running.But I think more likely cause is possible mistake with encryption. In this case decrypt will produce random bytes and firmware will not work.There is need to get flash content to understand what is actually going on and analyze it.We can try to play with different byte order for keys, but it's better to get the dump and analyze it.Can you share the firmware image which was used to upload and firmware dump taken with openocd?It should help to identify where is mistake and fix it.Currently I suspect that there is no need to reverse bytes in the keys, but needs to check it. The firmware dump from the radio can give the answer.

author: ruslik064
author_rank: Contributor
timestamp: August 23, 2024, 01:28:58 pm
content: this is not a complete output. everything ends normally. (done). i read the dump after the firmware but unfortunately i left on business. i will post it as soon as i can.

author: ruslik064
author_rank: Contributor
timestamp: August 26, 2024, 06:37:02 am
content: The archive contains a dump of firmware 5 and a dump taken after flashing with the new k5tool.

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2024, 07:40:21 am
content: Good. Can you share also the dump of your bootloader v5?

author: ruslik064
author_rank: Contributor
timestamp: August 26, 2024, 07:44:27 am
content: The dump is the same as the one posted on the UB4C network.

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2024, 08:08:28 am
content: Found mistake. It appears that there is mistyping in the code and k5tool actually didn't do byte reverse for the key.And this is the reason why it fails...Preliminary fixed version should works ok. Will be ready soon.

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2024, 08:52:52 am
content: Try this one. It should work ok.Also try to upload firmware v2 to the radio with bootloader v5, is it works?

author: ruslik064
author_rank: Contributor
timestamp: August 26, 2024, 09:12:48 am
content: Yes, it works. Raw format firmwares are flashed without problems.

author: ruslik064
author_rank: Contributor
timestamp: August 26, 2024, 09:18:23 am
content: I tried to flash unpacked v2 and fagci. But as I said v2 does not start on new stations. There will be a zebra on the screen.

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2024, 09:27:31 am
content: Does fagci works?

author: ruslik064
author_rank: Contributor
timestamp: August 26, 2024, 09:29:31 am
content: yes fagci works

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2024, 09:47:06 am
content: just released K5TOOL v1.8 with support for bootloader v5.https://github.com/qrp73/K5TOOL/releases

author: ftg
author_rank: Frequent Contributor
timestamp: August 26, 2024, 01:56:45 pm
content: Quote from: radiolistener on August 26, 2024, 09:47:06 amGreat work!I'll test this with my V5 radio later today to confirm.

author: eXisten
author_rank: Contributor
timestamp: August 26, 2024, 06:53:16 pm
content: Yes, Great work!Now, if I unpackedegzumer_v0.22.bintoegzumer_v0.22.raw(saved exactly like that), can I safely try to upload the software to the device?If I have copies of my_calibration.bin and my_config.bin, will I be able to revert to the original version in the same way?

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2024, 07:09:40 pm
content: Quote from: eXisten on August 26, 2024, 06:53:16 pmegzumer firmware uses * for version, so there is no need to unpack it, you can flash it as is with command -wrflash.Unpack is needed for original firmware, because it has version which will not be accepted by bootloader.You can specify version manually for unpacked firmware image to bypass bootloader version check.But since original firmware depends on NVR content, you cannot run original firmware v2 on v5.So, this operation useless with no NVR change.Quote from: eXisten on August 26, 2024, 06:53:16 pmjust run when the radio is powered on:Code:./k5tool -rdeeit will save full eeprom backup toeeprom-0000-2000.raw, save this file if you want to revert all configuration and calibrations back.

author: eXisten
author_rank: Contributor
timestamp: August 26, 2024, 07:15:04 pm
content: Yes! It works!Thanks for the great work guys!

author: radiolistener
author_rank: Super Contributor
timestamp: August 26, 2024, 07:29:12 pm
content: If you want to revert back to the stock v5, here is packed stock firmware v5.00.05:

author: eXisten
author_rank: Contributor
timestamp: August 26, 2024, 07:42:46 pm
content: Once again - many thanks!

author: Tumsk
author_rank: Newbie
timestamp: August 28, 2024, 09:01:49 pm
content: Great work guys, I just received one of the 2nd generation UV5R Plus units with the v5.00.01 bootloader and v5.00.05 factory firmware.It's got a 2024 serial number.It's factory marked as 8w output on the radio label but <= 5W in the manual.A USB-C charging port is present (and there is a reference to an on-screen USB charging icon in the manual, but I do not see it on the LCD).USB-C port does not support USB-C PD charging (or QC3.0), so it still needs a standard dumb USB charge port to charge at c. 4.7WThe battery is labelled as 3800mAh but also labelled 15.84Wh (which would make it 2200mAh) so I'm doubtful about real capacity.Factory firmware updater v1.1.12 does not support the radio. Factory CPS 1.0.38 appear to support this radio.So nothing obvious to suggest any hardware change that would warrant a new major boot/firmware revision.With the eeprom read and the file stored safely away. Thanks to your hard work, I'll be flashing my favourite firmware tomorrow!

author: adisapta
author_rank: Newbie
timestamp: August 29, 2024, 04:35:24 pm
content: it works !!...Thanks a lot...appreciate your hard work....btw, I've 2nd generation UV5R Plus unit with the v5.00.01 bootloader and v5.00.05 factory firmware with USB charging portNow have IJV on it...once again... big thanks... !!

author: Chris79
author_rank: Newbie
timestamp: September 04, 2024, 11:53:33 am
content: I can confirm it's working fine for me too.Thanks to all that figured it out.I flashed F4HWN 3.3 onto my new UV-5R plus this morning using K5Tool v1.8 on my Raspberry Pi 5 and copied all data onto it from another K5 using Chirp.

author: onurhan
author_rank: Newbie
timestamp: October 10, 2024, 11:10:26 am
content: Hi, everyoneUsing Flash Mode;While I'm doing the operation, I get the following error on the command line. Can you help?Opening COM8Handshake... InvalidOperationException: Unexpected response Packet5FlashBeaconAck {HdrSize=32Version="5.00.01"K0=0x02030201K1=0x334a530cK2=0x0dff434dK3=0x00a3006f}Using Normal Mode;k5tool -port COM8 -helloOpening COM8Handshake...Firmware: "5.00.03"HasCustomAesKey: 0IsPasswordLocked: 0Using ProtocolV2...Done

author: radiolistener
author_rank: Super Contributor
timestamp: October 10, 2024, 11:20:09 am
content: Quote from: onurhan on October 10, 2024, 11:10:26 amIf you have carefully read the README, to perform the firmware update, you need to put the radio intofirmware update mode. This is done by disconnecting the cable, turning off the radio, then turning it on while holding the PTT button. After that, connect the cable and run the update command.It is also important to note that thefirmware update modeis intendedonly for updating the firmware, all other operations, including reading/writing the EEPROM, should be done in thenormal mode.The firmware update will not work if the radio is powered on in normal mode, in this case, the error will be displayed.The same, if you attempt to perform any operation other than the firmware update while radio is in firmware update mode, it will result to an error, as in your case. Such operations must be performed when the radio is powered on in normal mode.Firmware update mode == for firmware opdate command only!Normal mode == for all other commands

author: onurhan
author_rank: Newbie
timestamp: October 10, 2024, 11:31:34 am
content: Hello;Yes, the device is in firmware mode. I turn it on by pressing the PTT button, then I plug in the cable and the light on it is constantly on. But I still have the problem I posted.

author: onurhan
author_rank: Newbie
timestamp: October 10, 2024, 11:32:14 am
content: Using Normal Mode (not firmware mode);k5tool -port COM8 -helloOpening COM8Handshake...Firmware: "5.00.03"HasCustomAesKey: 0IsPasswordLocked: 0Using ProtocolV2...Done

author: radiolistener
author_rank: Super Contributor
timestamp: October 10, 2024, 11:33:44 am
content: Quote from: onurhan on October 10, 2024, 11:31:34 amThe error you posted indicates that you're attempting to execute a non-firmware update command while the radio is still in firmware update mode. This is not the correct usage.Quote from: onurhan on October 10, 2024, 11:32:14 amYes, this is expected behavior for normal mode. hello command is intended just to show the firmware version.What operation you want to do?

author: onurhan
author_rank: Newbie
timestamp: October 10, 2024, 11:37:12 am
content: I would be very happy if you could write me exactly how I should do it. Thank you for everything.

author: radiolistener
author_rank: Super Contributor
timestamp: October 10, 2024, 11:44:05 am
content: Quote from: onurhan on October 10, 2024, 11:37:12 amYour screenshot shows that you're trying to execute the -hello command while the radio is in firmware update mode. As I mentioned earlier, only the firmware update command can be executed in this mode, all other commands (include -hello) will not work and should not be used in this mode.This error is expected behavior because you execute -hello command in firmware update mode. This command should be executed in normal mode.Could you explain what you want to do?If you want to update firmware, you need to execute-wrflashcommand, NOT-hello.For example:Code:k5tool -port COM8 -wrflash <your firmware file>Replace <your firmware file> with filename of your firmware.But before firmware update I strongly recommend to backup EEPROM dump, it should be executed in normal mode.So your steps to update firmware are following:1) download firmware file which you want to upload. Note that you have v5 boot, so old official firmware will not work. But custom firmware will works.2) Switch to normal mode: disconnect the cable, power off and then power on the radio, connect the cable again3) execute EEPROM backup command:Code:k5tool -port COM8 -rdeeit will saveeeprom-0000-2000.rawwith backup, store this backup file, it may need in future if you want to restore your radio.4) Switch to firmware update mode: disconnect the cable, power off and then power on the radio with pressed PTT button, connect the cable again5) execute firmware update command:Code:k5tool -port COM8 -wrflash <your firmware file>Here is video with manual:

author: onurhan
author_rank: Newbie
timestamp: October 10, 2024, 12:21:56 pm
content: That's great. Thank you very much for everything. It worked and I was able to update the firmware.

author: edo76mal
author_rank: Newbie
timestamp: November 15, 2024, 10:56:11 am
content: Hi.Is it possible to download from radio the bootloader, writing an extension of K5Tool?

author: radiolistener
author_rank: Super Contributor
timestamp: November 16, 2024, 05:17:05 pm
content: Quote from: edo76mal on November 15, 2024, 10:56:11 amNo, there is no code in bootloader which allows to download firmware from radio to PC.

author: NeilP
author_rank: Contributor
timestamp: December 01, 2024, 04:45:31 pm
content: Is there any news on this ?I am just waiting my new one to be delivered. Tracking says it is in the UK, but not seen it yet.Just trying to see if it is possible to run k5prog and k5tool on my peppermint Linux laptop ? so far have only found the Windows exe file for k5progCould run it on a mac too..but I ty and avoid windows!

author: ftg
author_rank: Frequent Contributor
timestamp: December 02, 2024, 08:41:53 am
content: Original k5prog was and is linux only, k5prog-win is a separate software.And K5TOOL worked fine on linux for me.

author: radiolistener
author_rank: Super Contributor
timestamp: December 03, 2024, 01:17:18 am
content: Quote from: NeilP on December 01, 2024, 04:45:31 pmYes you can run it on Linux, on MacOS and on Windows..net apps historically is stored in exe files, on linux you can run it with mono.Just install mono runtime:Code:sudo apt install mono-runtimeK5TOOL includes bash script k5tool to run it on linux and macos. it should works transparently on any system, just use ./k5tool on linux/macos instead of k5tool.exe. In case of need you can put it in the apps folder and run it anywhere with k5tool command.

author: gicko
author_rank: Newbie
timestamp: October 09, 2025, 11:46:08 pm
content: I goted UV K5 With new chipFW Version: firmware version: '1.02.01' This is not work with egzumer and bricked while flashing.I found fw and recovery.I have problem with calibration.How to fix these.Calibration from my old UV k5 will not work.Simplex channels RX working.Repeater channels not working.TX is work(Repeater back sound)Have the problem.I Not have the modulation only repeater backThanks for answer regardsfirmware version: '1.02.01'has custom AES key: nois in lock screen: nochallenge: 3E BC 89 5C

author: radiolistener
author_rank: Super Contributor
timestamp: October 10, 2025, 12:43:40 am
content: Quote from: gicko on October 09, 2025, 11:46:08 pmFirmware 1.02.01 belongs to the new UV-K5 hardware revision, which uses a different MCU. You can identify these stations by the “v2” mark on the label under the battery.This version is supported by k5tool, but you can only flash firmware made specifically for UV-K5-v2. Currently, the original factory firmware is the only one known to work.Flashing any firmware built for the older UV-K5 (non-v2) will brick the radio, since those are not compatible with the new processor.If your radio is already bricked, you need to restore it using one of the original firmware for this "v2" revision from attachment - use-wrflashcommand (unzip before flashing).In this v2 hardware revision, EEPROM writing is blocked, most likely to prevent users from flashing calibration or configuration data from older firmware versions, since the internal data layout has changed.As far as I know, the v2 revision is only a temporary model, and a v3 version is expected to follow. Because of that, the number of v2 units on the market will likely remain small, so it’s unlikely that many custom firmware projects or mods will appear for it.

author: ermionesrl
author_rank: Contributor
timestamp: October 10, 2025, 03:24:31 pm
content: Unfortunately I just bought a second K5 and it arrived with V2 hardware...At least I was lucky with the first :|However I just found this site:https://github.com/muzkr/k5_fw1The firmware in this repository is a port of DualTachyon's code for both V1 & V2 hardwares.I plan to try it.