[gnutls-devel] [PATCH] add pubkey export from private key in pkcs11 subsystem

Wolfgang Meyer zu Bergsten w.bergsten at sirrix.com
Mon Aug 4 15:25:14 CEST 2014


Hello,

there are cases where we need to export the public key of private
key at a later time. Previously, the public key was only available
immediately after creation of a key pair. This patch allows to
retrieve the public key of a private key at any time after
creation.


regards
Wolfgang Meyer zu Bergsten
-------------- next part --------------
>From 7f74419681967435fecb4bc1ee965ca4ed8cea0f Mon Sep 17 00:00:00 2001
From: Wolfgang Meyer zu Bergsten <w.mzb at mzb-it.de>
Date: Mon, 4 Aug 2014 15:09:05 +0200
Subject: [PATCH] add pubkey export from private key in pkcs11 subsystem

There are cases where we need to export the public key of private
key at a later time. Previously, the public key was only available
immediately after creation of a key pair. This patch allows to
retrieve the public key of a private key at any time after
creation.
---
 lib/includes/gnutls/pkcs11.h |   6 +++
 lib/libgnutls.map            |   1 +
 lib/pkcs11_privkey.c         | 117 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+)

diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h
index 87a54f2..e7445b8 100644
--- a/lib/includes/gnutls/pkcs11.h
+++ b/lib/includes/gnutls/pkcs11.h
@@ -349,6 +349,12 @@ gnutls_pkcs11_privkey_generate2(const char *url,
 				unsigned int flags);
 
 int
+gnutls_pkcs11_privkey_get_pubkey (const char* url, gnutls_pk_algorithm_t pk,
+			      gnutls_x509_crt_fmt_t fmt,
+			      gnutls_datum_t * pubkey,
+			      unsigned int flags);
+
+int
 gnutls_pkcs11_token_get_random(const char *token_url,
 			       void *data, size_t len);
 
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 263ad0e..9a47be7 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -856,6 +856,7 @@ GNUTLS_3_1_0 {
 	gnutls_ocsp_status_request_is_checked;
 	gnutls_sign_is_secure;
 	gnutls_pkcs11_privkey_generate2;
+	gnutls_pkcs11_privkey_get_pubkey;
 	gnutls_x509_crt_get_policy;
 	gnutls_x509_policy_release;
 	gnutls_x509_crt_set_policy;
diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c
index a9c473e..aba9f9d 100644
--- a/lib/pkcs11_privkey.c
+++ b/lib/pkcs11_privkey.c
@@ -864,6 +864,123 @@ gnutls_pkcs11_privkey_generate2(const char *url, gnutls_pk_algorithm_t pk,
 	return ret;
 }
 
+/*
+ * gnutls_pkcs11_privkey_get_pubkey
+ * @url: a private key url
+ * @pk: the public key algorithm
+ * @fmt: the format of output params. PEM or DER.
+ * @pubkey: will hold the public key
+ * @flags: should be zero
+ *
+ * This function will extract the public key (modulus and public
+ * exponent) from the private key specified by the @url private key.
+ * This public key will be stored in @pubkey in the format specified
+ * by @fmt. @pubkey should be deinitialized using gnutls_free().
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ **/
+int
+gnutls_pkcs11_privkey_get_pubkey (const char* url, gnutls_pk_algorithm_t pk,
+                                  gnutls_x509_crt_fmt_t fmt,
+                                  gnutls_datum_t * pubkey,
+                                  unsigned int flags)
+{
+	ck_object_handle_t priv = NULL;
+	struct pkcs11_session_info sinfo;
+	struct p11_kit_uri *info = NULL;
+	struct ck_mechanism mech;
+	gnutls_pubkey_t pkey = NULL;
+	gnutls_pkcs11_obj_t obj = NULL;
+	gnutls_pkcs11_privkey_t privkey = NULL;
+	int ret;
+
+	memset(&sinfo, 0, sizeof(sinfo));
+
+	if (!pubkey) {
+		gnutls_assert();
+		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+	}
+
+	/* extract the public key */
+	ret = gnutls_pkcs11_privkey_init(&privkey);
+	if (ret < 0) {
+		gnutls_assert();
+		goto cleanup;
+	}
+	ret = gnutls_pkcs11_privkey_import_url(privkey, url, 0);
+	if (ret < 0) {
+		gnutls_assert();
+		goto cleanup;
+	}
+	priv = privkey->obj;
+
+	ret = gnutls_pubkey_init(&pkey);
+	if (ret < 0) {
+		gnutls_assert();
+		goto cleanup;
+	}
+
+	ret = gnutls_pkcs11_obj_init(&obj);
+	if (ret < 0) {
+		gnutls_assert();
+		goto cleanup;
+	}
+
+	if (privkey->sinfo.init) {
+		memcpy(&sinfo, &privkey->sinfo, sizeof(sinfo));
+	} else {
+		ret = pkcs11_url_to_info(url, &info);
+		if (ret < 0) {
+			gnutls_assert();
+			goto cleanup;
+		}
+
+		ret = pkcs11_open_session(&sinfo, NULL, info,
+					  pkcs11_obj_flags_to_int(flags));
+		p11_kit_uri_free(info);
+
+		if (ret < 0) {
+			gnutls_assert();
+			goto cleanup;
+		}
+	}
+
+	obj->pk_algorithm = pk;
+	obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
+	mech.mechanism = pk_to_genmech(pk);
+	ret = pkcs11_read_pubkey(sinfo.module, sinfo.pks, priv, mech.mechanism, obj->pubkey);
+	if (ret < 0) {
+		gnutls_assert();
+		goto cleanup;
+	}
+
+	ret = gnutls_pubkey_import_pkcs11(pkey, obj, 0);
+	if (ret < 0) {
+		gnutls_assert();
+		goto cleanup;
+	}
+
+	ret = gnutls_pubkey_export2(pkey, fmt, pubkey);
+	if (ret < 0) {
+		gnutls_assert();
+		goto cleanup;
+	}
+
+
+      cleanup:
+	if (obj != NULL)
+		gnutls_pkcs11_obj_deinit(obj);
+	if (pkey != NULL)
+		gnutls_pubkey_deinit(pkey);
+	if (privkey != NULL)
+		gnutls_privkey_deinit(privkey);
+	if (sinfo.pks != 0)
+		pkcs11_close_session(&sinfo);
+
+	return ret;
+}
+
 /**
  * gnutls_pkcs11_privkey_set_pin_function:
  * @key: The private key
-- 
1.9.3



More information about the Gnutls-devel mailing list