netgear-encrypted-factory.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #!/usr/bin/env python3
  2. import argparse
  3. import re
  4. import struct
  5. import subprocess
  6. import zlib
  7. def main():
  8. parser = argparse.ArgumentParser()
  9. parser.add_argument('--input-file', type=str, required=True)
  10. parser.add_argument('--output-file', type=str, required=True)
  11. parser.add_argument('--model', type=str, required=True)
  12. parser.add_argument('--region', type=str, required=True)
  13. parser.add_argument('--version', type=str, required=True)
  14. parser.add_argument('--encryption-block-size', type=str, required=True)
  15. parser.add_argument('--openssl-bin', type=str, required=True)
  16. parser.add_argument('--key', type=str, required=True)
  17. parser.add_argument('--iv', type=str, required=True)
  18. args = parser.parse_args()
  19. assert re.match(r'V[0-9]\.[0-9]\.[0-9]\.[0-9]',
  20. args.version), 'Version must start with Vx.x.x.x'
  21. encryption_block_size = int(args.encryption_block_size, 0)
  22. assert (encryption_block_size > 0 and encryption_block_size % 16 ==
  23. 0), 'Encryption block size must be a multiple of the AES block size (16)'
  24. image = open(args.input_file, 'rb').read()
  25. image_enc = []
  26. for i in range(0, len(image), encryption_block_size):
  27. chunk = image[i:i + encryption_block_size]
  28. chunk += b'\x00' * ((-len(chunk)) % 16) # pad to AES block size (16)
  29. res = subprocess.run([
  30. args.openssl_bin,
  31. 'enc',
  32. '-aes-256-cbc',
  33. '-nosalt',
  34. '-nopad',
  35. '-K', args.key,
  36. '-iv', args.iv
  37. ],
  38. check=True, input=chunk, stdout=subprocess.PIPE)
  39. image_enc.append(res.stdout)
  40. image_enc = b''.join(image_enc)
  41. image_with_header = struct.pack(
  42. '>32s32s64s64s64s256s12sII',
  43. args.model.encode('ascii'),
  44. args.region.encode('ascii'),
  45. args.version.encode('ascii'),
  46. b'Thu Jan 1 00:00:00 1970', # static date for reproducibility
  47. b'', # reserved
  48. b'', # RSA signature - omitted for now
  49. b'encrpted_img',
  50. len(image_enc),
  51. encryption_block_size,
  52. ) + image_enc
  53. checksum = zlib.crc32(image_with_header, 0xffffffff) ^ 0xffffffff
  54. with open(args.output_file, 'wb') as outfile:
  55. outfile.write(image_with_header)
  56. outfile.write(struct.pack('>I', checksum))
  57. if __name__ == "__main__":
  58. main()