''' SPDX-License-Identifier: Apache-2.0 Copyright 2020 Luke Hinds ([email protected]), Red Hat, Inc. ''' import os from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, scoped_session from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.engine.url import URL from keylime import config from keylime import keylime_logging logger = keylime_logging.init_logging('keylime_db') class DBEngineManager: def __init__(self): self.service = None def make_engine(self, service): """ To use: engine = self.make_engine('cloud_verifier') """ self.service = service database_url = config.get(service, 'database_url') if database_url: engine = create_engine(database_url)
raise ("Simplejson is mandatory, please install") from keylime import httpclient_requests from keylime import common from keylime import keylime_logging from keylime import registrar_client from keylime.tpm import tpm_obj from keylime.tpm.tpm_abstract import TPM_Utilities, Hash_Algorithms, Encrypt_Algorithms, Sign_Algorithms from keylime import ima from keylime import crypto from keylime.cmd import user_data_encrypt from keylime import ca_util from keylime import cloud_verifier_common # setup logging logger = keylime_logging.init_logging('tenant') config = common.get_config() # special exception that suppresses stack traces when it happens class UserError(Exception): pass class Tenant(): """Simple command processor example.""" config = None
import simplejson as json from sqlalchemy.exc import SQLAlchemyError import tornado.ioloop import tornado.web from keylime import config from keylime.common import states from keylime.db.verifier_db import VerfierMain from keylime.db.keylime_db import DBEngineManager, SessionManager from keylime import keylime_logging from keylime import cloud_verifier_common from keylime import revocation_notifier import keylime.tornado_requests as tornado_requests logger = keylime_logging.init_logging('cloudverifier') try: engine = DBEngineManager().make_engine('cloud_verifier') except SQLAlchemyError as e: logger.error(f'Error creating SQL engine: {e}') sys.exit(1) # The "exclude_db" dict values are removed from the response before adding the dict to the DB # This is because we want these values to remain ephemeral and not stored in the database. exclude_db = { 'registrar_keys': '', 'nonce': '', 'b64_encrypted_V': '', 'provide_V': True, 'num_retries': 0,
import sys import base64 import os import errno import yaml try: from yaml import CSafeDumper as SafeDumper except ImportError: from yaml import SafeDumper from keylime import config from keylime import keylime_logging from keylime import registrar_client from keylime import vtpm_manager logger = keylime_logging.init_logging('provider_platform_init') def symlink_force(target, link_name): try: os.symlink(target, link_name) except OSError as err: if err.errno == errno.EEXIST: os.remove(link_name) os.symlink(target, link_name) else: raise err def main(argv=sys.argv):
import simplejson as json from keylime import config from keylime import keylime_logging from keylime import cmd_exec from keylime import crypto from keylime import openstack from keylime import revocation_notifier from keylime import registrar_client from keylime import secure_mount from keylime.tpm.tpm_main import tpm from keylime.tpm.tpm_abstract import TPM_Utilities # Configure logger logger = keylime_logging.init_logging('cloudagent') # lock required for multithreaded operation uvLock = threading.Lock() # Instaniate tpm tpm_instance = tpm(need_hw_tpm=True) class Handler(BaseHTTPRequestHandler): parsed_path = '' def do_HEAD(self): """Not supported""" config.echo_json_response(self, 405, "HEAD not supported")
from cryptography import x509 from cryptography.hazmat.backends import default_backend import keylime.secure_mount as secure_mount import keylime.keylime_logging as keylime_logging import keylime.config as common import keylime.keylime_logging as keylime_logging import keylime.cmd_exec as cmd_exec import keylime.ca_util as ca_util from keylime import json # read the config file config = common.get_config() logger = keylime_logging.init_logging('delete-sa') async def execute(revocation): json_meta = json.loads(revocation['meta_data']) serial = json_meta['cert_serial'] if revocation.get('type', None) != 'revocation' or serial is None: logger.error("Unsupported revocation message: %s" % revocation) # load up the ca cert secdir = secure_mount.mount() ca = ca_util.load_cert_by_path(f'{secdir}/unzipped/cacert.crt') # need to find any sa's that were established with that cert serial cmd = ('racoonctl', 'show-sa', 'ipsec') output = cmd_exec.run(cmd, raiseOnError=True)['retout']
- https://elixir.bootlin.com/linux/latest/source/security/integrity/ima/ima_template.c - https://www.kernel.org/doc/html/v5.12/security/IMA-templates.html ''' import binascii import codecs import struct import abc from typing import Dict, Callable, Any, Optional from keylime import config from keylime import keylime_logging from keylime.common.algorithms import Hash from keylime.failure import Failure, Component logger = keylime_logging.init_logging("ima") TCG_EVENT_NAME_LEN_MAX = 255 SHA_DIGEST_LEN = 20 MD5_DIGEST_LEN = 16 NULL_BYTE = ord('\0') COLON_BYTE = ord(':') def get_START_HASH(hash_alg: Hash): return codecs.decode(b'0' * (hash_alg.get_size() // 4), 'hex') def get_FF_HASH(hash_alg: Hash): return codecs.decode(b'f' * (hash_alg.get_size() // 4), 'hex')
above. Use of this work other than as specifically authorized by the U.S. Government may violate any copyrights that exist in this work. ''' import ast import codecs import sys import hashlib import struct import re import os import configparser from keylime import common from keylime import keylime_logging logger = keylime_logging.init_logging('ima') # setup config config = configparser.RawConfigParser() config.read(common.CONFIG_FILE) # m = ima_measure_re.match(measure_line) # measure = m.group('file_hash') # filename = m.group('file_path') START_HASH = (codecs.decode('0000000000000000000000000000000000000000', 'hex')) FF_HASH = (codecs.decode('ffffffffffffffffffffffffffffffffffffffff', 'hex')) # struct event { # struct {
from socketserver import ThreadingMixIn import functools import signal import time import yaml try: from yaml import CSafeLoader as SafeLoader, CSafeDumper as SafeDumper except ImportError: from yaml import SafeLoader as SafeLoader, SafeDumper as SafeDumper from keylime import crypto from keylime import cmd_exec from keylime import common from keylime import keylime_logging logger = keylime_logging.init_logging('ca-util') if common.CA_IMPL == 'cfssl': from keylime import ca_impl_cfssl as ca_impl elif common.CA_IMPL == 'openssl': from keylime import ca_impl_openssl as ca_impl else: raise Exception("Unknown CA implementation: %s" % common.CA_IMPL) from M2Crypto import X509, EVP, BIO config = configparser.ConfigParser() config.read(common.CONFIG_FILE) """ Tools for creating a CA cert and signed server certs. Divined from http://svn.osafoundation.org/m2crypto/trunk/tests/test_x509.py The mk_temporary_xxx calls return a NamedTemporaryFile with certs.
''' SPDX-License-Identifier: Apache-2.0 Copyright 2017 Massachusetts Institute of Technology. ''' import gnupg from keylime import keylime_logging logger = keylime_logging.init_logging('gpg') def gpg_verify_filesignature(gpg_key_file, filename, gpg_sig_file, file_description): """ Verify the file signature (gpg_sig_file) using a public GPG (gpg_key_file) with the file (filename). """ gpg = gnupg.GPG() with open(gpg_key_file, 'r') as key_f: logger.debug("Importing GPG key %s", gpg_key_file) gpg_imported = gpg.import_keys(key_f.read()) if gpg_imported.count == 1: # pylint: disable=E1101 logger.debug("GPG key successfully imported") else: raise Exception(f"Unable to import GPG key: {gpg_key_file}") with open(gpg_sig_file, 'rb') as sig_f: logger.debug("Comparing %s (%s) against GPG signature (%s)", file_description, filename, gpg_sig_file) verified = gpg.verify_file(sig_f, filename)
#!/usr/bin/python3 """ SPDX-License-Identifier: Apache-2.0 Copyright 2017 Massachusetts Institute of Technology. """ import keylime.cmd.migrations_apply from keylime import cloud_verifier_tornado, config, keylime_logging logger = keylime_logging.init_logging("cloudverifier") def main(): # if we are configured to auto-migrate the DB, check if there are any migrations to perform if config.has_option("cloud_verifier", "auto_migrate_db") and config.getboolean( "cloud_verifier", "auto_migrate_db"): keylime.cmd.migrations_apply.apply("cloud_verifier") cloud_verifier_tornado.main() if __name__ == "__main__": try: main() except Exception as e: logger.exception(e)
import time import requests import shutil import sys try: import simplejson as json except ImportError: raise ("Simplejson is mandatory, please install") from keylime import common from keylime import keylime_logging from keylime import secure_mount from M2Crypto import EVP, X509 logger = keylime_logging.init_logging('ca_impl_cfssl') config = configparser.ConfigParser() config.read(common.CONFIG_FILE) cfssl_ip = config.get('general', 'cfssl_ip') cfssl_port = config.get('general', 'cfssl_port') cfsslproc = None def post_cfssl(params, data): numtries = 0 maxr = 10 retry = 0.05 while True:
json, keylime_logging, registrar_client, revocation_notifier, secure_mount, user_utils, web_util, ) from keylime.common import algorithms, validators from keylime.ima import ima from keylime.tpm.tpm2_objects import pubkey_from_tpm2b_public from keylime.tpm.tpm_abstract import TPM_Utilities from keylime.tpm.tpm_main import tpm # Configure logger logger = keylime_logging.init_logging("cloudagent") # lock required for multithreaded operation uvLock = threading.Lock() # Instaniate tpm tpm_instance = tpm(need_hw_tpm=True) class Handler(BaseHTTPRequestHandler): parsed_path = "" def do_HEAD(self): """Not supported""" web_util.echo_json_response(self, 405, "HEAD not supported")
except ImportError: from yaml import SafeLoader as SafeLoader, SafeDumper as SafeDumper try: import simplejson as json except ImportError: raise ("Simplejson is mandatory, please install") from abc import ABCMeta, abstractmethod from keylime import common from keylime import keylime_logging from keylime import crypto from keylime import ima logger = keylime_logging.init_logging('tpm') class Hash_Algorithms: SHA1 = 'sha1' SHA256 = 'sha256' SHA384 = 'sha384' SHA512 = 'sha512' @staticmethod def get_hash_size(algorithm): if algorithm == Hash_Algorithms.SHA1: return 160 elif algorithm == Hash_Algorithms.SHA256: return 256 elif algorithm == Hash_Algorithms.SHA384:
import tempfile import gpg from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.serialization import load_pem_public_key from keylime import keylime_logging logger = keylime_logging.init_logging("signing") def verify_signature_from_file(key_file, filename, sig_file, file_description): """ Verify the file signature on disk (sig_file) using a public key on disk (key_file) with the file on disk (file). All inputs should be file paths. """ with open(key_file, "rb") as key_f: key = key_f.read() with open(sig_file, "rb") as sig_f: sig = sig_f.read() with open(filename, "rb") as file_f: file = file_f.read() if verify_signature(key, sig, file): logger.debug("%s passed signature verification", file_description.capitalize()) else:
SPDX-License-Identifier: Apache-2.0 Copyright 2021 Thore Sommer Tagging of failure events that might cause revocation in Keylime. ''' import ast import enum import functools import re from typing import List, Optional, Tuple, Callable, Union, Dict, Any, Pattern from keylime import config from keylime import json from keylime import keylime_logging logger = keylime_logging.init_logging("failure") @functools.total_ordering class SeverityLabel: """ Severity label that can be attached to an event. The severity level is assigned dynamically based on the configuration, so only use the name for use outside use of the tagging module. """ name: str severity: int def __init__(self, name: str, severity: int): self.name = name self.severity = severity
SPDX-License-Identifier: Apache-2.0 Copyright 2017 Massachusetts Institute of Technology. ''' import os import logging import sys from keylime import config from keylime import crypto from keylime import json from keylime import keylime_logging from keylime.requests_client import RequestsClient from keylime import api_version as keylime_api_version logger = keylime_logging.init_logging('registrar_client') tls_cert_info = () tls_enabled = False api_version = keylime_api_version.current_version() def init_client_tls(section): global tls_cert_info global tls_enabled # make this reentrant if tls_cert_info: return if not config.getboolean('general', "enable_tls"): logger.warning(
from cryptography import x509 from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat import backends from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey from cryptography.hazmat.primitives.asymmetric.utils import Prehashed from cryptography.exceptions import InvalidSignature from keylime import keylime_logging logger = keylime_logging.init_logging('ima_file_signatures') """ Tools for IMA file signature verification """ class HashAlgo(enum.IntEnum): """ The hash_algo's as Linux defines them: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/hash_info.h#L17 """ HASH_ALGO_MD4 = 0 HASH_ALGO_MD5 = 1 HASH_ALGO_SHA1 = 2 HASH_ALGO_RIPE_MD_160 = 3 HASH_ALGO_SHA256 = 4 HASH_ALGO_SHA384 = 5
import enum import json import struct from cryptography import utils, x509 from cryptography.exceptions import InvalidSignature, UnsupportedAlgorithm from cryptography.hazmat import backends from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec, padding from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey from cryptography.hazmat.primitives.asymmetric.utils import Prehashed from keylime import keylime_logging logger = keylime_logging.init_logging("file_signatures") """ Tools for IMA file signature verification """ class HashAlgo(enum.IntEnum): """The hash_algo's as Linux defines them: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/hash_info.h#L17 """ HASH_ALGO_MD4 = 0 HASH_ALGO_MD5 = 1 HASH_ALGO_SHA1 = 2 HASH_ALGO_RIPE_MD_160 = 3 HASH_ALGO_SHA256 = 4
import ssl import traceback import sys import simplejson as json import tornado.ioloop import tornado.web from keylime.requests_client import RequestsClient from keylime.common import states from keylime import config from keylime import keylime_logging from keylime import tenant logger = keylime_logging.init_logging('tenant_webapp') tenant_templ = tenant.Tenant() my_cert, my_priv_key = tenant_templ.get_tls_context() cert = (my_cert, my_priv_key) if config.getboolean('general', "enable_tls"): tls_enabled = True else: tls_enabled = False cert = "" logger.warning( "Warning: TLS is currently disabled, keys will be sent in the clear! This should only be used for testing.") verifier_ip = config.get('cloud_verifier', 'cloudverifier_ip') verifier_port = config.get('cloud_verifier', 'cloudverifier_port') verifier_base_url = f'{verifier_ip}:{verifier_port}'
import time import os import ConfigParser import keylime.tornado_requests as tornado_requests import keylime.ca_util as ca_util import keylime.secure_mount as secure_mount import keylime.common as common import keylime.keylime_logging as keylime_logging # read the config file config = ConfigParser.RawConfigParser() config.read(common.CONFIG_FILE) logger = keylime_logging.init_logging('update_crl') def execute(json_revocation): if json_revocation['type'] != 'revocation': return secdir = secure_mount.mount() cert_path = config.get('cloud_agent', '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))
''' SPDX-License-Identifier: BSD-2-Clause Copyright 2017 Massachusetts Institute of Technology. ''' import os from keylime import cmd_exec from keylime import common from keylime import keylime_logging logger = keylime_logging.init_logging('secure_mount') # read the config file config = common.get_config() def check_mounted(secdir): whatsmounted = cmd_exec.run("mount", lock=False)['retout'] whatsmounted_converted = common.list_convert(whatsmounted) for line in whatsmounted_converted: tokens = line.split() tmpfs = False if len(tokens) < 3: continue if tokens[0] == 'tmpfs': tmpfs = True if tokens[2] == secdir: if not tmpfs: logger.error( "secure storage location %s already mounted on wrong file system type: %s. Unmount to continue."
#!/usr/bin/python3 ''' SPDX-License-Identifier: Apache-2.0 Copyright 2017 Massachusetts Institute of Technology. ''' import sys from keylime import config from keylime import keylime_logging from keylime import registrar_common logger = keylime_logging.init_logging('provider-registrar') def main(argv=sys.argv): registrar_common.start( config.get('registrar', 'provider_registrar_ip'), config.getint('registrar', 'provider_registrar_tls_port'), config.getint('registrar', 'provider_registrar_port')) if __name__ == "__main__": try: main() except Exception as e: logger.exception(e)
''' SPDX-License-Identifier: Apache-2.0 Copyright 2017 Massachusetts Institute of Technology. ''' import glob import os import sys from keylime import config from keylime import keylime_logging logger = keylime_logging.init_logging('tpm_ek_ca') trusted_certs = {} tpm_cert_store = config.get('tenant', 'tpm_cert_store') def check_tpm_cert_store(): if not os.path.isdir(tpm_cert_store): logger.error(f"The directory {tpm_cert_store} does not exist.") sys.exit() else: for fname in os.listdir(tpm_cert_store): if fname.endswith('.pem'): break else: logger.error( f"The directory {tpm_cert_store} does not contain any .pem files." ) sys.exit()
from cryptography.hazmat.backends import default_backend from cryptography.x509 import load_der_x509_certificate from keylime.common import validators from keylime.db.registrar_db import RegistrarMain from keylime.db.keylime_db import DBEngineManager, SessionManager from keylime import config from keylime import crypto from keylime import json from keylime.tpm import tpm2_objects from keylime import keylime_logging from keylime.tpm.tpm_main import tpm from keylime import api_version as keylime_api_version from keylime import web_util logger = keylime_logging.init_logging('registrar') try: engine = DBEngineManager().make_engine('registrar') except SQLAlchemyError as err: logger.error('Error creating SQL engine: %s', err) sys.exit(1) class ProtectedHandler(BaseHTTPRequestHandler, SessionManager): def do_HEAD(self): """HEAD not supported""" web_util.echo_json_response(self, 405, "HEAD not supported") def do_PATCH(self): """PATCH not supported"""
from keylime import registrar_client from keylime import crypto from keylime import cloud_verifier_common from keylime.tpm import tpm_obj from keylime import common from keylime import keylime_logging # Database imports from keylime.db.registrar_db import RegistrarMain from keylime.db.keylime_db import SessionManager from sqlalchemy.exc import SQLAlchemyError from sqlalchemy import create_engine from sqlalchemy.engine.url import URL logger = keylime_logging.init_logging('registrar-common') # setup config config = common.get_config() drivername = config.get('registrar', 'drivername') if drivername == 'sqlite': database = "%s/%s" % (common.WORK_DIR, config.get('registrar', 'database')) # Create the path to where the sqlite database will be store with a perm umask of 077 os.umask(0o077) kl_dir = os.path.dirname(os.path.abspath(database)) if not os.path.exists(kl_dir): os.makedirs(kl_dir, 0o700) url = URL(drivername=drivername, username='',
try: import simplejson as json except ImportError: raise ("Simplejson is mandatory, please install") from keylime import common from keylime import keylime_logging from keylime import registrar_client from keylime import crypto from keylime import ca_util from keylime import revocation_notifier from keylime.tpm import tpm_obj from keylime.tpm.tpm_abstract import TPM_Utilities, Hash_Algorithms, Encrypt_Algorithms, Sign_Algorithms # setup logging logger = keylime_logging.init_logging('cloudverifier_common') # setup config config = common.get_config() class CloudAgent_Operational_State: REGISTERED = 0 START = 1 SAVED = 2 GET_QUOTE = 3 GET_QUOTE_RETRY = 4 PROVIDE_V = 5 PROVIDE_V_RETRY = 6 FAILED = 7 TERMINATED = 8
import os import sys import signal import zmq try: import simplejson as json except ImportError: raise ("Simplejson is mandatory, please install") from multiprocessing import Process from keylime import common from keylime import keylime_logging from keylime import crypto logger = keylime_logging.init_logging('revocation_notifier') config = configparser.ConfigParser() config.read(common.CONFIG_FILE) broker_proc = None def start_broker(): def worker(): context = zmq.Context(1) frontend = context.socket(zmq.SUB) frontend.bind("ipc:///tmp/keylime.verifier.ipc") frontend.setsockopt(zmq.SUBSCRIBE, b'')
#!/usr/bin/env python """ SPDX-License-Identifier: Apache-2.0 Copyright 2017 Massachusetts Institute of Technology. """ from keylime import json, keylime_logging logger = keylime_logging.init_logging("print_metadata") async def execute(revocation): print(json.loads(revocation["meta_data"]))
from yaml import CSafeDumper as SafeDumper except ImportError: from yaml import SafeDumper from keylime import config from keylime import json from keylime import keylime_logging from keylime.tpm.tpm_main import tpm # get the tpm object tpm_instance = tpm(need_hw_tpm=True) sys.path.append(os.path.dirname(__file__)) # Logging boiler plate logger = keylime_logging.init_logging('vtpmmgr') logger.setLevel(logging.INFO) # ./utils/encaik -ek ~/tmp/LLSRC-tci/scripts/llsrc-vtpm-host0_pubek.pem -ik ~/tmp/LLSRC-tci/scripts/llsrc-vtpm-host0_pubek.pem -ok key.blob -oak key.aes # cd /home/rudd/tmp/tpm4720/libtpm # VTPM Command Ordinals. Taken from Xen's stubdoms/vtpmmgr/vtpm_manager.h VTPM_ORD_GROUP_LIST = 0x02000101 VTPM_ORD_GROUP_NEW = 0x02000102 VTPM_ORD_GROUP_DEL = 0x02000103 VTPM_ORD_GROUP_ACTIVATE = 0x02000104 VTPM_ORD_GROUP_SHOW = 0x02000107 VTPM_ORD_VTPM_LIST = 0x02000201 VTPM_ORD_VTPM_NEW = 0x02000204