예제 #1
0
    def test_024_agent_keys_ukey_post(self):
        """Test agents's POST /v2/keys/ukey Interface"""
        global public_key

        self.assertIsNotNone(public_key, "Required value not set.  Previous step may have failed?")
        self.assertIsNotNone(self.U, "Required value not set.  Previous step may have failed?")
        self.assertIsNotNone(self.auth_tag, "Required value not set.  Previous step may have failed?")
        self.assertIsNotNone(self.payload, "Required value not set.  Previous step may have failed?")

        encrypted_U = crypto.rsa_encrypt(crypto.rsa_import_pubkey(public_key), self.U)
        b64_encrypted_u = base64.b64encode(encrypted_U)
        data = {
            'encrypted_key': b64_encrypted_u,
            'auth_tag': self.auth_tag,
            'payload': self.payload
        }

        test_024_agent_keys_ukey_post = RequestsClient(tenant_templ.agent_base_url, tls_enabled=False)
        response = test_024_agent_keys_ukey_post.post(
            f'/v{self.api_version}/keys/ukey',
            data=json.dumps(data),
            cert="",
            verify=False
        )

        self.assertEqual(response.status_code, 200, "Non-successful Agent ukey post return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
예제 #2
0
    def test_023_agent_keys_vkey_post(self):
        """Test agent's POST /keys/vkey Interface"""
        # CV should do this (during CV POST/PUT test)
        # Running this test might hide problems with the CV sending the V key

        self.assertIsNotNone(
            self.V, "Required value not set.  Previous step may have failed?")
        self.assertIsNotNone(
            public_key,
            "Required value not set.  Previous step may have failed?")

        encrypted_V = crypto.rsa_encrypt(crypto.rsa_import_pubkey(public_key),
                                         str(self.V))
        b64_encrypted_V = base64.b64encode(encrypted_V)
        data = {"encrypted_key": b64_encrypted_V}

        test_023_agent_keys_vkey_post = RequestsClient(
            tenant_templ.agent_base_url, tls_enabled=False)
        response = test_023_agent_keys_vkey_post.post(
            f"/v{self.api_version}/keys/vkey",
            data=json.dumps(data),
            cert="",
            verify=False)

        self.assertEqual(response.status_code, 200,
                         "Non-successful Agent vkey post return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
예제 #3
0
def doRegisterAgent(registrar_ip,
                    registrar_port,
                    agent_id,
                    tpm_version,
                    pub_ek,
                    ekcert,
                    pub_aik,
                    pub_ek_tpm=None,
                    aik_name=None):
    data = {
        'ek': pub_ek,
        'ekcert': ekcert,
        'aik': pub_aik,
        'aik_name': aik_name,
        'ek_tpm': pub_ek_tpm,
        'tpm_version': tpm_version,
    }
    response = None
    try:
        client = RequestsClient(f'{registrar_ip}:{registrar_port}',
                                tls_enabled)
        response = client.post(f'/agents/{agent_id}',
                               cert=tls_cert_info,
                               data=json.dumps(data),
                               verify=False)
        response_body = response.json()

        if response.status_code != 200:
            logger.error(
                f"Error: unexpected http response code from Registrar Server: {response.status_code}"
            )
            keylime_logging.log_http_response(logger, logging.ERROR,
                                              response_body)
            return None

        logger.info(f"Agent registration requested for {agent_id}")

        if "results" not in response_body:
            logger.critical(
                f"Error: unexpected http response body from Registrar Server: {response.status_code}"
            )
            return None

        if "blob" not in response_body["results"]:
            logger.critical(
                f"Error: did not receive blob from Registrar Server: {response.status_code}"
            )
            return None

        return response_body["results"]["blob"]
    except Exception as e:
        if response and response.status_code == 503:
            logger.error(
                f"Agent cannot establish connection to registrar at {registrar_ip}:{registrar_port}"
            )
            sys.exit()
        else:
            logger.exception(e)

    return None
예제 #4
0
    def test_034_cv_agent_post_invalid_exclude_list(self):
        """Test CV's POST /v2/agents/{UUID} Interface"""
        self.assertIsNotNone(self.V, "Required value not set.  Previous step may have failed?")

        b64_v = base64.b64encode(self.V)
        # Set unsupported regex in exclude list
        allowlist = {'exclude': ['*']}
        data = {
            'v': b64_v,
            'cloudagent_ip': tenant_templ.cloudagent_ip,
            'cloudagent_port': tenant_templ.cloudagent_port,
            'tpm_policy': json.dumps(self.tpm_policy),
            'vtpm_policy': json.dumps(self.vtpm_policy),
            'allowlist': json.dumps(allowlist),
            'ima_sign_verification_keys': '',
            'metadata': json.dumps(self.metadata),
            'revocation_key': self.revocation_key,
            'accept_tpm_hash_algs': config.get('tenant', 'accept_tpm_hash_algs').split(','),
            'accept_tpm_encryption_algs': config.get('tenant', 'accept_tpm_encryption_algs').split(','),
            'accept_tpm_signing_algs': config.get('tenant', 'accept_tpm_signing_algs').split(','),
        }

        client = RequestsClient(tenant_templ.verifier_base_url, tls_enabled)
        response = client.post(
            f'/v{self.api_version}/agents/{tenant_templ.agent_uuid}',
            cert=tenant_templ.cert,
            data=json.dumps(data),
            verify=False
        )

        self.assertEqual(response.status_code, 400, "Successful CV agent Post return code!")

        # Ensure response is well-formed
        json_response = response.json()
        self.assertIn("results", json_response, "Malformed response body!")
예제 #5
0
    def test_010_reg_agent_post(self):
        """Test registrar's POST /v2/agents/{UUID} Interface"""
        global keyblob, aik, vtpm, ek

        # Change CWD for TPM-related operations
        cwd = os.getcwd()
        config.ch_dir(config.WORK_DIR, None)
        _ = secure_mount.mount()

        # Initialize the TPM with AIK
        (ek, ekcert, aik, ek_tpm,
         aik_name) = tpm.tpm_init(self_activate=False,
                                  config_pw=config.get('cloud_agent',
                                                       'tpm_ownerpassword'))
        vtpm = tpm.is_vtpm()

        # Seed RNG (root only)
        if config.REQUIRE_ROOT:
            tpm.init_system_rand()

        # Handle virtualized and emulated TPMs
        if ekcert is None:
            if vtpm:
                ekcert = 'virtual'
            elif tpm.is_emulator():
                ekcert = 'emulator'

        # Get back to our original CWD
        config.ch_dir(cwd, None)

        data = {
            'ek': ek,
            'ekcert': ekcert,
            'aik': aik,
            'aik_name': aik_name,
            'ek_tpm': ek_tpm,
            'tpm_version': tpm.VERSION,
        }

        test_010_reg_agent_post = RequestsClient(
            tenant_templ.registrar_base_url, tls_enabled=False)
        response = test_010_reg_agent_post.post(
            f'/v{self.api_version}/agents/{tenant_templ.agent_uuid}',
            data=json.dumps(data),
            cert="",
            verify=False)

        self.assertEqual(response.status_code, 200,
                         "Non-successful Registrar agent Add return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("blob", json_response["results"],
                      "Malformed response body!")

        keyblob = json_response["results"]["blob"]
        self.assertIsNotNone(keyblob, "Malformed response body!")
예제 #6
0
    def test_030_cv_agent_post(self):
        """Test CV's POST /agents/{UUID} Interface"""
        self.assertIsNotNone(
            self.V, "Required value not set.  Previous step may have failed?")

        b64_v = base64.b64encode(self.V)
        data = {
            "v":
            b64_v,
            "cloudagent_ip":
            tenant_templ.cloudagent_ip,
            "cloudagent_port":
            tenant_templ.cloudagent_port,
            "tpm_policy":
            json.dumps(self.tpm_policy),
            "ima_policy_bundle":
            json.dumps(self.ima_policy_bundle),
            "ima_sign_verification_keys":
            "",
            "mb_refstate":
            None,
            "metadata":
            json.dumps(self.metadata),
            "revocation_key":
            self.revocation_key,
            "accept_tpm_hash_algs":
            config.get("tenant", "accept_tpm_hash_algs").split(","),
            "accept_tpm_encryption_algs":
            config.get("tenant", "accept_tpm_encryption_algs").split(","),
            "accept_tpm_signing_algs":
            config.get("tenant", "accept_tpm_signing_algs").split(","),
            "supported_version":
            tenant_templ.supported_version,
            "ak_tpm":
            aik_tpm,
            "mtls_cert":
            mtls_cert,
        }

        test_030_cv_agent_post = RequestsClient(tenant_templ.verifier_base_url,
                                                tls_enabled)
        response = test_030_cv_agent_post.post(
            f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}",
            data=json.dumps(data),
            cert=tenant_templ.cert,
            verify=False,
        )

        self.assertEqual(response.status_code, 200,
                         "Non-successful CV agent Post return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")

        time.sleep(10)
예제 #7
0
    def test_010_reg_agent_post(self):
        """Test registrar's POST /agents/{UUID} Interface"""
        global keyblob, vtpm, tpm_instance, ek_tpm, aik_tpm
        contact_ip = "127.0.0.1"
        contact_port = 9002
        tpm_instance = tpm_main.tpm()

        # Change CWD for TPM-related operations
        cwd = os.getcwd()
        config.ch_dir(config.WORK_DIR, None)
        _ = secure_mount.mount()

        # Initialize the TPM with AIK
        (ekcert, ek_tpm, aik_tpm) = tpm_instance.tpm_init(
            self_activate=False,
            config_pw=config.get('cloud_agent', 'tpm_ownerpassword'))
        vtpm = tpm_instance.is_vtpm()

        # Handle virtualized and emulated TPMs
        if ekcert is None:
            if vtpm:
                ekcert = 'virtual'
            elif tpm_instance.is_emulator():
                ekcert = 'emulator'

        # Get back to our original CWD
        config.ch_dir(cwd, None)

        data = {
            'ekcert': ekcert,
            'aik_tpm': aik_tpm,
            'ip': contact_ip,
            'port': contact_port
        }
        if ekcert is None or ekcert == 'emulator':
            data['ek_tpm'] = ek_tpm

        test_010_reg_agent_post = RequestsClient(
            tenant_templ.registrar_base_url, tls_enabled=False)
        response = test_010_reg_agent_post.post(
            f'/v{self.api_version}/agents/{tenant_templ.agent_uuid}',
            data=json.dumps(data),
            cert="",
            verify=False)

        self.assertEqual(response.status_code, 200,
                         "Non-successful Registrar agent Add return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("blob", json_response["results"],
                      "Malformed response body!")

        keyblob = json_response["results"]["blob"]
        self.assertIsNotNone(keyblob, "Malformed response body!")
예제 #8
0
    def test_010_reg_agent_post(self):
        """Test registrar's POST /agents/{UUID} Interface"""
        global keyblob, tpm_instance, ek_tpm, aik_tpm
        contact_ip = "127.0.0.1"
        contact_port = 9002
        tpm_instance = tpm_main.tpm()

        # Change CWD for TPM-related operations
        cwd = os.getcwd()
        fs_util.ch_dir(config.WORK_DIR)
        _ = secure_mount.mount()

        # Create a mTLS cert for testing
        global mtls_cert
        rsa_key = crypto.rsa_generate(2048)
        valid_util = datetime.datetime.utcnow() + datetime.timedelta(days=(360 * 5))
        mtls_cert = crypto.generate_selfsigned_cert("TEST_CERT", rsa_key, valid_util).public_bytes(
            serialization.Encoding.PEM
        )

        # Initialize the TPM with AIK
        (ekcert, ek_tpm, aik_tpm) = tpm_instance.tpm_init(
            self_activate=False, config_pw=config.get("cloud_agent", "tpm_ownerpassword")
        )

        # Handle emulated TPMs
        if ekcert is None:
            if tpm_instance.is_emulator():
                ekcert = "emulator"

        # Get back to our original CWD
        fs_util.ch_dir(cwd)

        data = {"ekcert": ekcert, "aik_tpm": aik_tpm, "ip": contact_ip, "port": contact_port, "mtls_cert": mtls_cert}
        if ekcert is None or ekcert == "emulator":
            data["ek_tpm"] = ek_tpm

        test_010_reg_agent_post = RequestsClient(tenant_templ.registrar_base_url, tls_enabled=False)
        response = test_010_reg_agent_post.post(
            f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}", data=json.dumps(data), cert="", verify=False
        )

        self.assertEqual(response.status_code, 200, "Non-successful Registrar agent Add return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
        self.assertIn("blob", json_response["results"], "Malformed response body!")

        keyblob = json_response["results"]["blob"]
        self.assertIsNotNone(keyblob, "Malformed response body!")
예제 #9
0
    def test_030_cv_agent_post(self):
        """Test CV's POST /v2/agents/{UUID} Interface"""
        self.assertIsNotNone(
            self.V, "Required value not set.  Previous step may have failed?")

        b64_v = base64.b64encode(self.V)
        data = {
            'v':
            b64_v,
            'cloudagent_ip':
            tenant_templ.cloudagent_ip,
            'cloudagent_port':
            tenant_templ.cloudagent_port,
            'tpm_policy':
            json.dumps(self.tpm_policy),
            'vtpm_policy':
            json.dumps(self.vtpm_policy),
            'allowlist':
            json.dumps(self.allowlist),
            'ima_sign_verification_keys':
            '',
            'mb_refstate':
            None,
            'metadata':
            json.dumps(self.metadata),
            'revocation_key':
            self.revocation_key,
            'accept_tpm_hash_algs':
            config.get('tenant', 'accept_tpm_hash_algs').split(','),
            'accept_tpm_encryption_algs':
            config.get('tenant', 'accept_tpm_encryption_algs').split(','),
            'accept_tpm_signing_algs':
            config.get('tenant', 'accept_tpm_signing_algs').split(','),
        }

        test_030_cv_agent_post = RequestsClient(tenant_templ.verifier_base_url,
                                                tls_enabled)
        response = test_030_cv_agent_post.post(
            f'/agents/{tenant_templ.agent_uuid}',
            data=json.dumps(data),
            cert=tenant_templ.cert,
            verify=False)

        self.assertEqual(response.status_code, 200,
                         "Non-successful CV agent Post return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")

        time.sleep(10)
예제 #10
0
def doRegisterAgent(registrar_ip, registrar_port, agent_id, ek_tpm, ekcert,
                    aik_tpm):
    data = {
        'ekcert': ekcert,
        'aik_tpm': aik_tpm,
    }
    if ekcert is None or ekcert == 'emulator':
        data['ek_tpm'] = ek_tpm
    response = None
    try:
        client = RequestsClient(f'{registrar_ip}:{registrar_port}',
                                tls_enabled)
        response = client.post(f'/agents/{agent_id}',
                               cert=tls_cert_info,
                               data=json.dumps(data),
                               verify=False)
        response_body = response.json()

        if response.status_code != 200:
            logger.error(
                "Error: unexpected http response code from Registrar Server: %s",
                response.status_code)
            keylime_logging.log_http_response(logger, logging.ERROR,
                                              response_body)
            return None

        logger.info("Agent registration requested for %s", agent_id)

        if "results" not in response_body:
            logger.critical(
                "Error: unexpected http response body from Registrar Server: %s",
                response.status_code)
            return None

        if "blob" not in response_body["results"]:
            logger.critical(
                "Error: did not receive blob from Registrar Server: %s",
                response.status_code)
            return None

        return response_body["results"]["blob"]
    except Exception as e:
        if response and response.status_code == 503:
            logger.error(
                "Agent cannot establish connection to registrar at %s:%s",
                registrar_ip, registrar_port)
            sys.exit()
        else:
            logger.exception(e)

    return None
예제 #11
0
    def do_cv(self):
        """ Initiaite v, agent_id and ip and initiate the cloudinit sequence
        """
        b64_v = base64.b64encode(self.V).decode('utf-8')
        logger.debug("b64_v:" + b64_v)
        data = {
            'v': b64_v,
            'cloudagent_ip': self.cv_cloudagent_ip,
            'cloudagent_port': self.agent_port,
            'tpm_policy': json.dumps(self.tpm_policy),
            'vtpm_policy': json.dumps(self.vtpm_policy),
            'allowlist': json.dumps(self.allowlist),
            'metadata': json.dumps(self.metadata),
            'revocation_key': self.revocation_key,
            'accept_tpm_hash_algs': self.accept_tpm_hash_algs,
            'accept_tpm_encryption_algs': self.accept_tpm_encryption_algs,
            'accept_tpm_signing_algs': self.accept_tpm_signing_algs,
        }
        json_message = json.dumps(data)
        do_cv = RequestsClient(self.verifier_base_url, self.tls_enabled)
        response = do_cv.post((f'/agents/{self.agent_uuid}'),
                              data=json_message,
                              cert=self.cert,
                              verify=False)

        if response.status_code == 503:
            logger.error(
                f"Cannot connect to Verifier at {self.verifier_ip} with Port {self.verifier_port}. Connection refused."
            )
            sys.exit()
        elif response.status_code == 504:
            logger.error(
                f"Verifier at {self.verifier_ip} with Port {self.verifier_port} timed out."
            )
            sys.exit()

        if response.status_code == 409:
            # this is a conflict, need to update or delete it
            logger.error(
                f"Agent {self.agent_uuid} already existed at CV.  Please use delete or update."
            )
            sys.exit()
        elif response.status_code != 200:
            keylime_logging.log_http_response(logger, logging.ERROR,
                                              response.json())
            logger.error(
                f"POST command response: {response.status} Unexpected response from Cloud Verifier: {response.read()}"
            )
            sys.exit()
예제 #12
0
    def do_add_allowlist(self, args):
        if 'allowlist_name' not in args or not args['allowlist_name']:
            raise UserError('allowlist_name is required to add an allowlist')

        allowlist_name = args['allowlist_name']
        self.process_allowlist(args)
        data = {
            'tpm_policy': json.dumps(self.tpm_policy),
            'vtpm_policy': json.dumps(self.vtpm_policy),
            'allowlist': json.dumps(self.allowlist)
        }
        body = json.dumps(data)
        cv_client = RequestsClient(self.verifier_base_url, self.tls_enabled)
        response = cv_client.post(f'/allowlists/{allowlist_name}', data=body,
                                  cert=self.cert, verify=False)
        print(response.json())
예제 #13
0
    def test_025_cv_allowlist_post(self):
        """Test CV's POST /allowlist/{name} Interface"""
        data = {
            "name": "test-allowlist",
            "tpm_policy": json.dumps(self.tpm_policy),
            "ima_policy": json.dumps(self.allowlist),
        }

        cv_client = RequestsClient(tenant_templ.verifier_base_url, tls_enabled)
        response = cv_client.post(
            f"/v{self.api_version}/allowlists/test-allowlist",
            data=json.dumps(data),
            cert=tenant_templ.cert,
            verify=False,
        )

        self.assertEqual(response.status_code, 201, "Non-successful CV allowlist Post return code!")
        json_response = response.json()

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
예제 #14
0
    def test_034_cv_agent_post_invalid_exclude_list(self):
        """Test CV's POST /agents/{UUID} Interface"""
        self.assertIsNotNone(self.V, "Required value not set.  Previous step may have failed?")

        b64_v = base64.b64encode(self.V)
        # Set unsupported regex in exclude list
        allowlist = {"exclude": ["*"]}
        data = {
            "v": b64_v,
            "mb_refstate": None,
            "cloudagent_ip": tenant_templ.cloudagent_ip,
            "cloudagent_port": tenant_templ.cloudagent_port,
            "tpm_policy": json.dumps(self.tpm_policy),
            "allowlist": json.dumps(allowlist),
            "ima_sign_verification_keys": "",
            "metadata": json.dumps(self.metadata),
            "revocation_key": self.revocation_key,
            "accept_tpm_hash_algs": config.get("tenant", "accept_tpm_hash_algs").split(","),
            "accept_tpm_encryption_algs": config.get("tenant", "accept_tpm_encryption_algs").split(","),
            "accept_tpm_signing_algs": config.get("tenant", "accept_tpm_signing_algs").split(","),
            "supported_version": tenant_templ.supported_version,
        }

        client = RequestsClient(tenant_templ.verifier_base_url, tls_enabled)
        response = client.post(
            f"/v{self.api_version}/agents/{tenant_templ.agent_uuid}",
            cert=tenant_templ.cert,
            data=json.dumps(data),
            verify=False,
        )

        self.assertEqual(response.status_code, 400, "Successful CV agent Post return code!")

        # Ensure response is well-formed
        json_response = response.json()
        self.assertIn("results", json_response, "Malformed response body!")
예제 #15
0
def doRegisterAgent(registrar_ip,
                    registrar_port,
                    agent_id,
                    ek_tpm,
                    ekcert,
                    aik_tpm,
                    mtls_cert=None,
                    contact_ip=None,
                    contact_port=None):
    data = {
        "ekcert": ekcert,
        "aik_tpm": aik_tpm,
    }
    if ekcert is None or ekcert == "emulator":
        data["ek_tpm"] = ek_tpm

    if mtls_cert is not None:
        data["mtls_cert"] = mtls_cert
    else:
        logger.error(
            "Most actions require the agent to have mTLS enabled, but no cert was provided!"
        )
    if contact_ip is not None:
        data["ip"] = contact_ip
    if contact_port is not None:
        data["port"] = contact_port

    response = None
    try:
        client = RequestsClient(f"{registrar_ip}:{registrar_port}",
                                tls_enabled,
                                ignore_hostname=True)
        response = client.post(f"/v{api_version}/agents/{agent_id}",
                               cert=tls_cert_info,
                               data=json.dumps(data),
                               verify=ca_cert)
        response_body = response.json()

        if response.status_code != 200:
            logger.error(
                "Error: unexpected http response code from Registrar Server: %s",
                response.status_code)
            keylime_logging.log_http_response(logger, logging.ERROR,
                                              response_body)
            return None

        logger.info("Agent registration requested for %s", agent_id)

        if "results" not in response_body:
            logger.critical(
                "Error: unexpected http response body from Registrar Server: %s",
                response.status_code)
            return None

        if "blob" not in response_body["results"]:
            logger.critical(
                "Error: did not receive blob from Registrar Server: %s",
                response.status_code)
            return None

        return response_body["results"]["blob"]
    except Exception as e:
        if response and response.status_code == 503:
            logger.error(
                "Agent cannot establish connection to registrar at %s:%s",
                registrar_ip, registrar_port)
            sys.exit()
        else:
            logger.exception(e)

    return None
예제 #16
0
    def do_quote(self):
        """ Perform TPM quote by GET towards Agent

        Raises:
            UserError: Connection handler
        """
        self.nonce = TPM_Utilities.random_password(20)

        numtries = 0
        response = None
        # Note: We need a specific retry handler (perhaps in common), no point having localised unless we have too.
        while True:
            try:
                params = '/quotes/identity?nonce=%s' % (self.nonce)
                cloudagent_base_url = f'{self.agent_ip}:{self.agent_port}'
                do_quote = RequestsClient(cloudagent_base_url, tls_enabled=False)
                response = do_quote.get(
                    params,
                    cert=self.cert
                )
                response_body = response.json()

            except Exception as e:
                if response.status_code in (503, 504):
                    numtries += 1
                    maxr = config.getint('tenant', 'max_retries')
                    if numtries >= maxr:
                        logger.error("Tenant cannot establish connection to agent on %s with port %s", self.agent_ip, self.agent_port)
                        sys.exit()
                    retry = config.getfloat('tenant', 'retry_interval')
                    logger.info("Tenant connection to agent at %s refused %s/%s times, trying again in %s seconds...",
                        self.agent_ip, numtries, maxr, retry)
                    time.sleep(retry)
                    continue

                raise e
            break

        try:
            if response is not None and response.status_code != 200:
                raise UserError(
                    "Status command response: %d Unexpected response from Cloud Agent." % response.status)

            if "results" not in response_body:
                raise UserError(
                    "Error: unexpected http response body from Cloud Agent: %s" % str(response.status))

            quote = response_body["results"]["quote"]
            logger.debug("Agent_quote received quote: %s", quote)

            public_key = response_body["results"]["pubkey"]
            logger.debug("Agent_quote received public key: %s", public_key)

            # Ensure hash_alg is in accept_tpm_hash_algs list
            hash_alg = response_body["results"]["hash_alg"]
            logger.debug("Agent_quote received hash algorithm: %s", hash_alg)
            if not algorithms.is_accepted(hash_alg, config.get('tenant', 'accept_tpm_hash_algs').split(',')):
                raise UserError(
                    "TPM Quote is using an unaccepted hash algorithm: %s" % hash_alg)

            # Ensure enc_alg is in accept_tpm_encryption_algs list
            enc_alg = response_body["results"]["enc_alg"]
            logger.debug("Agent_quote received encryption algorithm: %s", enc_alg)
            if not algorithms.is_accepted(enc_alg, config.get('tenant', 'accept_tpm_encryption_algs').split(',')):
                raise UserError(
                    "TPM Quote is using an unaccepted encryption algorithm: %s" % enc_alg)

            # Ensure sign_alg is in accept_tpm_encryption_algs list
            sign_alg = response_body["results"]["sign_alg"]
            logger.debug("Agent_quote received signing algorithm: %s", sign_alg)
            if not algorithms.is_accepted(sign_alg, config.get('tenant', 'accept_tpm_signing_algs').split(',')):
                raise UserError(
                    "TPM Quote is using an unaccepted signing algorithm: %s" % sign_alg)

            if not self.validate_tpm_quote(public_key, quote, hash_alg):
                raise UserError(
                    "TPM Quote from cloud agent is invalid for nonce: %s" % self.nonce)

            logger.info("Quote from %s validated", self.agent_ip)

            # encrypt U with the public key
            encrypted_U = crypto.rsa_encrypt(
                crypto.rsa_import_pubkey(public_key), self.U)

            b64_encrypted_u = base64.b64encode(encrypted_U)
            logger.debug("b64_encrypted_u: %s", b64_encrypted_u.decode('utf-8'))
            data = {
                'encrypted_key': b64_encrypted_u,
                'auth_tag': self.auth_tag
            }

            if self.payload is not None:
                data['payload'] = self.payload

            u_json_message = json.dumps(data)

            # post encrypted U back to CloudAgent
            params = '/keys/ukey'
            cloudagent_base_url = (
                f'{self.agent_ip}:{self.agent_port}'
            )

            post_ukey = RequestsClient(cloudagent_base_url, tls_enabled=False)
            response = post_ukey.post(
                params,
                data=u_json_message
            )

            if response.status_code == 503:
                logger.error("Cannot connect to Agent at %s with Port %s. Connection refused.", self.agent_ip, self.agent_port)
                sys.exit()
            elif response.status_code == 504:
                logger.error("Verifier at %s with Port %s timed out.", self.verifier_ip, self.verifier_port)
                sys.exit()

            if response.status_code != 200:
                keylime_logging.log_http_response(
                    logger, logging.ERROR, response_body)
                raise UserError(
                    "Posting of Encrypted U to the Cloud Agent failed with response code %d" % response.status)
        except Exception as e:
            self.do_cvstop()
            raise e