Beispiel #1
0
 def do_reglist(self):
     """List agents from Registrar
     """
     registrar_client.init_client_tls('tenant')
     response = registrar_client.doRegistrarList(
         self.registrar_ip, self.registrar_port)
     print(response)
Beispiel #2
0
 def do_regdelete(self):
     """ Delete agent from Registrar
     """
     registrar_client.init_client_tls('tenant')
     registrar_client.doRegistrarDelete(self.registrar_ip,
                                        self.registrar_port,
                                        self.agent_uuid)
def process_quote_response(agent, json_response):
    """Validates the response from the Cloud agent.

    This method invokes an Registrar Server call to register, and then check the quote.
    """
    received_public_key = None
    quote = None

    # in case of failure in response content do not continue
    try:
        received_public_key = json_response.get("pubkey", None)
        quote = json_response["quote"]

        ima_measurement_list = json_response.get("ima_measurement_list", None)

        logger.debug("received quote:      %s" % quote)
        logger.debug("for nonce:           %s" % agent['nonce'])
        logger.debug("received public key: %s" % received_public_key)
        logger.debug("received ima_measurement_list    %s" %
                     (ima_measurement_list is not None))
    except Exception:
        return None

    # if no public key provided, then ensure we have cached it
    if received_public_key is None:
        if agent.get('public_key', "") == "" or agent.get(
                'b64_encrypted_V', "") == "":
            logger.error(
                "agent did not provide public key and no key or encrypted_v was cached at CV"
            )
            return False
        agent['provide_V'] = False
        received_public_key = agent['public_key']

    if agent.get('registrar_keys', "") == "":
        registrar_client.init_client_tls('cloud_verifier')
        registrar_keys = registrar_client.getKeys(
            config.get("cloud_verifier", "registrar_ip"),
            config.get("cloud_verifier", "registrar_port"), agent['agent_id'])
        if registrar_keys is None:
            logger.warning("AIK not found in registrar, quote not validated")
            return False
        agent['registrar_keys'] = registrar_keys

    tpm_version = json_response.get('tpm_version')
    tpm = tpm_obj.getTPM(need_hw_tpm=False, tpm_version=tpm_version)
    hash_alg = json_response.get('hash_alg')
    enc_alg = json_response.get('enc_alg')
    sign_alg = json_response.get('sign_alg')

    # Update chosen tpm and algorithms
    agent['tpm_version'] = tpm_version
    agent['hash_alg'] = hash_alg
    agent['enc_alg'] = enc_alg
    agent['sign_alg'] = sign_alg

    # Ensure hash_alg is in accept_tpm_hash_alg list
    if not algorithms.is_accepted(hash_alg, agent['accept_tpm_hash_algs']):
        raise Exception("TPM Quote is using an unaccepted hash algorithm: %s" %
                        hash_alg)

    # Ensure enc_alg is in accept_tpm_encryption_algs list
    if not algorithms.is_accepted(enc_alg,
                                  agent['accept_tpm_encryption_algs']):
        raise Exception(
            "TPM Quote is using an unaccepted encryption algorithm: %s" %
            enc_alg)

    # Ensure sign_alg is in accept_tpm_encryption_algs list
    if not algorithms.is_accepted(sign_alg, agent['accept_tpm_signing_algs']):
        raise Exception(
            "TPM Quote is using an unaccepted signing algorithm: %s" %
            sign_alg)

    if tpm.is_deep_quote(quote):
        validQuote = tpm.check_deep_quote(
            agent['agent_id'], agent['nonce'], received_public_key, quote,
            agent['registrar_keys']['aik'],
            agent['registrar_keys']['provider_keys']['aik'],
            agent['vtpm_policy'], agent['tpm_policy'], ima_measurement_list,
            agent['allowlist'])
    else:
        validQuote = tpm.check_quote(agent['agent_id'], agent['nonce'],
                                     received_public_key, quote,
                                     agent['registrar_keys']['aik'],
                                     agent['tpm_policy'], ima_measurement_list,
                                     agent['allowlist'], hash_alg)
    if not validQuote:
        return False

    # set a flag so that we know that the agent was verified once.
    # we only issue notifications for agents that were at some point good
    agent['first_verified'] = True

    # has public key changed? if so, clear out b64_encrypted_V, it is no longer valid
    if received_public_key != agent.get('public_key', ""):
        agent['public_key'] = received_public_key
        agent['b64_encrypted_V'] = ""
        agent['provide_V'] = True

    # ok we're done
    return validQuote
    def do_PUT(self):
        """This method handles the PUT requests to add agents to the Registrar Server.

        Currently, only agents resources are available for PUTing, i.e. /agents. All other PUT uri's
        will return errors.
        """
        rest_params = common.get_restful_params(self.path)
        if rest_params is None:
            common.echo_json_response(
                self, 405, "Not Implemented: Use /agents/ interface")
            return

        if "agents" not in rest_params:
            common.echo_json_response(self, 400, "uri not supported")
            logger.warning(
                'PUT agent returning 400 response. uri not supported: ' +
                self.path)
            return

        agent_id = rest_params["agents"]

        if agent_id is None:
            common.echo_json_response(self, 400, "agent id not found in uri")
            logger.warning(
                'PUT agent returning 400 response. agent id not found in uri '
                + self.path)
            return

        try:
            content_length = int(self.headers.get('Content-Length', 0))
            if content_length == 0:
                common.echo_json_response(self, 400,
                                          "Expected non zero content length")
                logger.warning(
                    'PUT for ' + agent_id +
                    ' returning 400 response. Expected non zero content length.'
                )
                return

            post_body = self.rfile.read(content_length)
            json_body = json.loads(post_body)

            if "activate" in rest_params:
                auth_tag = json_body['auth_tag']

                agent = self.server.db.get_agent(agent_id)
                if agent is None:
                    raise Exception(
                        "attempting to activate agent before requesting registrar for %s"
                        % agent_id)

                if agent['virtual']:
                    raise Exception(
                        "attempting to activate virtual AIK using physical interface for %s"
                        % agent_id)

                if common.STUB_TPM:
                    self.server.db.update_agent(agent_id, 'active', True)
                else:
                    ex_mac = crypto.do_hmac(agent['key'], agent_id)
                    if ex_mac == auth_tag:
                        self.server.db.update_agent(agent_id, 'active', True)
                    else:
                        raise Exception(
                            "Auth tag %s does not match expected value %s" %
                            (auth_tag, ex_mac))

                common.echo_json_response(self, 200, "Success")
                logger.info('PUT activated: ' + agent_id)
            elif "vactivate" in rest_params:
                deepquote = json_body.get('deepquote', None)

                agent = self.server.db.get_agent(agent_id)
                if agent is None:
                    raise Exception(
                        "attempting to activate agent before requesting registrar for %s"
                        % agent_id)

                if not agent['virtual']:
                    raise Exception(
                        "attempting to activate physical AIK using virtual interface for %s"
                        % agent_id)

                # get an physical AIK for this host
                registrar_client.init_client_tls(config, 'registrar')
                provider_keys = registrar_client.getKeys(
                    config.get('general', 'provider_registrar_ip'),
                    config.get('general', 'provider_registrar_tls_port'),
                    agent_id)
                # we already have the vaik
                tpm = tpm_obj.getTPM(need_hw_tpm=False,
                                     tpm_version=agent['tpm_version'])
                if not tpm.check_deep_quote(
                        hashlib.sha1(agent['key']).hexdigest(),
                        agent_id + agent['aik'] + agent['ek'], deepquote,
                        agent['aik'], provider_keys['aik']):
                    raise Exception("Deep quote invalid")

                self.server.db.update_agent(agent_id, 'active', True)
                self.server.db.update_agent(agent_id, 'provider_keys',
                                            provider_keys)

                common.echo_json_response(self, 200, "Success")
                logger.info('PUT activated: ' + agent_id)
            else:
                pass
        except Exception as e:
            common.echo_json_response(self, 400, "Error: %s" % e)
            logger.warning("PUT for " + agent_id +
                           " returning 400 response. Error: %s" % e)
            logger.exception(e)
            return
Beispiel #5
0
 def do_regdelete(self):
     registrar_client.init_client_tls(config, 'tenant')
     registrar_client.doRegistrarDelete(self.registrar_ip,
                                        self.registrar_port,
                                        self.agent_uuid)
Beispiel #6
0
    def validate_tpm_quote(self, public_key, quote, tpm_version, hash_alg):
        registrar_client.init_client_tls(config, 'tenant')
        reg_keys = registrar_client.getKeys(self.registrar_ip,
                                            self.registrar_port,
                                            self.agent_uuid)
        if reg_keys is None:
            logger.warning("AIK not found in registrar, quote not validated")
            return False

        tpm = tpm_obj.getTPM(need_hw_tpm=False, tpm_version=tpm_version)
        if not tpm.check_quote(self.agent_uuid,
                               self.nonce,
                               public_key,
                               quote,
                               reg_keys['aik'],
                               hash_alg=hash_alg):
            if reg_keys['regcount'] > 1:
                logger.error(
                    "WARNING: This UUID had more than one ek-ekcert registered to it!  This might indicate that your system is misconfigured or a malicious host is present.  Run 'regdelete' for this agent and restart"
                )
                exit()
            return False

        if reg_keys['regcount'] > 1:
            logger.warn(
                "WARNING: This UUID had more than one ek-ekcert registered to it!  This might indicate that your system is misconfigured.  Run 'regdelete' for this agent and restart"
            )

        if not common.STUB_TPM and (
                not config.getboolean('tenant', 'require_ek_cert')
                and config.get('tenant', 'ek_check_script') == ""):
            logger.warn(
                "DANGER: EK cert checking is disabled and no additional checks on EKs have been specified with ek_check_script option. Keylime is not secure!!"
            )

        # check EK cert and make sure it matches EK
        if not self.check_ek(reg_keys['ek'], reg_keys['ekcert'], tpm):
            return False
        # if agent is virtual, check phyisical EK cert and make sure it matches phyiscal EK
        if 'provider_keys' in reg_keys:
            if not self.check_ek(reg_keys['provider_keys']['ek'],
                                 reg_keys['provider_keys']['ekcert'], tpm):
                return False

        # check all EKs with optional script:
        script = config.get('tenant', 'ek_check_script')
        if script != "":
            if script[0] != '/':
                script = "%s/%s" % (common.WORK_DIR, script)

            logger.info(f"Checking EK with script {script}")
            # now we need to exec the script with the ek and ek cert in vars
            env = os.environ.copy()
            env['AGENT_UUID'] = self.agent_uuid
            env['EK'] = reg_keys['ek']
            if reg_keys['ekcert'] is not None:
                env['EK_CERT'] = reg_keys['ekcert']
            else:
                env['EK_CERT'] = ""

            env['PROVKEYS'] = json.dumps(reg_keys.get('provider_keys', {}))
            proc = subprocess.Popen(script,
                                    env=env,
                                    shell=True,
                                    cwd=common.WORK_DIR,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.STDOUT)
            retval = proc.wait()

            if retval != 0:
                raise UserError("External check script failed to validate EK")
                while True:
                    line = proc.stdout.readline()
                    if line == "":
                        break
                    logger.debug(f"ek_check output: {line.strip()}")
                return False
            else:
                logger.debug(
                    "External check script successfully to validated EK")
                while True:
                    line = proc.stdout.readline()
                    if line == "":
                        break
                    logger.debug(f"ek_check output: {line.strip()}")
        return True
Beispiel #7
0
    def validate_tpm_quote(self, public_key, quote, hash_alg):
        """ Validate TPM Quote received from the Agent

        Arguments:
            public_key {[type]} -- [description]
            quote {[type]} -- [description]
            hash_alg {bool} -- [description]

        Raises:
            UserError: [description]

        Returns:
            [type] -- [description]
        """
        registrar_client.init_client_tls('tenant')
        reg_keys = registrar_client.getKeys(
            self.registrar_ip, self.registrar_port, self.agent_uuid)
        if reg_keys is None:
            logger.warning("AIK not found in registrar, quote not validated")
            return False

        if not self.tpm_instance.check_quote(self.agent_uuid, self.nonce, public_key, quote, reg_keys['aik_tpm'], hash_alg=hash_alg):
            if reg_keys['regcount'] > 1:
                logger.error("WARNING: This UUID had more than one ek-ekcert registered to it! This might indicate that your system is misconfigured or a malicious host is present. Run 'regdelete' for this agent and restart")
                sys.exit()
            return False

        if reg_keys['regcount'] > 1:
            logger.warning("WARNING: This UUID had more than one ek-ekcert registered to it! This might indicate that your system is misconfigured. Run 'regdelete' for this agent and restart")

        if not config.STUB_TPM and (not config.getboolean('tenant', 'require_ek_cert') and config.get('tenant', 'ek_check_script') == ""):
            logger.warning(
                "DANGER: EK cert checking is disabled and no additional checks on EKs have been specified with ek_check_script option. Keylime is not secure!!")

        # check EK cert and make sure it matches EK
        if not self.check_ek(reg_keys['ekcert']):
            return False
        # if agent is virtual, check phyisical EK cert and make sure it matches phyiscal EK
        if 'provider_keys' in reg_keys:
            if not self.check_ek(reg_keys['provider_keys']['ekcert']):
                return False

        # check all EKs with optional script:
        script = config.get('tenant', 'ek_check_script')
        if not script:
            return True

        if script[0] != '/':
            script = "%s/%s" % (config.WORK_DIR, script)

        logger.info("Checking EK with script %s", script)
        # now we need to exec the script with the ek and ek cert in vars
        env = os.environ.copy()
        env['AGENT_UUID'] = self.agent_uuid
        env['EK'] = tpm2_objects.pubkey_from_tpm2b_public(
            base64.b64decode(reg_keys['ek_tpm']),
            ).public_bytes(
                crypto_serialization.Encoding.PEM,
                crypto_serialization.PublicFormat.SubjectPublicKeyInfo,
            )
        env['EK_TPM'] = reg_keys['ek_tpm']
        if reg_keys['ekcert'] is not None:
            env['EK_CERT'] = reg_keys['ekcert']
        else:
            env['EK_CERT'] = ""

        env['PROVKEYS'] = json.dumps(reg_keys.get('provider_keys', {}))
        proc = subprocess.Popen(script, env=env, shell=True,
                                cwd=config.WORK_DIR, stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
        retval = proc.wait()
        if retval != 0:
            raise UserError("External check script failed to validate EK")
        logger.debug("External check script successfully to validated EK")
        while True:
            line = proc.stdout.readline().decode()
            if line == "":
                break
            logger.debug("ek_check output: %s", line.strip())
        return True
    def do_PUT(self):
        """This method handles the PUT requests to add agents to the Registrar Server.

        Currently, only agents resources are available for PUTing, i.e. /agents. All other PUT uri's
        will return errors.
        """
        session = SessionManager().make_session(engine)
        rest_params = config.get_restful_params(self.path)
        if rest_params is None:
            config.echo_json_response(
                self, 405, "Not Implemented: Use /agents/ interface")
            return

        if "agents" not in rest_params:
            config.echo_json_response(self, 400, "uri not supported")
            logger.warning(
                'PUT agent returning 400 response. uri not supported: ' +
                self.path)
            return

        agent_id = rest_params["agents"]

        if agent_id is None:
            config.echo_json_response(self, 400, "agent id not found in uri")
            logger.warning(
                'PUT agent returning 400 response. agent id not found in uri '
                + self.path)
            return

        try:
            content_length = int(self.headers.get('Content-Length', 0))
            if content_length == 0:
                config.echo_json_response(self, 400,
                                          "Expected non zero content length")
                logger.warning(
                    'PUT for ' + agent_id +
                    ' returning 400 response. Expected non zero content length.'
                )
                return

            post_body = self.rfile.read(content_length)
            json_body = json.loads(post_body)

            if "activate" in rest_params:
                auth_tag = json_body['auth_tag']
                try:
                    agent = session.query(RegistrarMain).filter_by(
                        agent_id=agent_id).first()
                except NoResultFound as e:
                    raise Exception(
                        "attempting to activate agent before requesting "
                        "registrar for %s" % agent_id) from e
                except SQLAlchemyError as e:
                    logger.error(f'SQLAlchemy Error: {e}')
                    raise

                if agent.virtual:
                    raise Exception(
                        "attempting to activate virtual AIK using physical interface for %s"
                        % agent_id)

                if config.STUB_TPM:
                    try:
                        session.query(RegistrarMain).filter(
                            RegistrarMain.agent_id == agent_id).update(
                                {'active': True})
                        session.commit()
                    except SQLAlchemyError as e:
                        logger.error(f'SQLAlchemy Error: {e}')
                        raise
                else:
                    # TODO(kaifeng) Special handling should be removed
                    if engine.dialect.name == "mysql":
                        agent.key = agent.key.encode('utf-8')

                    ex_mac = crypto.do_hmac(agent.key, agent_id)
                    if ex_mac == auth_tag:
                        try:
                            session.query(RegistrarMain).filter(
                                RegistrarMain.agent_id == agent_id).update(
                                    {'active': True})
                            session.commit()
                        except SQLAlchemyError as e:
                            logger.error(f'SQLAlchemy Error: {e}')
                            raise
                    else:
                        raise Exception(
                            "Auth tag %s does not match expected value %s" %
                            (auth_tag, ex_mac))

                config.echo_json_response(self, 200, "Success")
                logger.info('PUT activated: ' + agent_id)
            elif "vactivate" in rest_params:
                deepquote = json_body.get('deepquote', None)
                try:
                    agent = session.query(RegistrarMain).filter_by(
                        agent_id=agent_id).first()
                except NoResultFound as e:
                    raise Exception(
                        "attempting to activate agent before requesting "
                        "registrar for %s" % agent_id) from e
                except SQLAlchemyError as e:
                    logger.error(f'SQLAlchemy Error: {e}')
                    raise

                if not agent['virtual']:
                    raise Exception(
                        "attempting to activate physical AIK using virtual interface for %s"
                        % agent_id)

                # get an physical AIK for this host
                registrar_client.init_client_tls('registrar')
                provider_keys = registrar_client.getKeys(
                    config.get('registrar', 'provider_registrar_ip'),
                    config.get('registrar', 'provider_registrar_tls_port'),
                    agent_id)
                # we already have the vaik
                tpm = tpm_obj.getTPM(need_hw_tpm=False,
                                     tpm_version=agent['tpm_version'])
                if not tpm.check_deep_quote(
                        agent_id,
                        hashlib.sha1(agent['key']).hexdigest(),
                        agent_id + agent['aik'] + agent['ek'], deepquote,
                        agent['aik'], provider_keys['aik']):
                    raise Exception("Deep quote invalid")
                try:
                    session.query(RegistrarMain).filter(
                        RegistrarMain.agent_id == agent_id).update(
                            {'active': True})
                except SQLAlchemyError as e:
                    logger.error(f'SQLAlchemy Error: {e}')
                    raise
                try:
                    session.query(RegistrarMain).filter(
                        RegistrarMain.agent_id == agent_id).update(
                            {'provider_keys': provider_keys})
                except SQLAlchemyError as e:
                    logger.error(f'SQLAlchemy Error: {e}')
                    raise

                config.echo_json_response(self, 200, "Success")
                logger.info('PUT activated: ' + agent_id)
        except Exception as e:
            config.echo_json_response(self, 400, "Error: %s" % e)
            logger.warning("PUT for " + agent_id +
                           " returning 400 response. Error: %s" % e)
            logger.exception(e)
            return
    async def invoke_get_prov_quote(self, agent, need_pubkey):
        # obviously not need pubkey, delete latter
        params = cloud_verifier_common.prepare_get_quote(agent)

        logger.info(
            "invoking Teneant Verifier -> Provider Verifier communication")

        logger.debug(params['provider_ip'])
        logger.debug(params['provider_port'])

        agent[
            'operational_state'] = cloud_verifier_common.CloudAgent_Operational_State.GET_PROVIDER_QUOTE

        url = "http://%s:%d/verifier?nonce=%s&mask=%s&vmask=%s" % (
            params['provider_ip'], params['provider_port'], params["nonce"],
            params["mask"], params['vmask'])

        logger.debug(
            "Tenant Provider requesting quote from provider verifier, url: ",
            url)

        res = tornado_requests.request("GET", url, context=None)

        response = await res

        if response.status_code != 200:
            if response.status_code == 599:
                asyncio.ensure_future(
                    self.process_agent(
                        agent, cloud_verifier_common.
                        CloudAgent_Operational_State.GET_PROVIDER_QUOTE_RETRY))
            else:
                error = "Unexpected Get Quote response error for provider: " + params[
                    'provider_ip'] + ":" + str(
                        params['provider_port']) + ", Error: " + str(
                            response.status_code)
                logger.critical(error)
                asyncio.ensure_future(
                    self.process_agent(
                        agent, cloud_verifier_common.
                        CloudAgent_Operational_State.FAILED))
        else:
            try:
                json_response = json.loads(response.body)
                result = json_response.get('results')

                #Merkle Tree Proof that was returned with Provider Agent signed quote
                nonce_proof = string_to_proof(result['nonce_proof'])

                logger.debug(
                    "Was Tenant nonce in provider merkle tree: ",
                    merklelib.verify_leaf_inclusion(params.get("nonce"),
                                                    nonce_proof, hashfunc,
                                                    result['merkle_head']))

                #Hackish Way to "Register" the Tenant Verifier with public AIK of Provider Agent so that Tenant may
                #confirm quote

                #Sends get_keys request to Provider Registrar
                #Makes it so tenant dosn't have to harcode provider verifier information
                registrar_client.init_client_tls(config, 'cloud_verifier')
                registrar_keys = registrar_client.getKeys(
                    params['provider_ip'],
                    config.get("general", "registrar_tls_port"),
                    agent['agent_id'])

                #provider_agent = {'v': '5IDWvzBPeLjpJ6f1woEmm7/SU+/AA8JWtWR9mIQXDGk=', 'ip': '11.0.0.22', 'port': 9002, 'provider_ip': None, 'provider_port': 0, 'operational_state': 3, 'public_key': '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwp02Zhqyk3i/GFJPPH54\nlJSElPUQmLZeVpTXKYAvuttuYSjwz2fGATCiffKHnZmfIHUhMGH+zKvtFPCy/Dwo\nOKUWBfhU1QjEFP6EKywiPk8a0uDipQNq87ELJfnPRKA0leIIkyYFIpYfn/TvlthA\nweUlX15OpWHn+x9sDA2HldZZae4YS/51pW0GM8biHNhcQ4J1c+DYc+HKojobmBHz\nKtBAmmd5HdThFSSBhqFo8J+hs0+2Mr4LRiqYwAYwGsYNQblcZAvIAboqR2GZ4XL8\nYlJnzCpyoVLSQPM4FmupJhexp5PAHUzdJ96wsS8AVy/+i3tp+l43+fL9CI1LYBQD\newIDAQAB\n-----END PUBLIC KEY-----\n', 'tpm_policy': {'22': ['0000000000000000000000000000000000000001', '0000000000000000000000000000000000000000000000000000000000000001', '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', 'ffffffffffffffffffffffffffffffffffffffff', 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'], '15': ['0000000000000000000000000000000000000000', '0000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'], 'mask': '0x408000'}, 'vtpm_policy': {'23': ['ffffffffffffffffffffffffffffffffffffffff', '0000000000000000000000000000000000000000'], '15': ['0000000000000000000000000000000000000000'], 'mask': '0x808000'}, 'metadata': {}, 'ima_whitelist': {}, 'revocation_key': '', 'tpm_version': 2, 'accept_tpm_hash_algs': ['sha512', 'sha384', 'sha256', 'sha1'], 'accept_tpm_encryption_algs': ['ecc', 'rsa'], 'accept_tpm_signing_algs': ['ecschnorr', 'rsassa'], 'hash_alg': 'sha256', 'enc_alg': 'rsa', 'sign_alg': 'rsassa', 'need_provider_quote': False, 'quote_col': [], 'registrar_keys': {'aik': '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApG0MqAABAlDn1RefgQkw\ngAtoV6LVJaF19Zi3VSxbXkdFbgvObLHsRHcpR7HJKrCuX0yJo9T8r39v3WKHhiUt\nEpEAoQYGXHlWaG/Z01OE0DD19z3CEj9EvfkIpwJf15NAnkqrhVA4FKDyOMo5piHV\nixAIxpIbysGswo+PcTi9CjIE0dRFiGzju3wF8ObqcfSlX8VD24X2tOf1LYyxEUhs\nba9jfzwMgidaafA6gV+8e2cW9TiOM1VIMc1IofvrsspHTUxSD6jC6XbW88UUYC6i\nqTnh5wAl7Ag/TfENsRhCuaaeRellVVm/PfGF8+FjcdWX91vq76mcqwI0qaaOqBRl\n+QIDAQAB\n-----END PUBLIC KEY-----\n', 'ek': '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0dLxdAABVJO6qxamjCMh\nyhWZgiFHZHnPEe0tMFyK3fNVr/w8lX9r+QOLxLmkT0IdgsEYtGZGefbD+qQl4O1s\nk25823Xzu5tEF8966rTdkfsv8CRrNaBLwWlnt/n+qjIoU3xZJMmR+mFfqTc3a6zV\nmPOYJstFtM8r4b9HPCUq6Mte/J3Wx4FxI9R4UrCUyiAeH++0QapIxuEGsVIYs92n\nGyvFQYBZFRU6cIt33iaqTrRCICJp+YblMnw54YJGAH2vTVQf6/fLAnQt5L1UfmTy\nR/ZA6advx8soekSBOIAW7XmV8Xp9mSquIHZdSXMJlcn/B35PU3BdkUtIYm5JuGGt\nPQIDAQAB\n-----END PUBLIC KEY-----\n', 'ekcert': 'emulator', 'regcount': 1}, 'nonce': 'D9ge8y9zu60budeNVWMx', 'b64_encrypted_V': b'Wy5atU+joWoUVNrn3yIKWPVydG4mE3ngWF5N/bKTTzXSLbpO+IlayXuy6v+teC8OGO2bMnjJBeKUXEQmFyvei0XVFa3A76V9d2YPF8Vkf8nKT4rWm/6RiAwZqbzY+IR4e27P+Wf2ZExHE+2EbPgVefAD87RhUyjbuhqZXFB65i9DCeK93DapPj2gLhxnzirmdTn23bDOFhVyHAidhAoCiK7CA4TrT2N0j3q5ConyMx7ZNfyoDdkWKNGlcJgjFaCqJQYAFlcbfid4EytDZd6+gX6RhyYi82iwUg+LDASsrS7FbR/AdCnE1kJuYCIoluUhztHr7nzT2o9/r6YKTCDRXQ==', 'provide_V': False, 'num_retries': 0, 'first_verified': True, 'agent_id': 'D432FBB3-D2F1-4A97-9EF7-75BD81C00000'}
                tpm_version = result.get('tpm_version')
                tpm = tpm_obj.getTPM(need_hw_tpm=False,
                                     tpm_version=tpm_version)
                hash_alg = result.get('hash_alg')
                enc_alg = result.get('enc_alg')
                sign_alg = result.get('sign_alg')

                try:
                    #Before checking quote validity make sure Tenant nonce was in original batch request
                    #If not quote is at wrong tenant verifier, and it can not confirm quote validity
                    if merklelib.verify_leaf_inclusion(params.get("nonce"),
                                                       nonce_proof, hashfunc,
                                                       result['merkle_head']):
                        validQuote = tpm.check_quote(
                            result['merkle_head'],
                            agent['public_key'],  # NK keys 
                            result.get('quote'),
                            registrar_keys['aik'],
                            agent['tpm_policy'],
                            None,  # ima_measurement_list,
                            agent['ima_whitelist'],
                            hash_alg)
                        logger.info("Provider_IP: " +
                                    str(params['provider_ip']))
                        logger.info("Provider_Port: " +
                                    str(params['provider_port']))
                        logger.info("validation result for provider quote: " +
                                    str(validQuote))
                    else:
                        logger.error("Invalid Quote")
                except Exception as e:
                    print('error: ', e)

            except Exception as e:
                logger.exception(e)

        pass