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

Wolfgang Meyer zu Bergsten w.bergsten at sirrix.com
Wed Aug 6 14:34:57 CEST 2014


Hello

Am 05.08.2014 13:52, schrieb Nikos Mavrogiannopoulos:
> On Mon, Aug 4, 2014 at 3:25 PM, Wolfgang Meyer zu Bergsten
> <w.bergsten at sirrix.com> wrote:
>> 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.
> 
> Hello,
>  That's a nice functionality and it would allow
> _gnutls_privkey_get_mpis() work for pkcs11 private keys as well.
> 
>> 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)
> 
> The pk parameter looks a bit awkward. Wouldn't it be straightforward
> to omit it, and use gnutls_pkcs11_privkey_get_pk_algorithm() to obtain
> it on demand?

I changed it accordingly. Furthermore, I added the functionality to
p11tool. See the attached patches.

regards
Wolfgang
-------------- next part --------------
>From 6faa2029c7d093592f34ddad21f4a34bd6aa2b46 Mon Sep 17 00:00:00 2001
From: Wolfgang Meyer zu Bergsten <w.bergsten at sirrix.com>
Date: Mon, 4 Aug 2014 15:09:05 +0200
Subject: [PATCH 2/3] 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.

Signed-off-by: Wolfgang Meyer zu Bergsten <w.bergsten at sirrix.com>
---
 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 8f2d2d7..75a16c4 100644
--- a/lib/includes/gnutls/pkcs11.h
+++ b/lib/includes/gnutls/pkcs11.h
@@ -350,6 +350,12 @@ gnutls_pkcs11_privkey_generate2(const char *url,
 				unsigned int flags);
 
 int
+gnutls_pkcs11_privkey_get_pubkey (const char* url,
+			      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 bc5837d..2989e74 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 5575efc..b67e482 100644
--- a/lib/pkcs11_privkey.c
+++ b/lib/pkcs11_privkey.c
@@ -885,6 +885,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
+ * @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_x509_crt_fmt_t fmt,
+                                  gnutls_datum_t * pubkey,
+                                  unsigned int flags)
+{
+	ck_object_handle_t priv;
+	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;
+	ck_key_type_t key_type;
+	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 = gnutls_pkcs11_privkey_get_pk_algorithm(privkey, 0);
+	obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
+	mech.mechanism = pk_to_genmech(obj->pk_algorithm, &key_type);
+	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_pkcs11_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

-------------- next part --------------
>From e93fe75937679ad4b95c396e1e4bdfec68d75977 Mon Sep 17 00:00:00 2001
From: Wolfgang Meyer zu Bergsten <w.bergsten at sirrix.com>
Date: Wed, 6 Aug 2014 13:20:24 +0200
Subject: [PATCH 3/3] add public key export to p11tool

Signed-off-by: Wolfgang Meyer zu Bergsten <w.bergsten at sirrix.com>
---
 src/p11tool-args.def |  7 +++++++
 src/p11tool.c        |  2 ++
 src/p11tool.h        |  2 ++
 src/pkcs11.c         | 35 +++++++++++++++++++++++++++++++++++
 4 files changed, 46 insertions(+)

diff --git a/src/p11tool-args.def b/src/p11tool-args.def
index a20d2ef..807be43 100644
--- a/src/p11tool-args.def
+++ b/src/p11tool-args.def
@@ -122,6 +122,13 @@ flag = {
     doc = "Generates an RSA private-public key pair on the specified token.";
 };
 
+
+flag = {
+    name      = export-pubkey;
+    descrip   = "Export the public key for a private key";
+    doc = "Exports the public key for the specified private key";
+};
+
 flag = {
     name      = label;
     arg-type  = string;
diff --git a/src/p11tool.c b/src/p11tool.c
index e2d30ed..afd4413 100644
--- a/src/p11tool.c
+++ b/src/p11tool.c
@@ -269,6 +269,8 @@ static void cmd_parser(int argc, char **argv)
 				get_bits(key_type, bits, sec_param, 0),
 				label, ENABLED_OPT(PRIVATE), detailed_url,
 				login, &cinfo);
+	} else if (HAVE_OPT(EXPORT_PUBKEY)) {
+		pkcs11_export_pubkey(outfile, url, detailed_url, login, &cinfo);
 	} else {
 		USAGE(1);
 	}
diff --git a/src/p11tool.h b/src/p11tool.h
index ba2ef1b..24dd060 100644
--- a/src/p11tool.h
+++ b/src/p11tool.h
@@ -52,6 +52,8 @@ void pkcs11_generate(FILE * outfile, const char *url,
 		     gnutls_pk_algorithm_t type, unsigned int bits,
 		     const char *label, int private, int detailed,
 		     unsigned int login, common_info_st * info);
+void pkcs11_export_pubkey(FILE * outfile, const char *url, int detailed,
+		     unsigned int login, common_info_st * info);
 
 #define PKCS11_TYPE_CRT_ALL 1
 #define PKCS11_TYPE_TRUSTED 2
diff --git a/src/pkcs11.c b/src/pkcs11.c
index de91f43..47bfaac 100644
--- a/src/pkcs11.c
+++ b/src/pkcs11.c
@@ -577,6 +577,41 @@ pkcs11_generate(FILE * outfile, const char *url, gnutls_pk_algorithm_t pk,
 }
 
 void
+pkcs11_export_pubkey(FILE * outfile, const char *url, int detailed, unsigned int login_flags, common_info_st * info)
+{
+	int ret;
+	unsigned int flags = 0;
+	gnutls_datum_t pubkey;
+
+	if (login_flags) flags = login_flags;
+
+	pkcs11_common(info);
+
+	FIX(url, outfile, detailed, info);
+	CHECK_LOGIN_FLAG(login_flags);
+
+	if (outfile == stderr || outfile == stdout) {
+		fprintf(stderr, "warning: no --outfile was specified and the public key will be printed on screen.\n");
+		sleep(3);
+	}
+
+	ret =
+	    gnutls_pkcs11_privkey_get_pubkey(url,
+					    GNUTLS_X509_FMT_PEM, &pubkey,
+					    flags);
+	if (ret < 0) {
+		fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
+			gnutls_strerror(ret));
+		exit(1);
+	}
+
+	fwrite(pubkey.data, 1, pubkey.size, outfile);
+	gnutls_free(pubkey.data);
+
+	return;
+}
+
+void
 pkcs11_init(FILE * outfile, const char *url, const char *label,
 	    common_info_st * info)
 {
-- 
1.9.3



More information about the Gnutls-devel mailing list