about summary refs log tree commit diff
path: root/libnm-core/nm-crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-crypto.c')
-rw-r--r--libnm-core/nm-crypto.c73
1 files changed, 59 insertions, 14 deletions
diff --git a/libnm-core/nm-crypto.c b/libnm-core/nm-crypto.c
index c7142216..e0c3b7fd 100644
--- a/libnm-core/nm-crypto.c
+++ b/libnm-core/nm-crypto.c
@@ -1,5 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-
 /*
  * Dan Williams <dcbw@redhat.com>
  *
@@ -51,6 +49,12 @@
 #define PEM_PKCS8_DEC_KEY_BEGIN "-----BEGIN PRIVATE KEY-----"
 #define PEM_PKCS8_DEC_KEY_END   "-----END PRIVATE KEY-----"
 
+#define PEM_TPM2_WRAPPED_KEY_BEGIN "-----BEGIN TSS2 PRIVATE KEY-----"
+#define PEM_TPM2_WRAPPED_KEY_END "-----END TSS2 PRIVATE KEY-----"
+
+#define PEM_TPM2_OLD_WRAPPED_KEY_BEGIN "-----BEGIN TSS2 KEY BLOB-----"
+#define PEM_TPM2_OLD_WRAPPED_KEY_END "-----END TSS2 KEY BLOB-----"
+
 /*****************************************************************************/
 
 static const NMCryptoCipherInfo cipher_infos[] = {
@@ -118,21 +122,23 @@ find_tag (const char *tag,
           gsize start_at,
           gsize *out_pos)
 {
-	gsize i, taglen;
-	gsize len = data_len - start_at;
+	const guint8 *p;
+	gsize taglen;
 
-	g_return_val_if_fail (out_pos != NULL, FALSE);
+	nm_assert (out_pos);
+	nm_assert (start_at <= data_len);
 
 	taglen = strlen (tag);
-	if (len >= taglen) {
-		for (i = 0; i < len - taglen + 1; i++) {
-			if (memcmp (data + start_at + i, tag, taglen) == 0) {
-				*out_pos = start_at + i;
-				return TRUE;
-			}
-		}
-	}
-	return FALSE;
+
+	p = memmem (&data[start_at], data_len - start_at, tag, taglen);
+	if (!p)
+		return FALSE;
+
+	*out_pos = p - data;
+
+	nm_assert (memcmp (&data[*out_pos], tag, taglen) == 0);
+
+	return TRUE;
 }
 
 #define DEK_INFO_TAG "DEK-Info: "
@@ -387,6 +393,43 @@ parse_pkcs8_key_file (const guint8 *data,
 }
 
 static gboolean
+parse_tpm2_wrapped_key_file (const guint8 *data,
+                             gsize data_len,
+                             gboolean *out_encrypted,
+                             GError **error)
+{
+	gsize start = 0, end = 0;
+	const char *start_tag = NULL, *end_tag = NULL;
+
+	nm_assert (out_encrypted);
+
+	if (find_tag (PEM_TPM2_WRAPPED_KEY_BEGIN, data, data_len, 0, &start)) {
+		start_tag = PEM_TPM2_WRAPPED_KEY_BEGIN;
+		end_tag = PEM_TPM2_WRAPPED_KEY_END;
+	} else if (find_tag (PEM_TPM2_OLD_WRAPPED_KEY_BEGIN, data, data_len, 0, &start)) {
+		start_tag = PEM_TPM2_OLD_WRAPPED_KEY_BEGIN;
+		end_tag = PEM_TPM2_OLD_WRAPPED_KEY_END;
+	} else {
+		g_set_error_literal (error, NM_CRYPTO_ERROR,
+		                     NM_CRYPTO_ERROR_INVALID_DATA,
+		                     _("Failed to find expected TSS start tag."));
+		return FALSE;
+	}
+
+	start += strlen (start_tag);
+	if (!find_tag (end_tag, data, data_len, start, &end)) {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_INVALID_DATA,
+		             _("Failed to find expected TSS end tag '%s'."),
+		             end_tag);
+		return FALSE;
+	}
+
+	*out_encrypted = FALSE;
+	return TRUE;
+}
+
+static gboolean
 file_read_contents (const char *filename,
                     NMSecretPtr *out_contents,
                     GError **error)
@@ -824,6 +867,8 @@ nm_crypto_verify_private_key_data (const guint8 *data,
 			if (   !password
 			    || _nm_crypto_verify_pkcs8 (parsed.bin, parsed.len, is_encrypted, password, error))
 				format = NM_CRYPTO_FILE_FORMAT_RAW_KEY;
+		} else if (parse_tpm2_wrapped_key_file (data, data_len, &is_encrypted, NULL)) {
+			format = NM_CRYPTO_FILE_FORMAT_RAW_KEY;
 		} else {
 			NMCryptoCipherType cipher;
 			nm_auto_free_secret char *iv = NULL;