summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kobras <kobras@puzzle-itc.de>2019-06-24 12:09:12 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2019-07-10 17:31:48 +0200
commit107ba8e00ca576cf21c3b8a82d7f826178bd096c (patch)
tree672e7179670a076c69ca70392ba8ee40b5ab145a
parent68ad9aabf80d506fa9bde3161c6d6faf24db7eff (diff)
downloadNetworkManager-107ba8e00ca576cf21c3b8a82d7f826178bd096c.tar.gz
libnm/crypto: accept TPM2-wrapped PEM keys
Some tools that NM can interact with (eg. openconnect) have added automated support to handle TPM2-wrapped PEM keys as drop-in replacements for ordinary key files. Make sure that NM doesn't reject these keys upfront. We cannot reliably assume NM to be able to unwrap and validate the key. Therefore, accept any key as long as the PEM header and trailer look ok.
-rw-r--r--libnm-core/nm-crypto.c45
-rw-r--r--libnm-core/tests/certs/test-tpm2wrapped-key.pem14
-rw-r--r--libnm-core/tests/test-keyfile.c20
3 files changed, 76 insertions, 3 deletions
diff --git a/libnm-core/nm-crypto.c b/libnm-core/nm-crypto.c
index 98ac6844de..e0c3b7fde5 100644
--- a/libnm-core/nm-crypto.c
+++ b/libnm-core/nm-crypto.c
@@ -49,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[] = {
@@ -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;
diff --git a/libnm-core/tests/certs/test-tpm2wrapped-key.pem b/libnm-core/tests/certs/test-tpm2wrapped-key.pem
new file mode 100644
index 0000000000..f3fd271c32
--- /dev/null
+++ b/libnm-core/tests/certs/test-tpm2wrapped-key.pem
@@ -0,0 +1,14 @@
+-----BEGIN TSS2 PRIVATE KEY-----
+MIICEwYGZ4EFCgEDoAMBAQECBQCBAAABBIIBGAEWAAEACwACBEAAAAAQABAIAAAA
+AAABAOJdEXw1LO6JWskHBSYQc1NfJAe9DOAyLA4XbXI5asQ8aNbmL51DP9mQQpqq
+a1CSRZAIuuorMxyRBBAFpF4OZqjNd/Nskp3iMmifr5yqAYZ3M31MqlBFiiyctqKp
+VwIChwsIbKelrsXbty1icP2CH+k4w/nPymPjnfYtgpMe8QW8n6U156ujIdJcISds
+QFcl3nrDnD1IumX0/LfanQrRDVSI+m6szvTrdsPMtGeaNMnlz0gx74auo7/CgEjX
+69xjPvQpNLHO/nV4EHSdfXH3LamcpWO8aEAVne3MFFA9V0bpv7uKoGhRjssD9kSr
+PQzNXfjHpkcOLeH4pzxDMFXDIGUEgeAA3gAgrCL3RRcBryFXToo9ZN3/f4EeeEjK
+58ejYomsxqvckhgAEMxbT26fo2h27b4KPlnUpoiL2JPLB0Xz6PJAF8n0YdJUO381
+xhzPTIQop81BxljTLV2C9WGns5bWDPW9ItEbv4UalEwFfxsW4Ma5smLWn3A1UwVN
+Z1cW/oUx+3nOCF1TZgbMPszToqCPlpIHd9vO709qpSyULIUkZLHS6PUM7ESY5U81
+f4BITxJR+aYaqErni/FDLsDVP0MQ3CuFHeUDHI0uEzzbfurYFjpp9+caaoWuZzpg
+VYV5pjPdgg==
+-----END TSS2 PRIVATE KEY-----
diff --git a/libnm-core/tests/test-keyfile.c b/libnm-core/tests/test-keyfile.c
index 2c09b17c9e..195f3797dc 100644
--- a/libnm-core/tests/test-keyfile.c
+++ b/libnm-core/tests/test-keyfile.c
@@ -35,6 +35,7 @@
#define TEST_CERT_DIR NM_BUILD_SRCDIR"/libnm-core/tests/certs"
#define TEST_WIRED_TLS_CA_CERT TEST_CERT_DIR"/test-ca-cert.pem"
#define TEST_WIRED_TLS_PRIVKEY TEST_CERT_DIR"/test-key-and-cert.pem"
+#define TEST_WIRED_TLS_TPM2KEY TEST_CERT_DIR"/test-tpm2wrapped-key.pem"
/*****************************************************************************/
@@ -377,15 +378,15 @@ _test_8021x_cert_check_blob_full (NMConnection *con, const void *data, gsize len
#define _test_8021x_cert_check_blob(con, data) _test_8021x_cert_check_blob_full(con, data, NM_STRLEN (data))
static void
-test_8021x_cert (void)
+_test_8021x_cert_from_files (const char *cert, const char *key)
{
NMSetting8021x *s_8021x;
gs_unref_object NMConnection *con = nmtst_create_minimal_connection ("test-cert", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
GError *error = NULL;
gboolean success;
NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_PATH;
- gs_free char *full_TEST_WIRED_TLS_CA_CERT = nmtst_file_resolve_relative_path (TEST_WIRED_TLS_CA_CERT, NULL);
- gs_free char *full_TEST_WIRED_TLS_PRIVKEY = nmtst_file_resolve_relative_path (TEST_WIRED_TLS_PRIVKEY, NULL);
+ gs_free char *full_TEST_WIRED_TLS_CA_CERT = nmtst_file_resolve_relative_path (cert, NULL);
+ gs_free char *full_TEST_WIRED_TLS_PRIVKEY = nmtst_file_resolve_relative_path (key, NULL);
/* test writing/reading of certificates of NMSetting8021x */
@@ -444,6 +445,18 @@ test_8021x_cert (void)
}
+static void
+test_8021x_cert (void)
+{
+ _test_8021x_cert_from_files (TEST_WIRED_TLS_CA_CERT, TEST_WIRED_TLS_PRIVKEY);
+}
+
+static void
+test_8021x_cert_tpm2key (void)
+{
+ _test_8021x_cert_from_files (TEST_WIRED_TLS_CA_CERT, TEST_WIRED_TLS_TPM2KEY);
+}
+
/*****************************************************************************/
static void
@@ -850,6 +863,7 @@ int main (int argc, char **argv)
g_test_add_func ("/core/keyfile/encode_key", test_encode_key);
g_test_add_func ("/core/keyfile/test_8021x_cert", test_8021x_cert);
+ g_test_add_func ("/core/keyfile/test_8021x_cert_tpm2key", test_8021x_cert_tpm2key);
g_test_add_func ("/core/keyfile/test_8021x_cert_read", test_8021x_cert_read);
g_test_add_func ("/core/keyfile/test_team_conf_read/valid", test_team_conf_read_valid);
g_test_add_func ("/core/keyfile/test_team_conf_read/invalid", test_team_conf_read_invalid);