Hi Douglas, The extra bite is not a flag. It is needed in indata to the decryption command since it is one byte longer than the signing command. The change will not affect other cards since the pointer to the signing function is now pointing on the second byte in the buffer. The first byte will only be used by card decryption commands. If pkcs15-sec.c should be untouched we could allocate a new buffer inside card-cardos.c that is one byte longer than the input and copy. Just thought it was more simple and more effective doing as I did. Then it is also possible that some other card needs to have this extra byte for decryption in the future. But if you insist that I remove the changes from pkcs15-sec.c I will do that.
Lars Douglas E. Engert wrote: > > 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 > _______________________________________________ opensc-devel mailing list opensc-devel@lists.opensc-project.org http://www.opensc-project.org/mailman/listinfo/opensc-devel