1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

sm: Support generation of card-based ECDSA CSR.

* sm/call-agent.c (gpgsm_scd_pksign): Identify type of signing key
and format resulting S-expression accordingly.
* sm/misc.c (transform_sigval): Support ECDSA signatures.
--

Current GpgSM implementation assumes card-based keys are RSA keys.
This patch introduces support for ECDSA keys.

By itself this patch is not sufficient, we also need support
from libksba.

GnuPG-bug-id: 4092
Signed-off-by: Damien Goutte-Gattat <dgouttegattat@incenp.org>
This commit is contained in:
Damien Goutte-Gattat via Gnupg-devel 2018-11-16 01:27:37 +00:00 committed by NIIBE Yutaka
parent b89f1790e0
commit 74e9b579ca
2 changed files with 98 additions and 34 deletions

View file

@ -109,13 +109,16 @@ transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo,
gpg_error_t err;
const unsigned char *buf, *tok;
size_t buflen, toklen;
int depth, last_depth1, last_depth2;
int depth, last_depth1, last_depth2, pkalgo;
int is_pubkey = 0;
const unsigned char *rsa_s = NULL;
size_t rsa_s_len = 0;
const unsigned char *rsa_s, *ecc_r, *ecc_s;
size_t rsa_s_len, ecc_r_len, ecc_s_len;
const char *oid;
gcry_sexp_t sexp;
rsa_s = ecc_r = ecc_s = NULL;
rsa_s_len = ecc_r_len = ecc_s_len = 0;
*r_newsigval = NULL;
if (r_newsigvallen)
*r_newsigvallen = 0;
@ -137,7 +140,13 @@ transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo,
return err;
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
return err;
if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen))
if (!tok)
return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
if (toklen == 3 && !memcmp ("rsa", tok, 3))
pkalgo = GCRY_PK_RSA;
else if (toklen == 5 && !memcmp ("ecdsa", tok, 5))
pkalgo = GCRY_PK_ECC;
else
return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
last_depth1 = depth;
@ -150,16 +159,27 @@ transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo,
return err;
if (tok && toklen == 1)
{
const unsigned char **mpi;
size_t *mpi_len;
const unsigned char **mpi = NULL;
size_t *mpi_len = NULL;
switch (*tok)
{
case 's': mpi = &rsa_s; mpi_len = &rsa_s_len; break;
case 's':
if (pkalgo == GCRY_PK_RSA)
{
mpi = &rsa_s;
mpi_len = &rsa_s_len;
}
else if (pkalgo == GCRY_PK_ECC)
{
mpi = &ecc_s;
mpi_len = &ecc_s_len;
}
break;
case 'r': mpi = &ecc_r; mpi_len = &ecc_r_len; break;
default: mpi = NULL; mpi_len = NULL; break;
}
if (mpi && *mpi)
return gpg_error (GPG_ERR_DUP_VALUE);
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
return err;
@ -182,33 +202,52 @@ transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo,
return err;
/* Map the hash algorithm to an OID. */
switch (mdalgo)
switch (mdalgo | (pkalgo << 8))
{
case GCRY_MD_SHA1:
case GCRY_MD_SHA1 | (GCRY_PK_RSA << 8):
oid = "1.2.840.113549.1.1.5"; /* sha1WithRSAEncryption */
break;
case GCRY_MD_SHA256:
case GCRY_MD_SHA256 | (GCRY_PK_RSA << 8):
oid = "1.2.840.113549.1.1.11"; /* sha256WithRSAEncryption */
break;
case GCRY_MD_SHA384:
case GCRY_MD_SHA384 | (GCRY_PK_RSA << 8):
oid = "1.2.840.113549.1.1.12"; /* sha384WithRSAEncryption */
break;
case GCRY_MD_SHA512:
case GCRY_MD_SHA512 | (GCRY_PK_RSA << 8):
oid = "1.2.840.113549.1.1.13"; /* sha512WithRSAEncryption */
break;
case GCRY_MD_SHA224 | (GCRY_PK_ECC << 8):
oid = "1.2.840.10045.4.3.1"; /* ecdsa-with-sha224 */
break;
case GCRY_MD_SHA256 | (GCRY_PK_ECC << 8):
oid = "1.2.840.10045.4.3.2"; /* ecdsa-with-sha256 */
break;
case GCRY_MD_SHA384 | (GCRY_PK_ECC << 8):
oid = "1.2.840.10045.4.3.3"; /* ecdsa-with-sha384 */
break;
case GCRY_MD_SHA512 | (GCRY_PK_ECC << 8):
oid = "1.2.840.10045.4.3.4"; /* ecdsa-with-sha512 */
break;
default:
return gpg_error (GPG_ERR_DIGEST_ALGO);
}
if (rsa_s && !is_pubkey)
err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s(s%b)))",
oid, (int)rsa_s_len, rsa_s);
else
if (is_pubkey)
err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s))", oid);
else if (pkalgo == GCRY_PK_RSA)
err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s(s%b)))", oid,
(int)rsa_s_len, rsa_s);
else if (pkalgo == GCRY_PK_ECC)
err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s(r%b)(s%b)))", oid,
(int)ecc_r_len, ecc_r, (int)ecc_s_len, ecc_s);
if (err)
return err;
err = make_canon_sexp (sexp, r_newsigval, r_newsigvallen);