[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