Example #1
0
    def test_sgx_measurement(self):
        sgx_measurement = sgx_structs.SgxMeasurement()

        # Test with None and invalid types
        with self.assertRaises(TypeError):
            sgx_measurement.parse_from_bytes(None)
        with self.assertRaises(TypeError):
            sgx_measurement.parse_from_bytes([])
        with self.assertRaises(TypeError):
            sgx_measurement.parse_from_bytes({})
        with self.assertRaises(TypeError):
            sgx_measurement.parse_from_bytes(1)
        with self.assertRaises(TypeError):
            sgx_measurement.parse_from_bytes(1.0)
        with self.assertRaises(TypeError):
            sgx_measurement.parse_from_bytes('')

        # Test an empty string, a string that is one too short, and a string
        # that is one too long
        with self.assertRaises(ValueError):
            sgx_measurement.parse_from_bytes(b'')
        with self.assertRaises(ValueError):
            sgx_measurement.parse_from_bytes(
                b'\x00' * (sgx_structs.SgxMeasurement.STRUCT_SIZE - 1))
        with self.assertRaises(ValueError):
            sgx_measurement.parse_from_bytes(
                b'\x00' * (sgx_structs.SgxMeasurement.STRUCT_SIZE + 1))

        # Verify sgx_measurement unpacks properly
        measurement = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxMeasurement.STRUCT_SIZE)
        sgx_measurement.parse_from_bytes(measurement)

        self.assertTrue(sgx_measurement.m == measurement)

        # Reset the object using the field values and verify that we
        # get expected serialized buffer
        sgx_measurement = sgx_structs.SgxMeasurement(m=measurement)
        self.assertEqual(measurement, sgx_measurement.serialize_to_bytes())
Example #2
0
    def create_signup_info(self,
                           originator_public_key_hash,
                           nonce,
                           pse_manifest_status='OK'):
        # currently not used
        # _active_wait_timer = None

        # We are going to fake out the sealing the signup data.
        signup_data = {
            'poet_public_key': self.poet_public_key.as_hex(),
            'poet_private_key': self._poet_private_key.as_hex()
        }

        # Build up a fake SGX quote containing:
        # 1. The basename
        # 2. The report body that contains:
        #    a. The enclave measurement
        #    b. The report data SHA256(SHA256(OPK)|PPK)
        sgx_basename = \
            sgx_structs.SgxBasename(name=self.__VALID_BASENAME__)
        sgx_measurement = \
            sgx_structs.SgxMeasurement(
                m=self.__VALID_ENCLAVE_MEASUREMENT__)

        hash_input = \
            '{0}{1}'.format(
                originator_public_key_hash.upper(),
                self.poet_public_key.as_hex().upper()).encode()
        report_data = hashlib.sha256(hash_input).digest()

        sgx_report_data = sgx_structs.SgxReportData(d=report_data)
        sgx_report_body = \
            sgx_structs.SgxReportBody(
                mr_enclave=sgx_measurement,
                report_data=sgx_report_data)

        sgx_quote = \
            sgx_structs.SgxQuote(
                basename=sgx_basename,
                report_body=sgx_report_body)

        # Create a fake PSE manifest.  A base64 encoding of the
        # originator public key hash should suffice.
        pse_manifest = \
            base64.b64encode(originator_public_key_hash.encode())

        timestamp = '2017-02-16T15:21:24.437048'

        # Fake our "proof" data.
        verification_report = OrderedDict([
            ('epidPseudonym', originator_public_key_hash),
            ('id',
             base64.b64encode(
                 hashlib.sha256(
                     timestamp.encode()).hexdigest().encode()).decode()),
            ('isvEnclaveQuoteStatus', 'OK'),
            ('isvEnclaveQuoteBody',
             base64.b64encode(sgx_quote.serialize_to_bytes()).decode()),
            ('pseManifestStatus', pse_manifest_status),
            ('pseManifestHash',
             hashlib.sha256(base64.b64decode(pse_manifest)).hexdigest()),
            ('nonce', nonce), ('timestamp', timestamp)
        ])

        proof_data = \
            self.create_proof_data(
                verification_report=verification_report,
                evidence_payload={
                    'pse_manifest': pse_manifest.decode()
                })

        return \
            SignUpInfo(
                poet_public_key=signup_data['poet_public_key'],
                proof_data=proof_data,
                anti_sybil_id=originator_public_key_hash,
                nonce=nonce)
Example #3
0
    def create_signup_info(cls, originator_public_key_hash, nonce):
        with cls._lock:
            # First we need to create a public/private key pair for the PoET
            # enclave to use.
            # Counter ID is a placeholder for a hardware counter in a TEE.
            poet_private_key = Secp256k1PrivateKey.new_random()
            poet_public_key = \
                cls._context.get_public_key(poet_private_key)
            counter_id = None

            # Simulate sealing (encrypting) the signup data.
            signup_data = {
                'poet_private_key': poet_private_key.as_hex(),
                'poet_public_key': poet_public_key.as_hex(),
                'counter_id': counter_id
            }
            sealed_signup_data = \
                base64.b64encode(
                    dict2json(signup_data).encode()).decode('utf-8')

            # Build up a fake SGX quote containing:
            # 1. The basename
            # 2. The report body that contains:
            #    a. The enclave measurement
            #    b. The report data SHA256(SHA256(OPK)|PPK)
            sgx_basename = \
                sgx_structs.SgxBasename(name=cls.__VALID_BASENAME__)
            sgx_measurement = \
                sgx_structs.SgxMeasurement(
                    m=cls.__VALID_ENCLAVE_MEASUREMENT__)

            hash_input = \
                '{0}{1}'.format(
                    originator_public_key_hash.upper(),
                    poet_public_key.as_hex().upper()).encode()
            report_data = hashlib.sha256(hash_input).digest()
            sgx_report_data = sgx_structs.SgxReportData(d=report_data)
            sgx_report_body = \
                sgx_structs.SgxReportBody(
                    mr_enclave=sgx_measurement,
                    report_data=sgx_report_data)

            sgx_quote = \
                sgx_structs.SgxQuote(
                    basename=sgx_basename,
                    report_body=sgx_report_body)

            # Create a fake PSE manifest.  A base64 encoding of the
            # originator public key hash should suffice.
            pse_manifest = \
                base64.b64encode(originator_public_key_hash.encode())

            timestamp = datetime.datetime.now().isoformat()

            # Fake our "proof" data.
            verification_report = {
                'epidPseudonym':
                cls._anti_sybil_id,
                'id':
                base64.b64encode(
                    hashlib.sha256(
                        timestamp.encode()).hexdigest().encode()).decode(),
                'isvEnclaveQuoteStatus':
                'OK',
                'isvEnclaveQuoteBody':
                base64.b64encode(sgx_quote.serialize_to_bytes()).decode(),
                'pseManifestStatus':
                'OK',
                'pseManifestHash':
                hashlib.sha256(base64.b64decode(pse_manifest)).hexdigest(),
                'nonce':
                nonce,
                'timestamp':
                timestamp
            }

            # Serialize the verification report, sign it, and then put
            # in the proof data
            verification_report_json = dict2json(verification_report)
            signature = \
                cls._report_private_key.sign(
                    verification_report_json.encode(),
                    padding.PKCS1v15(),
                    hashes.SHA256())

            proof_data_dict = {
                'evidence_payload': {
                    'pse_manifest': pse_manifest.decode()
                },
                'verification_report': verification_report_json,
                'signature': base64.b64encode(signature).decode()
            }
            proof_data = dict2json(proof_data_dict)

            return \
                EnclaveSignupInfo(
                    poet_public_key=signup_data['poet_public_key'],
                    proof_data=proof_data,
                    anti_sybil_id=cls._anti_sybil_id,
                    sealed_signup_data=sealed_signup_data)
Example #4
0
    def test_sgx_quote(self):
        sgx_quote = sgx_structs.SgxQuote()

        # Test with None and invalid types
        with self.assertRaises(TypeError):
            sgx_quote.parse_from_bytes(None)
        with self.assertRaises(TypeError):
            sgx_quote.parse_from_bytes([])
        with self.assertRaises(TypeError):
            sgx_quote.parse_from_bytes({})
        with self.assertRaises(TypeError):
            sgx_quote.parse_from_bytes(1)
        with self.assertRaises(TypeError):
            sgx_quote.parse_from_bytes(1.0)
        with self.assertRaises(TypeError):
            sgx_quote.parse_from_bytes('')

        # Test an empty string and a buffer one too small
        with self.assertRaises(ValueError):
            sgx_quote.parse_from_bytes(b'')
        with self.assertRaises(ValueError):
            sgx_quote.parse_from_bytes(
                b'\x00' * (sgx_structs.SgxQuote.FIXED_STRUCT_SIZE - 1))

        # typedef uint8_t sgx_epid_group_id_t[4];
        # typedef uint16_t sgx_isv_svn_t;

        # uint16_t            version;                /* 0   */
        # uint16_t            sign_type;              /* 2   */
        # sgx_epid_group_id_t epid_group_id;          /* 4   */
        # sgx_isv_svn_t       qe_svn;                 /* 8   */
        # sgx_isv_svn_t       pce_svn;                /* 10  */
        # uint32_t            extended_epid_group_id; /* 12  */
        # sgx_basename_t      basename;               /* 16  */
        # sgx_report_body_t   report_body;            /* 48  */
        # uint32_t            signature_len;          /* 432 */
        # uint8_t             signature[];            /* 436 */

        # Verify sgx_quote unpacks properly
        version = 0x0102
        sign_type = 0x0304
        epid_group_id = TestSgxStructs.create_random_buffer(4)
        qe_svn = 0x0506
        pce_svn = 0x0708
        extended_epid_group_id = 0x090a0b0c
        basename = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxBasename.STRUCT_SIZE)
        svn = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxCpuSvn.STRUCT_SIZE)
        misc_select = 0x0d0e0f10
        reserved1 = b'\x00' * 28
        flags = 0x1112131415161718
        xfrm = 0x191a1b1c1d1e1f20
        mr_enclave = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxMeasurement.STRUCT_SIZE)
        reserved2 = b'\x00' * 32
        mr_signer = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxMeasurement.STRUCT_SIZE)
        reserved3 = b'\x00' * 96
        isv_prod_id = 0x2122
        isv_svn = 0x2324
        reserved4 = b'\x00' * 60
        report_data = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxReportData.STRUCT_SIZE)
        report_body = \
            struct.pack(
                '<{}sL{}sQQ{}s{}s{}s{}sHH{}s{}s'.format(
                    len(svn),
                    len(reserved1),
                    len(mr_enclave),
                    len(reserved2),
                    len(mr_signer),
                    len(reserved3),
                    len(reserved4),
                    len(report_data)
                ),
                svn,
                misc_select,
                reserved1,
                flags,
                xfrm,
                mr_enclave,
                reserved2,
                mr_signer,
                reserved3,
                isv_prod_id,
                isv_svn,
                reserved4,
                report_data)
        quote = \
            struct.pack(
                '<HH{}sHHL{}s{}s'.format(
                    len(epid_group_id),
                    len(basename),
                    len(report_body)),
                version,
                sign_type,
                epid_group_id,
                qe_svn,
                pce_svn,
                extended_epid_group_id,
                basename,
                report_body)

        sgx_quote.parse_from_bytes(quote)

        self.assertTrue(sgx_quote.version == version)
        self.assertTrue(sgx_quote.sign_type == sign_type)
        self.assertTrue(sgx_quote.epid_group_id == epid_group_id)
        self.assertTrue(sgx_quote.qe_svn == qe_svn)
        self.assertTrue(sgx_quote.pce_svn == pce_svn)
        self.assertTrue(sgx_quote.basename.name == basename)
        self.assertTrue(sgx_quote.report_body.cpu_svn.svn == svn)
        self.assertTrue(sgx_quote.report_body.misc_select == misc_select)
        self.assertTrue(sgx_quote.report_body.attributes.flags == flags)
        self.assertTrue(sgx_quote.report_body.attributes.xfrm == xfrm)
        self.assertTrue(sgx_quote.report_body.mr_enclave.m == mr_enclave)
        self.assertTrue(sgx_quote.report_body.mr_signer.m == mr_signer)
        self.assertTrue(sgx_quote.report_body.isv_prod_id == isv_prod_id)
        self.assertTrue(sgx_quote.report_body.isv_svn == isv_svn)
        self.assertTrue(sgx_quote.report_body.report_data.d == report_data)

        # Add a few bytes so that the signature length is partial.  Should
        # fail.
        bad_quote = quote[:]
        for _ in range(3):
            bad_quote += TestSgxStructs.create_random_buffer(1)
            with self.assertRaises(ValueError):
                sgx_quote.parse_from_bytes(bad_quote)

        # Add a non-zero signature length, but don't add a signature.  Should
        # fail.
        bad_quote = struct.pack('<{}sL'.format(len(quote)), quote, 4)
        with self.assertRaises(ValueError):
            sgx_quote.parse_from_bytes(bad_quote)

        # Add a signature that is too short
        short_signature = TestSgxStructs.create_random_buffer(31)
        bad_quote = \
            struct.pack(
                '<{}sL{}s'.format(
                    len(quote),
                    len(short_signature)),
                quote,
                len(short_signature) + 1,
                short_signature)
        with self.assertRaises(ValueError):
            sgx_quote.parse_from_bytes(bad_quote)

        # Add a signature length of zero without a signature and verify
        unsigned_quote = struct.pack('<{}sL'.format(len(quote)), quote, 0)

        sgx_quote.parse_from_bytes(unsigned_quote)

        self.assertTrue(sgx_quote.version == version)
        self.assertTrue(sgx_quote.sign_type == sign_type)
        self.assertTrue(sgx_quote.epid_group_id == epid_group_id)
        self.assertTrue(sgx_quote.qe_svn == qe_svn)
        self.assertTrue(sgx_quote.pce_svn == pce_svn)
        self.assertTrue(sgx_quote.basename.name == basename)
        self.assertTrue(sgx_quote.report_body.cpu_svn.svn == svn)
        self.assertTrue(sgx_quote.report_body.misc_select == misc_select)
        self.assertTrue(sgx_quote.report_body.attributes.flags == flags)
        self.assertTrue(sgx_quote.report_body.attributes.xfrm == xfrm)
        self.assertTrue(sgx_quote.report_body.mr_enclave.m == mr_enclave)
        self.assertTrue(sgx_quote.report_body.mr_signer.m == mr_signer)
        self.assertTrue(sgx_quote.report_body.isv_prod_id == isv_prod_id)
        self.assertTrue(sgx_quote.report_body.isv_svn == isv_svn)
        self.assertTrue(sgx_quote.report_body.report_data.d == report_data)
        self.assertTrue(sgx_quote.signature_len == 0)

        # Add a good signature and verify
        signature = TestSgxStructs.create_random_buffer(32)
        signed_quote = \
            struct.pack(
                '<{}sL{}s'.format(
                    len(quote),
                    len(signature)),
                quote,
                len(signature),
                signature)

        sgx_quote.parse_from_bytes(signed_quote)

        self.assertTrue(sgx_quote.version == version)
        self.assertTrue(sgx_quote.sign_type == sign_type)
        self.assertTrue(sgx_quote.epid_group_id == epid_group_id)
        self.assertTrue(sgx_quote.qe_svn == qe_svn)
        self.assertTrue(sgx_quote.pce_svn == pce_svn)
        self.assertTrue(sgx_quote.basename.name == basename)
        self.assertTrue(sgx_quote.report_body.cpu_svn.svn == svn)
        self.assertTrue(sgx_quote.report_body.misc_select == misc_select)
        self.assertTrue(sgx_quote.report_body.attributes.flags == flags)
        self.assertTrue(sgx_quote.report_body.attributes.xfrm == xfrm)
        self.assertTrue(sgx_quote.report_body.mr_enclave.m == mr_enclave)
        self.assertTrue(sgx_quote.report_body.mr_signer.m == mr_signer)
        self.assertTrue(sgx_quote.report_body.isv_prod_id == isv_prod_id)
        self.assertTrue(sgx_quote.report_body.isv_svn == isv_svn)
        self.assertTrue(sgx_quote.report_body.report_data.d == report_data)
        self.assertTrue(sgx_quote.signature_len == len(signature))
        self.assertTrue(sgx_quote.signature == signature)

        # Reset the object using the field values and verify that we
        # get expected serialized buffer
        sgx_basename = sgx_structs.SgxBasename(name=basename)
        sgx_cpu_svn = sgx_structs.SgxCpuSvn(svn=svn)
        sgx_attributes = sgx_structs.SgxAttributes(flags=flags, xfrm=xfrm)
        sgx_measurement_mr_enclave = sgx_structs.SgxMeasurement(m=mr_enclave)
        sgx_measurement_mr_signer = sgx_structs.SgxMeasurement(m=mr_signer)
        sgx_report_data = sgx_structs.SgxReportData(d=report_data)
        sgx_report_body = \
            sgx_structs.SgxReportBody(
                cpu_svn=sgx_cpu_svn,
                misc_select=misc_select,
                attributes=sgx_attributes,
                mr_enclave=sgx_measurement_mr_enclave,
                mr_signer=sgx_measurement_mr_signer,
                isv_prod_id=isv_prod_id,
                isv_svn=isv_svn,
                report_data=sgx_report_data)
        sgx_quote = sgx_structs.SgxQuote(
            version=version,
            sign_type=sign_type,
            epid_group_id=epid_group_id,
            qe_svn=qe_svn,
            pce_svn=pce_svn,
            extended_epid_group_id=extended_epid_group_id,
            basename=sgx_basename,
            report_body=sgx_report_body)

        self.assertEqual(quote, sgx_quote.serialize_to_bytes()[:len(quote)])

        # Verify that zero signature serializes successfully
        zero_sign_quote = struct.pack('<{}sL'.format(len(quote)), quote, 0)

        self.assertEqual(zero_sign_quote, sgx_quote.serialize_to_bytes())

        # Verify that non-zero signature serializes successfully
        non_zero_sign_quote = \
            struct.pack(
                '<{}sL{}s'.format(
                    len(quote),
                    len(signature)),
                quote,
                len(signature),
                signature)
        sgx_quote.signature_len = len(signature)
        sgx_quote.signature = signature
        self.assertEqual(non_zero_sign_quote, sgx_quote.serialize_to_bytes())
Example #5
0
    def test_sgx_report(self):
        sgx_report = sgx_structs.SgxReport()

        # Test with None and invalid types
        with self.assertRaises(TypeError):
            sgx_report.parse_from_bytes(None)
        with self.assertRaises(TypeError):
            sgx_report.parse_from_bytes([])
        with self.assertRaises(TypeError):
            sgx_report.parse_from_bytes({})
        with self.assertRaises(TypeError):
            sgx_report.parse_from_bytes(1)
        with self.assertRaises(TypeError):
            sgx_report.parse_from_bytes(1.0)
        with self.assertRaises(TypeError):
            sgx_report.parse_from_bytes('')

        # Test an empty string, a string that is one too short, and a string
        # that is one too long
        with self.assertRaises(ValueError):
            sgx_report.parse_from_bytes(b'')
        with self.assertRaises(ValueError):
            sgx_report.parse_from_bytes(
                b'\x00' * (sgx_structs.SgxReport.STRUCT_SIZE - 1))
        with self.assertRaises(ValueError):
            sgx_report.parse_from_bytes(
                b'\x00' * (sgx_structs.SgxReport.STRUCT_SIZE + 1))

        # Simply verify that buffer of correct size unpacks without error
        sgx_report.parse_from_bytes(
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxReport.STRUCT_SIZE))

        # The report body is laid out as follows:
        #
        # sgx_report_body_t   body;   /* 0   */
        # sgx_key_id_t        key_id; /* 384 */
        # sgx_mac_t           mac;    /* 416 */

        # Verify sgx_report unpacks properly
        svn = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxCpuSvn.STRUCT_SIZE)
        misc_select = 0x00010203
        reserved1 = b'\x00' * 28
        flags = 0x0405060708090a0b
        xfrm = 0x0c0d0e0f10111213
        mr_enclave = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxMeasurement.STRUCT_SIZE)
        reserved2 = b'\x00' * 32
        mr_signer = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxMeasurement.STRUCT_SIZE)
        reserved3 = b'\x00' * 96
        isv_prod_id = 0x1415
        isv_svn = 0x1617
        reserved4 = b'\x00' * 60
        report_data = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxReportData.STRUCT_SIZE)
        report_body = \
            struct.pack(
                '<{}sL{}sQQ{}s{}s{}s{}sHH{}s{}s'.format(
                    len(svn),
                    len(reserved1),
                    len(mr_enclave),
                    len(reserved2),
                    len(mr_signer),
                    len(reserved3),
                    len(reserved4),
                    len(report_data)
                ),
                svn,
                misc_select,
                reserved1,
                flags,
                xfrm,
                mr_enclave,
                reserved2,
                mr_signer,
                reserved3,
                isv_prod_id,
                isv_svn,
                reserved4,
                report_data)
        key_id = \
            TestSgxStructs.create_random_buffer(
                sgx_structs.SgxKeyId.STRUCT_SIZE)
        mac = TestSgxStructs.create_random_buffer(16)
        report = \
            struct.pack(
                '<{}s{}s{}s'.format(
                    len(report_body),
                    len(key_id),
                    len(mac)),
                report_body,
                key_id,
                mac)

        sgx_report.parse_from_bytes(report)

        self.assertTrue(sgx_report.body.cpu_svn.svn == svn)
        self.assertTrue(sgx_report.body.misc_select == misc_select)
        self.assertTrue(sgx_report.body.attributes.flags == flags)
        self.assertTrue(sgx_report.body.attributes.xfrm == xfrm)
        self.assertTrue(sgx_report.body.mr_enclave.m == mr_enclave)
        self.assertTrue(sgx_report.body.mr_signer.m == mr_signer)
        self.assertTrue(sgx_report.body.isv_prod_id == isv_prod_id)
        self.assertTrue(sgx_report.body.isv_svn == isv_svn)
        self.assertTrue(sgx_report.body.report_data.d == report_data)
        self.assertTrue(sgx_report.key_id.id == key_id)
        self.assertTrue(sgx_report.mac == mac)

        # Reset the object using the field values and verify that we
        # get expected serialized buffer
        sgx_cpu_svn = sgx_structs.SgxCpuSvn(svn=svn)
        sgx_attributes = sgx_structs.SgxAttributes(flags=flags, xfrm=xfrm)
        sgx_measurement_mr_enclave = sgx_structs.SgxMeasurement(m=mr_enclave)
        sgx_measurement_mr_signer = sgx_structs.SgxMeasurement(m=mr_signer)
        sgx_report_data = sgx_structs.SgxReportData(d=report_data)
        sgx_report_body = \
            sgx_structs.SgxReportBody(
                cpu_svn=sgx_cpu_svn,
                misc_select=misc_select,
                attributes=sgx_attributes,
                mr_enclave=sgx_measurement_mr_enclave,
                mr_signer=sgx_measurement_mr_signer,
                isv_prod_id=isv_prod_id,
                isv_svn=isv_svn,
                report_data=sgx_report_data)
        sgx_key_id = sgx_structs.SgxKeyId(identifier=key_id)
        sgx_report = \
            sgx_structs.SgxReport(
                body=sgx_report_body,
                key_id=sgx_key_id,
                mac=mac)
        self.assertEqual(report, sgx_report.serialize_to_bytes())