OpenSSL: Add support for TPM2-wrapped keys

If the header of a PEM-formatted certificate or key in private_key file
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.

This functionality needs
https://git.kernel.org/pub/scm/linux/kernel/git/jejb/openssl_tpm2_engine.git
to be installed as an OpenSSL engine.

Signed-off-by: Daniel Kobras <kobras@puzzle-itc.de>
This commit is contained in:
Daniel Kobras 2019-07-02 16:19:38 +02:00 committed by Jouni Malinen
parent deb92a6bf9
commit 18780c6d67

View file

@ -4908,6 +4908,76 @@ static int ocsp_status_cb(SSL *s, void *arg)
#endif /* HAVE_OCSP */
static size_t max_str_len(const char **lines)
{
const char **p;
size_t max_len = 0;
for (p = lines; *p; p++) {
size_t len = os_strlen(*p);
if (len > max_len)
max_len = len;
}
return max_len;
}
static int match_lines_in_file(const char *path, const char **lines)
{
FILE *f;
char *buf;
size_t bufsize;
int found = 0, is_linestart = 1;
bufsize = max_str_len(lines) + sizeof("\r\n");
buf = os_malloc(bufsize);
if (!buf)
return 0;
f = fopen(path, "r");
if (!f) {
os_free(buf);
return 0;
}
while (!found && fgets(buf, bufsize, f)) {
int is_lineend;
size_t len;
const char **p;
len = strcspn(buf, "\r\n");
is_lineend = buf[len] != '\0';
buf[len] = '\0';
if (is_linestart && is_lineend) {
for (p = lines; !found && *p; p++)
found = os_strcmp(buf, *p) == 0;
}
is_linestart = is_lineend;
}
fclose(f);
bin_clear_free(buf, bufsize);
return found;
}
static int is_tpm2_key(const char *path)
{
/* Check both new and old format of TPM2 PEM guard tag */
static 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)
{
@ -4960,6 +5030,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 (params->private_key &&
(!engine_id || os_strcmp(engine_id, "tpm2") == 0) &&
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) {
@ -4991,7 +5072,8 @@ 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)