1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-09-20 14:51:42 +02:00

Implement READKEY command.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2023-03-08 14:30:33 +09:00
parent 86d1d3ecd2
commit c3dee068f9
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054
3 changed files with 60 additions and 148 deletions

View File

@ -204,110 +204,23 @@ cmd_slotlist (assuan_context_t ctx, char *line)
} }
static const char hlp_readkey[] = static const char hlp_readkey[] =
"READKEY [--format=advanced|ssh] [--info[-only]] <keygrip>\n" "READKEY [--info[-only]] <keygrip>\n"
"\n" "\n"
"Return the public key for the given cert or key ID as a standard\n" "Return the public key for the given KEYGRIP, as a standard\n"
"S-expression. With --format option, it may be returned in advanced\n" "S-expression.";
"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.";
static gpg_error_t static gpg_error_t
cmd_readkey (assuan_context_t ctx, char *line) cmd_readkey (assuan_context_t ctx, char *line)
{ {
ctrl_t ctrl = assuan_get_pointer (ctx); ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err; 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; 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); keygrip = skip_options (line);
if (strlen (keygrip) != 40) if (strlen (keygrip) != 40)
err = gpg_error (GPG_ERR_INV_ID); err = gpg_error (GPG_ERR_INV_ID);
err = token_readkey (ctrl, ctx, keygrip, opt_info, &pk, &pklen); err = token_readkey (ctrl, ctx, keygrip);
if (err)
goto leave;
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; return err;
} }

View File

@ -54,10 +54,10 @@ enum key_type {
KEY_EDDSA, KEY_EDDSA,
}; };
#define KEY_FLAGS_VALID (1 << 0) #define KEY_FLAG_VALID (1 << 0)
#define KEY_FLAGS_NO_PUBKEY (1 << 1) #define KEY_FLAG_NO_PUBKEY (1 << 1)
#define KEY_FLAGS_USAGE_SIGN (1 << 2) #define KEY_FLAG_USAGE_SIGN (1 << 2)
#define KEY_FLAGS_USAGE_DECRYPT (1 << 3) #define KEY_FLAG_USAGE_DECRYPT (1 << 3)
struct key { struct key {
struct token *token; /* Back pointer. */ 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); err = ck->f->C_GetAttributeValue (token->session, obj, templ, 2);
if (err) if (err)
{ {
k->flags |= KEY_FLAGS_NO_PUBKEY; k->flags |= KEY_FLAG_NO_PUBKEY;
return 1; return 1;
} }
k->flags |= KEY_FLAGS_VALID; k->flags |= KEY_FLAG_VALID;
k->flags &= ~KEY_FLAGS_NO_PUBKEY; k->flags &= ~KEY_FLAG_NO_PUBKEY;
if ((modulus[0] & 0x80)) if ((modulus[0] & 0x80))
{ {
memmove (modulus+1, modulus, templ[0].ulValueLen); 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); err = ck->f->C_GetAttributeValue (token->session, obj, templ, 2);
if (err) if (err)
{ {
k->flags |= KEY_FLAGS_NO_PUBKEY; k->flags |= KEY_FLAG_NO_PUBKEY;
return 1; return 1;
} }
k->flags |= KEY_FLAGS_VALID; k->flags |= KEY_FLAG_VALID;
k->flags &= ~KEY_FLAGS_NO_PUBKEY; k->flags &= ~KEY_FLAG_NO_PUBKEY;
/* Found an ECC key. */ /* Found an ECC key. */
log_debug ("ECC: %ld %ld\n", log_debug ("ECC: %ld %ld\n",
templ[0].ulValueLen, templ[0].ulValueLen,
@ -444,7 +444,7 @@ examine_public_key (struct token *token, struct key *k, unsigned long keytype,
if (!err) if (!err)
{ {
/* XXX: Scute has the attribute, but not set. */ /* 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; 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); err = ck->f->C_GetAttributeValue (token->session, obj, templ, 1);
if (!err && supported) if (!err && supported)
{ {
k->flags |= KEY_FLAGS_USAGE_DECRYPT; k->flags |= KEY_FLAG_USAGE_DECRYPT;
} }
return 0; return 0;
@ -599,7 +599,7 @@ check_public_keys (struct token *token)
{ {
k = &token->key_list[i]; 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 && k->label_len == templ[0].ulValueLen
&& memcmp (label, k->label, k->label_len) == 0 && memcmp (label, k->label, k->label_len) == 0
&& ((keytype == CKK_RSA && k->key_type == KEY_RSA) && ((keytype == CKK_RSA && k->key_type == KEY_RSA)
@ -719,8 +719,8 @@ learn_keys (struct token *token)
{ {
struct key *k = &token->key_list[i]; struct key *k = &token->key_list[i];
if ((k->flags & KEY_FLAGS_NO_PUBKEY)) if ((k->flags & KEY_FLAG_NO_PUBKEY))
k->flags &= ~KEY_FLAGS_NO_PUBKEY; k->flags &= ~KEY_FLAG_NO_PUBKEY;
} }
#if 0 #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]; struct key *k = &token->key_list[j];
if ((k->flags & KEY_FLAGS_VALID) == 0) if ((k->flags & KEY_FLAG_VALID) == 0)
continue; continue;
if (memcmp (k->keygrip, keygrip, 40) == 0) 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->j = 0;
iter->mask = 0; iter->mask = 0;
if (cap == GCRY_PK_USAGE_SIGN) 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) else if (cap == GCRY_PK_USAGE_ENCR)
iter->mask = KEY_FLAGS_USAGE_DECRYPT; iter->mask = KEY_FLAG_USAGE_DECRYPT;
else else
iter->mask = KEY_FLAGS_USAGE_SIGN | KEY_FLAGS_USAGE_DECRYPT; iter->mask = KEY_FLAG_USAGE_SIGN | KEY_FLAG_USAGE_DECRYPT;
} }
static int static int
@ -830,7 +830,7 @@ iter_find_key (struct iter_key *iter, struct key **r_key)
if (token && iter->j < token->num_keys) if (token && iter->j < token->num_keys)
{ {
k = &token->key_list[iter->j++]; 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 */ /* Found */
*r_key = k; *r_key = k;
@ -1120,14 +1120,43 @@ token_sign (ctrl_t ctrl, assuan_context_t ctx,
return err; 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 gpg_error_t
token_readkey (ctrl_t ctrl, assuan_context_t ctx, token_readkey (ctrl_t ctrl, assuan_context_t ctx, const char *keygrip)
const char *keygrip, int opt_info,
unsigned char **r_pk,
size_t *r_pklen)
{ {
gpg_error_t err = 0; gpg_error_t err = 0;
struct key *k;
struct cryptoki *ck = ck_instance;
unsigned long r;
(void)ctrl; (void)ctrl;
r = find_key (ck, keygrip, &k);
if (r)
return gpg_error (GPG_ERR_NO_SECKEY);
return err; return err;
} }
@ -1147,21 +1176,7 @@ token_keyinfo (ctrl_t ctrl, const char *keygrip, int opt_data, int cap)
if (r) if (r)
return gpg_error (GPG_ERR_NO_SECKEY); return gpg_error (GPG_ERR_NO_SECKEY);
if ((k->flags & KEY_FLAGS_USAGE_SIGN)) usage = get_usage_string (k);
{
if ((k->flags & KEY_FLAGS_USAGE_DECRYPT))
usage = "se";
else
usage = "s";
}
else
{
if ((k->flags & KEY_FLAGS_USAGE_DECRYPT))
usage = "e";
else
usage = "-";
}
send_keyinfo (ctrl, opt_data, keygrip, send_keyinfo (ctrl, opt_data, keygrip,
k->label_len ? (const char *)k->label : "-", k->label_len ? (const char *)k->label : "-",
k->id_len ? (const char *)k->id : "-", 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); iter_find_key_setup (&iter, ck, cap);
while (iter_find_key (&iter, &k)) while (iter_find_key (&iter, &k))
{ {
if ((k->flags & KEY_FLAGS_USAGE_SIGN)) usage = get_usage_string (k);
{
if ((k->flags & KEY_FLAGS_USAGE_DECRYPT))
usage = "se";
else
usage = "s";
}
else
{
if ((k->flags & KEY_FLAGS_USAGE_DECRYPT))
usage = "e";
else
usage = "-";
}
send_keyinfo (ctrl, opt_data, k->keygrip, send_keyinfo (ctrl, opt_data, k->keygrip,
k->label_len ? (const char *)k->label : "-", k->label_len ? (const char *)k->label : "-",
k->id_len ? (const char *)k->id : "-", k->id_len ? (const char *)k->id : "-",

View File

@ -115,9 +115,7 @@ gpg_error_t token_sign (ctrl_t ctrl, assuan_context_t ctx,
unsigned char **r_outdata, unsigned char **r_outdata,
size_t *r_outdatalen); size_t *r_outdatalen);
gpg_error_t token_readkey (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t token_readkey (ctrl_t ctrl, assuan_context_t ctx,
const char *keygrip, int opt_info, const char *keygrip);
unsigned char **r_pk,
size_t *r_pklen);
gpg_error_t token_keyinfo (ctrl_t ctrl, gpg_error_t token_keyinfo (ctrl_t ctrl,
const char *keygrip, int opt_data, int cap); const char *keygrip, int opt_data, int cap);