Exemple #1
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!")
Exemple #2
0
    def test_023_agent_keys_vkey_post(self):
        """Test agent's POST /v2/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
        global public_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}
        v_json_message = json.dumps(data)

        params = f"/v{self.api_version}/keys/vkey"
        response = httpclient_requests.request("POST",
                                               "%s" %
                                               tenant_templ.cloudagent_ip,
                                               tenant_templ.cloudagent_port,
                                               params=params,
                                               data=v_json_message)
        self.assertEqual(response.status, 200,
                         "Non-successful Agent vkey post return code!")
        json_response = json.loads(response.read().decode())

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
Exemple #3
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!")
Exemple #4
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
                }
        u_yaml_message = json.dumps(data)

        params = '/v%s/keys/ukey'% self.api_version
        response = httpclient_requests.request("POST", "%s"%tenant_templ.cloudagent_ip,tenant_templ.cloudagent_port, params=params, data=u_yaml_message)
        self.assertEqual(response.status, 200, "Non-successful Agent ukey post return code!")
        json_response = json.loads(response.read().decode())

        # Ensure response is well-formed
        self.assertIn("results", json_response, "Malformed response body!")
Exemple #5
0
 def test_rsa(self):
     message = b"a secret message!"
     private = rsa_generate(2048)
     pubkeypem = rsa_export_pubkey(private)
     pubkey = rsa_import_pubkey(pubkeypem)
     keypem = rsa_export_privkey(private)
     key = rsa_import_privkey(keypem)
     ciphertext = rsa_encrypt(pubkey, message)
     plain = rsa_decrypt(key, ciphertext)
     self.assertEqual(plain, message)
Exemple #6
0
def prepare_v(agent):
    # be very careful printing K, U, or V as they leak in logs stored on unprotected disks
    if config.INSECURE_DEBUG:
        logger.debug("b64_V (non encrypted): %s", agent['v'])

    if agent.get('b64_encrypted_V', "") != "":
        b64_encrypted_V = agent['b64_encrypted_V']
        logger.debug("Re-using cached encrypted V")
    else:
        # encrypt V with the public key
        b64_encrypted_V = base64.b64encode(
            crypto.rsa_encrypt(crypto.rsa_import_pubkey(agent['public_key']),
                               base64.b64decode(agent['v'])))
        agent['b64_encrypted_V'] = b64_encrypted_V

    # logger.debug("b64_encrypted_V:" + b64_encrypted_V)
    post_data = {'encrypted_key': b64_encrypted_V}
    return post_data
Exemple #7
0
    def do_quote(self):
        """initiaite v, agent_id and ip
        initiate the cloudinit sequence"""
        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)
                params = f'/quotes/identity?nonce={self.nonce}'
                response = httpclient_requests.request("GET",
                                                       "%s" %
                                                       (self.cloudagent_ip),
                                                       self.cloudagent_port,
                                                       params=params,
                                                       context=None)
                response_body = json.loads(response.read().decode())
            except Exception as e:
                if response == 503 or response == 504:
                    numtries += 1
                    maxr = config.getint('tenant', 'max_retries')
                    if numtries >= maxr:
                        logger.error(
                            f"tenant cannot establish connection to agent on {self.cloudagent_ip} with port {self.cloudagent_port}"
                        )
                        exit()
                    retry = config.getfloat('tenant', 'retry_interval')
                    logger.info(
                        f"tenant connection to agent at {self.cloudagent_ip} refused {numtries}/{maxr} times, trying again in {retry} seconds..."
                    )
                    time.sleep(retry)
                    continue
                else:
                    raise (e)
            break

        try:
            if response is not None and response.status != 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(f"agent_quote received quote: {quote}")

            public_key = response_body["results"]["pubkey"]
            logger.debug(f"agent_quote received public key: {public_key}")

            # Get tpm_version, hash_alg
            tpm_version = response_body["results"]["tpm_version"]
            logger.debug(
                f"agent_quote received tpm version: {str(tpm_version)}")

            # Ensure hash_alg is in accept_tpm_hash_algs list
            hash_alg = response_body["results"]["hash_alg"]
            logger.debug(f"agent_quote received hash algorithm: {hash_alg}")
            if not Hash_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(
                f"agent_quote received encryption algorithm: {enc_alg}")
            if not Encrypt_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(f"agent_quote received signing algorithm: {sign_alg}")
            if not Sign_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, tpm_version,
                                           hash_alg):
                raise UserError(
                    "TPM Quote from cloud agent is invalid for nonce: %s" %
                    self.nonce)

            logger.info(f"Quote from {self.cloudagent_ip} validated")

            # encrypt U with the public key
            # encrypted_U = crypto.rsa_encrypt(crypto.rsa_import_pubkey(public_key),str(self.U))
            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: " + 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'
            response = httpclient_requests.request("POST",
                                                   "%s" % (self.cloudagent_ip),
                                                   self.cloudagent_port,
                                                   params=params,
                                                   data=u_json_message)

            if response == 503:
                logger.error(
                    f"Cannot connect to Agent at {self.cloudagent_ip} with Port {self.cloudagent_port}. Connection refused."
                )
                exit()
            elif response == 504:
                logger.error(
                    f"Verifier at {self.cloudverifier_ip} with Port {self.cloudverifier_port} timed out."
                )
                exit()

            if response.status != 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
Exemple #8
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