swupdate-common.bbclass 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. def swupdate_is_hash_needed(s, filename):
  2. with open(os.path.join(s, "sw-description"), 'r') as f:
  3. for line in f:
  4. if line.find("@%s" % (filename)) != -1:
  5. return True
  6. return False
  7. def swupdate_get_sha256(s, filename):
  8. import hashlib
  9. m = hashlib.sha256()
  10. with open(os.path.join(s, filename), 'rb') as f:
  11. while True:
  12. data = f.read(1024)
  13. if not data:
  14. break
  15. m.update(data)
  16. return m.hexdigest()
  17. def swupdate_extract_keys(keyfile):
  18. try:
  19. keys = open(keyfile)
  20. except IOError:
  21. bb.fatal("Failed to open file with keys %s" % (keyfile))
  22. lines = keys.read()
  23. keys.close()
  24. lines = lines.splitlines(True)
  25. for line in lines:
  26. line = line.replace('\n', '')
  27. kv = line.split('=')
  28. if kv[0] == 'salt':
  29. salt = kv[1]
  30. if kv[0] == 'key':
  31. key = kv[1]
  32. if kv[0] == 'iv' or kv[0] == 'iv ':
  33. iv = kv[1]
  34. return key,iv,salt
  35. def swupdate_encrypt_file(f, out, key, ivt, salt):
  36. cmd = "openssl enc -aes-256-cbc -in '%s' -out '%s' -K '%s' -iv '%s' -S '%s'" % (
  37. f,
  38. out,
  39. key,
  40. ivt,
  41. salt)
  42. if os.system(cmd) != 0:
  43. bb.fatal("Failed to encrypt %s" % (f))
  44. def swupdate_write_sha256(s, filename, hash):
  45. write_lines = []
  46. with open(os.path.join(s, "sw-description"), 'r') as f:
  47. for line in f:
  48. write_lines.append(line.replace("@%s" % (filename), hash))
  49. with open(os.path.join(s, "sw-description"), 'w+') as f:
  50. for line in write_lines:
  51. f.write(line)
  52. def swupdate_expand_bitbake_variables(d, s):
  53. write_lines = []
  54. with open(os.path.join(s, "sw-description"), 'r') as f:
  55. import re
  56. for line in f:
  57. found = False
  58. while True:
  59. m = re.match(r"^(?P<before_placeholder>.+)@@(?P<bitbake_variable_name>\w+)@@(?P<after_placeholder>.+)$", line)
  60. if m:
  61. bitbake_variable_value = d.getVar(m.group('bitbake_variable_name'), True)
  62. if bitbake_variable_value is None:
  63. bitbake_variable_value = ""
  64. bb.warn("BitBake variable %s not set" % (m.group('bitbake_variable_name')))
  65. line = m.group('before_placeholder') + bitbake_variable_value + m.group('after_placeholder')
  66. found = True
  67. continue
  68. else:
  69. m = re.match(r"^(?P<before_placeholder>.+)@@(?P<bitbake_variable_name>.+)\[(?P<flag_var_name>.+)\]@@(?P<after_placeholder>.+)$", line)
  70. if m:
  71. bitbake_variable_value = (d.getVarFlag(m.group('bitbake_variable_name'), m.group('flag_var_name'), True) or "")
  72. if bitbake_variable_value is None:
  73. bitbake_variable_value = ""
  74. line = m.group('before_placeholder') + bitbake_variable_value + m.group('after_placeholder')
  75. continue
  76. if found:
  77. line = line + "\n"
  78. break
  79. write_lines.append(line)
  80. with open(os.path.join(s, "sw-description"), 'w+') as f:
  81. for line in write_lines:
  82. f.write(line)
  83. def prepare_sw_description(d, s, list_for_cpio):
  84. import shutil
  85. swupdate_expand_bitbake_variables(d, s)
  86. for file in list_for_cpio:
  87. if file != 'sw-description' and swupdate_is_hash_needed(s, file):
  88. hash = swupdate_get_sha256(s, file)
  89. swupdate_write_sha256(s, file, hash)
  90. encrypt = d.getVar('SWUPDATE_ENCRYPT_SWDESC', True)
  91. if encrypt:
  92. bb.note("Encryption of sw-description")
  93. shutil.copyfile(os.path.join(s, 'sw-description'), os.path.join(s, 'sw-description.plain'))
  94. key,iv,salt = swupdate_extract_keys(d.getVar('SWUPDATE_AES_FILE', True))
  95. swupdate_encrypt_file(os.path.join(s, 'sw-description.plain'), os.path.join(s, 'sw-description'), key, iv, salt)
  96. signing = d.getVar('SWUPDATE_SIGNING', True)
  97. if signing == "1":
  98. bb.warn('SWUPDATE_SIGNING = "1" is deprecated, falling back to "RSA". It is advised to set it to "RSA" if using RSA signing.')
  99. signing = "RSA"
  100. if signing:
  101. if signing == "CUSTOM":
  102. sign_tool = d.getVar('SWUPDATE_SIGN_TOOL', True)
  103. if sign_tool:
  104. ret = os.system(sign_tool)
  105. if ret != 0:
  106. bb.fatal("Failed to sign with %s" % (sign_tool))
  107. else:
  108. bb.fatal("Custom SWUPDATE_SIGN_TOOL is not given")
  109. elif signing == "RSA":
  110. privkey = d.getVar('SWUPDATE_PRIVATE_KEY', True)
  111. if not privkey:
  112. bb.fatal("SWUPDATE_PRIVATE_KEY isn't set")
  113. if not os.path.exists(privkey):
  114. bb.fatal("SWUPDATE_PRIVATE_KEY %s doesn't exist" % (privkey))
  115. passout = d.getVar('SWUPDATE_PASSWORD_FILE', True)
  116. if passout:
  117. passout = "-passin file:'%s' " % (passout)
  118. else:
  119. passout = ""
  120. signcmd = "openssl dgst -sha256 -sign '%s' %s -out '%s' '%s'" % (
  121. privkey,
  122. passout,
  123. os.path.join(s, 'sw-description.sig'),
  124. os.path.join(s, 'sw-description'))
  125. if os.system(signcmd) != 0:
  126. bb.fatal("Failed to sign sw-description with %s" % (privkey))
  127. elif signing == "CMS":
  128. cms_cert = d.getVar('SWUPDATE_CMS_CERT', True)
  129. if not cms_cert:
  130. bb.fatal("SWUPDATE_CMS_CERT is not set")
  131. if not os.path.exists(cms_cert):
  132. bb.fatal("SWUPDATE_CMS_CERT %s doesn't exist" % (cms_cert))
  133. cms_key = d.getVar('SWUPDATE_CMS_KEY', True)
  134. if not cms_key:
  135. bb.fatal("SWUPDATE_CMS_KEY isn't set")
  136. if not os.path.exists(cms_key):
  137. bb.fatal("SWUPDATE_CMS_KEY %s doesn't exist" % (cms_key))
  138. passout = d.getVar('SWUPDATE_PASSWORD_FILE', True)
  139. if passout:
  140. passout = "-passin file:'%s' " % (passout)
  141. else:
  142. passout = ""
  143. signcmd = "openssl cms -sign -in '%s' -out '%s' -signer '%s' -inkey '%s' %s -outform DER -nosmimecap -binary" % (
  144. os.path.join(s, 'sw-description'),
  145. os.path.join(s, 'sw-description.sig'),
  146. cms_cert,
  147. cms_key,
  148. passout)
  149. if os.system(signcmd) != 0:
  150. bb.fatal("Failed to sign sw-description with %s" % (privkey))
  151. else:
  152. bb.fatal("Unrecognized SWUPDATE_SIGNING mechanism.");