From 30d4eb97db8562bb62367a66003fae7fa9107938 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 22 Mar 2023 15:28:56 +0900 Subject: [PATCH] tkd: Support READCERT command. Signed-off-by: NIIBE Yutaka --- tkd/command.c | 26 ++++++++++++++ tkd/pkcs11.c | 98 ++++++++++++++++++++++++++++++++------------------ tkd/tkdaemon.h | 3 +- 3 files changed, 91 insertions(+), 36 deletions(-) diff --git a/tkd/command.c b/tkd/command.c index a78ede3b7..2a583ace2 100644 --- a/tkd/command.c +++ b/tkd/command.c @@ -297,6 +297,31 @@ cmd_readkey (assuan_context_t ctx, char *line) return err; } +static const char hlp_readcert[] = + "READCERT \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[] = "PKSIGN [--hash=[sha{256,384,512}|none]] \n" "\n" @@ -469,6 +494,7 @@ register_commands (assuan_context_t ctx) { "PKSIGN", cmd_pksign, hlp_pksign }, { "KILLTKD", cmd_killtkd, hlp_killtkd }, { "KEYINFO", cmd_keyinfo, hlp_keyinfo }, + { "READCERT", cmd_readcert, hlp_readcert }, { "GETINFO", cmd_getinfo, hlp_getinfo }, { "RESTART", cmd_restart, hlp_restart }, { NULL } diff --git a/tkd/pkcs11.c b/tkd/pkcs11.c index 33c19ecdd..c89113cab 100644 --- a/tkd/pkcs11.c +++ b/tkd/pkcs11.c @@ -622,72 +622,73 @@ check_public_keys (struct token *token) return 0; } -#if 0 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 ck_attribute templ[1]; unsigned long class; unsigned char certificate[4096]; - unsigned long cert_len; - int certificate_available; - - ck_object_handle_t obj; - int i; + int certificate_available = 0; + unsigned char *cert; + size_t certlen; class = CKO_CERTIFICATE; 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) + r = ck->f->C_FindObjectsInit (token->session, templ, 1); + if (!r) { + ck_object_handle_t obj; + while (TRUE) { unsigned long any; /* 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) + r = ck->f->C_FindObjects (token->session, &obj, 1, &any); + if (r || any == 0) break; templ[0].type = CKA_VALUE; templ[0].pValue = (void *)certificate; templ[0].ulValueLen = sizeof (certificate); - err = ck->f->C_GetAttributeValue (token->session, obj, templ, 1); - if (err) - certificate_available = 0; - else + r = ck->f->C_GetAttributeValue (token->session, obj, templ, 1); + if (!r) { certificate_available = 1; - cert_len = templ[0].ulValueLen; - - puts ("Certificate available:"); - for (i = 0; i < cert_len; i++) - { - printf ("%02x", certificate[i]); - if ((i % 16) == 15) - puts (""); - } - puts (""); + break; } } - err = ck->f->C_FindObjectsFinal (token->session); - if (err) + r = ck->f->C_FindObjectsFinal (token->session); + if (r) { 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; } -#endif static long learn_keys (struct token *token) @@ -717,12 +718,6 @@ learn_keys (struct token *token) 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; } @@ -1358,6 +1353,39 @@ tkd_readkey (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip) 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 tkd_keyinfo (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip, int opt_data, int cap) diff --git a/tkd/tkdaemon.h b/tkd/tkdaemon.h index 5d2a15fea..181cd71ef 100644 --- a/tkd/tkdaemon.h +++ b/tkd/tkdaemon.h @@ -121,6 +121,7 @@ gpg_error_t tkd_readkey (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip); gpg_error_t tkd_keyinfo (ctrl_t ctrl, assuan_context_t ctx, 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*/