Browse Source

[Pal/Linux-SGX] pal-sgx-get-token, pal-sgx-sign: move to Python3 and cleanup

This commit rewrites pal-sgx-get-token and pal-sgx-sign in Python3 and
performs a comprehensive cleanup of the code:
- Outputs are sent to separate files (otherwise they were intermixed
  during parallel build)
- aesm_pb2.py is re-generated to Python3
- Numeric constants are replaced with symbolic ones
- Using argparse instead of home-grown argument parsing
- Replacing home-grown helper funcs int_to_bytes(), bytes_to_int(), etc.
  with standard functions
Isaku Yamahata 4 years ago
parent
commit
6e3c45c8e3

+ 2 - 0
.gitignore

@@ -30,6 +30,8 @@ pal.map
 *.sig
 *.token
 *.cached
+.output.sgx_get_token.*
+.output.sgx_sign.*
 
 # gnu global
 GPATH

+ 2 - 1
Jenkinsfiles/ubuntu-16.04.dockerfile

@@ -18,7 +18,7 @@ RUN apt-get update \
        linux-headers-4.4.0-161-generic \
        net-tools \
        python \
-       python-protobuf \
+       python3-pip \
        python3-minimal \
        python3-pytest \
        texinfo \
@@ -27,6 +27,7 @@ RUN apt-get update \
        libomp-dev \
        libprotobuf-c-dev \
        protobuf-c-compiler \
+    && /usr/bin/pip3 install protobuf \
 
 # Add the user UID:1001, GID:1001, home at /leeroy
     && groupadd -r leeroy -g 1001 \

+ 1 - 1
Jenkinsfiles/ubuntu-18.04.dockerfile

@@ -19,7 +19,7 @@ RUN apt-get update && apt-get install -y \
     linux-headers-4.15.0-20-generic \
     net-tools \
     python \
-    python-protobuf \
+    python3-protobuf \
     python3-pytest \
     texinfo \
     wget \

+ 1 - 1
LibOS/shim/test/Makefile.Test

@@ -86,4 +86,4 @@ endif
 
 .PHONY: clean
 clean: $(clean-extra)
-	rm -rf pal_loader $(call expand_target,$(exec_target)) $(target) $(wildcard *.d)
+	rm -rf pal_loader $(call expand_target,$(exec_target)) $(target) $(wildcard *.d) .output.*

+ 3 - 3
Makefile.rules

@@ -125,14 +125,14 @@ quiet_cmd_cxxsingle  = [ $@ ]
 
 # sgx sign
 quiet_cmd_sgx_sign_manifest = [ $*.{sig, manifest.sgx} ]
-      cmd_sgx_sign_manifest = $(SGX_SIGN) -output $*.manifest.sgx -exec $* -manifest $<
+      cmd_sgx_sign_manifest = $(SGX_SIGN) -output $*.manifest.sgx -exec $* -manifest $< > .output.sgx_sign.$*
 
 quiet_cmd_sgx_sign = [ $*.{sig, manifest.sgx} ]
-      cmd_sgx_sign = $(SGX_SIGN) -output $*.manifest.sgx -manifest $<
+      cmd_sgx_sign = $(SGX_SIGN) -output $*.manifest.sgx -manifest $< > .output.sgx_sign.$*
 
 # sgx token
 quiet_cmd_sgx_get_token = [ Token: $(basename $*) ]
-      cmd_sgx_get_token = $(SGX_GET_TOKEN) -output $@ -sig $^
+      cmd_sgx_get_token = $(SGX_GET_TOKEN) -output $@ -sig $^ > .output.sgx_get_token.$(basename $*)
 
 # sgx manifest dependency
 quiet_cmd_sgx_manifest_dependency = [ $@ ]

+ 1 - 1
Pal/regression/Makefile

@@ -106,4 +106,4 @@ pal-regression.xml: test_pal.py $(call expand_target,$(target))
 
 .PHONY: clean
 clean:
-	rm -rf $(call expand_target,$(target)) $(preloads) *.tmp .lib *.cached *.sig *.d
+	rm -rf $(call expand_target,$(target)) $(preloads) *.tmp .lib *.cached *.sig *.d .output.*

+ 6 - 0
Pal/src/host/Linux-SGX/generated-offsets.c

@@ -22,6 +22,12 @@ void dummy(void)
     DEFINE(SGX_XFRM_AVX512, SGX_XFRM_AVX512);
     DEFINE(SGX_MISCSELECT_EXINFO, SGX_MISCSELECT_EXINFO);
 
+    /* sgx_arch_key_t */
+    DEFINE(SGX_ARCH_KEY_SIZE, sizeof(sgx_arch_key_t));
+
+    /* sgx_arch_hash_t */
+    DEFINE(SGX_ARCH_HASH_SIZE, sizeof(sgx_arch_hash_t));
+
     /* sgx_arch_gpr_t */
     OFFSET_T(SGX_GPR_RAX, sgx_arch_gpr_t, rax);
     OFFSET_T(SGX_GPR_RCX, sgx_arch_gpr_t, rcx);

+ 45 - 21
Pal/src/host/Linux-SGX/signer/aesm_pb2.py

@@ -1,19 +1,27 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: aesm.proto
 
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
 from google.protobuf import descriptor as _descriptor
 from google.protobuf import message as _message
 from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
 from google.protobuf import descriptor_pb2
 # @@protoc_insertion_point(imports)
 
+_sym_db = _symbol_database.Default()
+
 
 
 
 DESCRIPTOR = _descriptor.FileDescriptor(
   name='aesm.proto',
   package='',
-  serialized_pb='\n\naesm.proto\"U\n\x0eGetTokenReqRaw\x12\x11\n\tsignature\x18\x01 \x02(\x0c\x12\x0b\n\x03key\x18\x02 \x02(\x0c\x12\x12\n\nattributes\x18\x03 \x02(\x0c\x12\x0f\n\x07timeout\x18\t \x02(\r\"+\n\x0bGetTokenReq\x12\x1c\n\x03req\x18\x03 \x02(\x0b\x32\x0f.GetTokenReqRaw\".\n\x0eGetTokenRetRaw\x12\r\n\x05\x65rror\x18\x01 \x02(\x05\x12\r\n\x05token\x18\x02 \x01(\x0c\"+\n\x0bGetTokenRet\x12\x1c\n\x03ret\x18\x03 \x02(\x0b\x32\x0f.GetTokenRetRaw')
+  syntax='proto2',
+  serialized_pb=_b('\n\naesm.proto\"U\n\x0eGetTokenReqRaw\x12\x11\n\tsignature\x18\x01 \x02(\x0c\x12\x0b\n\x03key\x18\x02 \x02(\x0c\x12\x12\n\nattributes\x18\x03 \x02(\x0c\x12\x0f\n\x07timeout\x18\t \x02(\r\"+\n\x0bGetTokenReq\x12\x1c\n\x03req\x18\x03 \x02(\x0b\x32\x0f.GetTokenReqRaw\".\n\x0eGetTokenRetRaw\x12\r\n\x05\x65rror\x18\x01 \x02(\x05\x12\r\n\x05token\x18\x02 \x01(\x0c\"+\n\x0bGetTokenRet\x12\x1c\n\x03ret\x18\x03 \x02(\x0b\x32\x0f.GetTokenRetRaw')
+)
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
 
 
 
@@ -28,21 +36,21 @@ _GETTOKENREQRAW = _descriptor.Descriptor(
     _descriptor.FieldDescriptor(
       name='signature', full_name='GetTokenReqRaw.signature', index=0,
       number=1, type=12, cpp_type=9, label=2,
-      has_default_value=False, default_value="",
+      has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       options=None),
     _descriptor.FieldDescriptor(
       name='key', full_name='GetTokenReqRaw.key', index=1,
       number=2, type=12, cpp_type=9, label=2,
-      has_default_value=False, default_value="",
+      has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       options=None),
     _descriptor.FieldDescriptor(
       name='attributes', full_name='GetTokenReqRaw.attributes', index=2,
       number=3, type=12, cpp_type=9, label=2,
-      has_default_value=False, default_value="",
+      has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       options=None),
@@ -61,7 +69,10 @@ _GETTOKENREQRAW = _descriptor.Descriptor(
   ],
   options=None,
   is_extendable=False,
+  syntax='proto2',
   extension_ranges=[],
+  oneofs=[
+  ],
   serialized_start=14,
   serialized_end=99,
 )
@@ -89,7 +100,10 @@ _GETTOKENREQ = _descriptor.Descriptor(
   ],
   options=None,
   is_extendable=False,
+  syntax='proto2',
   extension_ranges=[],
+  oneofs=[
+  ],
   serialized_start=101,
   serialized_end=144,
 )
@@ -112,7 +126,7 @@ _GETTOKENRETRAW = _descriptor.Descriptor(
     _descriptor.FieldDescriptor(
       name='token', full_name='GetTokenRetRaw.token', index=1,
       number=2, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value="",
+      has_default_value=False, default_value=_b(""),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       options=None),
@@ -124,7 +138,10 @@ _GETTOKENRETRAW = _descriptor.Descriptor(
   ],
   options=None,
   is_extendable=False,
+  syntax='proto2',
   extension_ranges=[],
+  oneofs=[
+  ],
   serialized_start=146,
   serialized_end=192,
 )
@@ -152,7 +169,10 @@ _GETTOKENRET = _descriptor.Descriptor(
   ],
   options=None,
   is_extendable=False,
+  syntax='proto2',
   extension_ranges=[],
+  oneofs=[
+  ],
   serialized_start=194,
   serialized_end=237,
 )
@@ -164,29 +184,33 @@ DESCRIPTOR.message_types_by_name['GetTokenReq'] = _GETTOKENREQ
 DESCRIPTOR.message_types_by_name['GetTokenRetRaw'] = _GETTOKENRETRAW
 DESCRIPTOR.message_types_by_name['GetTokenRet'] = _GETTOKENRET
 
-class GetTokenReqRaw(_message.Message):
-  __metaclass__ = _reflection.GeneratedProtocolMessageType
-  DESCRIPTOR = _GETTOKENREQRAW
-
+GetTokenReqRaw = _reflection.GeneratedProtocolMessageType('GetTokenReqRaw', (_message.Message,), dict(
+  DESCRIPTOR = _GETTOKENREQRAW,
+  __module__ = 'aesm_pb2'
   # @@protoc_insertion_point(class_scope:GetTokenReqRaw)
+  ))
+_sym_db.RegisterMessage(GetTokenReqRaw)
 
-class GetTokenReq(_message.Message):
-  __metaclass__ = _reflection.GeneratedProtocolMessageType
-  DESCRIPTOR = _GETTOKENREQ
-
+GetTokenReq = _reflection.GeneratedProtocolMessageType('GetTokenReq', (_message.Message,), dict(
+  DESCRIPTOR = _GETTOKENREQ,
+  __module__ = 'aesm_pb2'
   # @@protoc_insertion_point(class_scope:GetTokenReq)
+  ))
+_sym_db.RegisterMessage(GetTokenReq)
 
-class GetTokenRetRaw(_message.Message):
-  __metaclass__ = _reflection.GeneratedProtocolMessageType
-  DESCRIPTOR = _GETTOKENRETRAW
-
+GetTokenRetRaw = _reflection.GeneratedProtocolMessageType('GetTokenRetRaw', (_message.Message,), dict(
+  DESCRIPTOR = _GETTOKENRETRAW,
+  __module__ = 'aesm_pb2'
   # @@protoc_insertion_point(class_scope:GetTokenRetRaw)
+  ))
+_sym_db.RegisterMessage(GetTokenRetRaw)
 
-class GetTokenRet(_message.Message):
-  __metaclass__ = _reflection.GeneratedProtocolMessageType
-  DESCRIPTOR = _GETTOKENRET
-
+GetTokenRet = _reflection.GeneratedProtocolMessageType('GetTokenRet', (_message.Message,), dict(
+  DESCRIPTOR = _GETTOKENRET,
+  __module__ = 'aesm_pb2'
   # @@protoc_insertion_point(class_scope:GetTokenRet)
+  ))
+_sym_db.RegisterMessage(GetTokenRet)
 
 
 # @@protoc_insertion_point(module_scope)

+ 62 - 121
Pal/src/host/Linux-SGX/signer/pal-sgx-get-token

@@ -1,52 +1,39 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 
+import argparse
 import os
-import sys
-import struct
 import socket
-from google.protobuf import message as _message
-import aesm_pb2
-
-""" Utilities """
-
-def int_to_bytes(i):
-    b = ""
-    l = 0
-    while i > 0:
-        b = b + chr(i % 256)
-        i = i // 256
-        l = l + 1
-    return b
+import struct
+import sys
 
-def bytes_to_int(b):
-    i = 0
-    for c in b:
-        i = i * 256 + ord(c)
-    return i
+import aesm_pb2
 
+sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
+from generated_offsets import *
 
-""" Reading Sigstruct """
 
 def read_sigstruct(sig):
+    """Reading Sigstruct."""
     # field format: (offset, type, value)
-    fields = dict()
-
-    fields['date']      = (  20, "<HBB", 'year', 'month', 'day')
-
-    fields['modulus']   = ( 128, "384s", 'modulus')
-    fields['exponent']  = ( 512, "<L",   'exponent')
-    fields['signature'] = ( 516, "384s", 'signature')
-
-    fields['miscs']     = ( 900, "4s",   'miscs')
-    fields['miscmask']  = ( 904, "4s",   'miscmask')
-    fields['attrs']     = ( 928, "8s8s", 'flags', 'xfrms')
-    fields['attrmask']  = ( 944, "8s8s", 'flagmask', 'xfrmmask')
-    fields['mrenclave'] = ( 960, "32s",  'mrenclave')
-    fields['isvprodid'] = (1024, "<H",   'isvprodid')
-    fields['isvsvn']    = (1026, "<H",   'isvsvn')
+    # SGX_ARCH_SIGSTRUCT_
+    fields = {
+        'date': (SGX_ARCH_SIGSTRUCT_DATE, "<HBB", 'year', 'month', 'day'),
+        'modulus': (SGX_ARCH_SIGSTRUCT_MODULUS, "384s", 'modulus'),
+        'exponent': (SGX_ARCH_SIGSTRUCT_EXPONENT, "<L", 'exponent'),
+        'signature': (SGX_ARCH_SIGSTRUCT_SIGNATURE, "384s", 'signature'),
+
+        'miscs': (SGX_ARCH_SIGSTRUCT_MISCSELECT, "4s", 'miscs'),
+        'miscmask': (SGX_ARCH_SIGSTRUCT_MISCSELECT_MASK, "4s", 'miscmask'),
+        'attrs': (SGX_ARCH_SIGSTRUCT_ATTRIBUTES, "8s8s", 'flags', 'xfrms'),
+        'attrmask': (SGX_ARCH_SIGSTRUCT_ATTRIBUTES_MASK,
+                     "8s8s", 'flagmask', 'xfrmmask'),
+        'mrenclave': (SGX_ARCH_SIGSTRUCT_ENCLAVE_HASH, "32s", 'mrenclave'),
+        'isvprodid': (SGX_ARCH_SIGSTRUCT_ISVPRODID, "<H", 'isvprodid'),
+        'isvsvn': (SGX_ARCH_SIGSTRUCT_ISVSVN, "<H", 'isvsvn'),
+    }
 
     attr = dict()
-    for key, field in fields.items():
+    for field in fields.values():
         values = struct.unpack_from(field[1], sig, field[0])
 
         for i in range(len(values)):
@@ -54,9 +41,10 @@ def read_sigstruct(sig):
 
     return attr
 
-""" Connect with AESMD """
 
 def connect_aesmd(attr):
+    """Connect with AESMD."""
+
     req_msg = aesm_pb2.GetTokenReq()
     req_msg.req.signature = attr['mrenclave']
     req_msg.req.key = attr['modulus']
@@ -100,89 +88,42 @@ def connect_aesmd(attr):
 
     return ret_msg.ret.token
 
-""" Main Program """
-
-options = {
-#       Option name : (Required  Value)
-        'output':    (True,    'output'),
-        'sig':       (True,    'sigstruct file'),
-    }
-
-def usage():
-    usage_message = 'USAGE: ' + sys.argv[0] + ' -help|-h'
-
-    for opt, optval in options.items():
-        if not optval[0]:
-            usage_message += '['
-        usage_message += '|-' + opt
-        if optval[1]:
-            usage_message += ' <' + optval[1] + '>'
-        if not optval[0]:
-            usage_message += ']'
-
-    print >> sys.stderr, usage_message
-    os._exit(-1)
-
-def parse_args():
-    args = dict()
-    for opt, optval in options.items():
-        if optval[1] is None:
-            args[opt] = False
-
-    i = 1
-    while i < len(sys.argv):
-        got = sys.argv[i]
-
-        if got == '-help' or got == '-h':
-            usage()
-
-        invalid = True
-        for opt, optval in options.items():
-            if got != '-' + opt:
-                continue
-
-            if optval[1] is not None:
-                i += 1
-                if i == len(sys.argv):
-                    print >>sys.stderr, "Option %s needs a value." % (opt)
-                    usage()
-                args[opt] = sys.argv[i]
-            else:
-                args[opt] = True
-
-            invalid = False
-            break
-
-        if invalid:
-            print >>sys.stderr, "Unknown option: %s." % (got[1:])
-            usage()
-        i += 1
-
-    for opt, optval in options.items():
-        if optval[0] and opt not in args:
-            print >>sys.stderr, "Must specify %s <%s>." % (opt, optval[1])
-            usage()
-
-    return args
 
-if __name__ == "__main__":
-
-    # Parse arguments
-    args = parse_args()
+argparser = argparse.ArgumentParser()
+argparser.add_argument('--sig', '-sig', metavar='SIGNATURE',
+                       type=argparse.FileType('rb'), required=True,
+                       help='Input .sig file (contains SIGSTRUCT)')
+argparser.add_argument('--output', '-output', metavar='OUTPUT',
+                       type=argparse.FileType('wb'), required=True,
+                       help='Output .token file (contains EINITTOKEN)')
+
+
+def main(args=None):
+    """Main Program."""
+    args = argparser.parse_args(args)
+
+    attr = read_sigstruct(args.sig.read())
+
+    print("Attributes:")
+    print("    mrenclave: %s" % attr['mrenclave'].hex())
+    print("    isvprodid: %d" % attr['isvprodid'])
+    print("    isvsvn:    %d" % attr['isvsvn'])
+    print("    flags:     %016x" % int.from_bytes(attr['flags'],
+                                                  byteorder='big'))
+    print("    xfrms:     %016x" % int.from_bytes(attr['xfrms'],
+                                                  byteorder='big'))
+    print("    miscs:     %08x" % int.from_bytes(attr['miscs'],
+                                                 byteorder='big'))
+    print("    miscmask:  %08x" % int.from_bytes(attr['miscmask'],
+                                                 byteorder='big'))
+    print("    modulus:   %s..." % attr['modulus'].hex()[:32])
+    print("    exponent:  %d" % attr['exponent'])
+    print("    signature: %s..." % attr['signature'].hex()[:32])
 
-    attr = read_sigstruct(open(args['sig'], 'rb').read())
+    token = connect_aesmd(attr)
+    args.output.write(token)
+    return 0
 
-    print >>sys.stderr, "Attributes:"
-    print >>sys.stderr, "    mrenclave: %s" % (attr['mrenclave'].encode('hex'))
-    print >>sys.stderr, "    isvprodid: %d" % (attr['isvprodid'])
-    print >>sys.stderr, "    isvsvn:    %d" % (attr['isvsvn'])
-    print >>sys.stderr, "    flags:     %016x" % (bytes_to_int(attr['flags']))
-    print >>sys.stderr, "    xfrms:     %016x" % (bytes_to_int(attr['xfrms']))
-    print >>sys.stderr, "    miscs:     %08x"  % (bytes_to_int(attr['miscs']))
-    print >>sys.stderr, "    miscmask:  %08x"  % (bytes_to_int(attr['miscmask']))
-    print >>sys.stderr, "    modulus:   %s..." % (attr['modulus'].encode('hex')[:32])
-    print >>sys.stderr, "    exponent:  %d" % (attr['exponent'])
-    print >>sys.stderr, "    signature: %s..." % (attr['signature'].encode('hex')[:32])
 
-    token = connect_aesmd(attr)
-    open(args['output'], 'wb').write(token)
+if __name__ == "__main__":
+    sys.exit(main())

+ 288 - 312
Pal/src/host/Linux-SGX/signer/pal-sgx-sign

@@ -1,19 +1,19 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 
-import os
-import sys
-import re
+import argparse
 import datetime
-import struct
-import subprocess
 import hashlib
-import binascii
+import os
 import shutil
+import struct
+import subprocess
+import sys
 
 sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
 from generated_offsets import *
 
-""" Default / Architectural Options """
+
+# Default / Architectural Options
 
 ARCHITECTURE = "amd64"
 
@@ -23,44 +23,22 @@ DEFAULT_ENCLAVE_SIZE = '256M'
 DEFAULT_THREAD_NUM = 4
 enclave_heap_min = DEFAULT_HEAP_MIN
 
-""" Utilities """
 
-ZERO_PAGE = "\0" * PAGESIZE
+# Utilities
+
+ZERO_PAGE = bytes(PAGESIZE)
+
 
 def roundup(addr):
     remaining = addr % PAGESIZE
     if remaining:
         return addr + (PAGESIZE - remaining)
-    else:
-        return addr
+    return addr
+
 
 def rounddown(addr):
     return addr - addr % PAGESIZE
 
-def roundup_data(data):
-    return data + '\0' * (roundup(len(data)) - len(data))
-
-def int_to_bytes(i):
-    b = ""
-    l = 0
-    while i > 0:
-        b = b + chr(i % 256)
-        i = i // 256
-        l = l + 1
-    return b
-
-def bytes_to_int(b):
-    i = 0
-    for c in b:
-        i = i * 256 + ord(c)
-    return i
-
-def parse_int(s):
-    if len(s) > 2 and s.startswith("0x"):
-        return int(s[2:], 16)
-    if len(s) > 1 and s.startswith("0"):
-        return int(s[1:], 8)
-    return int(s)
 
 def parse_size(s):
     scale = 1
@@ -72,10 +50,10 @@ def parse_size(s):
         scale = 1024 * 1024 * 1024
     if scale != 1:
         s = s[:-1]
-    return parse_int(s) * scale
+    return int(s, 0) * scale
 
 
-""" Reading / Writing Manifests """
+# Reading / Writing Manifests
 
 def read_manifest(filename):
     manifest = dict()
@@ -105,6 +83,7 @@ def read_manifest(filename):
 
     return (manifest, manifest_layout)
 
+
 def output_manifest(filename, manifest, manifest_layout):
     with open(filename, 'w') as f:
         written = []
@@ -118,34 +97,35 @@ def output_manifest(filename, manifest, manifest_layout):
                 if line != '':
                     line += ' '
                 line += comment
-            print >>f, line
+            f.write(line)
+            f.write('\n')
 
-        print >>f
-        print >>f, "# Generated by Graphene"
-        print >>f
+        f.write('\n')
+        f.write("# Generated by Graphene\n")
+        f.write('\n')
 
-        for key in sorted(manifest.keys()):
+        for key in sorted(manifest):
             if key not in written:
-                print >>f, key, '=', manifest[key]
+                f.write("%s = %s\n" % (key, manifest[key]))
 
 
-""" Loading Enclave Attributes """
+# Loading Enclave Attributes
 
 def get_enclave_attributes(manifest):
     sgx_flags = {
-        'FLAG_DEBUG'          : struct.pack("<Q", SGX_FLAGS_DEBUG),
-        'FLAG_MODE64BIT'      : struct.pack("<Q", SGX_FLAGS_MODE64BIT),
+        'FLAG_DEBUG': struct.pack("<Q", SGX_FLAGS_DEBUG),
+        'FLAG_MODE64BIT': struct.pack("<Q", SGX_FLAGS_MODE64BIT),
     }
 
     sgx_xfrms = {
-        'XFRM_LEGACY'         : struct.pack("<Q", SGX_XFRM_LEGACY),
-        'XFRM_AVX'            : struct.pack("<Q", SGX_XFRM_AVX),
-        'XFRM_AVX512'         : struct.pack("<Q", SGX_XFRM_AVX512),
-        'XFRM_MPX'            : struct.pack("<Q", SGX_XFRM_MPX),
+        'XFRM_LEGACY': struct.pack("<Q", SGX_XFRM_LEGACY),
+        'XFRM_AVX': struct.pack("<Q", SGX_XFRM_AVX),
+        'XFRM_AVX512': struct.pack("<Q", SGX_XFRM_AVX512),
+        'XFRM_MPX': struct.pack("<Q", SGX_XFRM_MPX),
     }
 
     sgx_miscs = {
-        'MISC_EXINFO'         : struct.pack("<L", SGX_MISCSELECT_EXINFO),
+        'MISC_EXINFO': struct.pack("<L", SGX_MISCSELECT_EXINFO),
     }
 
     default_attributes = {
@@ -166,7 +146,7 @@ def get_enclave_attributes(manifest):
 
     attributes = default_attributes
 
-    for opt in manifest_options.keys():
+    for opt in manifest_options:
         key = 'sgx.' + opt
         if key in manifest:
             if manifest[key] == '1':
@@ -180,16 +160,19 @@ def get_enclave_attributes(manifest):
 
     for attr in attributes:
         if attr in sgx_flags:
-            flags_raw = ''.join([chr(ord(a)|ord(b)) for a, b in zip(flags_raw, sgx_flags[attr])])
+            flags_raw = bytes([a | b for a, b in
+                               zip(flags_raw, sgx_flags[attr])])
         if attr in sgx_xfrms:
-            xfrms_raw = ''.join([chr(ord(a)|ord(b)) for a, b in zip(xfrms_raw, sgx_xfrms[attr])])
+            xfrms_raw = bytes([a | b for a, b in
+                               zip(xfrms_raw, sgx_xfrms[attr])])
         if attr in sgx_miscs:
-            miscs_raw = ''.join([chr(ord(a)|ord(b)) for a, b in zip(miscs_raw, sgx_miscs[attr])])
+            miscs_raw = bytes([a | b for a, b in
+                               zip(miscs_raw, sgx_miscs[attr])])
 
     return flags_raw, xfrms_raw, miscs_raw
 
 
-""" Generate Checksums / Measurement """
+# Generate Checksums / Measurement
 
 def resolve_uri(uri, check_exist=True):
     orig_uri = uri
@@ -198,15 +181,18 @@ def resolve_uri(uri, check_exist=True):
     else:
         target = os.path.normpath(uri)
     if check_exist and not os.path.exists(target):
-        raise Exception('Cannot resolve ' + orig_uri + ' or the file does not exist.')
+        raise Exception(
+            'Cannot resolve ' + orig_uri + ' or the file does not exist.')
     return target
 
+
 def get_checksum(file):
     digest = hashlib.sha256()
     with open(file, 'rb') as f:
         digest.update(f.read())
     return digest.digest()
 
+
 def get_trusted_files(manifest, args):
     targets = dict()
 
@@ -226,17 +212,19 @@ def get_trusted_files(manifest, args):
             continue
         key = key[len('sgx.trusted_files.'):]
         if key in targets:
-            raise Exception('repeated key in manifest: sgx.trusted_files.' + key)
+            raise Exception(
+                'repeated key in manifest: sgx.trusted_files.' + key)
         targets[key] = (val, resolve_uri(val))
 
     for (key, val) in targets.items():
         (uri, target) = val
-        checksum = get_checksum(target).encode('hex')
+        checksum = get_checksum(target).hex()
         targets[key] = (uri, target, checksum)
 
     return targets
 
-def get_trusted_children(manifest, args):
+
+def get_trusted_children(manifest):
     targets = dict()
 
     for (key, val) in manifest.items():
@@ -244,17 +232,21 @@ def get_trusted_children(manifest, args):
             continue
         key = key[len('sgx.trusted_children.'):]
         if key in targets:
-            raise Exception('repeated key in manifest: sgx.trusted_children.' + key)
+            raise Exception(
+                'repeated key in manifest: sgx.trusted_children.' + key)
 
         target = resolve_uri(val)
         if not target.endswith('.sig'):
             target += '.sig'
-        sig = open(target, 'rb').read()[960:992].encode('hex')
+        sig = open(target, 'rb').read()[
+            SGX_ARCH_SIGSTRUCT_ENCLAVE_HASH:
+            SGX_ARCH_SIGSTRUCT_ENCLAVE_HASH + SGX_ARCH_HASH_SIZE].hex()
         targets[key] = (val, target, sig)
 
     return targets
 
-""" Populate Enclave Memory """
+
+# Populate Enclave Memory
 
 PAGEINFO_R = 0x1
 PAGEINFO_W = 0x2
@@ -262,15 +254,16 @@ PAGEINFO_X = 0x4
 PAGEINFO_TCS = 0x100
 PAGEINFO_REG = 0x200
 
+
 def get_loadcmds(filename):
     loadcmds = []
     p = subprocess.Popen(['readelf', '-l', '-W', filename],
-            stdout=subprocess.PIPE,
-            stderr=subprocess.PIPE)
+                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     while True:
         line = p.stdout.readline()
-        if line == '':
+        if not line:
             break
+        line = line.decode()
         stripped = line.strip()
         if not stripped.startswith('LOAD'):
             continue
@@ -298,8 +291,10 @@ def get_loadcmds(filename):
         return None
     return loadcmds
 
+
 class MemoryArea:
-    def __init__(self, desc, file=None, content=None, addr=None, size=None, flags=None, measure=True):
+    def __init__(self, desc, file=None, content=None, addr=None, size=None,
+                 flags=None, measure=True):
         self.desc = desc
         self.file = file
         self.content = content
@@ -314,11 +309,11 @@ class MemoryArea:
             if loadcmds:
                 mapaddr = 0xffffffffffffffff
                 mapaddr_end = 0
-                for (offset, addr, filesize, memsize, prot) in loadcmds:
-                    if rounddown(addr) < mapaddr:
-                        mapaddr = rounddown(addr)
-                    if roundup(addr + memsize) > mapaddr_end:
-                        mapaddr_end = roundup(addr + memsize)
+                for (_, addr_, _, memsize, _) in loadcmds:
+                    if rounddown(addr_) < mapaddr:
+                        mapaddr = rounddown(addr_)
+                    if roundup(addr_ + memsize) > mapaddr_end:
+                        mapaddr_end = roundup(addr_ + memsize)
 
                 self.is_binary = True
                 self.size = mapaddr_end - mapaddr
@@ -332,54 +327,64 @@ class MemoryArea:
         if self.size is not None:
             self.size = roundup(self.size)
 
-def get_memory_areas(manifest, attr, args):
+
+def get_memory_areas(attr, args):
     areas = []
-    areas.append(MemoryArea('ssa', size=attr['thread_num'] * SSAFRAMESIZE * SSAFRAMENUM,
-                            flags=PAGEINFO_R|PAGEINFO_W|PAGEINFO_REG))
+    areas.append(
+        MemoryArea('ssa',
+                   size=attr['thread_num'] * SSAFRAMESIZE * SSAFRAMENUM,
+                   flags=PAGEINFO_R | PAGEINFO_W | PAGEINFO_REG))
     areas.append(MemoryArea('tcs', size=attr['thread_num'] * TCS_SIZE,
                             flags=PAGEINFO_TCS))
     areas.append(MemoryArea('tls', size=attr['thread_num'] * PAGESIZE,
-                            flags=PAGEINFO_R|PAGEINFO_W|PAGEINFO_REG))
+                            flags=PAGEINFO_R | PAGEINFO_W | PAGEINFO_REG))
 
-    for t in range(attr['thread_num']):
+    for _ in range(attr['thread_num']):
         areas.append(MemoryArea('stack', size=ENCLAVE_STACK_SIZE,
-                                flags=PAGEINFO_R|PAGEINFO_W|PAGEINFO_REG))
+                                flags=PAGEINFO_R | PAGEINFO_W | PAGEINFO_REG))
 
     areas.append(MemoryArea('pal', file=args['libpal'], flags=PAGEINFO_REG))
 
     if 'exec' in args:
         areas.append(MemoryArea('exec', file=args['exec'],
-                                flags=PAGEINFO_W|PAGEINFO_REG))
+                                flags=PAGEINFO_W | PAGEINFO_REG))
     return areas
 
+
 def find_areas(areas, desc):
-    return filter(lambda area: area.desc == desc, areas)
+    return [area for area in areas if area.desc == desc]
+
 
 def find_area(areas, desc, allow_none=False):
     matching = find_areas(areas, desc)
 
-    if len(matching) == 0 and allow_none:
+    if not matching and allow_none:
         return None
 
     if len(matching) != 1:
-        raise KeyError("Could not find exactly one MemoryArea '{}'".format(desc))
+        raise KeyError(
+            "Could not find exactly one MemoryArea '{}'".format(desc))
 
     return matching[0]
 
+
 def entry_point(elf_path):
     env = os.environ
     env['LC_ALL'] = 'C'
-    out = subprocess.check_output(['readelf', '-l', '--', elf_path], env = env)
+    out = subprocess.check_output(
+        ['readelf', '-l', '--', elf_path], env=env)
     for line in out.splitlines():
+        line = line.decode()
         if line.startswith("Entry point "):
-            return parse_int(line[12:])
+            return int(line[12:], 0)
     raise ValueError("Could not find entry point of elf file")
 
+
 def baseaddr():
     if enclave_heap_min == 0:
         return ENCLAVE_HIGH_ADDRESS
-    else:
-        return 0
+    return 0
+
 
 def gen_area_content(attr, areas):
     manifest_area = find_area(areas, 'manifest')
@@ -391,10 +396,12 @@ def gen_area_content(attr, areas):
     stacks = find_areas(areas, 'stack')
 
     tcs_data = bytearray(tcs_area.size)
+
     def set_tcs_field(t, offset, pack_fmt, value):
         struct.pack_into(pack_fmt, tcs_data, t * TCS_SIZE + offset, value)
 
     tls_data = bytearray(tls_area.size)
+
     def set_tls_field(t, offset, value):
         struct.pack_into('<Q', tls_data, t * PAGESIZE + offset, value)
 
@@ -403,29 +410,35 @@ def gen_area_content(attr, areas):
     # Sanity check that we measure everything except the heap which is zeroed
     # on enclave startup.
     for area in areas:
-        if area.addr + area.size <= enclave_heap_min or area.addr >= enclave_heap_max or area is exec_area:
+        if (area.addr + area.size <= enclave_heap_min or
+                area.addr >= enclave_heap_max or area is exec_area):
             if not area.measure:
-                raise ValueError("Memory area, which is not the heap, is not measured")
+                raise ValueError("Memory area, which is not the heap, "
+                                 "is not measured")
         elif area.desc != 'free':
             raise ValueError("Unexpected memory area is in heap range")
 
     for t in range(0, attr['thread_num']):
-        ssa_offset = ssa_area.addr + SSAFRAMESIZE * SSAFRAMENUM * t;
+        ssa_offset = ssa_area.addr + SSAFRAMESIZE * SSAFRAMENUM * t
         ssa = baseaddr() + ssa_offset
         set_tcs_field(t, TCS_OSSA, '<Q', ssa_offset)
         set_tcs_field(t, TCS_NSSA, '<L', SSAFRAMENUM)
-        set_tcs_field(t, TCS_OENTRY, '<Q', pal_area.addr + entry_point(pal_area.file))
+        set_tcs_field(t, TCS_OENTRY, '<Q',
+                      pal_area.addr + entry_point(pal_area.file))
         set_tcs_field(t, TCS_OGSBASGX, '<Q', tls_area.addr + PAGESIZE * t)
         set_tcs_field(t, TCS_FSLIMIT, '<L', 0xfff)
         set_tcs_field(t, TCS_GSLIMIT, '<L', 0xfff)
 
-        set_tls_field(t, SGX_COMMON_SELF, tls_area.addr + PAGESIZE * t + baseaddr())
+        set_tls_field(t, SGX_COMMON_SELF,
+                      tls_area.addr + PAGESIZE * t + baseaddr())
         set_tls_field(t, SGX_ENCLAVE_SIZE, attr['enclave_size'])
         set_tls_field(t, SGX_TCS_OFFSET, tcs_area.addr + TCS_SIZE * t)
-        set_tls_field(t, SGX_INITIAL_STACK_OFFSET, stacks[t].addr + stacks[t].size)
+        set_tls_field(t, SGX_INITIAL_STACK_OFFSET,
+                      stacks[t].addr + stacks[t].size)
         set_tls_field(t, SGX_SSA, ssa)
         set_tls_field(t, SGX_GPR, ssa + SSAFRAMESIZE - SGX_GPR_SIZE)
-        set_tls_field(t, SGX_MANIFEST_SIZE, os.stat(manifest_area.file).st_size)
+        set_tls_field(t, SGX_MANIFEST_SIZE,
+                      os.stat(manifest_area.file).st_size)
         set_tls_field(t, SGX_HEAP_MIN, baseaddr() + enclave_heap_min)
         set_tls_field(t, SGX_HEAP_MAX, baseaddr() + enclave_heap_max)
         if exec_area is not None:
@@ -435,7 +448,8 @@ def gen_area_content(attr, areas):
     tcs_area.content = tcs_data
     tls_area.content = tls_data
 
-def populate_memory_areas(manifest, attr, areas):
+
+def populate_memory_areas(attr, areas):
     populating = attr['enclave_size']
 
     for area in areas:
@@ -446,7 +460,7 @@ def populate_memory_areas(manifest, attr, areas):
         if area.addr < enclave_heap_min:
             raise Exception("Enclave size is not large enough")
         if area.desc == 'exec':
-            populating = area.addr;
+            populating = area.addr
         else:
             populating = area.addr - MEMORY_GAP
 
@@ -454,36 +468,40 @@ def populate_memory_areas(manifest, attr, areas):
     for area in areas:
         if area.addr + area.size < populating:
             addr = area.addr + area.size
-            free_areas.append(MemoryArea('free', addr=addr, size=populating - addr,
-                                flags=PAGEINFO_R|PAGEINFO_W|PAGEINFO_X|PAGEINFO_REG,
-                                measure=False))
+            flags = PAGEINFO_R | PAGEINFO_W | PAGEINFO_X | PAGEINFO_REG
+            free_areas.append(
+                MemoryArea('free', addr=addr, size=populating - addr,
+                           flags=flags, measure=False))
             populating = area.addr
 
     if populating > enclave_heap_min:
-        free_areas.append(MemoryArea('free', addr=enclave_heap_min,
-                                     size=populating - enclave_heap_min,
-                                     flags=PAGEINFO_R|PAGEINFO_W|PAGEINFO_X|PAGEINFO_REG,
-                                     measure=False))
+        flags = PAGEINFO_R | PAGEINFO_W | PAGEINFO_X | PAGEINFO_REG
+        free_areas.append(
+            MemoryArea('free', addr=enclave_heap_min,
+                       size=populating - enclave_heap_min, flags=flags,
+                       measure=False))
 
     gen_area_content(attr, areas)
 
     return areas + free_areas
 
+
 def generate_measurement(attr, areas):
 
     def do_ecreate(digest, size):
-        data = struct.pack("<8sLQ44s", "ECREATE", SSAFRAMESIZE / PAGESIZE, size, "")
+        data = struct.pack("<8sLQ44s", b"ECREATE", SSAFRAMESIZE // PAGESIZE,
+                           size, b"")
         digest.update(data)
 
     def do_eadd(digest, offset, flags):
-        data = struct.pack("<8sQQ40s", "EADD", offset, flags, "")
+        data = struct.pack("<8sQQ40s", b"EADD", offset, flags, b"")
         digest.update(data)
 
     def do_eextend(digest, offset, content):
         if len(content) != 256:
             raise ValueError("Exactly 256 bytes expected")
 
-        data = struct.pack("<8sQ48s", "EEXTEND", offset, "")
+        data = struct.pack("<8sQ48s", b"EEXTEND", offset, b"")
         digest.update(data)
         digest.update(content)
 
@@ -501,9 +519,9 @@ def generate_measurement(attr, areas):
 
     def print_area(addr, size, flags, desc, measured):
         if flags & PAGEINFO_REG:
-            type = 'REG'
+            type_ = 'REG'
         if flags & PAGEINFO_TCS:
-            type = 'TCS'
+            type_ = 'TCS'
         prot = ['-', '-', '-']
         if flags & PAGEINFO_R:
             prot[0] = 'R'
@@ -518,14 +536,14 @@ def generate_measurement(attr, areas):
             desc += ' measured'
 
         if size == PAGESIZE:
-            print >>sys.stderr, "    %016x [%s:%s] %s" % (addr, type, prot, desc)
+            print("    %016x [%s:%s] %s" % (addr, type_, prot, desc))
         else:
-            print >>sys.stderr, "    %016x-%016lx [%s:%s] %s" % (addr, addr + size, type, prot, desc)
+            print("    %016x-%016lx [%s:%s] %s" %
+                  (addr, addr + size, type_, prot, desc))
 
     def load_file(digest, f, offset, addr, filesize, memsize, desc, flags):
         f_addr = rounddown(offset)
         m_addr = rounddown(addr)
-        f_size = roundup(offset + filesize) - f_addr
         m_size = roundup(addr + memsize) - m_addr
 
         print_area(m_addr, m_size, flags, desc, True)
@@ -533,27 +551,27 @@ def generate_measurement(attr, areas):
         for pg in range(m_addr, m_addr + m_size, PAGESIZE):
             start = pg - m_addr + f_addr
             end = start + PAGESIZE
-            start_zero = ""
+            start_zero = b""
             if start < offset:
                 if offset - start >= PAGESIZE:
                     start_zero = ZERO_PAGE
                 else:
-                    start_zero = chr(0) * (offset - start)
-            end_zero = ""
+                    start_zero = bytes(offset - start)
+            end_zero = b""
             if end > offset + filesize:
                 if end - offset - filesize >= PAGESIZE:
                     end_zero = ZERO_PAGE
                 else:
-                    end_zero = chr(0) * (end - offset - filesize)
+                    end_zero = bytes(end - offset - filesize)
             start += len(start_zero)
             end -= len(end_zero)
             if start < end:
                 f.seek(start)
                 data = f.read(end - start)
             else:
-                data = ""
+                data = b""
             if len(start_zero + data + end_zero) != PAGESIZE:
-                    raise Exception("wrong calculation")
+                raise Exception("wrong calculation")
 
             include_page(digest, pg, flags, start_zero + data + end_zero, True)
 
@@ -564,10 +582,11 @@ def generate_measurement(attr, areas):
                     loadcmds = get_loadcmds(area.file)
                     if loadcmds:
                         mapaddr = 0xffffffffffffffff
-                        for (offset, addr, filesize, memsize, prot) in loadcmds:
+                        for (offset, addr, filesize, memsize,
+                             prot) in loadcmds:
                             if rounddown(addr) < mapaddr:
                                 mapaddr = rounddown(addr)
-                    baseaddr = area.addr - mapaddr
+                    baseaddr_ = area.addr - mapaddr
                     for (offset, addr, filesize, memsize, prot) in loadcmds:
                         flags = area.flags
                         if prot & 4:
@@ -581,7 +600,7 @@ def generate_measurement(attr, areas):
                             desc = 'code'
                         else:
                             desc = 'data'
-                        load_file(mrenclave, f, offset, baseaddr + addr,
+                        load_file(mrenclave, f, offset, baseaddr_ + addr,
                                   filesize, memsize, desc, flags)
                 else:
                     load_file(mrenclave, f, 0, area.addr,
@@ -597,177 +616,128 @@ def generate_measurement(attr, areas):
 
                 include_page(mrenclave, a, area.flags, data, area.measure)
 
-            print_area(area.addr, area.size, area.flags, area.desc, area.measure)
+            print_area(area.addr, area.size, area.flags, area.desc,
+                       area.measure)
 
     return mrenclave.digest()
 
-""" Generate Sigstruct """
 
 def generate_sigstruct(attr, args, mrenclave):
+    """Generate Sigstruct."""
     today = datetime.date.today()
 
     # field format: (offset, type, value)
-    fields = dict()
-
-    fields['header']    = (SGX_ARCH_SIGSTRUCT_HEADER,
-                           "<4L",  0x00000006, 0x000000e1, 0x00010000, 0x00000000)
-    fields['vendor']    = (SGX_ARCH_SIGSTRUCT_VENDOR,
-                           "<L",   0x00000000)
-    fields['date']      = (SGX_ARCH_SIGSTRUCT_DATE,
-                           "<HBB", today.year, today.month, today.day)
-    fields['header2']   = (SGX_ARCH_SIGSTRUCT_HEADER2,
-                           "<4L",  0x00000101, 0x00000060, 0x00000060, 0x00000001)
-    fields['swdefined'] = (SGX_ARCH_SIGSTRUCT_SWDEFINED,
-                           "<L",   0x00000000)
-
-    fields['miscs']     = (SGX_ARCH_SIGSTRUCT_MISCSELECT,
-                           "4s",   attr['miscs'])
-    fields['miscmask']  = (SGX_ARCH_SIGSTRUCT_MISCSELECT_MASK,
-                           "4s",   attr['miscs'])
-    fields['attrs']     = (SGX_ARCH_SIGSTRUCT_ATTRIBUTES,
-                           "8s8s", attr['flags'], attr['xfrms'])
-    fields['attrmask']  = (SGX_ARCH_SIGSTRUCT_ATTRIBUTES_MASK,
-                           "8s8s", attr['flags'], attr['xfrms'])
-    fields['mrenclave'] = (SGX_ARCH_SIGSTRUCT_ENCLAVE_HASH,
-                           "32s",  mrenclave)
-    fields['isvprodid'] = (SGX_ARCH_SIGSTRUCT_ISVPRODID,
-                           "<H",   attr['isvprodid'])
-    fields['isvsvn']    = (SGX_ARCH_SIGSTRUCT_ISVSVN,
-                           "<H",   attr['isvsvn'])
+    fields = {
+        'header': (SGX_ARCH_SIGSTRUCT_HEADER,
+                   "<4L", 0x00000006, 0x000000e1, 0x00010000, 0x00000000),
+        'vendor': (SGX_ARCH_SIGSTRUCT_VENDOR, "<L", 0x00000000),
+        'date': (SGX_ARCH_SIGSTRUCT_DATE,
+                 "<HBB", today.year, today.month, today.day),
+        'header2': (SGX_ARCH_SIGSTRUCT_HEADER2,
+                    "<4L", 0x00000101, 0x00000060, 0x00000060, 0x00000001),
+        'swdefined': (SGX_ARCH_SIGSTRUCT_SWDEFINED, "<L", 0x00000000),
+
+        'miscs': (SGX_ARCH_SIGSTRUCT_MISCSELECT, "4s", attr['miscs']),
+        'miscmask': (SGX_ARCH_SIGSTRUCT_MISCSELECT_MASK, "4s", attr['miscs']),
+        'attrs': (SGX_ARCH_SIGSTRUCT_ATTRIBUTES,
+                  "8s8s", attr['flags'], attr['xfrms']),
+        'attrmask': (SGX_ARCH_SIGSTRUCT_ATTRIBUTES_MASK,
+                     "8s8s", attr['flags'], attr['xfrms']),
+        'mrenclave': (SGX_ARCH_SIGSTRUCT_ENCLAVE_HASH, "32s", mrenclave),
+        'isvprodid': (SGX_ARCH_SIGSTRUCT_ISVPRODID, "<H", attr['isvprodid']),
+        'isvsvn': (SGX_ARCH_SIGSTRUCT_ISVSVN, "<H", attr['isvsvn']),
+    }
 
     sign_buffer = bytearray(128 + 128)
 
-    for key, field in fields.items():
-        if field[0] >= 900:
-            struct.pack_into(field[1], sign_buffer, field[0] - 900 + 128, *field[2:])
+    for field in fields.values():
+        if field[0] >= SGX_ARCH_SIGSTRUCT_MISCSELECT:
+            struct.pack_into(field[1], sign_buffer,
+                             field[0] - SGX_ARCH_SIGSTRUCT_MISCSELECT + 128,
+                             *field[2:])
         else:
             struct.pack_into(field[1], sign_buffer, field[0], *field[2:])
 
-    p = subprocess.Popen(['openssl', 'rsa', '-modulus', '-in', args['key'], '-noout'], stdout=subprocess.PIPE)
+    p = subprocess.Popen(
+        ['openssl', 'rsa', '-modulus', '-in', args['key'], '-noout'],
+        stdout=subprocess.PIPE)
     modulus_out = p.communicate()[0]
-    modulus = modulus_out[8:8+384*2].lower().decode('hex')
-    modulus = modulus[::-1]
+    modulus = bytes.fromhex(modulus_out[8:8+SGX_ARCH_KEY_SIZE*2].decode())
+    modulus = bytes(reversed(modulus))
 
-    p = subprocess.Popen(['openssl', 'sha256', '-binary', '-sign', args['key']],
-            stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+    p = subprocess.Popen(
+        ['openssl', 'sha256', '-binary', '-sign', args['key']],
+        stdin=subprocess.PIPE, stdout=subprocess.PIPE)
     signature = p.communicate(sign_buffer)[0]
     signature = signature[::-1]
 
-    def bytes_to_int(bytes):
-        i = 0
-        q = 1
-        for digit in bytes:
-            if ord(digit) != 0:
-                i = i + ord(digit) * q
-            q = q * 256
-        return i
-
-    def int_to_bytes(i):
-        b = ""
-        l = 0
-        while i > 0:
-            b = b + chr(i % 256)
-            i = i // 256
-            l = l + 1
-        return b
-
-    modulus_int = bytes_to_int(modulus)
-    signature_int = bytes_to_int(signature)
-
-    tmp1   = signature_int * signature_int
+    modulus_int = int.from_bytes(modulus, byteorder='little')
+    signature_int = int.from_bytes(signature, byteorder='little')
+
+    tmp1 = signature_int * signature_int
     q1_int = tmp1 // modulus_int
-    tmp2   = tmp1 % modulus_int
+    tmp2 = tmp1 % modulus_int
     q2_int = tmp2 * signature_int // modulus_int
 
-    q1 = int_to_bytes(q1_int)
-    q2 = int_to_bytes(q2_int)
+    q1 = q1_int.to_bytes(384, byteorder='little')
+    q2 = q2_int.to_bytes(384, byteorder='little')
 
-    fields['modulus']   = (SGX_ARCH_SIGSTRUCT_MODULUS, "384s", modulus)
-    fields['exponent']  = (SGX_ARCH_SIGSTRUCT_EXPONENT, "<L",   3)
-    fields['signature'] = (SGX_ARCH_SIGSTRUCT_SIGNATURE, "384s", signature)
+    fields.update({
+        'modulus': (SGX_ARCH_SIGSTRUCT_MODULUS, "384s", modulus),
+        'exponent': (SGX_ARCH_SIGSTRUCT_EXPONENT, "<L", 3),
+        'signature': (SGX_ARCH_SIGSTRUCT_SIGNATURE, "384s", signature),
 
-    fields['q1']        = (SGX_ARCH_SIGSTRUCT_Q1, "384s", q1)
-    fields['q2']        = (SGX_ARCH_SIGSTRUCT_Q2, "384s", q2)
+        'q1': (SGX_ARCH_SIGSTRUCT_Q1, "384s", q1),
+        'q2': (SGX_ARCH_SIGSTRUCT_Q2, "384s", q2),
+    })
 
     buffer = bytearray(SGX_ARCH_SIGSTRUCT_SIZE)
 
-    for key, field in fields.items():
+    for field in fields.values():
         struct.pack_into(field[1], buffer, field[0], *field[2:])
 
     return buffer
 
-""" Main Program """
-
-options = {
-#       Option name : (Required  Value)
-        'output':    (True,    'output'),
-        'libpal':    (True,    'libpal path'),
-        'key':       (True,    'signing key'),
-        'manifest':  (True,    'manifest'),
-        'exec':      (False,   'executable'),
+# Main Program
+
+argparser = argparse.ArgumentParser()
+argparser.add_argument('--output', '-output', metavar='OUTPUT',
+                       type=str, required=True,
+                       help='Output .manifest.sgx file '
+                            '(manifest augmented with autogenerated fields)')
+argparser.add_argument('--libpal', '-libpal', metavar='LIBPAL',
+                       type=str, required=True,
+                       help='Input libpal file '
+                            '(required as part of the enclave measurement)')
+argparser.add_argument('--key', '-key', metavar='KEY',
+                       type=str, required=True,
+                       help='specify signing key(.pem) file')
+argparser.add_argument('--manifest', '-manifest', metavar='MANIFEST',
+                       type=str, required=True,
+                       help='Input .manifest file '
+                            '(user-prepared manifest template)')
+argparser.add_argument('--exec', '-exec', metavar='EXEC',
+                       type=str, required=False,
+                       help='Input executable file '
+                            '(required as part of the enclave measurement)')
+
+
+def parse_args(args):
+    args = argparser.parse_args(args)
+    args_dict = {
+        'output': args.output,
+        'libpal': args.libpal,
+        'key': args.key,
+        'manifest': args.manifest,
     }
+    if args.exec is not None:
+        args_dict['exec'] = args.exec
 
-def usage():
-    usage_message = 'USAGE: ' + sys.argv[0] + ' -help|-h'
-
-    for opt, optval in options.items():
-        if not optval[0]:
-            usage_message += '['
-        usage_message += '|-' + opt
-        if optval[1]:
-            usage_message += ' <' + optval[1] + '>'
-        if not optval[0]:
-            usage_message += ']'
-
-    print >> sys.stderr, usage_message
-    os._exit(-1)
-
-def parse_args():
-    args = dict()
-    for opt, optval in options.items():
-        if not optval[1]:
-            args[opt] = False
-
-    i = 1
-    while i < len(sys.argv):
-        got = sys.argv[i]
-
-        if got == '-help' or got == '-h':
-            usage()
-
-        invalid = True
-        for opt, optval in options.items():
-            if got != '-' + opt:
-                continue
-
-            if optval[1] is not None:
-                i += 1
-                if i == len(sys.argv):
-                    print >>sys.stderr, "Option %s needs a value." % (opt)
-                    usage()
-                args[opt] = sys.argv[i]
-            else:
-                args[opt] = True
-
-            invalid = False
-            break
-
-        if invalid:
-            print >>sys.stderr, "Unknown option: %s." % (got[1:])
-            usage()
-        i += 1
+    return args_dict
 
-    for opt, optval in options.items():
-        if optval[0] and opt not in args:
-            print >>sys.stderr, "Must specify %s <%s>." % (opt, optval[1])
-            usage()
-
-    return args
-
-if __name__ == "__main__":
 
-    # Parse arguments
-    args = parse_args()
+def main(args=None):
+    args = parse_args(args)
 
     (manifest, manifest_layout) = read_manifest(args['manifest'])
 
@@ -775,10 +745,11 @@ if __name__ == "__main__":
         if 'loader.exec' in manifest:
             exec_url = manifest['loader.exec']
             if exec_url[:5] != 'file:':
-                print "executable must be a local file"
-                os._exit(-1)
+                print("executable must be a local file", file=sys.stderr)
+                return -1
 
-            args['exec'] = os.path.join(os.path.dirname(args['manifest']), exec_url[5:])
+            args['exec'] = os.path.join(os.path.dirname(args['manifest']),
+                                        exec_url[5:])
 
     args['root'] = os.path.dirname(os.path.abspath(args['output']))
 
@@ -795,69 +766,69 @@ if __name__ == "__main__":
 
     # Get attributes from manifest
     attr = dict()
+    parse_int = lambda s: int(s, 0)
 
     for key, default, parse in [
-        ('enclave_size', DEFAULT_ENCLAVE_SIZE,    parse_size),
-        ('thread_num',   str(DEFAULT_THREAD_NUM), parse_int),
-        ('isvprodid',    '0',                     parse_int),
-        ('isvsvn',       '0',                     parse_int),
+            ('enclave_size', DEFAULT_ENCLAVE_SIZE, parse_size),
+            ('thread_num', str(DEFAULT_THREAD_NUM), parse_int),
+            ('isvprodid', '0', parse_int),
+            ('isvsvn', '0', parse_int),
     ]:
-        if 'sgx.' + key not in manifest:
-            manifest['sgx.' + key] = default
-        attr[key] = parse(manifest['sgx.' + key])
-
-    (attr['flags'], attr['xfrms'], attr['miscs']) = get_enclave_attributes(manifest)
-
-    print >>sys.stderr, "Attributes:"
-    print >>sys.stderr, "    size:      %d" % (attr['enclave_size'])
-    print >>sys.stderr, "    threadnum: %d" % (attr['thread_num'])
-    print >>sys.stderr, "    isvprodid: %d" % (attr['isvprodid'])
-    print >>sys.stderr, "    isvsvn:    %d" % (attr['isvsvn'])
-    print >>sys.stderr, "    flags:     %016x" % (bytes_to_int(attr['flags']))
-    print >>sys.stderr, "    xfrms:     %016x" % (bytes_to_int(attr['xfrms']))
-    print >>sys.stderr, "    miscs:     %08x"  % (bytes_to_int(attr['miscs']))
-
-    # Check client info for remote attestation. Skip and warn if sgx.ra_client.spid is not provided.
-    print >>sys.stderr, "Attestation:"
+        attr[key] = parse(manifest.setdefault('sgx.' + key, default))
+
+    (attr['flags'], attr['xfrms'], attr['miscs']) = get_enclave_attributes(
+        manifest)
+
+    print("Attributes:")
+    print("    size:      %d" % attr['enclave_size'])
+    print("    threadnum: %d" % attr['thread_num'])
+    print("    isvprodid: %d" % attr['isvprodid'])
+    print("    isvsvn:    %d" % attr['isvsvn'])
+    print("    flags:     %016x" % int.from_bytes(attr['flags'],
+                                                  byteorder='big'))
+    print("    xfrms:     %016x" % int.from_bytes(attr['xfrms'],
+                                                  byteorder='big'))
+    print("    miscs:     %08x" % int.from_bytes(attr['miscs'],
+                                                 byteorder='big'))
+
+    # Check client info for remote attestation (if sgx.ra_client.spid is provided)
+    print("Attestation:")
     if 'sgx.ra_client_spid' in manifest and manifest['sgx.ra_client_spid']:
-        print >>sys.stderr, "    spid:     " + manifest['sgx.ra_client_spid']
-        need_client_info = False
-        if 'sgx.ra_client_key' not in manifest or not manifest['sgx.ra_client_key']:
-            print >>sys.stderr, "    *** sgx.ra_client_key not specified ***"
-            need_client_info = True
+        print("    spid:     " + manifest['sgx.ra_client_spid'])
+        if 'sgx.ra_client_key' in manifest and manifest['sgx.ra_client_key']:
+            print("    key:   " + manifest['sgx.ra_client_key'])
         else:
-            print >>sys.stderr, "    key:   " + manifest['sgx.ra_client_key']
+            print("    *** sgx.ra_client_key not specified ***")
+            return -1
         if 'sgx.ra_client_linkable' in manifest:
-            print >>sys.stderr, "    linkable: " + manifest['sgx.ra_client_linkable']
+            print("    linkable: " + manifest['sgx.ra_client_linkable'])
         else:
-            print >>sys.stderr, "    linkable: 0"
-        if need_client_info: sys.exit(-1)
-
+            print("    linkable: 0")
     else:
-        print >>sys.stderr, "    *** Client info is not specified. Graphene" + \
-            " will not perform remote attestation before execution." + \
-            " Please provide sgx.ra_client_spid and sgx.ra_client_key in the manifest. ***"
-
+        print("    *** Client info is not specified. Graphene will not perform"
+              " remote attestation before execution. Please provide"
+              " sgx.ra_client_spid and sgx.ra_client_key in the manifest. ***")
 
     # Get trusted checksums and measurements
-    print >>sys.stderr, "Trusted files:"
+    print("Trusted files:")
     for key, val in get_trusted_files(manifest, args).items():
-        (uri, target, checksum) = val
-        print >>sys.stderr, "    %s %s" % (checksum, uri)
+        (uri, _, checksum) = val
+        print("    %s %s" % (checksum, uri))
         manifest['sgx.trusted_checksum.' + key] = checksum
 
-    print >>sys.stderr, "Trusted children:"
-    for key, val in get_trusted_children(manifest, args).items():
-        (uri, target, mrenclave) = val
-        print >>sys.stderr, "    %s %s" % (mrenclave, uri)
+    print("Trusted children:")
+    for key, val in get_trusted_children(manifest).items():
+        (uri, _, mrenclave) = val
+        print("    %s %s" % (mrenclave, uri))
         manifest['sgx.trusted_mrenclave.' + key] = mrenclave
 
     # Try populate memory areas
-    memory_areas = get_memory_areas(manifest, attr, args)
+    memory_areas = get_memory_areas(attr, args)
 
-    if len([a for a in memory_areas if a.addr is not None]) > 0:
+    if any([a.addr is not None for a in memory_areas]):
         manifest['sgx.static_address'] = '1'
     else:
+        global enclave_heap_min
         enclave_heap_min = 0
 
     # Add manifest at the top
@@ -865,18 +836,23 @@ if __name__ == "__main__":
     output_manifest(args['output'], manifest, manifest_layout)
 
     memory_areas = [
-            MemoryArea('manifest', file=args['output'],
-                       flags=PAGEINFO_R|PAGEINFO_REG)
-            ] + memory_areas
+        MemoryArea('manifest', file=args['output'],
+                   flags=PAGEINFO_R | PAGEINFO_REG)
+        ] + memory_areas
 
-    memory_areas = populate_memory_areas(manifest, attr, memory_areas)
+    memory_areas = populate_memory_areas(attr, memory_areas)
 
-    print >>sys.stderr, "Memory:"
+    print("Memory:")
     # Generate measurement
     mrenclave = generate_measurement(attr, memory_areas)
-
-    print >>sys.stderr, "Measurement:"
-    print >>sys.stderr, "    " + mrenclave.encode('hex')
+    print("Measurement:")
+    print("    %s" % mrenclave.hex())
 
     # Generate sigstruct
-    open(args['sigfile'], 'wb').write(generate_sigstruct(attr, args, mrenclave))
+    open(args['sigfile'], 'wb').write(
+        generate_sigstruct(attr, args, mrenclave))
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(main())

+ 2 - 1
Pal/test/Makefile

@@ -70,4 +70,5 @@ clean:
 	rm -rf pal_loader $(call expand_target,$(target)) .lib *.cached \
 	       $(addsuffix .d, $(executables)) $(addsuffix .i.d, $(executables)) \
 	       $(addsuffix .s.d, $(executables)) \
-	       $(addsuffix .manifest.sgx.d,$(executables))
+	       $(addsuffix .manifest.sgx.d,$(executables)) \
+		   .output.*