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 > opensc-devel@lists.opensc-project.org > 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 opensc-devel@lists.opensc-project.org http://www.opensc-project.org/mailman/listinfo/opensc-devel