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
1 changed files with 81 additions and 4 deletions

View File

@ -5513,6 +5513,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
unsigned char oidbuf[64];
size_t oidbuflen;
size_t n;
int i;
unsigned char *indata_buffer = NULL; /* Malloced helper. */
(void)ctrl;
@ -5610,7 +5611,6 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
{
unsigned int framelen;
unsigned char *frame;
int i;
framelen = (prkdf->keynbits+7) / 8;
if (!framelen)
@ -5685,6 +5685,23 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
memcpy (frame, indata, 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
{
n = 0;
@ -5774,7 +5791,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
else
{
/* 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
* cipher and message digest used. The spec states SE-ID 0x25 for
* 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);
}
}
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)
{
unsigned char mse[3];
@ -5817,9 +5889,14 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
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,
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:
xfree (indata_buffer);