If the header of a PEM-formatted cert or key indicates that it is wrapped with a TPM2 key, try to autoload the appropriate OpenSSL engine that can transparently unwrap the key. This enables systems to use TPM2-wrapped keys as drop-in replacements to ordinary SSL keys. Signed-off-by: Daniel Kobras <kobras@xxxxxxxxxxxxx> --- Hi! This patch adds support for TPM2-wrapped keys, similar to what David Woodhouse did in openconnect, and suggested earlier on this list for wpa_supplicant as well. It requires https://git.kernel.org/pub/scm/linux/kernel/git/jejb/openssl_tpm2_engine.git/ to be installed as an openssl engine. The match_line_in_file() helper function is rather generic. If there's a better place to put it, please let me know. Kind regards, Daniel --- src/crypto/tls_openssl.c | 74 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index 1073f6450..7f61f7560 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -4819,6 +4819,67 @@ static int ocsp_status_cb(SSL *s, void *arg) #endif /* HAVE_OCSP */ +static int match_lines_in_file(const char *path, const char **lines) +{ + FILE *f = NULL; + const char **p; + char *buf; + size_t bufsize = 0; + int found, is_linestart; + + if (!path || !lines || !*lines) + return 0; + + for (p = lines; *p; p++) { + size_t size = strlen(*p) + sizeof("\r\n"); + bufsize = (size > bufsize) ? size : bufsize; + } + + buf = os_malloc(bufsize); + if (!buf) + return 0; + + f = fopen(path, "r"); + if (!f) { + os_free(buf); + return 0; + } + + found = 0; + is_linestart = 1; + + while (!found && fgets(buf, bufsize, f)) { + int is_lineend; + size_t buflen = strlen(buf); + + buf[strcspn(buf, "\r\n")] = '\0'; + is_lineend = strlen(buf) < buflen; + + if (is_linestart && is_lineend) { + for (p = lines; !found && *p; p++) { + found = !os_strcmp(buf, *p); + } + } + is_linestart = is_lineend; + } + + fclose(f); + os_free(buf); + + return found; +} + +static int is_tpm2_key(const char *path) +{ + /* Check both new and old format of TPM2 PEM guard tag */ + const char *tpm2_tags[] = { + "-----BEGIN TSS2 PRIVATE KEY-----", + "-----BEGIN TSS2 KEY BLOB-----", + NULL + }; + + return match_lines_in_file(path, tpm2_tags); +} int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) @@ -4872,6 +4933,17 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, if (can_pkcs11 == 2 && !engine_id) engine_id = "pkcs11"; + /* If private_key points to a TPM2-wrapped key, automatically enable + * tpm2 engine and use it to unwrap the key. */ + if (!engine_id || os_strcmp(engine_id, "tpm2")) { + if (is_tpm2_key(params->private_key)) { + wpa_printf(MSG_DEBUG, "OpenSSL: Found TPM2 wrapped key %s", + params->private_key); + key_id = key_id ? key_id : params->private_key; + engine_id = engine_id ? engine_id : "tpm2"; + } + } + #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) if (params->flags & TLS_CONN_EAP_FAST) { @@ -4903,7 +4975,7 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, } if (engine_id) { - wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine"); + wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine %s", engine_id); ret = tls_engine_init(conn, engine_id, params->pin, key_id, cert_id, ca_cert_id); if (ret) -- 2.20.1 -- Daniel Kobras Principal Architect Puzzle ITC Deutschland +49 7071 14316 0 www.puzzle-itc.de -- Puzzle ITC Deutschland GmbH Sitz der Gesellschaft: Jurastr. 27/1, 72072 Tübingen Eingetragen am Amtsgericht Stuttgart HRB 765802 Geschäftsführer: Lukas Kallies, Daniel Kobras, Mark Pröhl _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap