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) response = tornado_requests.request( "POST", "http://%s:%s/v%s/keys/vkey"%(tenant_templ.cloudagent_ip,tenant_templ.cloudagent_port,self.api_version), data=v_json_message ) self.assertEqual(response.status_code, 200, "Non-successful Agent vkey post return code!") response_body = response.json() # Ensure response is well-formed self.assertIn("results", response_body, "Malformed response body!")
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),str(self.U)) b64_encrypted_u = base64.b64encode(encrypted_U) data = { 'encrypted_key': b64_encrypted_u, 'auth_tag': self.auth_tag, 'payload': self.payload } u_json_message = json.dumps(data) response = tornado_requests.request( "POST", "http://%s:%s/v%s/keys/ukey"%(tenant_templ.cloudagent_ip,tenant_templ.cloudagent_port,self.api_version), data=u_json_message ) self.assertEqual(response.status_code, 200, "Non-successful Agent ukey post return code!") response_body = response.json() # Ensure response is well-formed self.assertIn("results", response_body, "Malformed response body!")
def await_notifications(callback,revocation_cert_path): global cert_key if revocation_cert_path is None: raise Exception("must specify revocation_cert_path") context = zmq.Context() mysock = context.socket(zmq.SUB) mysock.setsockopt(zmq.SUBSCRIBE, '') mysock.connect("tcp://%s:%s"%(config.get('general','revocation_notifier_ip'),config.getint('general','revocation_notifier_port'))) logger.info('Waiting for revocation messages on 0mq %s:%s'% (config.get('general','revocation_notifier_ip'),config.getint('general','revocation_notifier_port'))) while True: rawbody = mysock.recv() body = json.loads(rawbody) if cert_key is None: # load up the CV signing public key if revocation_cert_path is not None and os.path.exists(revocation_cert_path): logger.info("Lazy loading the revocation certificate from %s"%revocation_cert_path) with open(revocation_cert_path,'r') as f: certpem = f.read() cert_key = crypto.rsa_import_pubkey(certpem) if cert_key is None: logger.warning("Unable to check signature of revocation message: %s not available"%revocation_cert_path) elif str(body['signature'])=='none': logger.warning("No signature on revocation message from server") elif not crypto.rsa_verify(cert_key,str(body['msg']),str(body['signature'])): logger.error("Invalid revocation message siganture %s"%body) else: message = json.loads(body['msg']) logger.debug("Revocation signature validated for revocation: %s"%message) callback(message)
def prepare_v(agent): # be very careful printing K, U, or V as they leak in logs stored on unprotected disks if common.INSECURE_DEBUG: logger.debug("b64_V (non encrypted): " + 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']),str(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 } v_json_message = json.dumps(post_data) return v_json_message
def prepare_v(instance): # be very careful printing K, U, or V as they leak in logs stored on unprotected disks if common.DEVELOP_IN_ECLIPSE: logger.debug("b64_V (non encrypted): " + instance['v']) if instance.get('b64_encrypted_V', "") != "": b64_encrypted_V = instance['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(instance['public_key']), str(base64.b64decode(instance['v'])))) instance['b64_encrypted_V'] = b64_encrypted_V logger.debug("b64_encrypted_V:" + b64_encrypted_V) post_data = {'encrypted_key': b64_encrypted_V} v_json_message = json.dumps(post_data) return v_json_message
def do_quote(self): """initiaite v, instance_id and ip initiate the cloudinit sequence""" self.nonce = tpm_initialize.random_password(20) params = { 'nonce': self.nonce, } numtries = 0 while True: try: response = tornado_requests.request( "GET", "http://%s:%s/v1/quotes/tenant" % (self.cloudnode_ip, self.cloudnode_port), params=params) except Exception as e: # this is one exception that should return a 'keep going' response if tornado_requests.is_refused(e): numtries += 1 maxr = config.getint('tenant', 'max_retries') if numtries >= maxr: logger.error( "Quiting after max number of retries to connect to %s" % (self.cloudnode_ip)) raise e retry = config.getfloat('tenant', 'retry_interval') logger.info( "Connection to %s refused %d/%d times, trying again in %f seconds..." % (self.cloudnode_ip, numtries, maxr, retry)) time.sleep(retry) continue else: raise e if response.status_code == 200: response_body = response.json() public_key = response_body["pubkey"] logger.debug("cnquote received public key:" + public_key) quote = response_body["quote"] logger.debug("cnquote received quote:" + quote) if self.validate_tpm_quote(public_key, quote): logger.info("Quote from %s validated" % self.cloudnode_ip) # encrypt U with the public key encrypted_U = crypto.rsa_encrypt( crypto.rsa_import_pubkey(public_key), str(self.U)) b64_encrypted_u = base64.b64encode(encrypted_U) logger.debug("b64_encrypted_u: " + b64_encrypted_u) 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 CloudNode response = tornado_requests.request( "POST", "http://%s:%s/v1/quotes/tenant" % (self.cloudnode_ip, self.cloudnode_port), data=u_json_message) if response.status_code != 200: logger.error( "Posting of Encrypted U to the Cloud Node failed with response code %d" % response.status_code) break else: logger.error( "TPM Quote from cloud node is invalid for nonce: %s" % self.nonce) break else: logger.error( "Status command response: %d Unexpected response from Cloud Node." % response.status_code) break break
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 while True: # Get quote try: response = tornado_requests.request( "GET", "http://%s:%s/quotes/identity?nonce=%s" % (self.cloudagent_ip, self.cloudagent_port, self.nonce)) except Exception as e: # this is one exception that should return a 'keep going' response if tornado_requests.is_refused(e): numtries += 1 maxr = config.getint('tenant', 'max_retries') if numtries >= maxr: raise UserError( "Quitting after max number of retries to connect to %s" % (self.cloudagent_ip)) retry = config.getfloat('tenant', 'retry_interval') logger.info( "Connection to %s refused %d/%d times, trying again in %f seconds..." % (self.cloudagent_ip, numtries, maxr, retry)) time.sleep(retry) continue else: 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_code) response_body = response.json() if "results" not in response_body: raise UserError( "Error: unexpected http response body from Cloud Agent: %s" % str(response.status_code)) quote = response_body["results"]["quote"] logger.debug("agent_quote received quote:" + quote) public_key = response_body["results"]["pubkey"] logger.debug("agent_quote received public key:" + public_key) # Get tpm_version, hash_alg tpm_version = response_body["results"]["tpm_version"] logger.debug("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("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("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("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("Quote from %s validated" % self.cloudagent_ip) # encrypt U with the public key encrypted_U = crypto.rsa_encrypt( crypto.rsa_import_pubkey(public_key), str(self.U)) b64_encrypted_u = base64.b64encode(encrypted_U) logger.debug("b64_encrypted_u: " + b64_encrypted_u) 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 response = tornado_requests.request( "POST", "http://%s:%s/keys/ukey" % (self.cloudagent_ip, self.cloudagent_port), data=u_json_message) if response.status_code != 200: common.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_code) except Exception as e: self.do_cvstop() raise e
def get_mod_from_pem(pem): pubkey = crypto.rsa_import_pubkey(pem) return base64.b64encode(bytearray.fromhex('{:0192x}'.format(pubkey.n)))
def get_mod_from_pem(pemfile): with open(pemfile, "r") as f: pem = f.read() pubkey = crypto.rsa_import_pubkey(pem) return base64.b64encode(bytearray.fromhex('{:0192x}'.format(pubkey.n)))