sm: Support signing using ECDSA.

* sm/gpgsm.h (struct certlist_s): Add helper field pk_algo.
* sm/sign.c (gpgsm_sign): Store the public key algo.  Take the hash
algo from the curve.  Improve diagnostic output in verbose mode.
--

GnuPG-bug-id: 4098
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-05-11 18:41:21 +02:00
parent 68b857df13
commit f44d395bdf
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 52 additions and 30 deletions

View File

@ -245,6 +245,7 @@ struct certlist_s
ksba_cert_t cert;
int is_encrypt_to; /* True if the certificate has been set through
the --encrypto-to option. */
int pk_algo; /* The PK_ALGO from CERT or 0 if not yet known. */
int hash_algo; /* Used to track the hash algorithm to use. */
const char *hash_algo_oid; /* And the corresponding OID. */
};

View File

@ -529,6 +529,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
release_signerlist = 1;
}
/* Figure out the hash algorithm to use. We do not want to use the
one for the certificate but if possible an OID for the plain
algorithm. */
@ -537,6 +538,11 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
for (i=0, cl=signerlist; cl; cl = cl->next, i++)
{
const char *oid;
unsigned int nbits;
int pk_algo;
pk_algo = gpgsm_get_key_algo_info (cl->cert, &nbits);
cl->pk_algo = pk_algo;
if (opt.forced_digest_algo)
{
@ -545,7 +551,21 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
}
else
{
oid = ksba_cert_get_digest_algo (cl->cert);
if (pk_algo == GCRY_PK_ECC)
{
/* Map the Curve to a corresponding hash algo. */
if (nbits <= 256)
oid = "2.16.840.1.101.3.4.2.1"; /* sha256 */
else if (nbits <= 384)
oid = "2.16.840.1.101.3.4.2.2"; /* sha384 */
else
oid = "2.16.840.1.101.3.4.2.3"; /* sha512 */
}
else
{
/* For RSA we reuse the hash algo used by the certificate. */
oid = ksba_cert_get_digest_algo (cl->cert);
}
cl->hash_algo = oid ? gcry_md_map_name (oid) : 0;
}
switch (cl->hash_algo)
@ -581,27 +601,23 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
goto leave;
}
{
unsigned int nbits;
int pk_algo = gpgsm_get_key_algo_info (cl->cert, &nbits);
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING, pk_algo,
NULL, nbits, NULL))
{
char kidstr[10+1];
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING, pk_algo,
NULL, nbits, NULL))
{
char kidstr[10+1];
snprintf (kidstr, sizeof kidstr, "0x%08lX",
gpgsm_get_short_fingerprint (cl->cert, NULL));
log_error (_("key %s may not be used for signing in %s mode\n"),
kidstr,
gnupg_compliance_option_string (opt.compliance));
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
goto leave;
}
snprintf (kidstr, sizeof kidstr, "0x%08lX",
gpgsm_get_short_fingerprint (cl->cert, NULL));
log_error (_("key %s may not be used for signing in %s mode\n"),
kidstr,
gnupg_compliance_option_string (opt.compliance));
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
goto leave;
}
}
}
if (opt.verbose)
if (opt.verbose > 1 || opt.debug)
{
for (i=0, cl=signerlist; cl; cl = cl->next, i++)
log_info (_("hash algorithm used for signer %d: %s (%s)\n"),
@ -891,17 +907,23 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
goto leave;
}
rc = 0;
{
int pkalgo = gpgsm_get_key_algo_info (cl->cert, NULL);
buf = xtryasprintf ("%c %d %d 00 %s %s",
detached? 'D':'S',
pkalgo,
cl->hash_algo,
signed_at,
fpr);
if (!buf)
rc = gpg_error_from_syserror ();
}
if (opt.verbose)
{
char *pkalgostr = gpgsm_pubkey_algo_string (cl->cert, NULL);
log_info (_("%s/%s signature using %s key %s\n"),
pubkey_algo_to_string (cl->pk_algo),
gcry_md_algo_name (cl->hash_algo),
pkalgostr, fpr);
xfree (pkalgostr);
}
buf = xtryasprintf ("%c %d %d 00 %s %s",
detached? 'D':'S',
cl->pk_algo,
cl->hash_algo,
signed_at,
fpr);
if (!buf)
rc = gpg_error_from_syserror ();
xfree (fpr);
if (rc)
{
@ -927,7 +949,6 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
audit_log (ctrl->audit, AUDIT_SIGNING_DONE);
log_info ("signature created\n");
leave:
if (rc)
log_error ("error creating signature: %s <%s>\n",