1
0

netgear-encrypted-factory.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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('--hw-id-list', type=str)
  15. parser.add_argument('--model-list', type=str)
  16. parser.add_argument('--encryption-block-size', type=str, required=True)
  17. parser.add_argument('--openssl-bin', type=str, required=True)
  18. parser.add_argument('--key', type=str, required=True)
  19. parser.add_argument('--iv', type=str, required=True)
  20. args = parser.parse_args()
  21. assert re.match(r'V[0-9]\.[0-9]\.[0-9]\.[0-9]',
  22. args.version), 'Version must start with Vx.x.x.x'
  23. encryption_block_size = int(args.encryption_block_size, 0)
  24. assert (encryption_block_size > 0 and encryption_block_size % 16 ==
  25. 0), 'Encryption block size must be a multiple of the AES block size (16)'
  26. hw_id_list = args.hw_id_list.split(';') if args.hw_id_list else []
  27. model_list = args.model_list.split(';') if args.model_list else []
  28. hw_info = ';'.join(hw_id_list + model_list)
  29. image = open(args.input_file, 'rb').read()
  30. image_enc = []
  31. for i in range(0, len(image), encryption_block_size):
  32. chunk = image[i:i + encryption_block_size]
  33. chunk += b'\x00' * ((-len(chunk)) % 16) # pad to AES block size (16)
  34. res = subprocess.run([
  35. args.openssl_bin,
  36. 'enc',
  37. '-aes-256-cbc',
  38. '-nosalt',
  39. '-nopad',
  40. '-K', args.key,
  41. '-iv', args.iv
  42. ],
  43. check=True, input=chunk, stdout=subprocess.PIPE)
  44. image_enc.append(res.stdout)
  45. image_enc = b''.join(image_enc)
  46. image_with_header = struct.pack(
  47. '>32s32s64s64sIBBB13s200s100s12sII',
  48. args.model.encode('ascii'),
  49. args.region.encode('ascii'),
  50. args.version.encode('ascii'),
  51. b'Thu Jan 1 00:00:00 1970', # static date for reproducibility
  52. 0, # product hw model
  53. 0, # model index
  54. len(hw_id_list),
  55. len(model_list),
  56. b'', # reserved
  57. hw_info.encode('ascii'),
  58. b'', # reserved
  59. b'encrpted_img',
  60. len(image_enc),
  61. encryption_block_size,
  62. ) + image_enc
  63. checksum = zlib.crc32(image_with_header, 0xffffffff) ^ 0xffffffff
  64. with open(args.output_file, 'wb') as outfile:
  65. outfile.write(image_with_header)
  66. outfile.write(struct.pack('>I', checksum))
  67. if __name__ == "__main__":
  68. main()