tkd: Support READCERT command.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2023-03-22 15:28:56 +09:00
parent 01eef54e2c
commit 30d4eb97db
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054
3 changed files with 91 additions and 36 deletions

View File

@ -297,6 +297,31 @@ cmd_readkey (assuan_context_t ctx, char *line)
return err; return err;
} }
static const char hlp_readcert[] =
"READCERT <keygrip>\n"
"\n"
"Return the certificate for the given KEYGRIP.";
static gpg_error_t
cmd_readcert (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err;
const char *keygrip;
line = xtrystrdup (line); /* Need a copy of the line. */
if (!line)
return gpg_error_from_syserror ();
keygrip = skip_options (line);
if (strlen (keygrip) != 40)
err = gpg_error (GPG_ERR_INV_ID);
err = tkd_readcert (ctrl, ctx, keygrip);
xfree (line);
return err;
}
static const char hlp_pksign[] = static const char hlp_pksign[] =
"PKSIGN [--hash=[sha{256,384,512}|none]] <keygrip>\n" "PKSIGN [--hash=[sha{256,384,512}|none]] <keygrip>\n"
"\n" "\n"
@ -469,6 +494,7 @@ register_commands (assuan_context_t ctx)
{ "PKSIGN", cmd_pksign, hlp_pksign }, { "PKSIGN", cmd_pksign, hlp_pksign },
{ "KILLTKD", cmd_killtkd, hlp_killtkd }, { "KILLTKD", cmd_killtkd, hlp_killtkd },
{ "KEYINFO", cmd_keyinfo, hlp_keyinfo }, { "KEYINFO", cmd_keyinfo, hlp_keyinfo },
{ "READCERT", cmd_readcert, hlp_readcert },
{ "GETINFO", cmd_getinfo, hlp_getinfo }, { "GETINFO", cmd_getinfo, hlp_getinfo },
{ "RESTART", cmd_restart, hlp_restart }, { "RESTART", cmd_restart, hlp_restart },
{ NULL } { NULL }

View File

@ -622,72 +622,73 @@ check_public_keys (struct token *token)
return 0; return 0;
} }
#if 0
static long static long
get_certificate (struct token *token) get_certificate (struct token *token,
unsigned char **r_cert, size_t *r_certlen)
{ {
unsigned long err = 0; unsigned long r = 0;
struct cryptoki *ck = token->ck; struct cryptoki *ck = token->ck;
struct ck_attribute templ[1]; struct ck_attribute templ[1];
unsigned long class; unsigned long class;
unsigned char certificate[4096]; unsigned char certificate[4096];
unsigned long cert_len; int certificate_available = 0;
int certificate_available; unsigned char *cert;
size_t certlen;
ck_object_handle_t obj;
int i;
class = CKO_CERTIFICATE; class = CKO_CERTIFICATE;
templ[0].type = CKA_CLASS; templ[0].type = CKA_CLASS;
templ[0].pValue = (void *)&class; templ[0].pValue = (void *)&class;
templ[0].ulValueLen = sizeof (class); templ[0].ulValueLen = sizeof (class);
err = ck->f->C_FindObjectsInit (token->session, templ, 1); r = ck->f->C_FindObjectsInit (token->session, templ, 1);
if (!err) if (!r)
{ {
ck_object_handle_t obj;
while (TRUE) while (TRUE)
{ {
unsigned long any; unsigned long any;
/* Portable way to get objects... is get it one by one. */ /* Portable way to get objects... is get it one by one. */
err = ck->f->C_FindObjects (token->session, &obj, 1, &any); r = ck->f->C_FindObjects (token->session, &obj, 1, &any);
if (err || any == 0) if (r || any == 0)
break; break;
templ[0].type = CKA_VALUE; templ[0].type = CKA_VALUE;
templ[0].pValue = (void *)certificate; templ[0].pValue = (void *)certificate;
templ[0].ulValueLen = sizeof (certificate); templ[0].ulValueLen = sizeof (certificate);
err = ck->f->C_GetAttributeValue (token->session, obj, templ, 1); r = ck->f->C_GetAttributeValue (token->session, obj, templ, 1);
if (err) if (!r)
certificate_available = 0;
else
{ {
certificate_available = 1; certificate_available = 1;
cert_len = templ[0].ulValueLen; break;
puts ("Certificate available:");
for (i = 0; i < cert_len; i++)
{
printf ("%02x", certificate[i]);
if ((i % 16) == 15)
puts ("");
}
puts ("");
} }
} }
err = ck->f->C_FindObjectsFinal (token->session); r = ck->f->C_FindObjectsFinal (token->session);
if (err) if (r)
{ {
return -1; return -1;
} }
} }
if (!certificate_available)
return -1;
certlen = templ[0].ulValueLen;
cert = xtrymalloc (certlen);
if (!cert)
{
return gpg_error_from_syserror ();
}
memcpy (cert, certificate, certlen);
*r_cert = cert;
*r_certlen = certlen;
return 0; return 0;
} }
#endif
static long static long
learn_keys (struct token *token) learn_keys (struct token *token)
@ -717,12 +718,6 @@ learn_keys (struct token *token)
k->flags &= ~KEY_FLAG_NO_PUBKEY; k->flags &= ~KEY_FLAG_NO_PUBKEY;
} }
#if 0
/* Another way to get raw public key material is get it from the
certificate, if available. */
get_certificate (token);
#endif
return 0; return 0;
} }
@ -1358,6 +1353,39 @@ tkd_readkey (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip)
return err; return err;
} }
gpg_error_t
tkd_readcert (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip)
{
gpg_error_t err = 0;
struct key *k;
struct cryptoki *ck = ck_instance;
unsigned long r;
unsigned char *cert;
size_t certlen;
(void)ctrl;
(void)ctx;
if (!ck->handle)
{
err = tkd_init (ctrl, ctx, 0);
if (err)
return err;
}
r = find_key (ck, keygrip, &k);
if (r)
return gpg_error (GPG_ERR_NO_SECKEY);
if (get_certificate (k->token, &cert, &certlen))
return gpg_error (GPG_ERR_NOT_FOUND);
err = assuan_send_data (ctx, cert, certlen);
xfree (cert);
return err;
}
gpg_error_t gpg_error_t
tkd_keyinfo (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip, tkd_keyinfo (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip,
int opt_data, int cap) int opt_data, int cap)

View File

@ -121,6 +121,7 @@ gpg_error_t tkd_readkey (ctrl_t ctrl, assuan_context_t ctx,
const char *keygrip); const char *keygrip);
gpg_error_t tkd_keyinfo (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t tkd_keyinfo (ctrl_t ctrl, assuan_context_t ctx,
const char *keygrip, int opt_data, int cap); const char *keygrip, int opt_data, int cap);
gpg_error_t tkd_readcert (ctrl_t ctrl, assuan_context_t ctx,
const char *keygrip);
#endif /*TKDAEMON_H*/ #endif /*TKDAEMON_H*/