コード例 #1
0
ファイル: cloud_agent.py プロジェクト: mrcdb/keylime
 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
コード例 #2
0
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)
コード例 #3
0
    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)
コード例 #4
0
    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!")
コード例 #5
0
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)
コード例 #6
0
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
コード例 #7
0
    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
コード例 #8
0
ファイル: cloud_agent.py プロジェクト: mrcdb/keylime
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()
コード例 #9
0
ファイル: cloud_agent.py プロジェクト: mrcdb/keylime
    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
コード例 #10
0
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)
コード例 #11
0
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)
コード例 #12
0
ファイル: cloud_node.py プロジェクト: henn/python-keylime
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()
コード例 #13
0
ファイル: cloud_node.py プロジェクト: henn/python-keylime
    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