From c3dee068f9bd126ccc8f205819c1b25862591bb4 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 8 Mar 2023 14:30:33 +0900 Subject: [PATCH] Implement READKEY command. Signed-off-by: NIIBE Yutaka --- tkd/command.c | 95 ++---------------------------------------- tkd/pkcs11.c | 109 +++++++++++++++++++++++++------------------------ tkd/tkdaemon.h | 4 +- 3 files changed, 60 insertions(+), 148 deletions(-) diff --git a/tkd/command.c b/tkd/command.c index f0f528462..772b3d3e4 100644 --- a/tkd/command.c +++ b/tkd/command.c @@ -204,110 +204,23 @@ cmd_slotlist (assuan_context_t ctx, char *line) } static const char hlp_readkey[] = - "READKEY [--format=advanced|ssh] [--info[-only]] \n" + "READKEY [--info[-only]] \n" "\n" - "Return the public key for the given cert or key ID as a standard\n" - "S-expression. With --format option, it may be returned in advanced\n" - "S-expression format, or SSH format. With --info a KEYPAIRINFO\n" - "status line is also emitted; with --info-only the regular output is\n" - "suppressed."; + "Return the public key for the given KEYGRIP, as a standard\n" + "S-expression."; static gpg_error_t cmd_readkey (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); gpg_error_t err; - int advanced = 0; - int ssh = 0; - int opt_info = 0; - int opt_nokey = 0; - unsigned char *pk = NULL; - size_t pklen; const char *keygrip; - if (has_option (line, "--format=advanced")) - advanced = 1; - if (has_option (line, "--format=ssh")) - ssh = 1; - if (has_option (line, "--info")) - opt_info = 1; - if (has_option (line, "--info-only")) - opt_info = opt_nokey = 1; - keygrip = skip_options (line); if (strlen (keygrip) != 40) err = gpg_error (GPG_ERR_INV_ID); - err = token_readkey (ctrl, ctx, keygrip, opt_info, &pk, &pklen); - if (err) - goto leave; + err = token_readkey (ctrl, ctx, keygrip); - if (opt_nokey) - ; - else if (ssh) - { - estream_t stream = NULL; - gcry_sexp_t s_key; - void *buf = NULL; - size_t buflen; - - stream = es_fopenmem (0, "r+b"); - if (!stream) - { - err = gpg_error_from_syserror (); - goto leave; - } - - err = gcry_sexp_new (&s_key, pk, pklen, 0); - if (err) - { - es_fclose (stream); - goto leave; - } - - err = ssh_public_key_in_base64 (s_key, stream, "(none)"); - if (err) - { - gcry_sexp_release (s_key); - es_fclose (stream); - goto leave; - } - - err = es_fclose_snatch (stream, &buf, &buflen); - gcry_sexp_release (s_key); - if (!err) - err = assuan_send_data (ctx, buf, buflen); - } - else if (advanced) - { - gcry_sexp_t s_key; - unsigned char *pkadv; - size_t pkadvlen; - - err = gcry_sexp_new (&s_key, pk, pklen, 0); - if (err) - goto leave; - - pkadvlen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_ADVANCED, NULL, 0); - pkadv = xtrymalloc (pkadvlen); - if (!pkadv) - { - err = gpg_error_from_syserror (); - gcry_sexp_release (s_key); - goto leave; - } - log_assert (pkadvlen); - - gcry_sexp_sprint (s_key, GCRYSEXP_FMT_ADVANCED, pkadv, pkadvlen); - gcry_sexp_release (s_key); - /* (One less to adjust for the trailing '\0') */ - err = assuan_send_data (ctx, pkadv, pkadvlen-1); - xfree (pkadv); - } - else - err = assuan_send_data (ctx, pk, pklen); - - leave: - xfree (pk); return err; } diff --git a/tkd/pkcs11.c b/tkd/pkcs11.c index 79ca8f7d6..21ef32875 100644 --- a/tkd/pkcs11.c +++ b/tkd/pkcs11.c @@ -54,10 +54,10 @@ enum key_type { KEY_EDDSA, }; -#define KEY_FLAGS_VALID (1 << 0) -#define KEY_FLAGS_NO_PUBKEY (1 << 1) -#define KEY_FLAGS_USAGE_SIGN (1 << 2) -#define KEY_FLAGS_USAGE_DECRYPT (1 << 3) +#define KEY_FLAG_VALID (1 << 0) +#define KEY_FLAG_NO_PUBKEY (1 << 1) +#define KEY_FLAG_USAGE_SIGN (1 << 2) +#define KEY_FLAG_USAGE_DECRYPT (1 << 3) struct key { struct token *token; /* Back pointer. */ @@ -346,12 +346,12 @@ examine_public_key (struct token *token, struct key *k, unsigned long keytype, err = ck->f->C_GetAttributeValue (token->session, obj, templ, 2); if (err) { - k->flags |= KEY_FLAGS_NO_PUBKEY; + k->flags |= KEY_FLAG_NO_PUBKEY; return 1; } - k->flags |= KEY_FLAGS_VALID; - k->flags &= ~KEY_FLAGS_NO_PUBKEY; + k->flags |= KEY_FLAG_VALID; + k->flags &= ~KEY_FLAG_NO_PUBKEY; if ((modulus[0] & 0x80)) { memmove (modulus+1, modulus, templ[0].ulValueLen); @@ -390,12 +390,12 @@ examine_public_key (struct token *token, struct key *k, unsigned long keytype, err = ck->f->C_GetAttributeValue (token->session, obj, templ, 2); if (err) { - k->flags |= KEY_FLAGS_NO_PUBKEY; + k->flags |= KEY_FLAG_NO_PUBKEY; return 1; } - k->flags |= KEY_FLAGS_VALID; - k->flags &= ~KEY_FLAGS_NO_PUBKEY; + k->flags |= KEY_FLAG_VALID; + k->flags &= ~KEY_FLAG_NO_PUBKEY; /* Found an ECC key. */ log_debug ("ECC: %ld %ld\n", templ[0].ulValueLen, @@ -444,7 +444,7 @@ examine_public_key (struct token *token, struct key *k, unsigned long keytype, if (!err) { /* XXX: Scute has the attribute, but not set. */ - k->flags |= KEY_FLAGS_USAGE_SIGN; + k->flags |= KEY_FLAG_USAGE_SIGN; } templ[0].type = CKA_DECRYPT; @@ -454,7 +454,7 @@ examine_public_key (struct token *token, struct key *k, unsigned long keytype, err = ck->f->C_GetAttributeValue (token->session, obj, templ, 1); if (!err && supported) { - k->flags |= KEY_FLAGS_USAGE_DECRYPT; + k->flags |= KEY_FLAG_USAGE_DECRYPT; } return 0; @@ -599,7 +599,7 @@ check_public_keys (struct token *token) { k = &token->key_list[i]; - if ((k->flags & KEY_FLAGS_NO_PUBKEY) + if ((k->flags & KEY_FLAG_NO_PUBKEY) && k->label_len == templ[0].ulValueLen && memcmp (label, k->label, k->label_len) == 0 && ((keytype == CKK_RSA && k->key_type == KEY_RSA) @@ -719,8 +719,8 @@ learn_keys (struct token *token) { struct key *k = &token->key_list[i]; - if ((k->flags & KEY_FLAGS_NO_PUBKEY)) - k->flags &= ~KEY_FLAGS_NO_PUBKEY; + if ((k->flags & KEY_FLAG_NO_PUBKEY)) + k->flags &= ~KEY_FLAG_NO_PUBKEY; } #if 0 @@ -751,7 +751,7 @@ find_key (struct cryptoki *ck, const char *keygrip, struct key **r_key) { struct key *k = &token->key_list[j]; - if ((k->flags & KEY_FLAGS_VALID) == 0) + if ((k->flags & KEY_FLAG_VALID) == 0) continue; if (memcmp (k->keygrip, keygrip, 40) == 0) @@ -783,11 +783,11 @@ iter_find_key_setup (struct iter_key *iter, struct cryptoki *ck, int cap) iter->j = 0; iter->mask = 0; if (cap == GCRY_PK_USAGE_SIGN) - iter->mask |= KEY_FLAGS_USAGE_SIGN; + iter->mask |= KEY_FLAG_USAGE_SIGN; else if (cap == GCRY_PK_USAGE_ENCR) - iter->mask = KEY_FLAGS_USAGE_DECRYPT; + iter->mask = KEY_FLAG_USAGE_DECRYPT; else - iter->mask = KEY_FLAGS_USAGE_SIGN | KEY_FLAGS_USAGE_DECRYPT; + iter->mask = KEY_FLAG_USAGE_SIGN | KEY_FLAG_USAGE_DECRYPT; } static int @@ -830,7 +830,7 @@ iter_find_key (struct iter_key *iter, struct key **r_key) if (token && iter->j < token->num_keys) { k = &token->key_list[iter->j++]; - if ((k->flags & KEY_FLAGS_VALID) && (k->flags & iter->mask)) + if ((k->flags & KEY_FLAG_VALID) && (k->flags & iter->mask)) { /* Found */ *r_key = k; @@ -1120,14 +1120,43 @@ token_sign (ctrl_t ctrl, assuan_context_t ctx, return err; } +static const char * +get_usage_string (struct key *k) +{ + const char *usage = NULL; + + if ((k->flags & KEY_FLAG_USAGE_SIGN)) + { + if ((k->flags & KEY_FLAG_USAGE_DECRYPT)) + usage = "se"; + else + usage = "s"; + } + else + { + if ((k->flags & KEY_FLAG_USAGE_DECRYPT)) + usage = "e"; + else + usage = "-"; + } + + return usage; +} + gpg_error_t -token_readkey (ctrl_t ctrl, assuan_context_t ctx, - const char *keygrip, int opt_info, - unsigned char **r_pk, - size_t *r_pklen) +token_readkey (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; + (void)ctrl; + + r = find_key (ck, keygrip, &k); + if (r) + return gpg_error (GPG_ERR_NO_SECKEY); + return err; } @@ -1147,21 +1176,7 @@ token_keyinfo (ctrl_t ctrl, const char *keygrip, int opt_data, int cap) if (r) return gpg_error (GPG_ERR_NO_SECKEY); - if ((k->flags & KEY_FLAGS_USAGE_SIGN)) - { - if ((k->flags & KEY_FLAGS_USAGE_DECRYPT)) - usage = "se"; - else - usage = "s"; - } - else - { - if ((k->flags & KEY_FLAGS_USAGE_DECRYPT)) - usage = "e"; - else - usage = "-"; - } - + usage = get_usage_string (k); send_keyinfo (ctrl, opt_data, keygrip, k->label_len ? (const char *)k->label : "-", k->id_len ? (const char *)k->id : "-", @@ -1174,21 +1189,7 @@ token_keyinfo (ctrl_t ctrl, const char *keygrip, int opt_data, int cap) iter_find_key_setup (&iter, ck, cap); while (iter_find_key (&iter, &k)) { - if ((k->flags & KEY_FLAGS_USAGE_SIGN)) - { - if ((k->flags & KEY_FLAGS_USAGE_DECRYPT)) - usage = "se"; - else - usage = "s"; - } - else - { - if ((k->flags & KEY_FLAGS_USAGE_DECRYPT)) - usage = "e"; - else - usage = "-"; - } - + usage = get_usage_string (k); send_keyinfo (ctrl, opt_data, k->keygrip, k->label_len ? (const char *)k->label : "-", k->id_len ? (const char *)k->id : "-", diff --git a/tkd/tkdaemon.h b/tkd/tkdaemon.h index 528117af1..85873ecbc 100644 --- a/tkd/tkdaemon.h +++ b/tkd/tkdaemon.h @@ -115,9 +115,7 @@ gpg_error_t token_sign (ctrl_t ctrl, assuan_context_t ctx, unsigned char **r_outdata, size_t *r_outdatalen); gpg_error_t token_readkey (ctrl_t ctrl, assuan_context_t ctx, - const char *keygrip, int opt_info, - unsigned char **r_pk, - size_t *r_pklen); + const char *keygrip); gpg_error_t token_keyinfo (ctrl_t ctrl, const char *keygrip, int opt_data, int cap);