pal-sgx-sign 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. #!/usr/bin/env python
  2. import os
  3. import sys
  4. import re
  5. import datetime
  6. import struct
  7. import subprocess
  8. import hashlib
  9. import binascii
  10. import shutil
  11. """ Default / Architectural Options """
  12. ARCHITECTURE = "amd64"
  13. PAGESIZE = 4096
  14. MEMORY_GAP = PAGESIZE
  15. TCSSIZE = PAGESIZE
  16. SSAFRAMESIZE = PAGESIZE
  17. SSAFRAMENUM = 2
  18. ENCLAVE_STACK_SIZE = PAGESIZE * 16
  19. DEFAULT_ENCLAVE_SIZE = '256M'
  20. DEFAULT_THREAD_NUM = 4
  21. DEFAULT_HEAP_MIN = '0x10000'
  22. """ Utilities """
  23. def roundup(addr):
  24. remaining = addr % PAGESIZE
  25. if remaining:
  26. return addr + (PAGESIZE - remaining)
  27. else:
  28. return addr
  29. def rounddown(addr):
  30. return addr - addr % PAGESIZE
  31. def roundup_data(data):
  32. return data + '\0' * (roundup(len(data)) - len(data))
  33. def int_to_bytes(i):
  34. b = ""
  35. l = 0
  36. while i > 0:
  37. b = b + chr(i % 256)
  38. i = i // 256
  39. l = l + 1
  40. return b
  41. def bytes_to_int(b):
  42. i = 0
  43. for c in b:
  44. i = i * 256 + ord(c)
  45. return i
  46. def parse_int(s):
  47. if len(s) > 2 and s.startswith("0x"):
  48. return int(s[2:], 16)
  49. if len(s) > 1 and s.startswith("0"):
  50. return int(s[1:], 8)
  51. return int(s)
  52. def parse_size(s):
  53. scale = 1
  54. if s.endswith("K"):
  55. scale = 1024
  56. if s.endswith("M"):
  57. scale = 1024 * 1024
  58. if s.endswith("G"):
  59. scale = 1024 * 1024 * 1024
  60. if scale != 1:
  61. s = s[:-1]
  62. return parse_int(s) * scale
  63. """ Reading / Writing Manifests """
  64. def read_manifest(filename):
  65. manifest = dict()
  66. manifest_layout = []
  67. with open(filename, "r") as f:
  68. for line in f.readlines():
  69. if line == "":
  70. manifest_layout.append((None, None))
  71. break
  72. pound = line.find("#")
  73. if pound != -1:
  74. comment = line[pound:].strip()
  75. line = line[:pound]
  76. else:
  77. comment = None
  78. line = line.strip()
  79. equal = line.find("=")
  80. if equal != -1:
  81. key = line[:equal].strip()
  82. manifest[key] = line[equal + 1:].strip()
  83. else:
  84. key = None
  85. manifest_layout.append((key, comment))
  86. return (manifest, manifest_layout)
  87. def output_manifest(filename, manifest, manifest_layout):
  88. with open(filename, 'w') as f:
  89. written = []
  90. for (key, comment) in manifest_layout:
  91. line = ''
  92. if key is not None:
  93. line += key + ' = ' + manifest[key]
  94. written.append(key)
  95. if comment is not None:
  96. if line != '':
  97. line += ' '
  98. line += comment
  99. print >>f, line
  100. print >>f
  101. print >>f, "# Generated by Graphene"
  102. print >>f
  103. for key in sorted(manifest.keys()):
  104. if key not in written:
  105. print >>f, key, '=', manifest[key]
  106. """ Loading Enclave Attributes """
  107. def get_enclave_attributes(manifest):
  108. sgx_flags = {
  109. 'FLAG_DEBUG' : struct.pack("<Q", 0x02),
  110. 'FLAG_MODE64BIT' : struct.pack("<Q", 0x04),
  111. }
  112. sgx_xfrms = {
  113. 'XFRM_LEGACY' : struct.pack("<Q", 0x03),
  114. 'XFRM_AVX' : struct.pack("<Q", 0x06),
  115. 'XFRM_AVX3' : struct.pack("<Q", 0xe6),
  116. 'XFRM_MPX' : struct.pack("<Q", 0x18),
  117. }
  118. sgx_miscs = {
  119. 'MISC_EXINFO' : struct.pack("<L", 0x01),
  120. }
  121. default_attributes = [
  122. 'FLAG_DEBUG',
  123. 'XFRM_LEGACY',
  124. 'XFRM_AVX',
  125. ]
  126. if ARCHITECTURE == 'amd64':
  127. default_attributes.append('FLAG_MODE64BIT')
  128. manifest_options = {
  129. 'debug' : 'FLAG_DEBUG',
  130. 'enable_avx3' : 'XFRM_AVX3',
  131. 'enable_mpx' : 'XFRM_MPX',
  132. 'support_exinfo' : 'MISC_EXINFO',
  133. }
  134. attributes = default_attributes
  135. for opt in manifest_options.keys():
  136. key = 'sgx.' + opt
  137. if key in manifest:
  138. if manifest[key] == '1':
  139. attributes.append(manifest_options[opt])
  140. else:
  141. if manifest_options[opt] in attributes:
  142. attributes.pop(manifest_options[opt])
  143. flags_raw = struct.pack("<Q", 0)
  144. xfrms_raw = struct.pack("<Q", 0)
  145. miscs_raw = struct.pack("<L", 0)
  146. for attr in attributes:
  147. if attr in sgx_flags:
  148. flags_raw = ''.join([chr(ord(a)|ord(b)) for a, b in zip(flags_raw, sgx_flags[attr])])
  149. if attr in sgx_xfrms:
  150. xfrms_raw = ''.join([chr(ord(a)|ord(b)) for a, b in zip(xfrms_raw, sgx_xfrms[attr])])
  151. if attr in sgx_miscs:
  152. miscs_raw = ''.join([chr(ord(a)|ord(b)) for a, b in zip(miscs_raw, sgx_miscs[attr])])
  153. return flags_raw, xfrms_raw, miscs_raw
  154. """ Generate Checksums / Measurement """
  155. def resolve_uri(uri, check_exist=True):
  156. orig_uri = uri
  157. if uri.startswith('file:'):
  158. target = os.path.normpath(uri[5:])
  159. else:
  160. target = os.path.normpath(uri)
  161. if check_exist and not os.path.exists(target):
  162. raise Exception('Cannot resolve ' + orig_uri + ' or the file does not exist.')
  163. return target
  164. def get_checksum(file):
  165. digest = hashlib.sha256()
  166. with open(file, 'rb') as f:
  167. digest.update(f.read())
  168. return digest.digest()
  169. def get_trusted_files(manifest, args):
  170. targets = dict()
  171. if 'exec' in args:
  172. targets['exec'] = (args['exec'], resolve_uri(args['exec']))
  173. if 'loader.preload' in manifest:
  174. i = 0
  175. preloads = []
  176. for uri in str.split(manifest['loader.preload'], ','):
  177. targets['preload' + str(i)] = (uri, resolve_uri(uri))
  178. preloads.append(uri)
  179. i += 1
  180. for (key, val) in manifest.items():
  181. if not key.startswith('sgx.trusted_files.'):
  182. continue
  183. key = key[len('sgx.trusted_files.'):]
  184. if key in targets:
  185. raise Exception('repeated key in manifest: sgx.trusted_files.' + key)
  186. targets[key] = (val, resolve_uri(val))
  187. for (key, val) in targets.items():
  188. (uri, target) = val
  189. checksum = get_checksum(target).encode('hex')
  190. targets[key] = (uri, target, checksum)
  191. return targets
  192. def get_trusted_children(manifest, args):
  193. targets = dict()
  194. for (key, val) in manifest.items():
  195. if not key.startswith('sgx.trusted_children.'):
  196. continue
  197. key = key[len('sgx.trusted_children.'):]
  198. if key in targets:
  199. raise Exception('repeated key in manifest: sgx.trusted_children.' + key)
  200. target = resolve_uri(val)
  201. sig = open(target, 'rb').read()[960:992].encode('hex')
  202. targets[key] = (val, target, sig)
  203. return targets
  204. """ Populate Enclave Memory """
  205. PAGEINFO_R = 0x1
  206. PAGEINFO_W = 0x2
  207. PAGEINFO_X = 0x4
  208. PAGEINFO_TCS = 0x100
  209. PAGEINFO_REG = 0x200
  210. def get_loadcmds(filename):
  211. loadcmds = []
  212. p = subprocess.Popen(['readelf', '-l', '-W', filename],
  213. stdout=subprocess.PIPE,
  214. stderr=subprocess.PIPE)
  215. while True:
  216. line = p.stdout.readline()
  217. if line == '':
  218. break
  219. stripped = line.strip()
  220. if not stripped.startswith('LOAD'):
  221. continue
  222. tokens = stripped.split()
  223. if len(tokens) < 6:
  224. continue
  225. if len(tokens) >= 7 and tokens[7] == "E":
  226. tokens[6] += tokens[7]
  227. prot = 0
  228. for t in tokens[6]:
  229. if t == "R":
  230. prot = prot | 4
  231. if t == "W":
  232. prot = prot | 2
  233. if t == "E":
  234. prot = prot | 1
  235. loadcmds.append((int(tokens[1][2:], 16), # offset
  236. int(tokens[2][2:], 16), # addr
  237. int(tokens[4][2:], 16), # filesize
  238. int(tokens[5][2:], 16), # memsize
  239. prot))
  240. p.wait()
  241. if p.returncode != 0:
  242. return None
  243. return loadcmds
  244. class MemoryArea:
  245. def __init__(self, desc, file=None, addr=None, size=None, flags=None):
  246. self.desc = desc
  247. self.file = file
  248. self.addr = addr
  249. self.size = size
  250. self.flags = flags
  251. self.is_binary = False
  252. if file:
  253. loadcmds = get_loadcmds(file)
  254. if loadcmds:
  255. mapaddr = 0xffffffffffffffff
  256. mapaddr_end = 0
  257. for (offset, addr, filesize, memsize, prot) in loadcmds:
  258. if rounddown(addr) < mapaddr:
  259. mapaddr = rounddown(addr)
  260. if roundup(addr + memsize) > mapaddr_end:
  261. mapaddr_end = roundup(addr + memsize)
  262. self.is_binary = True
  263. self.size = mapaddr_end - mapaddr
  264. if mapaddr > 0:
  265. self.addr = mapaddr
  266. else:
  267. self.size = os.stat(file).st_size
  268. if self.addr is not None:
  269. self.addr = rounddown(self.addr)
  270. if self.size is not None:
  271. self.size = roundup(self.size)
  272. def get_memory_areas(manifest, attr, args):
  273. areas = []
  274. areas.append(MemoryArea('ssa', size=attr['thread_num'] * SSAFRAMESIZE * SSAFRAMENUM,
  275. flags=PAGEINFO_R|PAGEINFO_W|PAGEINFO_REG))
  276. areas.append(MemoryArea('tcs', size=attr['thread_num'] * TCSSIZE,
  277. flags=PAGEINFO_TCS))
  278. areas.append(MemoryArea('tls', size=attr['thread_num'] * PAGESIZE,
  279. flags=PAGEINFO_R|PAGEINFO_W|PAGEINFO_REG))
  280. for t in range(attr['thread_num']):
  281. areas.append(MemoryArea('stack', size=ENCLAVE_STACK_SIZE,
  282. flags=PAGEINFO_R|PAGEINFO_W|PAGEINFO_REG))
  283. areas.append(MemoryArea('pal', file=args['libpal'], flags=PAGEINFO_REG))
  284. if 'exec' in args:
  285. areas.append(MemoryArea('exec', file=args['exec'],
  286. flags=PAGEINFO_W|PAGEINFO_REG))
  287. return areas
  288. def populate_memory_areas(manifest, attr, areas):
  289. populating = attr['enclave_size']
  290. heap_min = attr['heap_min']
  291. for area in areas:
  292. if area.addr is not None:
  293. continue
  294. area.addr = populating - area.size
  295. if area.addr < heap_min:
  296. raise Exception("Enclave size is not large enough")
  297. if area.desc == 'exec':
  298. populating = area.addr;
  299. else:
  300. populating = area.addr - MEMORY_GAP
  301. free_areas = []
  302. for area in areas:
  303. if area.addr + area.size < populating:
  304. if populating > heap_min:
  305. addr = area.addr + area.size
  306. if addr < heap_min:
  307. addr = heap_min
  308. free_areas.append(MemoryArea('free', addr=addr, size=populating - addr,
  309. flags=PAGEINFO_R|PAGEINFO_W|PAGEINFO_X|PAGEINFO_REG))
  310. populating = area.addr
  311. if populating > heap_min:
  312. free_areas.append(MemoryArea('free', addr=heap_min,
  313. size=populating - heap_min,
  314. flags=PAGEINFO_R|PAGEINFO_W|PAGEINFO_X|PAGEINFO_REG))
  315. return areas + free_areas
  316. def generate_measurement(attr, areas):
  317. def do_ecreate(digest, size):
  318. data = struct.pack("<8sLQ44s", "ECREATE", SSAFRAMESIZE / PAGESIZE, size, "")
  319. digest.update(data)
  320. def do_eadd(digest, offset, flags):
  321. data = struct.pack("<8sQQ40s", "EADD", offset, flags, "")
  322. digest.update(data)
  323. def do_eextend(digest, offset):
  324. data = struct.pack("<8sQ48s", "EEXTEND", offset, "")
  325. digest.update(data)
  326. class mrenclave_digest:
  327. def __init__(self):
  328. self.digest = hashlib.sha256()
  329. def update(self, payload):
  330. for er in range(0, len(payload), 64):
  331. self.digest.update(payload[er:er+64])
  332. def finalize(self):
  333. return self.digest.digest()
  334. mrenclave = mrenclave_digest()
  335. do_ecreate(mrenclave, attr['enclave_size'])
  336. def print_area(addr, size, flags, desc, measured):
  337. if flags & PAGEINFO_REG:
  338. type = 'REG'
  339. if flags & PAGEINFO_TCS:
  340. type = 'TCS'
  341. prot = ['-', '-', '-']
  342. if flags & PAGEINFO_R:
  343. prot[0] = 'R'
  344. if flags & PAGEINFO_W:
  345. prot[1] = 'W'
  346. if flags & PAGEINFO_X:
  347. prot[2] = 'X'
  348. prot = ''.join(prot)
  349. desc = '(' + desc + ')'
  350. if measured:
  351. desc += ' measured'
  352. if size == PAGESIZE:
  353. print >>sys.stderr, " %016x [%s:%s] %s" % (addr, type, prot, desc)
  354. else:
  355. print >>sys.stderr, " %016x-%016lx [%s:%s] %s" % (addr, addr + size, type, prot, desc)
  356. def load_file(digest, f, offset, addr, filesize, memsize, desc, flags):
  357. f_addr = rounddown(offset)
  358. m_addr = rounddown(addr)
  359. f_size = roundup(offset + filesize) - f_addr
  360. m_size = roundup(addr + memsize) - m_addr
  361. print_area(m_addr, f_size, flags, desc, True)
  362. if f_size < m_size:
  363. print_area(m_addr + f_size, m_size - f_size, flags, "bss", False)
  364. for pg in range(m_addr, m_addr + m_size, PAGESIZE):
  365. do_eadd(digest, pg, flags)
  366. if (pg >= m_addr + f_size):
  367. continue
  368. for er in range(pg, pg + PAGESIZE, 256):
  369. do_eextend(digest, er)
  370. start = er - m_addr + f_addr
  371. end = start + 256
  372. start_zero = ""
  373. if start < offset:
  374. if offset - start >= 256:
  375. start_zero = chr(0) * 256
  376. else:
  377. start_zero = chr(0) * (offset - start)
  378. end_zero = ""
  379. if end > offset + filesize:
  380. if end - offset - filesize >= 256:
  381. end_zero = chr(0) * 256
  382. else:
  383. end_zero = chr(0) * (end - offset - filesize)
  384. start += len(start_zero)
  385. end -= len(end_zero)
  386. if start < end:
  387. f.seek(start)
  388. data = f.read(end - start)
  389. else:
  390. data = ""
  391. if len(start_zero + data + end_zero) != 256:
  392. raise Exception("wrong calculation")
  393. digest.update(start_zero + data + end_zero)
  394. for area in areas:
  395. if area.file:
  396. with open(area.file, 'rb') as f:
  397. if area.is_binary:
  398. loadcmds = get_loadcmds(area.file)
  399. if loadcmds:
  400. mapaddr = 0xffffffffffffffff
  401. for (offset, addr, filesize, memsize, prot) in loadcmds:
  402. if rounddown(addr) < mapaddr:
  403. mapaddr = rounddown(addr)
  404. baseaddr = area.addr - mapaddr
  405. for (offset, addr, filesize, memsize, prot) in loadcmds:
  406. flags = area.flags
  407. if prot & 4:
  408. flags = flags | PAGEINFO_R
  409. if prot & 2:
  410. flags = flags | PAGEINFO_W
  411. if prot & 1:
  412. flags = flags | PAGEINFO_X
  413. if flags & PAGEINFO_X:
  414. desc = 'code'
  415. else:
  416. desc = 'data'
  417. load_file(mrenclave, f, offset, baseaddr + addr,
  418. filesize, memsize, desc, flags)
  419. else:
  420. load_file(mrenclave, f, 0, area.addr,
  421. os.stat(area.file).st_size, area.size,
  422. area.desc, area.flags)
  423. else:
  424. for a in range(area.addr, area.addr + area.size, PAGESIZE):
  425. do_eadd(mrenclave, a, area.flags)
  426. print_area(area.addr, area.size, area.flags, area.desc, False)
  427. return mrenclave.finalize()
  428. """ Generate Sigstruct """
  429. def generate_sigstruct(attr, args, mrenclave):
  430. today = datetime.date.today()
  431. # field format: (offset, type, value)
  432. fields = dict()
  433. fields['header'] = ( 0, "<4L", 0x00000006, 0x000000e1, 0x00010000, 0x00000000)
  434. fields['vendor'] = ( 16, "<L", 0x00000000)
  435. fields['date'] = ( 20, "<HBB", today.year, today.month, today.day)
  436. fields['header2'] = ( 24, "<4L", 0x00000101, 0x00000060, 0x00000060, 0x00000001)
  437. fields['swdefined'] = ( 40, "<L", 0x00000000)
  438. fields['miscs'] = ( 900, "4s", attr['miscs'])
  439. fields['miscmask'] = ( 904, "4s", attr['miscs'])
  440. fields['attrs'] = ( 928, "8s8s", attr['flags'], attr['xfrms'])
  441. fields['attrmask'] = ( 944, "8s8s", attr['flags'], attr['xfrms'])
  442. fields['mrencalve'] = ( 960, "32s", mrenclave)
  443. fields['isvprodid'] = (1024, "<H", attr['isvprodid'])
  444. fields['isvsvn'] = (1026, "<H", attr['isvsvn'])
  445. sign_buffer = bytearray(128 + 128)
  446. for key, field in fields.items():
  447. if field[0] >= 900:
  448. struct.pack_into(field[1], sign_buffer, field[0] - 900 + 128, *field[2:])
  449. else:
  450. struct.pack_into(field[1], sign_buffer, field[0], *field[2:])
  451. p = subprocess.Popen(['openssl', 'rsa', '-modulus', '-in', args['key'], '-noout'], stdout=subprocess.PIPE)
  452. modulus_out = p.communicate()[0]
  453. modulus = modulus_out[8:8+384*2].lower().decode('hex')
  454. modulus = modulus[::-1]
  455. p = subprocess.Popen(['openssl', 'sha256', '-binary', '-sign', args['key']],
  456. stdin=subprocess.PIPE, stdout=subprocess.PIPE)
  457. signature = p.communicate(sign_buffer)[0]
  458. signature = signature[::-1]
  459. def bytes_to_int(bytes):
  460. i = 0
  461. q = 1
  462. for digit in bytes:
  463. if ord(digit) != 0:
  464. i = i + ord(digit) * q
  465. q = q * 256
  466. return i
  467. def int_to_bytes(i):
  468. b = ""
  469. l = 0
  470. while i > 0:
  471. b = b + chr(i % 256)
  472. i = i // 256
  473. l = l + 1
  474. return b
  475. modulus_int = bytes_to_int(modulus)
  476. signature_int = bytes_to_int(signature)
  477. tmp1 = signature_int * signature_int
  478. q1_int = tmp1 // modulus_int
  479. tmp2 = tmp1 % modulus_int
  480. q2_int = tmp2 * signature_int // modulus_int
  481. q1 = int_to_bytes(q1_int)
  482. q2 = int_to_bytes(q2_int)
  483. fields['modulus'] = ( 128, "384s", modulus)
  484. fields['exponent'] = ( 512, "<L", 3)
  485. fields['signature'] = ( 516, "384s", signature)
  486. fields['q1'] = (1040, "384s", q1)
  487. fields['q2'] = (1424, "384s", q2)
  488. buffer = bytearray(1808)
  489. for key, field in fields.items():
  490. struct.pack_into(field[1], buffer, field[0], *field[2:])
  491. return buffer
  492. """ Main Program """
  493. options = {
  494. # Option name : (Required Value)
  495. 'output': (True, 'output'),
  496. 'libpal': (True, 'libpal path'),
  497. 'key': (True, 'signing key'),
  498. 'manifest': (True, 'manifest'),
  499. 'exec': (False, 'executable'),
  500. }
  501. def usage():
  502. usage_message = 'USAGE: ' + sys.argv[0] + ' -help|-h'
  503. for opt, optval in options.items():
  504. if not optval[0]:
  505. usage_message += '['
  506. usage_message += '|-' + opt
  507. if optval[1]:
  508. usage_message += ' <' + optval[1] + '>'
  509. if not optval[0]:
  510. usage_message += ']'
  511. print >> sys.stderr, usage_message
  512. os._exit(-1)
  513. def parse_args():
  514. args = dict()
  515. for opt, optval in options.items():
  516. if not optval[1]:
  517. args[opt] = False
  518. i = 1
  519. while i < len(sys.argv):
  520. got = sys.argv[i]
  521. if got == '-help' or got == '-h':
  522. usage()
  523. invalid = True
  524. for opt, optval in options.items():
  525. if got != '-' + opt:
  526. continue
  527. if optval[1] is not None:
  528. i += 1
  529. if i == len(sys.argv):
  530. print >>sys.stderr, "Option %s needs a value." % (opt)
  531. usage()
  532. args[opt] = sys.argv[i]
  533. else:
  534. args[opt] = True
  535. invalid = False
  536. break
  537. if invalid:
  538. print >>sys.stderr, "Unknown option: %s." % (got[1:])
  539. usage()
  540. i += 1
  541. for opt, optval in options.items():
  542. if optval[0] and opt not in args:
  543. print >>sys.stderr, "Must specify %s <%s>." % (opt, optval[1])
  544. usage()
  545. return args
  546. if __name__ == "__main__":
  547. # Parse arguments
  548. args = parse_args()
  549. (manifest, manifest_layout) = read_manifest(args['manifest'])
  550. if 'exec' not in args:
  551. if 'loader.exec' in manifest:
  552. exec_url = manifest['loader.exec']
  553. if exec_url[:5] != 'file:':
  554. print "executable must be a local file"
  555. os._exit(-1)
  556. args['exec'] = os.path.join(os.path.dirname(args['manifest']), exec_url[5:])
  557. args['root'] = os.path.dirname(os.path.abspath(args['output']))
  558. if 'sgx.sigfile' in manifest:
  559. args['sigfile'] = resolve_uri(manifest['sgx.sigfile'], False)
  560. else:
  561. sigfile = args['output']
  562. for ext in ['.manifest.sgx', '.manifest']:
  563. if sigfile.endswith(ext):
  564. sigfile = sigfile[:-len(ext)]
  565. break
  566. args['sigfile'] = sigfile + '.sig'
  567. manifest['sgx.sigfile'] = 'file:' + os.path.basename(args['sigfile'])
  568. # Get attributes from manifest
  569. attr = dict()
  570. for key, default, parse in [
  571. ('enclave_size', DEFAULT_ENCLAVE_SIZE, parse_size),
  572. ('heap_min', DEFAULT_HEAP_MIN, parse_int),
  573. ('thread_num', str(DEFAULT_THREAD_NUM), parse_int),
  574. ('isvprodid', '0', parse_int),
  575. ('isvsvn', '0', parse_int),
  576. ]:
  577. if 'sgx.' + key not in manifest:
  578. manifest['sgx.' + key] = default
  579. attr[key] = parse(manifest['sgx.' + key])
  580. (attr['flags'], attr['xfrms'], attr['miscs']) = get_enclave_attributes(manifest)
  581. print >>sys.stderr, "Attributes:"
  582. print >>sys.stderr, " size: %d" % (attr['enclave_size'])
  583. print >>sys.stderr, " threadnum: %d" % (attr['thread_num'])
  584. print >>sys.stderr, " isvprodid: %d" % (attr['isvprodid'])
  585. print >>sys.stderr, " isvsvn: %d" % (attr['isvsvn'])
  586. print >>sys.stderr, " flags: %016x" % (bytes_to_int(attr['flags']))
  587. print >>sys.stderr, " xfrms: %016x" % (bytes_to_int(attr['xfrms']))
  588. print >>sys.stderr, " miscs: %08x" % (bytes_to_int(attr['miscs']))
  589. # Get trusted checksums and measurements
  590. print >>sys.stderr, "Trusted files:"
  591. for key, val in get_trusted_files(manifest, args).items():
  592. (uri, target, checksum) = val
  593. print >>sys.stderr, " %s %s" % (checksum, uri)
  594. manifest['sgx.trusted_checksum.' + key] = checksum
  595. print >>sys.stderr, "Trusted children:"
  596. for key, val in get_trusted_children(manifest, args).items():
  597. (uri, target, mrenclave) = val
  598. print >>sys.stderr, " %s %s" % (mrenclave, uri)
  599. manifest['sgx.trusted_mrenclave.' + key] = mrenclave
  600. # Try populate memory areas
  601. memory_areas = get_memory_areas(manifest, attr, args)
  602. if len([a for a in memory_areas if a.addr is not None]) > 0:
  603. manifest['sgx.static_address'] = '1'
  604. # Add manifest at the top
  605. shutil.copy2(args['manifest'], args['output'])
  606. output_manifest(args['output'], manifest, manifest_layout)
  607. memory_areas = [
  608. MemoryArea('manifest', file=args['output'],
  609. flags=PAGEINFO_R|PAGEINFO_REG)
  610. ] + memory_areas
  611. memory_areas = populate_memory_areas(manifest, attr, memory_areas)
  612. print >>sys.stderr, "Memory:"
  613. # Generate measurement
  614. mrenclave = generate_measurement(attr, memory_areas)
  615. print >>sys.stderr, "Measurement:"
  616. print >>sys.stderr, " " + mrenclave.encode('hex')
  617. # Generate sigstruct
  618. open(args['sigfile'], 'wb').write(generate_sigstruct(attr, args, mrenclave))