Skip to content

Add support for DAP-1325 decryption#10

Merged
impervius merged 1 commit into
mainfrom
add-ecb-aes
Jul 2, 2026
Merged

Add support for DAP-1325 decryption#10
impervius merged 1 commit into
mainfrom
add-ecb-aes

Conversation

@impervius

@impervius impervius commented Jun 23, 2026

Copy link
Copy Markdown

Closes #7

Summary by CodeRabbit

  • New Features

    • Added firmware decryption support for D-Link DAP-1325 A1 devices
    • Added firmware decryption support for D-Link DAP-1610 B1 (v1.03+) devices
  • Documentation

    • Updated supported devices list to include DAP-1325

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds AES-128-ECB block decryption and PKCS#7 unpadding helpers to src/aes.rs, then implements a new src/dap1325.rs module that decrypts DAP-1325 A1 and DAP-1610 B1 firmware using a hardcoded key. The module is registered in the decryptor registry and exported, with documentation updated accordingly.

Changes

DAP-1325/DAP-1610 Decryption Support

Layer / File(s) Summary
AES-128-ECB and PKCS#7 decryption helpers
src/aes.rs
Imports Array and BlockCipherDecrypt; adds aes_128_ecb_decrypt (validates len % 16, truncates key to 16 bytes, decrypts blocks with aes::Aes128) and aes_128_ecb_decrypt_pkcs7 (wraps the former, reads last byte as pad length, validates bounds and byte values, strips padding).
DAP-1325 decryptor, registry wiring, and docs
src/dap1325.rs, src/decryptor.rs, src/lib.rs, README.md
Adds dap1325::decrypt which checks input size, validates the plaintext 64-byte header against DAP-1325/DAP-1610 magic strings, calls aes_128_ecb_decrypt_pkcs7 with a hardcoded key, verifies ustar magic at offset 0x101, and returns the header concatenated with decrypted body or a typed DecryptError. Registers the decryptor in DECRYPTORS, exports pub mod dap1325, and adds DAP-1325 to supported device lists.

Sequence Diagram(s)

sequenceDiagram
    participant decryptor as decryptor::decrypt
    participant dap1325 as dap1325::decrypt
    participant aes as aes_128_ecb_decrypt_pkcs7
    participant Aes128

    decryptor->>dap1325: encrypted_data
    dap1325->>dap1325: check len >= 0x40
    dap1325->>dap1325: validate header magic (DAP-1325 or DAP-1610)
    dap1325->>aes: encrypted_data[0x40..], hardcoded key
    aes->>aes: validate len % 16 == 0, truncate key
    loop each 16-byte block
        aes->>Aes128: decrypt_block
        Aes128-->>aes: plaintext block
    end
    aes->>aes: strip and validate PKCS#7 padding
    aes-->>dap1325: decrypted body
    dap1325->>dap1325: verify ustar at offset 0x101
    dap1325-->>decryptor: Ok(header + decrypted body)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hoppin' through encrypted bytes,
A hardcoded key unlocks the night,
ECB blocks fall one by one,
PKCS#7 padding — done!
DAP-1325 is free at last,
The rabbit decrypts it, hopping fast~ 🗝️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding DAP-1325 decryption support, which aligns directly with the changeset.
Linked Issues check ✅ Passed The PR fully implements the decryption requirements from issue #7: AES-128 ECB decryption with hardcoded key, PKCS7 padding removal, header preservation, and support for DAP-1325 firmware.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing DAP-1325 decryption support; no unrelated modifications are present in the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-ecb-aes

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/aes.rs`:
- Around line 198-219: The aes_128_ecb_decrypt function uses the is_multiple_of
method which requires Rust 1.87 to be available. Add rust-version = "1.87" to
the Cargo.toml file to explicitly document the Minimum Supported Rust Version
(MSRV) requirement for this project, ensuring it matches the stabilization
version of the is_multiple_of method used in the code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e499cf72-525b-4dd3-b0c1-76ec38ba2bba

📥 Commits

Reviewing files that changed from the base of the PR and between b2041e2 and 329b565.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • README.md
  • src/aes.rs
  • src/dap1325.rs
  • src/decryptor.rs
  • src/lib.rs

Comment thread src/aes.rs
Comment on lines +198 to +219
pub fn aes_128_ecb_decrypt(encrypted_data: &[u8], key: &[u8]) -> Result<Vec<u8>, DecryptError> {
if !encrypted_data.len().is_multiple_of(16) {
return Err(DecryptError::InvalidInputLength);
}

let key_bytes: &[u8; 16] = key
.get(..16)
.and_then(|slice| slice.try_into().ok())
.ok_or(DecryptError::InvalidKeySize(key.len()))?;
let cipher = aes::Aes128::new(key_bytes.into());

let mut decrypted = Vec::with_capacity(encrypted_data.len());
for chunk in encrypted_data.chunks(16) {
let mut block: Array<u8, typenum::U16> = chunk
.try_into()
.map_err(|_| DecryptError::InvalidInputLength)?;
cipher.decrypt_block(&mut block);
decrypted.extend_from_slice(&block);
}

Ok(decrypted)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Look for MSRV / toolchain declarations
fd -H -t f 'rust-toolchain*'
rg -n 'rust-version|edition' Cargo.toml
cat rust-toolchain.toml 2>/dev/null || true

Repository: binwalk-ng/delink

Length of output: 174


🏁 Script executed:

cat Cargo.toml

Repository: binwalk-ng/delink

Length of output: 573


🌐 Web query:

is_multiple_of Rust stabilization version 1.87

💡 Result:

The is_multiple_of method for unsigned integer types was stabilized in Rust 1.87.0, which was released on May 15, 2025 [1][2][3]. This method, which returns true if self is an integer multiple of rhs, was introduced to provide a way to check for multiples without the risk of panicking when rhs is zero [4][5]. Unlike the standard remainder operator (%), which panics if the divisor is zero, n.is_multiple_of(0) returns false (for non-zero n) and 0.is_multiple_of(0) returns true [4][5]. Prior to this stabilization, similar functionality was commonly found in external crates like num [6].

Citations:


🌐 Web query:

Rust 2024 edition official release

💡 Result:

The Rust 2024 edition was officially released as stable on February 20, 2025, alongside the release of Rust version 1.85.0 [1][2]. It was introduced as the largest edition since Rust 2015, featuring various improvements to language consistency, ergonomics, and safety [1][3]. Migration to the 2024 edition is supported by automated tooling, specifically through the cargo fix command [1][4].

Citations:


Add rust-version = "1.87" to Cargo.toml to document the MSRV requirement.

The code uses is_multiple_of (line 199), which was stabilized in Rust 1.87. While the project declares edition = "2024" (released with 1.85), this does not guarantee Rust 1.87+ is available. Explicitly declare the MSRV to match the code's requirement.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/aes.rs` around lines 198 - 219, The aes_128_ecb_decrypt function uses the
is_multiple_of method which requires Rust 1.87 to be available. Add rust-version
= "1.87" to the Cargo.toml file to explicitly document the Minimum Supported
Rust Version (MSRV) requirement for this project, ensuring it matches the
stabilization version of the is_multiple_of method used in the code.

@impervius impervius merged commit c3a7de6 into main Jul 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decrypting DAP-1325, DAP-1610, and possibly others.

1 participant