LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File 0004-pkcs11-read-TPM2-based-ssh-private-keys.patch of Package gnome-keyring (Project home:jejb1:Tumbleweed)

From 6dcb37f130e6309a4e0767b9d3aa8546f9edcedb Mon Sep 17 00:00:00 2001
From: James Bottomley <James.Bottomley@HansenPartnership.com>
Date: Thu, 29 Dec 2016 21:54:58 -0800
Subject: [PATCH 4/6] pkcs11: read TPM2 based ssh private keys

ssh private keys can be converted into TPM2 private keys using the
openssl_tpm2_engine create_tpm2_key command.  When this happens they
have 'TSS2 KEY BLOB' pem guards.  Teach the code to recognise these
and convert them to an s-expr of the form:

(private-key
  (rsa
    (tpm2
      (auth %b)
      (parent %u)
      (priv %b)
      (pub %b))))

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 egg/Makefile.am                    |  4 ++-
 egg/egg-asn1-defs.c                |  1 +
 egg/egg-asn1-defs.h                |  1 +
 egg/tpm2.asn                       | 16 ++++++++++
 egg/tpm2.asn.h                     | 20 +++++++++++++
 pkcs11/gkm/gkm-data-der.c          | 61 ++++++++++++++++++++++++++++++++++++++
 pkcs11/gkm/gkm-data-der.h          |  4 +++
 pkcs11/ssh-store/gkm-ssh-openssh.c | 21 +++++++++++++
 8 files changed, 127 insertions(+), 1 deletion(-)
 create mode 100644 egg/tpm2.asn
 create mode 100644 egg/tpm2.asn.h

diff --git a/egg/Makefile.am b/egg/Makefile.am
index 1e3bc88..a28652f 100644
--- a/egg/Makefile.am
+++ b/egg/Makefile.am
@@ -39,12 +39,13 @@ libegg_la_SOURCES = \
 	egg/egg-testing.c egg/egg-testing.h \
 	egg/egg-timegm.c egg/egg-timegm.h \
 	egg/egg-asn1-defs.h \
-	egg/pk.asn.h egg/pkix.asn.h \
+	egg/pk.asn.h egg/pkix.asn.h egg/tpm2.asn.h \
 	$(NULL)
 
 ASN1_FILES += \
 	egg/pk.asn \
 	egg/pkix.asn \
+	egg/tpm2.asn \
 	$(NULL)
 	
 # --------------------------------------------------------------------
@@ -116,6 +117,7 @@ libegg_test_la_LIBS = \
 ASN1_FILES += \
 	egg/pk.asn \
 	egg/pkix.asn \
+	egg/tpm2.asn \
 	egg/test.asn
 
 # -------------------------------------------------------------------
diff --git a/egg/egg-asn1-defs.c b/egg/egg-asn1-defs.c
index 3774f32..adea594 100644
--- a/egg/egg-asn1-defs.c
+++ b/egg/egg-asn1-defs.c
@@ -31,3 +31,4 @@ typedef struct _EggAsn1xDef asn1_static_node;
 
 #include "pk.asn.h"
 #include "pkix.asn.h"
+#include "tpm2.asn.h"
diff --git a/egg/egg-asn1-defs.h b/egg/egg-asn1-defs.h
index cd1eee8..6364450 100644
--- a/egg/egg-asn1-defs.h
+++ b/egg/egg-asn1-defs.h
@@ -31,5 +31,6 @@ struct _EggAsn1xDef {
 
 extern const struct _EggAsn1xDef pkix_asn1_tab[];
 extern const struct _EggAsn1xDef pk_asn1_tab[];
+extern const struct _EggAsn1xDef tpm2_asn1_tab[];
 
 #endif /* EGG_ASN1_DEFS_H_ */
diff --git a/egg/tpm2.asn b/egg/tpm2.asn
new file mode 100644
index 0000000..3e5dc6b
--- /dev/null
+++ b/egg/tpm2.asn
@@ -0,0 +1,16 @@
+
+TPM2 { }
+
+DEFINITIONS EXPLICIT TAGS ::=
+
+BEGIN
+
+TPMKey ::= SEQUENCE {
+	type		OBJECT IDENTIFIER,
+	emptyAuth	[0] EXPLICIT BOOLEAN OPTIONAL,
+	parent		[1] EXPLICIT INTEGER OPTIONAL,
+	pubkey		[2] EXPLICIT OCTET STRING OPTIONAL,
+	privkey		OCTET STRING
+}
+
+END
diff --git a/egg/tpm2.asn.h b/egg/tpm2.asn.h
new file mode 100644
index 0000000..356c85c
--- /dev/null
+++ b/egg/tpm2.asn.h
@@ -0,0 +1,20 @@
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/* #include <libtasn1.h> */
+
+const asn1_static_node tpm2_asn1_tab[] = {
+  { "TPM2", 536872976, NULL },
+  { NULL, 1073741836, NULL },
+  { "TPMKey", 536870917, NULL },
+  { "type", 1073741836, NULL },
+  { "emptyAuth", 1610637316, NULL },
+  { NULL, 2056, "0"},
+  { "parent", 1610637315, NULL },
+  { NULL, 2056, "1"},
+  { "pubkey", 1610637319, NULL },
+  { NULL, 2056, "2"},
+  { "privkey", 7, NULL },
+  { NULL, 0, NULL }
+};
diff --git a/pkcs11/gkm/gkm-data-der.c b/pkcs11/gkm/gkm-data-der.c
index 7f21ef2..436ee02 100644
--- a/pkcs11/gkm/gkm-data-der.c
+++ b/pkcs11/gkm/gkm-data-der.c
@@ -114,6 +114,67 @@ done:
 	return ret;
 }
 
+#define SEXP_PRIVATE_TPM2	\
+	"(private-key"		\
+	"  (rsa"		\
+	"    (tpm2"		\
+	"      (auth %b)"	\
+	"      (parent %u)"	\
+	"      (priv %b)"	\
+	"      (pub %b))))"
+
+GkmDataResult
+gkm_data_der_read_private_tpm2_key (GBytes *data,
+				    const gchar *password,
+				    gssize n_password,
+				    gcry_sexp_t *s_key)
+{
+	GNode *asn = NULL;
+	GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
+	gulong parent;
+	gboolean empty_auth = TRUE;
+	guchar *pubkey, *privkey;
+	gsize n_pubkey, n_privkey;
+
+	asn = egg_asn1x_create_and_decode (tpm2_asn1_tab, "TPMKey", data);
+	if (!asn)
+		goto done;
+
+	ret = GKM_DATA_LOCKED;
+
+	egg_asn1x_get_boolean(egg_asn1x_node(asn, "emptyAuth", NULL), &empty_auth);
+
+	if (!empty_auth && n_password == 0)
+		goto done;
+
+	ret = GKM_DATA_FAILURE;
+
+	if (!egg_asn1x_get_integer_as_ulong(egg_asn1x_node(asn, "parent", NULL), &parent))
+		goto done;
+
+	pubkey = egg_asn1x_get_string_as_raw(egg_asn1x_node(asn, "pubkey", NULL), NULL, &n_pubkey);
+	if (!pubkey)
+		goto done;
+
+	privkey = egg_asn1x_get_string_as_raw(egg_asn1x_node(asn, "privkey", NULL), NULL, &n_privkey);
+	if (!privkey)
+		goto done_free;
+
+	if (gcry_sexp_build(s_key, NULL, SEXP_PRIVATE_TPM2, n_password, password, parent, n_privkey, privkey, n_pubkey, pubkey))
+		goto done_free;
+
+	ret = GKM_DATA_SUCCESS;
+
+ done_free:
+	g_free(pubkey);
+	g_free(privkey);
+
+ done:
+	egg_asn1x_destroy (asn);
+
+	return ret;
+}
+
 #define SEXP_PRIVATE_TPM	\
 	"(private-key"		\
 	"  (rsa"		\
diff --git a/pkcs11/gkm/gkm-data-der.h b/pkcs11/gkm/gkm-data-der.h
index f6d2cd8..3d8cc32 100644
--- a/pkcs11/gkm/gkm-data-der.h
+++ b/pkcs11/gkm/gkm-data-der.h
@@ -38,6 +38,10 @@ GkmDataResult	   gkm_data_der_read_private_tpm_key	     (GBytes *data,
 							      const gchar *password,
 							      gssize n_password,
 							      gcry_sexp_t *s_key);
+GkmDataResult	   gkm_data_der_read_private_tpm2_key	     (GBytes *data,
+							      const gchar *password,
+							      gssize n_password,
+							      gcry_sexp_t *s_key);
 GkmDataResult      gkm_data_der_read_private_key_rsa         (GBytes *data,
                                                               gcry_sexp_t *s_key);
 
diff --git a/pkcs11/ssh-store/gkm-ssh-openssh.c b/pkcs11/ssh-store/gkm-ssh-openssh.c
index e6ae173..39a0dac 100644
--- a/pkcs11/ssh-store/gkm-ssh-openssh.c
+++ b/pkcs11/ssh-store/gkm-ssh-openssh.c
@@ -206,6 +206,21 @@ is_tpm_key_type (GQuark type)
 }
 
 static gboolean
+is_tpm2_key_type (GQuark type)
+{
+	static GQuark PEM_TPM2_KEY_BLOB;
+	static gsize quarks_inited = 0;
+
+	/* Initialize the first time through */
+	if (g_once_init_enter (&quarks_inited)) {
+		PEM_TPM2_KEY_BLOB = g_quark_from_static_string ("TSS2 KEY BLOB");
+		g_once_init_leave (&quarks_inited, 1);
+	}
+
+	return (type == PEM_TPM2_KEY_BLOB);
+}
+
+static gboolean
 is_private_key_type (GQuark type)
 {
 	static GQuark PEM_RSA_PRIVATE_KEY;
@@ -239,6 +254,12 @@ parsed_pem_block (GQuark type,
 		return;
 	}
 
+	if (is_tpm2_key_type(type)) {
+		ctx->result = gkm_data_der_read_private_tpm2_key(data, ctx->password, ctx->n_password, &ctx->sexp);
+		ctx->seen = TRUE;
+		return;
+	}
+
 	if (!is_private_key_type (type))
 		return;
 
-- 
2.6.6