mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-21 14:47:03 +01: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:
parent
7637d39fe2
commit
96577e2e46
@ -211,6 +211,8 @@ gpg_error_t app_help_get_keygrip_string_pk (const void *pk, size_t pklen,
|
||||
int *r_algo);
|
||||
gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip,
|
||||
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);
|
||||
|
||||
|
||||
|
@ -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
|
||||
certificate contained in that file. Returns 0 if the file does not
|
||||
exists or does not contain a certificate. If R_CERTOFF is not
|
||||
|
@ -513,9 +513,7 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
||||
int rc;
|
||||
int advanced = 0;
|
||||
unsigned char *cert = NULL;
|
||||
size_t ncert, n;
|
||||
ksba_cert_t kc = NULL;
|
||||
ksba_sexp_t p;
|
||||
size_t ncert;
|
||||
unsigned char *pk;
|
||||
size_t pklen;
|
||||
|
||||
@ -526,60 +524,38 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
||||
advanced = 1;
|
||||
|
||||
line = skip_options (line);
|
||||
|
||||
line = xstrdup (line); /* Need a copy of the line. */
|
||||
|
||||
/* If the application supports the READKEY function we use that.
|
||||
Otherwise we use the old way by extracting it from the
|
||||
certificate. */
|
||||
rc = app_readkey (ctrl->app_ctx, ctrl, advanced, line, &pk, &pklen);
|
||||
if (!rc)
|
||||
{ /* Yeah, got that key - send it back. */
|
||||
rc = assuan_send_data (ctx, pk, pklen);
|
||||
xfree (pk);
|
||||
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
|
||||
; /* Yeah, got that key - send it back. */
|
||||
else if (gpg_err_code (rc) == GPG_ERR_UNSUPPORTED_OPERATION
|
||||
|| gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
|
||||
{
|
||||
/* Fall back to certificate reading. */
|
||||
rc = app_readcert (ctrl->app_ctx, ctrl, line, &cert, &ncert);
|
||||
if (rc)
|
||||
log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
|
||||
}
|
||||
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)
|
||||
else
|
||||
{
|
||||
log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
|
||||
goto leave;
|
||||
rc = app_help_pubkey_from_cert (cert, ncert, &pk, &pklen);
|
||||
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);
|
||||
rc = assuan_send_data (ctx, p, n);
|
||||
xfree (p);
|
||||
if (!rc && pk && pklen)
|
||||
rc = assuan_send_data (ctx, pk, pklen);
|
||||
|
||||
|
||||
leave:
|
||||
ksba_cert_release (kc);
|
||||
xfree (cert);
|
||||
xfree (pk);
|
||||
xfree (line);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user