[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