Lars Silvén wrote:
> Hi list,
>
> This is an attempt to persuade you to add functionality to opensc.
> I have already made a patch that implements what is needed. This file is
> attached.
>
> The patch make it possible to sign with keys on CardOS cards that was
> generated to use only the decryption card command.
> This is because you can not generate keys on CardOS that accepts both the
> sign and decryption commands.
>
> Sometimes you want keys that is capable of both signing and decryption.
> Even when a key only should be used for signing it could be preferable to use
> the decryption command. This is when you use a padding where the MSB in
> the RSA input differs 0 in the input (of modulus length) to the RSA algorithm.
>
> All CardOS keys created by PrimeCard (see
> http://primekey.se/primekey/en/Products/PrimeCard.html) are keys where only
> the decrypt card command could
> be used. But some of these keys are intended only for signing.
>
> The patch is only tested with cards issued by PrimeCard. https authentication
> works fine with firefox using the opensc p11.
> So you have to test that I have not messed anything up regarding other card
> but I don't think it will be any problems with that.
You are proposing changes to pkcs15-sec.c. this is used by all cards, not just
the cardOS.
I don't understand the need to add the leading 0 in the buf, and how this
change would effect
other cards. Is this meant to be a flag? Then add a flag to the sc_card card
structure.
Can you move your code out of pkcs15-sec, and into card-cardos.c?
>
> I will be happy to send PrimeCard issued cards to those of you that will test
> and add this patch to opensc as well as to maintainers of the project.
> Just give me the mailing addresses.
>
> Best Regards
> Lars
>
>
> ------------------------------------------------------------------------
>
> diff -Naur opensc-0.11.3/src/libopensc/card-cardos.c
> opensc-0.11.3-new/src/libopensc/card-cardos.c
> --- opensc-0.11.3/src/libopensc/card-cardos.c 2007-07-09 10:17:32.000000000
> +0200
> +++ opensc-0.11.3-new/src/libopensc/card-cardos.c 2007-08-01
> 22:46:30.000000000 +0200
> @@ -686,6 +686,12 @@
> SC_FUNC_RETURN(card->ctx, 1, r);
> }
>
> +/*
> + * Saved when cardos_set_security_env is called.
> + * To be used when signing if decryption command must be used.
> + * The object of the pointer is on the stack of
> pkcs15-sec.c:sc_pkcs15_compute_signature
> + */
> +static sc_security_env_t *pEnvSaved;
> /*
> * Set the security context
> * Things get a little messy here. It seems you cannot do any
> @@ -704,7 +710,7 @@
> sc_apdu_t apdu;
> u8 data[3];
> int key_id, r;
> -
> + pEnvSaved = env;
> assert(card != NULL && env != NULL);
>
> if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
> @@ -774,6 +780,35 @@
> SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1,
> apdu.sw2));
> }
>
> +/* Internal function using the decryption command of the card to do the RSA
> operation in a signing. Used when the signing command on the card does not
> work for a key. */
> +static int
> +do_decryption(sc_card_t *card, const u8 *data, size_t datalen,
> + u8 *out, size_t outlen)
> +{
> + int r;
> + sc_apdu_t apdu;
> +
> + /* INS: 0x2A PERFORM SECURITY OPERATION
> + * P1: 0x80 Resp: Decryption
> + * P2: 0x86 Cmd: Input for Decrytption */
> + sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86);
> + apdu.resp = out;
> + apdu.le = outlen;
> + apdu.resplen = outlen;
> +
> + apdu.data = data-1; /* a first extra byte must be appended when the
> decryption command is used for the RSA operation */
> + apdu.lc = datalen+1; /* this byte is allocated by
> pkcs15-sec.c:sc_pkcs15_compute_signature */
> + apdu.datalen = datalen+1;
> + apdu.sensitive = 1;
> + r = sc_transmit_apdu(card, &apdu);
> + SC_TEST_RET(card->ctx, r, "APDU transmit failed");
> +
> + if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
> + SC_FUNC_RETURN(card->ctx, 4, apdu.resplen);
> + else
> + SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
> +}
> +
> static int
> cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
> u8 *out, size_t outlen)
> @@ -831,7 +866,18 @@
> r = sc_pkcs1_strip_digest_info_prefix(NULL,buf,tmp_len,buf,&buf_len);
> if (r != SC_SUCCESS)
> SC_FUNC_RETURN(ctx, 4, r);
> - return do_compute_signature(card, buf, buf_len, out, outlen);
> + sc_ctx_suppress_errors_on(ctx);
> + r = do_compute_signature(card, buf, buf_len, out, outlen);
> + sc_ctx_suppress_errors_off(ctx);
> + if (r >= SC_SUCCESS)
> + SC_FUNC_RETURN(ctx, 4, r);
> + /* maybe it is only possible to use the decryption command of the card
> for this key.*/
> + /* pEnvSaved is set in the call to cardos_set_security_env */
> + pEnvSaved->operation = SC_SEC_OPERATION_DECIPHER;
> + r = sc_set_security_env(card, pEnvSaved, 0);
> + if (r != SC_SUCCESS)
> + SC_FUNC_RETURN(ctx, 4, r);
> + return do_decryption(card, data, datalen, out, outlen);
> }
>
> static int
> diff -Naur opensc-0.11.3/src/libopensc/pkcs15-sec.c
> opensc-0.11.3-new/src/libopensc/pkcs15-sec.c
> --- opensc-0.11.3/src/libopensc/pkcs15-sec.c 2007-04-20 09:12:54.000000000
> +0200
> +++ opensc-0.11.3-new/src/libopensc/pkcs15-sec.c 2007-08-01
> 21:46:19.000000000 +0200
> @@ -143,7 +143,7 @@
> sc_context_t *ctx = p15card->card->ctx;
> sc_algorithm_info_t *alg_info;
> const struct sc_pkcs15_prkey_info *prkey = (const struct
> sc_pkcs15_prkey_info *) obj->data;
> - u8 buf[512], *tmp;
> + u8 buf[513], *tmp;
> size_t modlen = prkey->modulus_length / 8;
> unsigned long pad_flags = 0, sec_flags = 0;
>
> @@ -167,10 +167,14 @@
> senv.algorithm = SC_ALGORITHM_RSA;
>
> /* Probably never happens, but better make sure */
> - if (inlen > sizeof(buf) || outlen < modlen)
> + if (inlen+1 > sizeof(buf) || outlen < modlen)
> return SC_ERROR_BUFFER_TOO_SMALL;
> - memcpy(buf, in, inlen);
> - tmp = buf;
> + memcpy(buf+1, in, inlen);
> + /* First byte buf[0] to be used when the decryption command of the card
> has to be used for the RSA operation in the signing. */
> + /* Only used when the signing command of the card can't be used on a
> key. When signing command is used for RSA operation buf[0] is not used.*/
> + /* All calls to the signing implementation function are done with the
> data input pointer pointing to buf[1] */
> + tmp = buf+1;
> + *buf = 0;
>
> /* flags: the requested algo
> * algo_info->flags: what is supported by the card
> @@ -181,7 +185,7 @@
> if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 |
> SC_ALGORITHM_RSA_HASH_NONE)) &&
> !(alg_info->flags & (SC_ALGORITHM_RSA_RAW |
> SC_ALGORITHM_RSA_HASH_NONE))) {
> unsigned int algo;
> - size_t tmplen = sizeof(buf);
> + size_t tmplen = sizeof(buf)-1;
> r = sc_pkcs1_strip_digest_info_prefix(&algo, tmp, inlen, tmp,
> &tmplen);
> if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) {
> sc_mem_clear(buf, sizeof(buf));
> @@ -201,14 +205,14 @@
>
> /* add the padding bytes (if necessary) */
> if (pad_flags != 0) {
> - size_t tmplen = sizeof(buf);
> + size_t tmplen = sizeof(buf)-1;
> r = sc_pkcs1_encode(ctx, pad_flags, tmp, inlen, tmp, &tmplen,
> modlen);
> SC_TEST_RET(ctx, r, "Unable to add padding");
> inlen = tmplen;
> } else if ((flags & SC_ALGORITHM_RSA_PADS) ==
> SC_ALGORITHM_RSA_PAD_NONE) {
> /* Add zero-padding if input is shorter than the modulus */
> if (inlen < modlen) {
> - if (modlen > sizeof(buf))
> + if (modlen+1 > sizeof(buf))
> return SC_ERROR_BUFFER_TOO_SMALL;
> memmove(tmp+modlen-inlen, tmp, inlen);
> memset(tmp, 0, modlen-inlen);
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> opensc-devel mailing list
> [email protected]
> http://www.opensc-project.org/mailman/listinfo/opensc-devel
--
Douglas E. Engert <[EMAIL PROTECTED]>
Argonne National Laboratory
9700 South Cass Avenue
Argonne, Illinois 60439
(630) 252-5444
_______________________________________________
opensc-devel mailing list
[email protected]
http://www.opensc-project.org/mailman/listinfo/opensc-devel