key2dtsi.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #!/usr/bin/env python3
  2. # SPDX-License-Identifier: GPL-2.0-only
  3. #
  4. # Public key to dtsi converter.
  5. #
  6. # Copyright (c) Siemens AG, 2022
  7. #
  8. from argparse import ArgumentParser, FileType
  9. from os.path import basename, splitext
  10. from Cryptodome.PublicKey import RSA
  11. from Cryptodome.Util.number import inverse
  12. def int_to_bytestr(n, length=None):
  13. if not length:
  14. length = (n.bit_length() + 7) // 8
  15. byte_array = n.to_bytes(length, 'big')
  16. return ' '.join(['{:02x}'.format(byte) for byte in byte_array])
  17. ap = ArgumentParser(description='Public key to dtsi converter')
  18. ap.add_argument('--hash', '-H', default='sha256',
  19. help='hash to be used with key (default: sha256)')
  20. ap.add_argument('--required-conf', '-c', action='store_true',
  21. help='mark key required for configuration')
  22. ap.add_argument('--required-image', '-i', action='store_true',
  23. help='mark key required for image')
  24. ap.add_argument('--spl', '-s', action='store_true',
  25. help='mark key for usage in SPL')
  26. ap.add_argument('key_file', metavar='KEY_FILE', type=FileType('r'),
  27. help='key file (formats: X.509, PKCS#1, OpenSSH)')
  28. ap.add_argument('dtsi_file', metavar='DTSI_FILE', type=FileType('w'),
  29. help='dtsi output file')
  30. args = ap.parse_args()
  31. key_name, _ = splitext(basename(args.key_file.name))
  32. key_data = args.key_file.read()
  33. key = RSA.importKey(key_data)
  34. r_squared = (2**key.size_in_bits())**2 % key.n
  35. n0_inverse = 2**32 - inverse(key.n, 2**32)
  36. out = args.dtsi_file
  37. out.write('/ {\n')
  38. out.write('\tsignature {\n')
  39. out.write('\t\tkey-{} {{\n'.format(key_name))
  40. out.write('\t\t\tkey-name-hint = "{}";\n'.format(key_name))
  41. out.write('\t\t\talgo = "{},rsa{}";\n'.format(args.hash, key.size_in_bits()))
  42. out.write('\t\t\trsa,num-bits = <{}>;\n'.format(key.size_in_bits()))
  43. out.write('\t\t\trsa,modulus = [{}];\n'.format(int_to_bytestr(key.n)))
  44. out.write('\t\t\trsa,exponent = [{}];\n'.format(int_to_bytestr(key.e, 8)))
  45. out.write('\t\t\trsa,r-squared = [{}];\n'.format(int_to_bytestr(r_squared)))
  46. out.write('\t\t\trsa,n0-inverse = <0x{:x}>;\n'.format(n0_inverse))
  47. if args.required_conf:
  48. out.write('\t\t\trequired = "conf";\n')
  49. elif args.required_image:
  50. out.write('\t\t\trequired = "image";\n')
  51. if args.spl:
  52. out.write('\t\t\tu-boot,dm-spl;\n')
  53. out.write('\t\t};\n')
  54. out.write('\t};\n')
  55. out.write('};\n')