コード例 #1
0
def makedir(dirname, purpose):
    """ Create a directory if it does not exist """
    if not os.path.exists(dirname):
        logit(LOGFILE, "Creating swtpm-local dir '%s'.\n" % dirname)
        try:
            os.makedirs(dirname)
        except OSError as err:
            logerr(LOGFILE, "Could not create directory for '%s': %s\n" % (purpose, str(err)))
            return 1
    return 0
コード例 #2
0
ファイル: swtpm_localca.py プロジェクト: elms/swtpm
def main():
    """ main function - parses command line parameters and low level dealing with them """
    global LOGFILE  # pylint: disable=W0603

    try:
        opts, _ = getopt.getopt(sys.argv[1:], "h?", [
            "type=", "ek=", "dir=", "vmid=", "optsfile=", "configfile=",
            "logfile=", "tpm-spec-family=", "tpm-spec-revision=",
            "tpm-spec-level=", "tpm-manufacturer=", "tpm-model=",
            "tpm-version=", "tpm2", "allow-signing", "decryption", "help"
        ])
    except getopt.GetoptError as err:
        print(err)
        usage(sys.argv[0])
        sys.exit(1)

    flags = 0
    typ = ""
    ekparams = ""
    directory = ""
    vmid = ""
    optsfile = DEFAULT_LOCALCA_OPTIONS
    configfile = DEFAULT_LOCALCA_CONFIG
    tpm_spec_params = []
    tpm_attr_params = []

    for opt, arg in opts:
        if opt == '--type':
            typ = arg
        elif opt == '--ek':
            ekparams = arg
        elif opt == '--dir':
            directory = arg
        elif opt == '--vmid':
            vmid = arg
        elif opt == '--optsfile':
            optsfile = arg
        elif opt == '--configfile':
            configfile = arg
        elif opt == '--logfile':
            LOGFILE = arg
        elif opt in [
                '--tpm-spec-family', '--tpm-spec-revision', '--tpm-spec-level'
        ]:
            tpm_spec_params.extend([opt, arg])
        elif opt in ['--tpm-manufacturer', '--tpm-model', '--tpm-version']:
            tpm_attr_params.extend([opt, arg])
        elif opt == '--tpm2':
            flags |= SETUP_TPM2_F
        elif opt == '--allow-signing':
            flags |= ALLOW_SIGNING_F
        elif opt == '--decryption':
            flags |= DECRYPTION_F
        elif opt in ['--help', '-h', '-?']:
            usage(sys.argv[0])
            sys.exit(0)

    if len(LOGFILE) > 0:
        try:
            fobj = open(LOGFILE, "w")
            fobj.close()
        except PermissionError:
            sys.stderr.write("Cannot write to logfile %s.\n", LOGFILE)
            sys.exit(1)

    if not os.access(optsfile, os.R_OK):
        logerr(
            LOGFILE, "Need read rights on options file %s for user %s.\n" %
            (optsfile, getpass.getuser()))
        sys.exit(1)

    if not os.access(configfile, os.R_OK):
        logerr(
            LOGFILE, "Need read rights on options file %s for user %s.\n" %
            (configfile, getpass.getuser()))
        sys.exit(1)

    lines, ret = read_file_lines(configfile)
    if ret != 0:
        sys.exit(1)

    statedir = get_config_value(lines, "statedir")
    if not statedir:
        logerr(
            LOGFILE, "Missing 'statedir' config value in config file %s.\n" %
            configfile)
        sys.exit(1)
    if not os.access(statedir, os.W_OK | os.R_OK):
        logerr(
            LOGFILE, "Need read/write rights on statedir %s for user %s.\n" %
            (statedir, getpass.getuser()))
    if makedir(statedir, "statedir") != 0:
        sys.exit(1)

    lockfile = os.path.join(statedir, ".lock.swtpm-localca")
    if os.path.exists(lockfile) and not os.access(lockfile, os.W_OK | os.R_OK):
        logerr(
            LOGFILE, "Need read/write rights on %s for user %s.\n" %
            (lockfile, getpass.getuser()))
        sys.exit(1)

    signkey = get_config_value(lines, "signingkey")
    if not signkey:
        logerr(
            LOGFILE, "Missing 'signingkey' config value in config file %s.\n" %
            configfile)
        sys.exit(1)

    # SIGNKEY may be a GNUTLS url like tpmkey:file= or tpmkey:uuid=
    if not signkey.startswith("tpmkey:file=") and \
       not signkey.startswith("tpmkey:uuid=") and \
       not signkey.startswith("pkcs11:"):
        if makedir(os.path.dirname(signkey), "signkey") != 0:
            sys.exit(1)

    signkey_password = get_config_value(lines, "signingkey_password")
    parentkey_password = get_config_value(lines, "parentkey_password")

    issuercert = get_config_value(lines, 'issuercert')
    if not issuercert:
        logerr(
            LOGFILE, "Missing 'issuercert' config value in config file %s.\n" %
            configfile)
        sys.exit(1)
    if makedir(os.path.dirname(issuercert), "issuercert") != 0:
        sys.exit(1)

    # environment needed for calling swtpm_cert
    swtpm_cert_env = os.environ

    # TPM keys are GNUTLS URIs...
    if signkey.startswith("tpmkey:file=") or signkey.startswith(
            "tpmkey:uuid="):
        tss_tcsd_hostname = get_config_value(lines, "TSS_TCSD_HOSTNAME",
                                             "localhost")
        tss_tcsd_port = get_config_value(lines, "TSS_TCSD_PORT", 30003)
        swtpm_cert_env["TSS_TCSD_HOSTNAME"] = tss_tcsd_hostname
        swtpm_cert_env["TSS_TCSD_PORT"] = tss_tcsd_port

        logit(LOGFILE, "CA uses a GnuTLS TPM key; using TSS_TCSD_HOSTNAME=%s " \
   "TSS_TCSD_PORT=%s\n" % (tss_tcsd_hostname, tss_tcsd_port))
    elif signkey.startswith("pkcs11:"):
        signkey = signkey.replace(r"\;", ";")
        if signkey_password:
            swtpm_cert_env["SWTPM_PKCS11_PIN"] = signkey_password
            logit(
                LOGFILE,
                "CA uses a PKCS#11 key; using password from 'signingkey_password'\n"
            )
        else:
            swtpm_pkcs11_pin = get_config_value(lines, "SWTPM_PKCS11_PIN",
                                                "swtpm-tpmca")
            swtpm_cert_env["SWTPM_PKCS11_PIN"] = swtpm_pkcs11_pin
            logit(LOGFILE, "CA uses a PKCS#11 key; using SWTPM_PKCS11_PIN\n")
        # Get additional environment variables pkcs11 modules may need
        envvars, ret = get_config_envvars(lines)
        if ret != 0:
            sys.exit(1)
        swtpm_cert_env.update(envvars)
    else:
        # if signkey does not exists it will be created...
        if not os.access(signkey, os.R_OK):
            if os.path.exists(signkey):
                logerr(
                    LOGFILE,
                    "Need read rights on signing key %s for user %s.\n" %
                    (signkey, getpass.getuser()))
                sys.exit(1)

            logit(
                LOGFILE,
                "Creating root CA and a local CA's signing key and issuer cert.\n"
            )
            if create_localca_cert(lockfile, statedir, signkey,
                                   signkey_password, issuercert) != 0:
                logerr(LOGFILE,
                       "Error creating local CA's signing key and cert.\n")
                sys.exit(1)

            if not os.access(signkey, os.R_OK):
                logerr(
                    LOGFILE,
                    "Need read rights on signing key %s for user %s.\n" %
                    (signkey, getpass.getuser()))
                sys.exit(1)

    if not os.access(issuercert, os.R_OK):
        logerr(
            LOGFILE,
            "Need read rights on issuer certificate %s for user %s.\n" %
            (issuercert, getpass.getuser()))
        sys.exit(1)

    certserial = get_config_value(lines, "certserial",
                                  os.path.join(statedir, "certserial"))
    if makedir(os.path.dirname(certserial), "certserial") != 0:
        sys.exit(1)

    ret = create_cert(flags, typ, directory, ekparams, vmid, tpm_spec_params,
                      tpm_attr_params, signkey, signkey_password, issuercert,
                      parentkey_password, swtpm_cert_env, certserial, lockfile,
                      optsfile)

    sys.exit(ret)
コード例 #3
0
ファイル: swtpm_localca.py プロジェクト: elms/swtpm
def create_cert(flags, typ, directory, ekparams, vmid, tpm_spec_params,
                tpm_attr_params, signkey, signkey_password, issuercert,
                parentkey_password, swtpm_cert_env, certserial, lockfile,
                optsfile):
    """ Create the certificate """
    serial, ret = get_next_cert_serial(certserial, lockfile)
    if ret != 0:
        return 1

    options = []
    lines, _ = read_file_lines(optsfile)
    for line in lines:
        if not line.strip():
            continue
        options.extend([x.strip() for x in line.split(" ", 1)])

    if vmid:
        subj = "CN=%s" % vmid
    else:
        subj = "CN=unknown"

    if flags & SETUP_TPM2_F:
        options.append("--tpm2")
    else:
        options.append("--add-header")

    if typ == "ek":
        if flags & ALLOW_SIGNING_F:
            options.append("--allow-signing")
        if flags & DECRYPTION_F:
            options.append("--decryption")

    match = re.search(r'x=([0-9A-Fa-f]+),y=([0-9A-Fa-f]+)(,id=([^,]+))?',
                      ekparams)
    if match:
        keyparams = ["--ecc-x", match.group(1), "--ecc-y", match.group(2)]
        if match.group(4):
            keyparams.extend(["--ecc-curveid", match.group(4)])
    else:
        keyparams = ["--modulus", ekparams]

    cmd = ["swtpm_cert", "--subject", subj]
    cmd.extend(options)

    temp1 = None
    temp2 = None

    if signkey_password:
        temp1 = tempfile.NamedTemporaryFile()
        temp1.write(signkey_password.encode())
        temp1.seek(0)
        cmd.extend(["--signkey-pwd", "file:%s" % temp1.name])

    if parentkey_password:
        temp2 = tempfile.NamedTemporaryFile()
        temp2.write(parentkey_password.encode())
        temp2.seek(0)
        cmd.extend(["--parentkey-pwd", "file:%s" % temp2.name])

    if typ == "ek":
        cmd.extend(tpm_spec_params)

    cmd.extend(tpm_attr_params)

    if typ == "platform":
        cmd.extend([
            "--type", "platform", "--out-cert",
            os.path.join(directory, "platform.cert")
        ])
    else:
        cmd.extend(["--out-cert", os.path.join(directory, "ek.cert")])

    cmd.extend(keyparams)
    cmd.extend([
        "--signkey", signkey, "--issuercert", issuercert, "--days", "3650",
        "--serial", serial
    ])

    if typ == "ek":
        certtype = "EK"
    else:
        certtype = "platform"

    try:
        proc = subprocess.Popen(cmd,
                                env=swtpm_cert_env,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
        output = proc.communicate()[0]
        if proc.returncode:
            logerr(LOGFILE,
                   "Could not create %s certificate locally\n" % certtype)
            logerr(LOGFILE, "%s" % output.decode())
            return 1
    except Exception as err:
        logerr(LOGFILE, "Could not run swtpm_cert: %s\n" % str(err))
        return 1
    finally:
        if temp1:
            temp1.close()
        if temp2:
            temp2.close()

    logit(LOGFILE, "Successfully created %s certificate locally.\n" % certtype)

    return 0