1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

scd:p15: Allow signing for CVISION cards

* scd/app-p15.c (do_sign): Add code for Starcos 3.2 and the CVISION
product.
--

The code for the Starcos cards has been implemented according to the
3.52 manual However, this does not work with my test cards.  Protocol
analysis shows that decryption can be used for the cryptovision
product.  Thus we do it the same for now.
This commit is contained in:
Werner Koch 2024-01-10 14:35:26 +01:00
parent 6233a17ac9
commit 275ced5067
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B

View File

@ -5513,6 +5513,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
unsigned char oidbuf[64]; unsigned char oidbuf[64];
size_t oidbuflen; size_t oidbuflen;
size_t n; size_t n;
int i;
unsigned char *indata_buffer = NULL; /* Malloced helper. */ unsigned char *indata_buffer = NULL; /* Malloced helper. */
(void)ctrl; (void)ctrl;
@ -5610,7 +5611,6 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
{ {
unsigned int framelen; unsigned int framelen;
unsigned char *frame; unsigned char *frame;
int i;
framelen = (prkdf->keynbits+7) / 8; framelen = (prkdf->keynbits+7) / 8;
if (!framelen) if (!framelen)
@ -5685,6 +5685,23 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
memcpy (frame, indata, indatalen); memcpy (frame, indata, indatalen);
framelen = indatalen; framelen = indatalen;
} }
else if (hashalgo && IS_STARCOS_3 (app)
&& app->app_local->card_product != CARD_PRODUCT_CVISION)
{
/* For Starcos we need the plain hash w/o the prefix. */
/* Note: This has never been tested because the cvision
* sample cards seem not to work this way. */
if (indatalen != oidbuflen + digestlen
|| memcmp (indata, oidbuf, oidbuflen))
{
log_error ("p15: non-matching input data for Starcos:"
" hash=%d len=%zu\n", hashalgo, indatalen);
err = gpg_error (GPG_ERR_INV_VALUE);
goto leave;
}
framelen = indatalen - oidbuflen;
memcpy (frame, (const char*)indata + oidbuflen, framelen);
}
else else
{ {
n = 0; n = 0;
@ -5774,7 +5791,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
else else
{ {
/* The D-TRUST Card 4.x doesn't support setting a security /* The D-TRUST Card 4.x doesn't support setting a security
* environment, at least as specified in the specs. Insted a * environment, at least as specified in the specs. Instead a
* predefined security environment has to be loaded depending on the * predefined security environment has to be loaded depending on the
* cipher and message digest used. The spec states SE-ID 0x25 for * cipher and message digest used. The spec states SE-ID 0x25 for
* SHA256, 0x26 for SHA384 and 0x27 for SHA512, when using PKCS#1 * SHA256, 0x26 for SHA384 and 0x27 for SHA512, when using PKCS#1
@ -5788,6 +5805,61 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
0xf3, 0x25, NULL, 0); 0xf3, 0x25, NULL, 0);
} }
} }
else if (app->app_local->card_product == CARD_PRODUCT_CVISION)
{
/* I can't make the Starcos 3.2 work the correct way, so let's
* make them work in the same way the cryptovision product seems
* to do it: Use the plain RSA decryption instead. */
unsigned char mse[9];
i = 0;
mse[i++] = 0x84; /* Key reference. */
mse[i++] = 1;
mse[i++] = prkdf->key_reference;
mse[i++] = 0x89; /* Algorithm reference (BCD encoded). */
mse[i++] = 2;
mse[i++] = 0x11; /* RSA no padding (1 1 3 0). */
mse[i++] = 0x30;
log_assert (i <= DIM(mse));
err = iso7816_manage_security_env (app_get_slot (app), 0x41, 0xB8,
mse, i);
}
else if (prkdf->key_reference_valid && IS_STARCOS_3 (app))
{
unsigned char mse[9];
i = 0;
if (prkdf->is_ecc)
{
log_info ("Note: ECC is not yet implemented for Starcos 3 cards\n");
err = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
}
else
{
err = 0;
mse[i++] = 0x84; /* Key reference. */
mse[i++] = 1;
mse[i++] = prkdf->key_reference;
mse[i++] = 0x89; /* Algorithm reference (BCD encoded). */
mse[i++] = 3;
mse[i++] = 0x13; /* RSA PKCS#1 (standard) (1 3 2 3). */
mse[i++] = 0x23;
switch (hashalgo)
{
case GCRY_MD_SHA1: mse[i++] = 0x10; break;
case GCRY_MD_RMD160: mse[i++] = 0x20; break;
case GCRY_MD_SHA256: mse[i++] = 0x30; break;
case GCRY_MD_SHA384: mse[i++] = 0x40; break;
case GCRY_MD_SHA512: mse[i++] = 0x50; break;
case GCRY_MD_SHA224: mse[i++] = 0x60; break;
default: err = gpg_error (GPG_ERR_DIGEST_ALGO); break;
}
log_assert (i <= DIM(mse));
if (!err)
err = iso7816_manage_security_env (app_get_slot (app), 0x41, 0xB6,
mse, i);
}
}
else if (prkdf->key_reference_valid) else if (prkdf->key_reference_valid)
{ {
unsigned char mse[3]; unsigned char mse[3];
@ -5817,9 +5889,14 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
le_value = 0; le_value = 0;
} }
err = iso7816_compute_ds (app_get_slot (app), if (app->app_local->card_product == CARD_PRODUCT_CVISION)
err = iso7816_decipher (app_get_slot (app),
exmode, indata, indatalen, exmode, indata, indatalen,
le_value, outdata, outdatalen); le_value, 0, outdata, outdatalen);
else
err = iso7816_compute_ds (app_get_slot (app),
exmode, indata, indatalen,
le_value, outdata, outdatalen);
leave: leave:
xfree (indata_buffer); xfree (indata_buffer);