diff --git a/Makefile.am b/Makefile.am
index 6a2508b11..6ee94561a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -87,6 +87,11 @@ scd = scd
else
scd =
endif
+if BUILD_TKDAEMON
+tkd = tkd
+else
+tkd =
+endif
if BUILD_G13
g13 = g13
else
@@ -114,7 +119,7 @@ tpm2d =
endif
SUBDIRS = m4 common regexp kbx \
- ${gpg} ${sm} ${agent} ${scd} ${g13} ${dirmngr} \
+ ${gpg} ${sm} ${agent} ${scd} ${tkd} ${g13} ${dirmngr} \
tools po ${doc} ${tests} ${tpm2d}
dist_doc_DATA = README
diff --git a/configure.ac b/configure.ac
index c31ae026a..a9509b2e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,6 +125,7 @@ GNUPG_BUILD_PROGRAM(gpgsm, yes)
# The agent is a required part and can't be disabled anymore.
build_agent=yes
GNUPG_BUILD_PROGRAM(scdaemon, yes)
+GNUPG_BUILD_PROGRAM(tkdaemon, yes)
GNUPG_BUILD_PROGRAM(g13, no)
GNUPG_BUILD_PROGRAM(dirmngr, yes)
GNUPG_BUILD_PROGRAM(keyboxd, yes)
@@ -1840,6 +1841,7 @@ AM_CONDITIONAL(BUILD_GPG, test "$build_gpg" = "yes")
AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes")
AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes")
AM_CONDITIONAL(BUILD_SCDAEMON, test "$build_scdaemon" = "yes")
+AM_CONDITIONAL(BUILD_TKDAEMON, test "$build_tkdaemon" = "yes")
AM_CONDITIONAL(BUILD_G13, test "$build_g13" = "yes")
AM_CONDITIONAL(BUILD_DIRMNGR, test "$build_dirmngr" = "yes")
AM_CONDITIONAL(BUILD_KEYBOXD, test "$build_keyboxd" = "yes")
@@ -2088,6 +2090,7 @@ g10/Makefile
sm/Makefile
agent/Makefile
scd/Makefile
+tkd/Makefile
tpm2d/Makefile
g13/Makefile
dirmngr/Makefile
diff --git a/tkd/Makefile.am b/tkd/Makefile.am
new file mode 100644
index 000000000..b6c30eccb
--- /dev/null
+++ b/tkd/Makefile.am
@@ -0,0 +1,44 @@
+# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see .
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+EXTRA_DIST =
+
+# libexec_PROGRAMS = tkdaemon
+
+noinst_PROGRAMS = pksign
+
+AM_CPPFLAGS =
+
+AM_CFLAGS = $(LIBGCRYPT_CFLAGS) \
+ $(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
+
+include $(top_srcdir)/am/cmacros.am
+
+tkdaemon_SOURCES = \
+ tkdaemon.c tkdaemon.h \
+ command.c
+
+tkdaemon_LDADD = $(libcommonpth) \
+ $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
+ $(GPG_ERROR_LIBS) \
+ $(LIBINTL) $(DL_LIBS) $(NETLIBS) $(LIBICONV)
+
+pksign_LDADD = $(libcommonpth) \
+ $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
+ $(GPG_ERROR_LIBS) \
+ $(LIBINTL) $(DL_LIBS) $(NETLIBS) $(LIBICONV)
diff --git a/tkd/pksign.c b/tkd/pksign.c
index ade6bfe7d..7995d9ed4 100644
--- a/tkd/pksign.c
+++ b/tkd/pksign.c
@@ -1,34 +1,57 @@
+#include
#include
#include
#include
#include
+#include
#include
+#include "../common/util.h"
#include "pkcs11.h"
-/*
- * For now, we don't COMPUTE_KEYGRIP, assuming Scute.
- * ... which used the ID as keygrip.
- */
-
-#ifdef COMPUTE_KEYGRIP
static void
compute_keygrip_rsa (char *keygrip,
const char *modulus, unsigned long modulus_len,
const char *exponent, unsigned long exponent_len)
{
- ;
+ gpg_error_t err;
+ gcry_sexp_t s_pkey = NULL;
+ const char *format = "(public-key(rsa(n%b)(e%b)))";
+ unsigned char grip[20];
+
+ err = gcry_sexp_build (&s_pkey, NULL, format,
+ (int)modulus_len, modulus,
+ (int)exponent_len, exponent);
+ if (!err && !gcry_pk_get_keygrip (s_pkey, grip))
+ err = gpg_error (GPG_ERR_INTERNAL);
+ else
+ {
+ gcry_sexp_release (s_pkey);
+ bin2hex (grip, 20, keygrip);
+ }
}
static void
-compute_keygrip_ec (char *keygrip,
- const char *oid, unsigned long oid_len,
- const char *ecpoint, unsigned long ecpoing_len)
+compute_keygrip_ec (char *keygrip, const char *curve,
+ const char *ecpoint, unsigned long ecpoint_len)
{
- ;
+ gpg_error_t err;
+ gcry_sexp_t s_pkey = NULL;
+ const char *format = "(public-key(ecc(curve %s)(q%b)))";
+ unsigned char grip[20];
+
+ err = gcry_sexp_build (&s_pkey, NULL, format, curve, (int)ecpoint_len,
+ ecpoint);
+ if (!err && !gcry_pk_get_keygrip (s_pkey, grip))
+ err = gpg_error (GPG_ERR_INTERNAL);
+ else
+ {
+ gcry_sexp_release (s_pkey);
+ bin2hex (grip, 20, keygrip);
+ }
}
-#endif
+
#define ck_function_list _CK_FUNCTION_LIST
#define ck_token_info _CK_TOKEN_INFO
@@ -50,7 +73,6 @@ compute_keygrip_ec (char *keygrip,
* session -> key_list -> key
*
*/
-#define KEYGRIP_LEN (40+1)
/*
* Major use cases:
@@ -72,9 +94,12 @@ struct key {
struct token *token; /* Back pointer. */
int valid;
ck_object_handle_t p11_keyid;
- char keygrip[KEYGRIP_LEN];
+ char keygrip[2*KEYGRIP_LEN+1];
int key_type;
- /* Possibly, ID, LABEL, etc. */
+ unsigned char label[256];
+ unsigned long label_len;
+ unsigned char id[256];
+ unsigned long id_len;
/* Allowed mechanisms??? */
};
@@ -178,7 +203,7 @@ struct p11dev {
int d;
};
-static struct p11dev priv;
+static struct p11dev p11_priv;
static unsigned long
notify_cb (ck_session_handle_t session,
@@ -205,7 +230,7 @@ open_session (struct token *token)
session_flags = session_flags | CKF_SERIAL_SESSION;
err = ck->f->C_OpenSession (slot_id, session_flags,
- (void *)&priv, notify_cb, &session_handle);
+ (void *)&p11_priv, notify_cb, &session_handle);
if (err)
{
printf ("open_session: %d\n", err);
@@ -271,31 +296,123 @@ logout (struct token *token)
}
static long
-detect_key (int try_private, struct token *token)
+examine_public_key (struct token *token, struct key *k, unsigned long keytype,
+ int update_keyid, ck_object_handle_t obj)
+{
+ unsigned long err = 0;
+ struct cryptoki *ck = token->ck;
+ unsigned char modulus[1024];
+ unsigned char exponent[8];
+ unsigned char ecparams[256];
+ unsigned char ecpoint[256];
+ struct ck_attribute templ[3];
+ unsigned long mechanisms[3];
+ int i;
+
+ templ[0].type = CKA_ALLOWED_MECHANISMS;
+ templ[0].pValue = (void *)mechanisms;
+ templ[0].ulValueLen = sizeof (mechanisms);
+
+ if (keytype == CKK_RSA)
+ {
+ k->valid = 1;
+ if (update_keyid)
+ k->p11_keyid = obj;
+ k->key_type = KEY_RSA;
+
+ templ[1].type = CKA_MODULUS;
+ templ[1].pValue = (void *)modulus;
+ templ[1].ulValueLen = sizeof (modulus);
+
+ templ[2].type = CKA_PUBLIC_EXPONENT;
+ templ[2].pValue = (void *)exponent;
+ templ[2].ulValueLen = sizeof (exponent);
+
+ err = ck->f->C_GetAttributeValue (token->session, obj, templ, 3);
+ if (err)
+ {
+ k->valid = -1;
+ return 1;
+ }
+
+ if ((modulus[0] & 0x80))
+ {
+ memmove (modulus+1, modulus, templ[1].ulValueLen);
+ templ[1].ulValueLen++;
+ modulus[0] = 0;
+ }
+
+ /* Found a RSA key. */
+ printf ("RSA: %d %d %d\n",
+ templ[0].ulValueLen,
+ templ[1].ulValueLen,
+ templ[2].ulValueLen);
+ puts ("Public key:");
+ compute_keygrip_rsa (k->keygrip,
+ modulus, templ[1].ulValueLen,
+ exponent, templ[2].ulValueLen);
+ puts (k->keygrip);
+ }
+ else if (keytype == CKK_EC)
+ {
+ char *curve_oid = NULL;
+ const char *curve;
+
+ k->valid = 1;
+ if (update_keyid)
+ k->p11_keyid = obj;
+ k->key_type = KEY_EC;
+
+ templ[1].type = CKA_EC_PARAMS;
+ templ[1].pValue = ecparams;
+ templ[1].ulValueLen = sizeof (ecparams);
+
+ templ[2].type = CKA_EC_POINT;
+ templ[2].pValue = (void *)ecpoint;
+ templ[2].ulValueLen = sizeof (ecpoint);
+
+ err = ck->f->C_GetAttributeValue (token->session, obj, templ, 3);
+ if (err)
+ {
+ k->valid = -1;
+ return 1;
+ }
+
+ /* Found an ECC key. */
+ printf ("ECC: %d %d %d\n",
+ templ[0].ulValueLen,
+ templ[1].ulValueLen,
+ templ[2].ulValueLen);
+
+ curve_oid = openpgp_oidbuf_to_str (ecparams+1, templ[1].ulValueLen-1);
+ curve = openpgp_oid_to_curve (curve_oid, 1);
+ xfree (curve_oid);
+
+ puts ("Public key:");
+ puts (curve);
+ compute_keygrip_ec (k->keygrip, curve, ecpoint, templ[2].ulValueLen);
+ puts (k->keygrip);
+ }
+
+ return 0;
+}
+
+static long
+detect_private_keys (struct token *token)
{
unsigned long err = 0;
struct cryptoki *ck = token->ck;
struct ck_attribute templ[8];
- unsigned char label[256];
unsigned long class;
- unsigned long key_type;
- unsigned long mechanisms[3];
- unsigned char id[256];
- unsigned char modulus[1024];
- unsigned char exponent[8];
- unsigned char ecparams[256];
- unsigned char ecpoint[256];
+ unsigned long keytype;
unsigned long cnt = 0;
ck_object_handle_t obj;
int i;
- if (try_private)
- class = CKO_PRIVATE_KEY;
- else
- class = CKO_PUBLIC_KEY;
+ class = CKO_PRIVATE_KEY;
templ[0].type = CKA_CLASS;
templ[0].pValue = (void *)&class;
templ[0].ulValueLen = sizeof (class);
@@ -313,6 +430,81 @@ detect_key (int try_private, struct token *token)
k->token = token;
k->valid = 0;
+ /* Portable way to get objects... is get it one by one. */
+ err = ck->f->C_FindObjects (token->session, &obj, 1, &any);
+ if (err || any == 0)
+ break;
+
+ templ[0].type = CKA_KEY_TYPE;
+ templ[0].pValue = &keytype;
+ templ[0].ulValueLen = sizeof (keytype);
+
+ templ[1].type = CKA_LABEL;
+ templ[1].pValue = (void *)k->label;
+ templ[1].ulValueLen = sizeof (k->label) - 1;
+
+ templ[2].type = CKA_ID;
+ templ[2].pValue = (void *)k->id;
+ templ[2].ulValueLen = sizeof (k->id) - 1;
+
+ err = ck->f->C_GetAttributeValue (token->session, obj, templ, 3);
+ if (err)
+ {
+ continue;
+ }
+
+ cnt++;
+
+ k->label_len = templ[1].ulValueLen;
+ k->label[k->label_len] = 0;
+ k->id_len = templ[2].ulValueLen;
+ k->id[k->id_len] = 0;
+
+ printf ("handle: %ld label: %s key_type: %d id: %s\n",
+ obj, k->label, keytype, k->id);
+
+ if (examine_public_key (token, k, keytype, 1, obj))
+ continue;
+ }
+
+ token->num_keys = cnt;
+ err = ck->f->C_FindObjectsFinal (token->session);
+ if (err)
+ {
+ return -1;
+ }
+ }
+}
+
+static long
+check_public_keys (struct token *token)
+{
+ unsigned long err = 0;
+ struct cryptoki *ck = token->ck;
+
+ struct ck_attribute templ[8];
+
+ unsigned char label[256];
+ unsigned long class;
+ unsigned long keytype;
+ unsigned char id[256];
+
+ ck_object_handle_t obj;
+ int i;
+
+ class = CKO_PUBLIC_KEY;
+ templ[0].type = CKA_CLASS;
+ templ[0].pValue = (void *)&class;
+ templ[0].ulValueLen = sizeof (class);
+
+ err = ck->f->C_FindObjectsInit (token->session, templ, 1);
+ if (!err)
+ {
+ while (TRUE)
+ {
+ unsigned long any;
+ struct key *k = NULL;
+
/* Portable way to get objects... is get it one by one. */
err = ck->f->C_FindObjects (token->session, &obj, 1, &any);
if (err || any == 0)
@@ -323,8 +515,8 @@ detect_key (int try_private, struct token *token)
templ[0].ulValueLen = sizeof (label);
templ[1].type = CKA_KEY_TYPE;
- templ[1].pValue = &key_type;
- templ[1].ulValueLen = sizeof (key_type);
+ templ[1].pValue = &keytype;
+ templ[1].ulValueLen = sizeof (keytype);
templ[2].type = CKA_ID;
templ[2].pValue = (void *)id;
@@ -339,102 +531,31 @@ detect_key (int try_private, struct token *token)
label[templ[0].ulValueLen] = 0;
id[templ[2].ulValueLen] = 0;
- printf ("handle: %ld label: %s key_type: %d id: %s\n",
- obj, label, key_type, id);
-
- templ[0].type = CKA_ALLOWED_MECHANISMS;
- templ[0].pValue = (void *)mechanisms;
- templ[0].ulValueLen = sizeof (mechanisms);
-
- if (key_type == CKK_RSA)
+ /* Locate matching private key. */
+ for (i = 0; i < token->num_keys; i++)
{
- templ[1].type = CKA_MODULUS;
- templ[1].pValue = (void *)modulus;
- templ[1].ulValueLen = sizeof (modulus);
+ k = &token->key_list[i];
- templ[2].type = CKA_PUBLIC_EXPONENT;
- templ[2].pValue = (void *)exponent;
- templ[2].ulValueLen = sizeof (exponent);
-
- err = ck->f->C_GetAttributeValue (token->session, obj, templ, 3);
- if (err)
- {
- continue;
- }
-
- /* Found a RSA key. */
- printf ("RSA: %d %d %d\n",
- templ[0].ulValueLen,
- templ[1].ulValueLen,
- templ[2].ulValueLen);
- puts ("Public key:");
- for (i = 0; i < templ[1].ulValueLen; i++)
- {
- printf ("%02x", modulus[i]);
- if ((i % 16) == 15)
- puts ("");
- }
- puts ("");
-
- k->valid = 1;
- k->p11_keyid = obj;
- k->key_type = KEY_RSA;
-#ifdef COMPUTE_KEYGRIP
- compute_keygrip_rsa (k->keygrip,
- modulus, templ[0].ulValueLen,
- exponent, templ[1].ulValueLen);
-#else
- memcpy (k->keygrip, id, 40);
- k->keygrip[40] = 0;
-#endif
- cnt++;
+ if (k->valid == -1
+ && k->label_len == templ[0].ulValueLen
+ && memcmp (label, k->label, k->label_len) == 0
+ && ((keytype == CKK_RSA && k->key_type == KEY_RSA)
+ || (keytype == CKK_EC && k->key_type == KEY_EC))
+ && k->id_len == templ[0].ulValueLen
+ && memcmp (id, k->id, k->id_len) == 0)
+ break;
}
- else if (key_type == CKK_EC)
- {
- templ[1].type = CKA_EC_PARAMS;
- templ[1].pValue = ecparams;
- templ[1].ulValueLen = sizeof (ecparams);
- templ[2].type = CKA_EC_POINT;
- templ[2].pValue = (void *)ecpoint;
- templ[2].ulValueLen = sizeof (ecpoint);
+ if (i == token->num_keys)
+ continue;
- err = ck->f->C_GetAttributeValue (token->session, obj, templ, 3);
- if (err)
- {
- continue;
- }
+ printf ("pub: handle: %ld label: %s key_type: %d id: %s\n",
+ obj, label, keytype, id);
- /* Found an ECC key. */
- printf ("ECC: %d %d %d\n",
- templ[0].ulValueLen,
- templ[1].ulValueLen,
- templ[2].ulValueLen);
- puts ("Public key:");
- for (i = 0; i < templ[2].ulValueLen; i++)
- {
- printf ("%02x", ecpoint[i]);
- if ((i % 16) == 15)
- puts ("");
- }
- puts ("");
-
- k->valid = 1;
- k->p11_keyid = obj;
- k->key_type = KEY_EC;
-#ifdef COMPUTE_KEYGRIP
- compute_keygrip_ec (k->keygrip,
- ecparams, templ[1].ulValueLen,
- ecpoint, templ[2].ulValueLen);
-#else
- memcpy (k->keygrip, id, 40);
- k->keygrip[40] = 0;
-#endif
- cnt++;
- }
+ if (examine_public_key (token, k, keytype, 0, obj))
+ continue;
}
- token->num_keys = cnt;
err = ck->f->C_FindObjectsFinal (token->session);
if (err)
{
@@ -512,13 +633,31 @@ static long
learn_keys (struct token *token)
{
unsigned long err = 0;
+ int i;
+
+ /* Detect private keys on the token. */
+ detect_private_keys (token);
+
+ /*
+ * In some implementations (EC key on SoftHSMv2, for example),
+ * public key is not available in CKO_PRIVATE_KEY objects.
+ *
+ * So, try to examine CKO_PUBLIC_KEY objects, if it provides
+ * public keys.
+ */
+ check_public_keys (token);
+
+ for (i = 0; i < token->num_keys; i++)
+ {
+ struct key *k = &token->key_list[i];
+
+ if (k->valid == -1)
+ k->valid = 0;
+ }
- detect_key (1, token);
#if 0
- if (token->num_keys == 0)
- detect_key (0, token);
-#endif
get_certificate (token);
+#endif
return 0;
}
@@ -539,9 +678,13 @@ find_key (struct cryptoki *ck, const char *keygrip, struct key **r_key)
{
struct key *k = &token->key_list[j];
+ if (k->valid != 1)
+ continue;
+
if (memcmp (k->keygrip, keygrip, 40) == 0)
{
*r_key = k;
+ printf ("found a key at %d:%d\n", i, j);
return 0;
}
}
@@ -677,6 +820,10 @@ main (int argc, const char *argv[])
unsigned char sig[1024];
unsigned long siglen = sizeof (sig);
+ printf ("key object id: %d\n", k->p11_keyid);
+ printf ("key type: %d\n", k->key_type);
+ puts (k->keygrip);
+
r = do_pksign (k, "test test", 9, sig, &siglen);
if (!r)
{