def __init__(self, server_address, RequestHandlerClass, agent_uuid): """Constructor overridden to provide ability to pass configuration arguments to the server""" secdir = secure_mount.mount() keyname = "%s/%s"%(secdir,config.get('cloud_agent','rsa_keyname')) # read or generate the key depending on configuration if os.path.isfile(keyname): # read in private key logger.debug( "Using existing key in %s"%keyname) f = open(keyname,"r") rsa_key = crypto.rsa_import_privkey(f.read()) else: logger.debug("key not found, generating a new one") rsa_key = crypto.rsa_generate(2048) with open(keyname,"w") as f: f.write(crypto.rsa_export_privkey(rsa_key)) self.rsaprivatekey = rsa_key self.rsapublickey_exportable = crypto.rsa_export_pubkey(self.rsaprivatekey) #attempt to get a U value from the TPM NVRAM nvram_u = tpm.read_key_nvram() if nvram_u is not None: logger.info("Existing U loaded from TPM NVRAM") self.add_U(nvram_u) BaseHTTPServer.HTTPServer.__init__(self, server_address, RequestHandlerClass) self.enc_keyname = config.get('cloud_agent','enc_keyname') self.agent_uuid = agent_uuid
def execute(json_revocation): if json_revocation['type'] != 'revocation': return secdir = secure_mount.mount() cert_path = config.get('cloud_node', 'revocation_cert') if cert_path == "default": cert_path = '%s/unzipped/RevocationNotifier-cert.crt' % (secdir) else: # if it is a relative, convert to absolute in work_dir if cert_path[0] != '/': cert_path = os.path.abspath('%s/%s' % (common.WORK_DIR, cert_path)) if not os.path.exists(cert_path): raise Exception("revocation_cert %s not found" % (os.path.abspath(cert_path))) # get the updated CRL dist_path = ca_util.get_crl_distpoint(cert_path) time.sleep(1) logger.debug("Getting updated CRL from %s" % dist_path) response = tornado_requests.request("GET", dist_path, None, None, None) if response.status_code != 200: logger.warn("Unable to get updated CRL from %s. Code %d" % (dist_path, response.status_code)) else: # write out the updated CRL logger.debug("Updating CRL in %s/unzipped/cacrl.der" % (secdir)) with open("%s/unzipped/cacrl.der" % (secdir), "w") as f: f.write(response.body) ca_util.convert_crl_to_pem("%s/unzipped/cacrl.der" % (secdir), "%s/unzipped/cacrl.pem" % secdir)
def worker(): def print_notification(revocation): logger.warning("Received revocation: %s" % revocation) keypath = '%s/unzipped/RevocationNotifier-cert.crt' % ( secure_mount.mount()) await_notifications(print_notification, revocation_cert_path=keypath)
def test_010_reg_instance_post(self): """Test registrar's POST /v2/instances/{UUID} Interface""" global keyblob, aik, vtpm, ek # Change CWD for TPM-related operations cwd = os.getcwdu() common.ch_dir(common.WORK_DIR, None) secdir = secure_mount.mount() # Initialize the TPM with AIK (ek, ekcert, aik) = tpm_initialize.init(self_activate=False, config_pw=config.get( 'cloud_node', 'tpm_ownerpassword')) vtpm = tpm_initialize.is_vtpm() # Seed RNG (root only) if common.REQUIRE_ROOT: tpm_random.init_system_rand() # Handle virtualized and emulated TPMs if ekcert is None: if vtpm: ekcert = 'virtual' elif tpm_initialize.is_emulator(): ekcert = 'emulator' # Get back to our original CWD common.ch_dir(cwd, None) data = { 'ek': ek, 'ekcert': ekcert, 'aik': aik, } v_json_message = json.dumps(data) response = tornado_requests.request( "POST", "http://%s:%s/v2/instances/%s" % (tenant_templ.registrar_ip, tenant_templ.registrar_boot_port, tenant_templ.node_uuid), data=v_json_message, context=None) self.assertEqual(response.status_code, 200, "Non-successful Registrar Instance Add return code!") response_body = response.json() # Ensure response is well-formed self.assertIn("results", response_body, "Malformed response body!") self.assertIn("blob", response_body["results"], "Malformed response body!") keyblob = response_body["results"]["blob"] self.assertIsNotNone(keyblob, "Malformed response body!")
def gencrl(serials,cert,ca_pk): request = {"certificate": cert, "serialNumber": serials, "issuingKey": ca_pk, "expireTime": "" } data = json.dumps(request) secdir = common.WORK_DIR+"/secure" try: secure_mount.mount() if not os.path.isdir(secdir): os.makedirs(secdir) # need to temporarily write out the private key with no password # to tmpfs with open('%s/ca-key.pem'%secdir,'wb') as f: f.write(ca_pk) priv_key = os.path.abspath("%s/secure/ca-key.pem"%common.WORK_DIR) cmdline = " -ca-key %s -ca cacert.crt"%(priv_key) start_cfssl(cmdline) response = post_cfssl("http://127.0.0.1:8888/api/v1/cfssl/gencrl",data=data) finally: stop_cfssl() os.remove('%s/ca-key.pem'%secdir) body = json.loads(response.body) if body['success']: #pk = EVP.load_key_string(str(body['result']['private_key'])) #cert = X509.load_cert_string(str(body['result']['certificate'])) #return cert, pk retval = base64.b64decode(body['result']) with open("my.crl",'wb') as f: f.write(retval) else: raise Exception("Unable to create crl for cert serials %s. Error: %s"%(serials,body['errors'])) return retval # ./cfssl gencrl revoke ca.pem ca-key.pem | base64 -D > mycrl.der # mk_cacert() # mk_signed_cert("", "", "hello", None)
def activate_identity(keyblob): if common.STUB_TPM: return base64.b64encode(common.TEST_AES_REG_KEY) owner_pw = get_tpm_metadata('owner_pw') keyblobFile = None secpath = None try: # write out key blob kfd, ktemp = tempfile.mkstemp() keyblobFile = open(ktemp, "wb") keyblobFile.write(base64.b64decode(keyblob)) keyblobFile.close() os.close(kfd) keyhandle = load_aik() keyfd, keypath = tempfile.mkstemp() # read in the key f = open(keypath, "rb") key = f.read() f.close() os.close(keyfd) # ok lets write out the key now secdir = secure_mount.mount( ) # confirm that storage is still securely mounted secfd, secpath = tempfile.mkstemp(dir=secdir) tpm_exec.run("activateidentity -hk %s -pwdo %s -if %s -ok %s" % (keyhandle, owner_pw, keyblobFile.name, secpath)) logger.info("AIK activated.") f = open(secpath, 'rb') key = base64.b64encode(f.read()) f.close() os.close(secfd) os.remove(secpath) except Exception as e: logger.error("Error decrypting AIK: " + str(e)) logger.error(traceback.format_exc()) return False finally: if keyblobFile is not None: os.remove(keyblobFile.name) if secpath is not None and os.path.exists(secpath): os.remove(secpath) return key
def activate_identity(self, keyblob): owner_pw = self.get_tpm_metadata('owner_pw') keyhandle = self.get_tpm_metadata('aik_handle') keyblobFile = None secpath = None try: # write out key blob kfd, ktemp = tempfile.mkstemp() keyblobFile = open(ktemp, "wb") keyblobFile.write(base64.b64decode(keyblob)) keyblobFile.close() os.close(kfd) # ok lets write out the key now secdir = secure_mount.mount( ) # confirm that storage is still securely mounted secfd, secpath = tempfile.mkstemp(dir=secdir) command = "activateidentity -hk %s -pwdo %s -pwdk %s -if %s -ok %s" % ( keyhandle, owner_pw, self.get_tpm_metadata('aik_pw'), keyblobFile.name, secpath) retDict = self.__run(command, outputpaths=secpath) retout = retDict['retout'] code = retDict['code'] fileout = retDict['fileouts'][secpath] logger.info("AIK activated.") key = base64.b64encode(fileout) os.close(secfd) os.remove(secpath) except Exception as e: logger.error("Error decrypting AIK: " + str(e)) logger.exception(e) return False finally: if keyblobFile is not None: os.remove(keyblobFile.name) if secpath is not None and os.path.exists(secpath): os.remove(secpath) return key
def main(argv=sys.argv): if os.getuid()!=0 and common.REQUIRE_ROOT: logger.critical("This process must be run as root.") return # get params for initialization registrar_ip = config.get('general', 'registrar_ip') registrar_port = config.get('general', 'registrar_port') # initialize the tmpfs partition to store keys if it isn't already available secdir = secure_mount.mount() # change dir to working dir common.ch_dir(common.WORK_DIR,logger) #initialize tpm (ek,ekcert,aik,ek_tpm,aik_name) = tpm.tpm_init(self_activate=False,config_pw=config.get('cloud_agent','tpm_ownerpassword')) # this tells initialize not to self activate the AIK virtual_agent = tpm.is_vtpm() # try to get some TPM randomness into the system entropy pool tpm.init_system_rand() if ekcert is None: if virtual_agent: ekcert = 'virtual' elif tpm.is_emulator(): ekcert = 'emulator' # now we need the UUID try: agent_uuid = config.get('cloud_agent','agent_uuid') except ConfigParser.NoOptionError: agent_uuid = None if agent_uuid == 'openstack': agent_uuid = openstack.get_openstack_uuid() elif agent_uuid == 'hash_ek': agent_uuid = hashlib.sha256(ek).hexdigest() elif agent_uuid == 'generate' or agent_uuid is None: agent_uuid = str(uuid.uuid4()) if common.DEVELOP_IN_ECLIPSE: agent_uuid = "C432FBB3-D2F1-4A97-9EF7-75BD81C866E9" if common.STUB_VTPM and common.TPM_CANNED_VALUES is not None: # Use canned values for stubbing jsonIn = common.TPM_CANNED_VALUES if "add_vtpm_to_group" in jsonIn: # The value we're looking for has been canned! agent_uuid = jsonIn['add_vtpm_to_group']['retout'] else: # Our command hasn't been canned! raise Exception("Command %s not found in canned JSON!"%("add_vtpm_to_group")) logger.info("Agent UUID: %s"%agent_uuid) # register it and get back a blob keyblob = registrar_client.doRegisterAgent(registrar_ip,registrar_port,agent_uuid,tpm_version,ek,ekcert,aik,ek_tpm,aik_name) if keyblob is None: raise Exception("Registration failed") # get the ephemeral registrar key key = tpm.activate_identity(keyblob) # tell the registrar server we know the key retval=False if virtual_agent: deepquote = tpm.create_deep_quote(hashlib.sha1(key).hexdigest(),agent_uuid+aik+ek) retval = registrar_client.doActivateVirtualAgent(registrar_ip, registrar_port, agent_uuid, deepquote) else: retval = registrar_client.doActivateAgent(registrar_ip,registrar_port,agent_uuid,key) if not retval: raise Exception("Registration failed on activate") serveraddr = ('', config.getint('general', 'cloudagent_port')) server = CloudAgentHTTPServer(serveraddr,Handler,agent_uuid) serverthread = threading.Thread(target=server.serve_forever) logger.info( 'Starting Cloud Agent on port %s use <Ctrl-C> to stop'%serveraddr[1]) serverthread.start() # want to listen for revocations? if config.getboolean('cloud_agent','listen_notfications'): cert_path = config.get('cloud_agent','revocation_cert') if cert_path == "default": cert_path = '%s/unzipped/RevocationNotifier-cert.crt'%(secdir) elif cert_path[0]!='/': # if it is a relative, convert to absolute in work_dir cert_path = os.path.abspath('%s/%s'%(common.WORK_DIR,cert_path)) def perform_actions(revocation): actionlist = [] # load the actions from inside the keylime module actionlisttxt = config.get('cloud_agent','revocation_actions') if actionlisttxt.strip() != "": actionlist = actionlisttxt.split(',') actionlist = ["revocation_actions.%s"%i for i in actionlist] # load actions from unzipped if os.path.exists("%s/unzipped/action_list"%secdir): with open("%s/unzipped/action_list"%secdir,'r') as f: actionlisttxt = f.read() if actionlisttxt.strip()!="": localactions = actionlisttxt.strip().split(',') for action in localactions: if not action.startswith('local_action_'): logger.warning("invalid local action: %s. must start with local_action_"%action) else: actionlist.append(action) uzpath = "%s/unzipped"%secdir if uzpath not in sys.path: sys.path.append(uzpath) for action in actionlist: logger.debug("executing revocation action %s"%action) try: module = importlib.import_module(action) execute = getattr(module,'execute') execute(revocation) except Exception as e: logger.warn("Exception during execution of revocation action %s: %s"%(action,e)) try: while True: try: revocation_notifier.await_notifications(perform_actions,revocation_cert_path=cert_path) except Exception as e: logger.exception(e) logger.warn("No connection to revocation server, retrying in 10s...") time.sleep(10) except KeyboardInterrupt: logger.info("TERM Signal received, shutting down...") tpm.flush_keys() server.shutdown() else: try: while True: time.sleep(1) except KeyboardInterrupt: logger.info("TERM Signal received, shutting down...") tpm.flush_keys() server.shutdown()
def do_POST(self): """This method services the POST request typically from either the Tenant or the Cloud Verifier. Only tenant and cloudverifier uri's are supported. Both requests require a nonce parameter. The Cloud verifier requires an additional mask parameter. If the uri or parameters are incorrect, a 400 response is returned. """ rest_params = common.get_restful_params(self.path) if rest_params is None: common.echo_json_response(self, 405, "Not Implemented: Use /keys/ interface") return content_length = int(self.headers.get('Content-Length', 0)) if content_length <= 0: logger.warning('POST returning 400 response, expected content in message. url: ' + self.path) common.echo_json_response(self, 400, "expected content in message") return post_body = self.rfile.read(content_length) json_body = json.loads(post_body) b64_encrypted_key = json_body['encrypted_key'] decrypted_key = crypto.rsa_decrypt(self.server.rsaprivatekey,base64.b64decode(b64_encrypted_key)) have_derived_key = False if rest_params["keys"] == "ukey": self.server.add_U(decrypted_key) self.server.auth_tag = json_body['auth_tag'] self.server.payload = json_body.get('payload',None) have_derived_key = self.server.attempt_decryption(self) elif rest_params["keys"] == "vkey": self.server.add_V(decrypted_key) have_derived_key = self.server.attempt_decryption(self) else: logger.warning('POST returning response. uri not supported: ' + self.path) common.echo_json_response(self, 400, "uri not supported") return logger.info('POST of %s key returning 200'%(('V','U')[rest_params["keys"] == "ukey"])) common.echo_json_response(self, 200, "Success") # no key yet, then we're done if not have_derived_key: return # woo hoo we have a key # ok lets write out the key now secdir = secure_mount.mount() # confirm that storage is still securely mounted # clean out the secure dir of any previous info before we extract files if os.path.isdir("%s/unzipped"%secdir): shutil.rmtree("%s/unzipped"%secdir) # write out key file f = open(secdir+"/"+self.server.enc_keyname,'w') f.write(base64.b64encode(self.server.K)) f.close() #stow the U value for later tpm.write_key_nvram(self.server.final_U) # optionally extend a hash of they key and payload into specified PCR tomeasure = self.server.K # if we have a good key, now attempt to write out the encrypted payload dec_path = "%s/%s"%(secdir, config.get('cloud_agent',"dec_payload_file")) enc_path = "%s/encrypted_payload"%common.WORK_DIR dec_payload = None enc_payload = None if self.server.payload is not None: dec_payload = crypto.decrypt(self.server.payload, str(self.server.K)) enc_payload = self.server.payload elif os.path.exists(enc_path): # if no payload provided, try to decrypt one from a previous run stored in encrypted_payload with open(enc_path,'r') as f: enc_payload = f.read() try: dec_payload = crypto.decrypt(enc_payload,str(self.server.K)) logger.info("Decrypted previous payload in %s to %s"%(enc_path,dec_path)) except Exception as e: logger.warning("Unable to decrypt previous payload %s with derived key: %s"%(enc_path,e)) os.remove(enc_path) enc_payload=None # also write out encrypted payload to be decrytped next time if enc_payload is not None: with open(enc_path,'w') as f: f.write(self.server.payload) # deal with payload payload_thread = None if dec_payload is not None: tomeasure += dec_payload # see if payload is a zip zfio = cStringIO.StringIO(dec_payload) if config.getboolean('cloud_agent','extract_payload_zip') and zipfile.is_zipfile(zfio): logger.info("Decrypting and unzipping payload to %s/unzipped"%secdir) with zipfile.ZipFile(zfio,'r')as f: f.extractall('%s/unzipped'%secdir) # run an included script if one has been provided initscript = config.get('cloud_agent','payload_script') if initscript is not "": def initthread(): import subprocess env = os.environ.copy() env['AGENT_UUID']=self.server.agent_uuid proc= subprocess.Popen(["/bin/bash",initscript],env=env,shell=False,cwd='%s/unzipped'%secdir, stdout=subprocess.PIPE,stderr=subprocess.STDOUT) while True: line = proc.stdout.readline(); if line == '' and proc.poll() is not None: break if line: logger.debug("init-output: %s"%line.strip()) # should be a no-op as poll already told us it's done proc.wait() if not os.path.exists("%s/unzipped/%s"%(secdir,initscript)): logger.info("No payload script %s found in %s/unzipped"%(initscript,secdir)) else: logger.info("Executing payload script: %s/unzipped/%s"%(secdir,initscript)) payload_thread = threading.Thread(target=initthread) else: logger.info("Decrypting payload to %s"%dec_path) with open(dec_path,'w') as f: f.write(dec_payload) zfio.close() # now extend a measurement of the payload and key if there was one pcr = config.getint('cloud_agent','measure_payload_pcr') if pcr>0 and pcr<24: logger.info("extending measurement of payload into PCR %s"%pcr) measured = tpm.hashdigest(tomeasure) tpm.extendPCR(pcr,measured) if payload_thread is not None: payload_thread.start() return
def mk_signed_cert(cacert,ca_pk,name,serialnum): csr = {"request": { "CN": name, "hosts": [ name, ], "key": { "algo": "rsa", "size": config.getint('ca','cert_bits') }, "names": [ { "C": config.get('ca','cert_country'), "L": config.get('ca','cert_locality'), "O": config.get('ca','cert_organization'), "OU": config.get('ca','cert_org_unit'), "ST": config.get('ca','cert_state') } ] } } # check CRL distribution point disturl = config.get('ca','cert_crl_dist') if disturl == 'default': disturl = "http://%s:%s/crl.der"%(socket.getfqdn(),common.CRL_PORT) # set up config for cfssl server cfsslconfig = { "signing": { "default": { "usages": ["client auth","server auth","key agreement","key encipherment","signing","digital signature","data encipherment"], "expiry": "8760h", "crl_url": disturl, } } } data = json.dumps(csr) secdir = secure_mount.mount() try: # need to temporarily write out the private key with no password # to tmpfs ca_pk.save_key('%s/ca-key.pem'%secdir, None) with open('%s/cfsslconfig.json'%secdir,'w') as f: json.dump(cfsslconfig, f) cmdline = "-config=%s/cfsslconfig.json"%secdir priv_key = os.path.abspath("%s/ca-key.pem"%secdir) cmdline += " -ca-key %s -ca cacert.crt"%(priv_key) start_cfssl(cmdline) response = post_cfssl("http://127.0.0.1:8888/api/v1/cfssl/newcert",data=data) finally: stop_cfssl() os.remove('%s/ca-key.pem'%secdir) os.remove('%s/cfsslconfig.json'%secdir) if response.status_code!=200: raise Exception("Unable to create cert for %s. Error: %s"%(name,response.body)) body = json.loads(response.body) if body['success']: pk = EVP.load_key_string(str(body['result']['private_key'])) cert = X509.load_cert_string(str(body['result']['certificate'])) return cert, pk else: raise Exception("Unable to create cert for %s"%name)
def mk_signed_cert(cacert,ca_pk,name,serialnum): csr = {"request": { "CN": name, "hosts": [ name, ], "key": { "algo": "rsa", "size": config.getint('ca','cert_bits') }, "names": [ { "C": config.get('ca','cert_country'), "L": config.get('ca','cert_locality'), "O": config.get('ca','cert_organization'), "OU": config.get('ca','cert_org_unit'), "ST": config.get('ca','cert_state') } ] } } # set up config for cfssl server cfsslconfig = { "signing": { "default": { "usages": ["client auth","server auth","key agreement","key encipherment","signing","digital signature","data encipherment"], "expiry": "8760h", # TODO, this needs to be set to where the CRL will be hosted "crl_url": "http://localhost/crl.pem", } } } data = json.dumps(csr) secdir = common.WORK_DIR+"/secure" try: secure_mount.mount() if not os.path.isdir(secdir): os.makedirs(secdir) # need to temporarily write out the private key with no password # to tmpfs ca_pk.save_key('%s/ca-key.pem'%secdir, None) with open('%s/cfsslconfig.json'%secdir,'w') as f: json.dump(cfsslconfig, f) cmdline = "-config=%s/cfsslconfig.json"%secdir priv_key = os.path.abspath("%s/secure/ca-key.pem"%common.WORK_DIR) cmdline += " -ca-key %s -ca cacert.crt"%(priv_key) start_cfssl(cmdline) response = post_cfssl("http://127.0.0.1:8888/api/v1/cfssl/newcert",data=data) finally: stop_cfssl() os.remove('%s/ca-key.pem'%secdir) os.remove('%s/cfsslconfig.json'%secdir) body = json.loads(response.body) if body['success']: pk = EVP.load_key_string(str(body['result']['private_key'])) cert = X509.load_cert_string(str(body['result']['certificate'])) return cert, pk else: raise Exception("Unable to create cert for %s"%name)
def main(argv=sys.argv): if os.getuid() != 0 and not common.DEVELOP_IN_ECLIPSE: logger.critical("This process must be run as root.") return # get params for initialization registrar_ip = config.get('general', 'registrar_ip') registrar_port = config.get('general', 'registrar_port') # initialize the tmpfs partition to store keys if it isn't already available secure_mount.mount() # change dir to working dir common.ch_dir() #initialize tpm (ek, ekcert, aik) = tpm_initialize.init( self_activate=False, config_pw=config.get('cloud_node', 'tpm_ownerpassword') ) # this tells initialize not to self activate the AIK virtual_node = tpm_initialize.is_vtpm() if common.STUB_TPM: ekcert = common.TEST_EK_CERT if virtual_node and (ekcert is None or common.STUB_TPM): ekcert = 'virtual' # now we need the UUID try: node_uuid = config.get('cloud_node', 'node_uuid') except ConfigParser.NoOptionError: node_uuid = None if node_uuid == 'openstack': node_uuid = openstack.get_openstack_uuid() elif node_uuid == 'hash_ek': node_uuid = hashlib.sha256(ek).hexdigest() elif node_uuid == 'generate' or node_uuid is None: node_uuid = str(uuid.uuid4()) if common.DEVELOP_IN_ECLIPSE: node_uuid = "C432FBB3-D2F1-4A97-9EF7-75BD81C866E9" # use an TLS context with no certificate checking registrar_client.noAuthTLSContext(config) # register it and get back a blob keyblob = registrar_client.doRegisterNode(registrar_ip, registrar_port, node_uuid, ek, ekcert, aik) if keyblob is None: raise Exception("Registration failed") # get the ephemeral registrar key key = tpm_initialize.activate_identity(keyblob) # tell the registrar server we know the key if virtual_node: deepquote = tpm_quote.create_deep_quote( hashlib.sha1(key).hexdigest(), node_uuid + aik + ek) registrar_client.doActivateVirtualNode(registrar_ip, registrar_port, node_uuid, deepquote) else: registrar_client.doActivateNode(registrar_ip, registrar_port, node_uuid, key) serveraddr = ('', config.getint('general', 'cloudnode_port')) server = CloudNodeHTTPServer(serveraddr, Handler, node_uuid) thread = threading.Thread(target=server.serve_forever) threads = [] servers = [] threads.append(thread) servers.append(server) # start the server logger.info('Starting Cloud Node on port %s use <Ctrl-C> to stop' % serveraddr[1]) for thread in threads: thread.start() def signal_handler(signal, frame): do_shutdown(servers) sys.exit(0) # Catch these signals. Note that a SIGKILL cannot be caught, so # killing this process with "kill -9" may result in improper shutdown signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGQUIT, signal_handler) signal.signal(signal.SIGINT, signal_handler) # keep the main thread active, so it can process the signals and gracefully shutdown while True: if not any([thread.isAlive() for thread in threads]): # All threads have stopped break else: # Some threads are still going time.sleep(1) for thread in threads: thread.join()
def do_POST(self): """This method services the GET request typically from either the Tenant or the Cloud Verifier. Only tenant and cloudverifier uri's are supported. Both requests require a nonce parameter. The Cloud verifier requires an additional mask parameter. If the uri or parameters are incorrect, a 400 response is returned. """ tn_quote_flag = self.is_tenant_quote() cv_quote_flag = self.is_cloudverifier_quote() if tn_quote_flag or cv_quote_flag: content_length = int(self.headers.get('Content-Length', 0)) if content_length > 0: post_body = self.rfile.read(content_length) json_body = json.loads(post_body) b64_encrypted_key = json_body['encrypted_key'] decrypted_key = crypto.rsa_decrypt( self.server.rsaprivatekey, base64.b64decode(b64_encrypted_key)) have_derived_key = False if tn_quote_flag: self.server.add_U(decrypted_key) self.server.auth_tag = json_body['auth_tag'] self.server.payload = json_body.get('payload', None) have_derived_key = self.server.attempt_decryption(self) elif cv_quote_flag: self.server.add_V(decrypted_key) have_derived_key = self.server.attempt_decryption(self) else: logger.warning( 'POST returning response. uri not supported: ' + self.path) self.send_response(400) self.end_headers() return logger.info('POST of %s key returning 200' % (('V', 'U')[tn_quote_flag])) self.send_response(200) self.end_headers() if have_derived_key: # ok lets write out the key now secdir = secure_mount.mount( ) # confirm that storage is still securely mounted f = open(secdir + "/" + self.server.enc_keyname, 'w') f.write(base64.b64encode(self.server.K)) f.close() # if we have a good key, now attempt to write out the encrypted payload dec_path = "%s/%s" % ( secdir, config.get('cloud_node', "dec_payload_file")) enc_path = "%s/encrypted_payload" % common.WORK_DIR if self.server.payload is not None: plaintext = crypto.decrypt(self.server.payload, str(self.server.K)) zfio = cStringIO.StringIO(plaintext) if config.getboolean('cloud_node', 'extract_payload_zip' ) and zipfile.is_zipfile(zfio): logger.info( "Decrypting and unzipping payload to %s/unzipped" % dec_path) with zipfile.ZipFile(zfio, 'r') as f: f.extractall('%s/unzipped' % secdir) else: logger.info("Decrypting payload to %s" % dec_path) with open(dec_path, 'w') as f: f.write(plaintext) zfio.close() # also write out encrypted payload to be decrytped next time with open(enc_path, 'w') as f: f.write(self.server.payload) elif os.path.exists(enc_path): # if no payload provided, try to decrypt one from a previous run stored in encrypted_payload with open(enc_path, 'r') as f: payload = f.read() try: with open(dec_path, 'w') as fp: fp.write( crypto.decrypt(payload, str(self.server.K))) logger.info( "Decrypted previous payload in %s to %s" % (enc_path, dec_path)) except Exception as e: logger.warning( "Unable to decrypt previous payload %s with derived key: %s" % (enc_path, e)) os.remove(enc_path) #stow the U value for later tpm_nvram.write_key_nvram(self.server.final_U) return else: logger.warning( 'POST returning 400 response, expected content in message. url: ' + self.path) self.send_response(400) self.end_headers() return else: logger.warning('POST returning 400 response. uri not supported: ' + self.path) self.send_response(400) self.end_headers() return