Support for DLink M32 Mesh System and R32 Router

I can test some combinations on the weekend. GPL code is currently not available. I asked them to provide it but they asked me to call a number in the US to clarify this topic as far as I remember.

Based on the length, it could be MD5. I calculated MD5 for all strings I found in all partitions of the firmware dump and also in the decrypted OEM firmware. None of them matches the firmware key.

Flashing via recovery web interface is now working on my device, no need to open the device anymore for switching to OpenWrt.

One question regarding the build: I have a TFTP image which contains the padded kernel and the rootfs filesystem. For the recovery image, I need basically the same but with a header in the beginning. I tried to use append-image in the image rule, but it looks like the TFTP image is built after the recovery image, so append-image will not use the latest TFTP image for appending. In case there is no TFTP image from the previous build, the build will fail. Is there a better solution for that?
The changes to get it working can be seen here:

But from my point of view, it's not a good solution to have redundant rules for creating similar images.
Maybe anybody knows how to specify the order in which the images are built or can give me other advice.

GPL code is now available at D-Link

1 Like

Were you able to download it? I only get

<Message>The specified key does not exist.</Message>

I downloaded it from the German site, but strange that it is a different file name on german site: M32_sw_reva_GPLcode.tar.gz

I had a short look in the GPL sources:

  • There are keys in BPI-R2/meta-myproject/recipes-dlink/imgcrypto/files/919251a1_dlink-fw-encdec-keys-native.tar.gz/git/M32
    • Key.firmware and are identical to the one I extracted from my device
    • Key.pri differs from the one I have. So I assume the private key in the router is used for something different. As the public keys are the same, I think it will work when using the private key from the GPL package. The also provided the passphrase for the key:
      openssl dgst -sign Key.pri --passin pass:wrpd -sha512 -binary -out Sig1.bin FWdgst.bin which seems to work as expected
      The GPL code contains the private keys and firmware keys for about 50 models from D-Link, maybe this will help in future
1 Like

Oh wow, I just happened to find your M32 release on github while looking for your latest build of COVR-X1860. So I found this thread and see that we basically did the same work on this device, even roughly around the same time (I started in March, but eventually fixed Ethernet settings around July).

Reminds me of Discourse "saved searches" plugin?

Is there anything you still need about this device? My last state was that I did not have a factory image, since I did not fully understand the inner format of the factory image. How did you find all the specs of the headers, e.g. the byte sum and xor of the 16bytes AMIT-Split Header? Was anything contained in the GPL release that I did not find (I think there was not even a GPL release when I started).
I found this by mere reverse engineering with ghidra :innocent:

What's the current state of your work, is there any use in pushing my (dirty) branch anymore?

By the way, I also own the R32, which is the same Mediatek-based platform from Amit, unlike the other EAGLE AI devices from the series, that are based on Realtek chips.

Currently I'm working on a tool to create firmware images which can be flashed in the recovery and the OEM firmware interface. Recovery already looks quite good, the factory image is WIP but didn't invest a lot of time in it.
I'm also able to decrypt the OEM firmware images, they can be used to revert to stock firmware.
I created a pull request for basic device support:

As soon as I'm done with the image encryption, I'll try to create another pull request.

Yes, GPL code for this device was published quite late. Ghidra and ChatGPT helped me to understand what is happening :smiley:

Awesome, I think my last state of progress was only tested successfully when using initramfs, I didn't have much time / nerves afterwards to look deeper into this, but great to see that some progress is made here :slightly_smiling_face: I probably can't help much either in terms of factory image, but I will build this by the start of next week and try it on my device, thanks for your work!

When your PR gets merged, I can also try to add R32 which should be very similar (technically just a few more Gigabit ports), we could have a shared .dtsi for both devices eventually.

1 Like

I'm no able to decrypt an OEM image which results in an image which can be used in recovery mode.
Other way around, I'm also able to create the OEM image from the factory image again.
The code is still messy and needs some cleanup, but it's working in general.

1 Like

Awesome, so they left the private key in the GPL release again? :innocent:
Last thing I remember is, I was able to AES decrypt it, but would have needed the private key to actually create an image, also the inner format (DLK6E...) was unknown to me, but later turned out to be the same as in some DGS-1210 switches if I recall correctly (though those are made by Cameo, not AMIT).

I have been thinking about making a standalone encryption/decryption tool (with a user-friendly GUI) for D-Link devices for a while now, since many users cannot even recover their devices with firmware provided by D-Link, when the bootloader requires the unencrypted recovery image.

Great to see we now have another range of D-Link devices solved here, not sure if it would ever make it into OpenWrt though.

I will dig out my R32 next week, they can probably share a .dtsi.
Besides, I own a few of the Realtek based ones, especially the M15 (which I only purchased to have a look at the encryption, while waiting for M32 to be delivered, which was delayed again and again :innocent: )
The realtek ones also have the ODM partition (even made a little parser in Python for the TLV-like format, starting somewhere at 0x20 in the file), but I think these chips will not be relevant for OpenWrt anytime soon.

Besides, I'm also thrilled about the Bluetooth capabilities, someone in our Freifunk community mentioned the idea of using the Apple Find My Network as a telemetry backup for gluon nodes that are offline for unknown reasons (e.g. trigger a reboot etc.), but we need more MT7622 based devices inthe market first :slightly_smiling_face:

the private key for signing the images including the pass phrase are included in the GPL sources.

See also Support for DLink M32 Mesh System - #48 by RolandoMagico

Update: I compared the keys for M32 and R32, they are the same. So the tool should also work with R32. I tried decrypting R32A1_FW103B01.bin which worked without any errors. The resulting file also look valid.


  • Compile the sources (there migth be some deprecated warnings depending on the used OpenSSL version):
    gcc m32-firmware-util.c -lcrypto -o m32-firmware-util

  • Decrypt the image:
    ./m32-firmware-util M32 --DecryptFactoryImage R32A1_FW103B01.bin R32A1_FW103B01_decrypted.bin

  • Encrypt the image:
    ./m32-firmware-util M32 --CreateFactoryImage R32A1_FW103B01_decrypted.bin R32A1_FW103B01_encrypted.bin

Not that the re-encrypted image will differ from the original image because of the used IV and Salt (currently I'm using a fixed values for testing)

A web interface where this can be done would be great, but no clue how to implement somthing like that.

Strange behavior today after flashing a new image to the device. In the wireless settings, all modules are shown as "Generic Unknown":

Scanning for networks is also not possible. But after enabling the AP, the correct devices are shown again:

Also did a factory reset and downgraded to previous versions. Same result. Not sure whats wrong here.

Also tried building an OpenWrt factory image. Building the image works but flashing does not yet work:

process_method_post_file: total_length 14025897, BUFF_SIZE_1 16384
Upload filename="openwrt-mediatek-mt7622-dlink_eagle-pro-ai-m32-a1-squashfs-factory.bin" (Stage: 4)
Save BIN files to /tmp/fw.bin
open /tmp/fw.bin for write data
Enter GetFirmwareValidation_put
FW(/tmp/fw.bin) is checking, please wait...
open_upgbuf: flags.secid=0x0
check_upgbuf: System build on Apr 14 2023 03:35:25
checking header!
check_upgbuf: get full upgrade header!
header_id mis-match: (0x530a: 0x4842)
1397:HEADER boot=0x0000, atf=0x0000, p_section=0x0000, kernel=0x0000, ui=0x0000, roootfs=0x0000, config=0x0000, mydlink=0x0000, signature=0x0000
1401:FW boot=0x0000, atf=0x0000, p_section=0x0000, kernel=0x0000, ui=0x0000, roootfs=0x0000, config=0x0000, mydlink=0x0000, signature=0x0000
Firmware checking result: failed
check_file:189:Check firmware error(-101)
[  221.989644] sh (10308): drop_caches: 1
==      Pre-Check        ==
Found input file, continue.
Found public Key, continue.
Found Firmware Key, continue.
== Split FW.enc and Sig2 ==
Output: /tmp/IV_and_FWenc.bin, /tmp/Sig2.bin
==  Verify Signature2    ==
Output: /tmp/FWencdgst.bin
verify sinature....
verify failed in Sig2
[dlink_led][ERROR] : SIGTERM
process_GetFirmwareValidation_action:174, dec fw failed

I also cannot decrypt the created factory image:

EVP_DigestVerifyFinal failed
4097A986E27F0000:error:0200006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01:../crypto/rsa/rsa_pk1.c:82:
4097A986E27F0000:error:02000072:rsa routines:rsa_ossl_public_decrypt:padding check failed:../crypto/rsa/rsa_ossl.c:598:
4097A986E27F0000:error:1C880004:Provider routines:rsa_verify:RSA lib:../providers/implementations/signature/rsa_sig.c:774:
Verification of IVandFWenc failed

Seems like my tool doesn't do something as expected :frowning:

Appending 4 bytes to the image before encryption seems to fix the poblem, maybe something related to padding implementation. With the new image, there is a new issue during flashing:

FW(/tmp/FW.bin) is checking, please wait...
open_upgbuf: flags.secid=0x0
check_upgbuf: System build on Apr 14 2023 03:35:25
checking header!
check_upgbuf: get full upgrade header!
 enter icksum UPGHEADER_HLEN=80
 chksum=0xffff headerchk=0x6362
 header: major_version = 0x02,minjor_version = 0x00
 family_member = (F)6E60 vs (T)6E60
 ROM_ID = (F)DLK6E6010001 vs (T)DLK6E6010001
upg_check_header:image info: ichksum=0x33cf es=0x002c0000 el=0x02d00000 do=0x002c0000 dl=0x00d60000 io=0x00000000, s_id=0x08
check_upgbuf:image info: ichksum=0x33cf es=0x002c0000 el=0x02d00000 do=0x002c0000 dl=0x00d60000 io=0x00000000, s_id=0x08
image check ERROR! checksum=0x89b2
1397:HEADER boot=0x0000, atf=0x0000, p_section=0x0000, kernel=0x0000, ui=0x0000, roootfs=0x33cf, config=0x0000, mydlink=0x0000, signature=0x0000
1401:FW boot=0x0000, atf=0x0000, p_section=0x0000, kernel=0x0000, ui=0x0000, roootfs=0x89b2, config=0x0000, mydlink=0x0000, signature=0x0000
Image Rootfs check failed
Firmware checking result: failed

Awesome, thanks :innocent: I couldn't find it at first, was probably looking at a different path.
I'm not sure these are all devices built by AMIT, e.g. the DAP series business access points could be either from Alpha Networks or Edimax. So this really looks like there should be a tool for all of them, I had started something in Python a while ago, but not much to show yet (it was intended to be more like a library for working with binary images and header components, like an abstract model for a firmware format, which is then evaluated by a composer or parser to generate / analyze an image, respectively).

But first, I hope the M32 PR will go well :blush:

Flashed your release (2023-07-20) to my M32, both wifis are working after manually enabling them, i.e. also scanning would not work right away (while the radios are still shown as a generic wifi). Has this been addresses in the meantime? Otherwise I would build an image manually and compare it to the last state of my branch, as far as I can recall it was working right away on my branch, after flashing with settings discarded.
R32 would be next (hopefully next week, eventually :innocent: was too busy with my LoRa gateway -.-)
I thought I could at least post a serial bootlog for now, but it seems I hadn't even made one yet... Not sure if we need a separate forum thread for that device.