1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-04-17 15:44:34 +02:00

scd: Rewrite READKEY to allow for compressed points.

* scd/app-help.c (app_help_pubkey_from_cert): New.  Taken from 2.3.
* scd/command.c (cmd_readkey): Rewrite using new helper.
--

Actually the readkey functions needs to return the uncompressed points
but if there is no readkey function, like in app-p15.c, readcert is
used and here we need to extract and the key and uncompress the point.

Noet that the --advanced flag did not and still does not work if the
key is fetched via readcert.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2021-04-29 16:05:19 +02:00
parent 7637d39fe2
commit 96577e2e46
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 75 additions and 43 deletions

View File

@ -211,6 +211,8 @@ gpg_error_t app_help_get_keygrip_string_pk (const void *pk, size_t pklen,
int *r_algo); int *r_algo);
gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip, gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip,
gcry_sexp_t *r_pkey, int *r_algo); gcry_sexp_t *r_pkey, int *r_algo);
gpg_error_t app_help_pubkey_from_cert (const void *cert, size_t certlen,
unsigned char **r_pk, size_t *r_pklen);
size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff); size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff);

View File

@ -122,6 +122,60 @@ app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip,
} }
/* Get the public key from the binary encoded (CERT,CERTLEN). */
gpg_error_t
app_help_pubkey_from_cert (const void *cert, size_t certlen,
unsigned char **r_pk, size_t *r_pklen)
{
gpg_error_t err;
ksba_cert_t kc;
unsigned char *pk, *fixed_pk;
size_t pklen, fixed_pklen;
*r_pk = NULL;
*r_pklen = 0;
pk = NULL; /*(avoid cc warning)*/
err = ksba_cert_new (&kc);
if (err)
return err;
err = ksba_cert_init_from_mem (kc, cert, certlen);
if (err)
goto leave;
pk = ksba_cert_get_public_key (kc);
if (!pk)
{
err = gpg_error (GPG_ERR_NO_PUBKEY);
goto leave;
}
pklen = gcry_sexp_canon_len (pk, 0, NULL, &err);
err = uncompress_ecc_q_in_canon_sexp (pk, pklen, &fixed_pk, &fixed_pklen);
if (err)
goto leave;
if (fixed_pk)
{
ksba_free (pk); pk = NULL;
pk = fixed_pk;
pklen = fixed_pklen;
}
leave:
if (!err)
{
*r_pk = pk;
*r_pklen = pklen;
}
else
ksba_free (pk);
ksba_cert_release (kc);
return err;
}
/* Given the SLOT and the File ID FID, return the length of the /* Given the SLOT and the File ID FID, return the length of the
certificate contained in that file. Returns 0 if the file does not certificate contained in that file. Returns 0 if the file does not
exists or does not contain a certificate. If R_CERTOFF is not exists or does not contain a certificate. If R_CERTOFF is not

View File

@ -513,9 +513,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
int rc; int rc;
int advanced = 0; int advanced = 0;
unsigned char *cert = NULL; unsigned char *cert = NULL;
size_t ncert, n; size_t ncert;
ksba_cert_t kc = NULL;
ksba_sexp_t p;
unsigned char *pk; unsigned char *pk;
size_t pklen; size_t pklen;
@ -526,60 +524,38 @@ cmd_readkey (assuan_context_t ctx, char *line)
advanced = 1; advanced = 1;
line = skip_options (line); line = skip_options (line);
line = xstrdup (line); /* Need a copy of the line. */ line = xstrdup (line); /* Need a copy of the line. */
/* If the application supports the READKEY function we use that. /* If the application supports the READKEY function we use that.
Otherwise we use the old way by extracting it from the Otherwise we use the old way by extracting it from the
certificate. */ certificate. */
rc = app_readkey (ctrl->app_ctx, ctrl, advanced, line, &pk, &pklen); rc = app_readkey (ctrl->app_ctx, ctrl, advanced, line, &pk, &pklen);
if (!rc) if (!rc)
{ /* Yeah, got that key - send it back. */ ; /* Yeah, got that key - send it back. */
rc = assuan_send_data (ctx, pk, pklen); else if (gpg_err_code (rc) == GPG_ERR_UNSUPPORTED_OPERATION
xfree (pk); || gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
xfree (line);
line = NULL;
goto leave;
}
if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
else
{ {
/* Fall back to certificate reading. */
rc = app_readcert (ctrl->app_ctx, ctrl, line, &cert, &ncert); rc = app_readcert (ctrl->app_ctx, ctrl, line, &cert, &ncert);
if (rc) if (rc)
log_error ("app_readcert failed: %s\n", gpg_strerror (rc)); log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
} else
xfree (line);
line = NULL;
if (rc)
goto leave;
rc = ksba_cert_new (&kc);
if (rc)
goto leave;
rc = ksba_cert_init_from_mem (kc, cert, ncert);
if (rc)
{ {
log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc)); rc = app_help_pubkey_from_cert (cert, ncert, &pk, &pklen);
goto leave; if (rc)
log_error ("failed to parse the certificate: %s\n",
gpg_strerror (rc));
} }
p = ksba_cert_get_public_key (kc);
if (!p)
{
rc = gpg_error (GPG_ERR_NO_PUBKEY);
goto leave;
} }
else
log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!rc && pk && pklen)
rc = assuan_send_data (ctx, p, n); rc = assuan_send_data (ctx, pk, pklen);
xfree (p);
leave:
ksba_cert_release (kc);
xfree (cert); xfree (cert);
xfree (pk);
xfree (line);
return rc; return rc;
} }