forked from openwrt/openwrt
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
image: add support for Netgear encrypted image
Netgear encrypted image is used in various devices including WAX202, WAX206, and EX6400v3. This image format also requires a dummy squashfs4 image which is added here as well. References in WAX202 GPL source: https://www.downloads.netgear.com/files/GPL/WAX202_V1.0.5.1_Source.rar * openwrt/bootloader/u-boot-mt7621-2018.09-gitb178829-20200526/board/ralink/common/dual_image.c Bootloader code that verifies the presence of a squashfs4 image, thus a dummy image is added here. * openwrt/tools/imgencoder/src/gj_enc.c Contains code that generates the encrypted image. There is support for adding an RSA signature, but it does not look like the signature is verified by the stock firmware or bootloader. * openwrt/tools/imgencoder/src/imagekey.h Contains the encryption key and IV. It appears the same key/IV is used for other Netgear devices including WAX206 and EX6400v3. Signed-off-by: Wenli Looi <wlooi@ucalgary.ca>
- Loading branch information
Showing
2 changed files
with
90 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import argparse | ||
import re | ||
import struct | ||
import subprocess | ||
import zlib | ||
|
||
|
||
def main(): | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument('--input-file', type=str, required=True) | ||
parser.add_argument('--output-file', type=str, required=True) | ||
parser.add_argument('--model', type=str, required=True) | ||
parser.add_argument('--region', type=str, required=True) | ||
parser.add_argument('--version', type=str, required=True) | ||
parser.add_argument('--encryption-block-size', type=str, required=True) | ||
parser.add_argument('--openssl-bin', type=str, required=True) | ||
parser.add_argument('--key', type=str, required=True) | ||
parser.add_argument('--iv', type=str, required=True) | ||
args = parser.parse_args() | ||
|
||
assert re.match(r'V[0-9]\.[0-9]\.[0-9]\.[0-9]', | ||
args.version), 'Version must start with Vx.x.x.x' | ||
encryption_block_size = int(args.encryption_block_size, 0) | ||
assert (encryption_block_size > 0 and encryption_block_size % 16 == | ||
0), 'Encryption block size must be a multiple of the AES block size (16)' | ||
|
||
image = open(args.input_file, 'rb').read() | ||
image_enc = [] | ||
for i in range(0, len(image), encryption_block_size): | ||
chunk = image[i:i + encryption_block_size] | ||
chunk += b'\x00' * ((-len(chunk)) % 16) # pad to AES block size (16) | ||
res = subprocess.run([ | ||
args.openssl_bin, | ||
'enc', | ||
'-aes-256-cbc', | ||
'-nosalt', | ||
'-nopad', | ||
'-K', args.key, | ||
'-iv', args.iv | ||
], | ||
check=True, input=chunk, stdout=subprocess.PIPE) | ||
image_enc.append(res.stdout) | ||
image_enc = b''.join(image_enc) | ||
|
||
image_with_header = struct.pack( | ||
'>32s32s64s64s64s256s12sII', | ||
args.model.encode('ascii'), | ||
args.region.encode('ascii'), | ||
args.version.encode('ascii'), | ||
b'Thu Jan 1 00:00:00 1970', # static date for reproducibility | ||
b'', # reserved | ||
b'', # RSA signature - omitted for now | ||
b'encrpted_img', | ||
len(image_enc), | ||
encryption_block_size, | ||
) + image_enc | ||
|
||
checksum = zlib.crc32(image_with_header, 0xffffffff) ^ 0xffffffff | ||
|
||
with open(args.output_file, 'wb') as outfile: | ||
outfile.write(image_with_header) | ||
outfile.write(struct.pack('>I', checksum)) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |