pal-sgx-get-token 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #!/usr/bin/env python
  2. import os
  3. import sys
  4. import struct
  5. import socket
  6. from google.protobuf import message as _message
  7. from Crypto.PublicKey import RSA
  8. import aesm_pb2
  9. """ Utilities """
  10. def int_to_bytes(i):
  11. b = ""
  12. l = 0
  13. while i > 0:
  14. b = b + chr(i % 256)
  15. i = i // 256
  16. l = l + 1
  17. return b
  18. def bytes_to_int(b):
  19. i = 0
  20. for c in b:
  21. i = i * 256 + ord(c)
  22. return i
  23. """ Reading Sigstruct """
  24. def read_sigstruct(sig):
  25. # field format: (offset, type, value)
  26. fields = dict()
  27. fields['date'] = ( 20, "<HBB", 'year', 'month', 'day')
  28. fields['modulus'] = ( 128, "384s", 'modulus')
  29. fields['exponent'] = ( 512, "<L", 'exponent')
  30. fields['signature'] = ( 516, "384s", 'signature')
  31. fields['miscs'] = ( 900, "4s", 'miscs')
  32. fields['miscmask'] = ( 904, "4s", 'miscmask')
  33. fields['attrs'] = ( 928, "8s8s", 'flags', 'xfrms')
  34. fields['attrmask'] = ( 944, "8s8s", 'flagmask', 'xfrmmask')
  35. fields['mrencalve'] = ( 960, "32s", 'mrenclave')
  36. fields['isvprodid'] = (1024, "<H", 'isvprodid')
  37. fields['isvsvn'] = (1026, "<H", 'isvsvn')
  38. attr = dict()
  39. for key, field in fields.items():
  40. values = struct.unpack_from(field[1], sig, field[0])
  41. for i in range(len(values)):
  42. attr[field[i + 2]] = values[i]
  43. return attr
  44. """ Connect with AESMD """
  45. def connect_aesmd(attr):
  46. req_msg = aesm_pb2.GetTokenReq()
  47. req_msg.req.signature = attr['mrenclave']
  48. req_msg.req.key = attr['modulus']
  49. req_msg.req.attributes = attr['flags'] + attr['xfrms']
  50. req_msg.req.timeout = 10000
  51. req_msg_raw = req_msg.SerializeToString()
  52. aesm_service = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
  53. connected = False
  54. # try to connect to the unnamed socket (for PSW 1.6 and 1.7)
  55. if not connected:
  56. try:
  57. aesm_service.connect("\0sgx_aesm_socket_base" + "\0" * 87)
  58. connected = True
  59. except socket.error:
  60. pass
  61. # try to connect to the named socket (for PSW 1.8+)
  62. if not connected:
  63. try:
  64. aesm_service.connect("/var/run/aesmd/aesm.socket")
  65. connected = True
  66. except socket.error:
  67. pass
  68. if not connected:
  69. raise socket.error("Cannot connect to the AESMD service")
  70. aesm_service.send(struct.pack("<I", len(req_msg_raw)))
  71. aesm_service.send(req_msg_raw)
  72. ret_msg_size = struct.unpack("<I", aesm_service.recv(4))[0]
  73. ret_msg = aesm_pb2.GetTokenRet()
  74. ret_msg_raw = aesm_service.recv(ret_msg_size)
  75. ret_msg.ParseFromString(ret_msg_raw)
  76. if ret_msg.ret.error != 0:
  77. raise Exception("Failed. (Error Code = %d)" % (ret_msg.ret.error))
  78. return ret_msg.ret.token
  79. """ Main Program """
  80. options = {
  81. # Option name : (Required Value)
  82. 'output': (True, 'output'),
  83. 'sig': (True, 'sigstruct file'),
  84. }
  85. def usage():
  86. usage_message = 'USAGE: ' + sys.argv[0] + ' -help|-h'
  87. for opt, optval in options.items():
  88. if not optval[0]:
  89. usage_message += '['
  90. usage_message += '|-' + opt
  91. if optval[1]:
  92. usage_message += ' <' + optval[1] + '>'
  93. if not optval[0]:
  94. usage_message += ']'
  95. print >> sys.stderr, usage_message
  96. os._exit(-1)
  97. def parse_args():
  98. args = dict()
  99. for opt, optval in options.items():
  100. if optval[1] is None:
  101. args[opt] = False
  102. i = 1
  103. while i < len(sys.argv):
  104. got = sys.argv[i]
  105. if got == '-help' or got == '-h':
  106. usage()
  107. invalid = True
  108. for opt, optval in options.items():
  109. if got != '-' + opt:
  110. continue
  111. if optval[1] is not None:
  112. i += 1
  113. if i == len(sys.argv):
  114. print >>sys.stderr, "Option %s needs a value." % (opt)
  115. usage()
  116. args[opt] = sys.argv[i]
  117. else:
  118. args[opt] = True
  119. invalid = False
  120. break
  121. if invalid:
  122. print >>sys.stderr, "Unknown option: %s." % (got[1:])
  123. usage()
  124. i += 1
  125. for opt, optval in options.items():
  126. if optval[0] and opt not in args:
  127. print >>sys.stderr, "Must specify %s <%s>." % (opt, optval[1])
  128. usage()
  129. return args
  130. if __name__ == "__main__":
  131. # Parse arguments
  132. args = parse_args()
  133. attr = read_sigstruct(open(args['sig'], 'rb').read())
  134. print >>sys.stderr, "Attributes:"
  135. print >>sys.stderr, " mrenclave: %s" % (attr['mrenclave'].encode('hex'))
  136. print >>sys.stderr, " isvprodid: %d" % (attr['isvprodid'])
  137. print >>sys.stderr, " isvsvn: %d" % (attr['isvsvn'])
  138. print >>sys.stderr, " flags: %016x" % (bytes_to_int(attr['flags']))
  139. print >>sys.stderr, " xfrms: %016x" % (bytes_to_int(attr['xfrms']))
  140. print >>sys.stderr, " miscs: %08x" % (bytes_to_int(attr['miscs']))
  141. print >>sys.stderr, " modulus: %s..." % (attr['modulus'].encode('hex')[:32])
  142. print >>sys.stderr, " exponent: %d" % (attr['exponent'])
  143. print >>sys.stderr, " signature: %s..." % (attr['signature'].encode('hex')[:32])
  144. token = connect_aesmd(attr)
  145. open(args['output'], 'wb').write(token)