From 4d098d96502cb8f5086b52182cf809986af79c2e Mon Sep 17 00:00:00 2001 From: "ludovic.rousseau" Date: Fri, 7 Dec 2007 09:46:21 +0000 Subject: [PATCH] do not add a signature prefix for D-Trust cards Thanks to Simon Eisenmann for the patch http://www.opensc-project.org/pipermail/opensc-devel/2007-December/010609.html git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3303 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/card-cardos.c | 51 +++++++++++++++++++++++++++---------- src/libopensc/opensc.h | 4 +++ src/libopensc/pkcs15.c | 32 +++++++++++++++++++++++ 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index 6e7ca10d..eb8c19d8 100644 --- a/src/libopensc/card-cardos.c +++ b/src/libopensc/card-cardos.c @@ -802,14 +802,28 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, * certain key, let's try RSA_PURE etc. and see which operation * succeeds (this is not really beautiful, but currently the * only way I see) -- Nils + * + * We also check for several caps flags here to pervent generating + * invalid signatures with duplicated hash prefixes with some cards */ - if (ctx->debug >= 3) - sc_debug(ctx, "trying RSA_PURE_SIG (padded DigestInfo)\n"); - sc_ctx_suppress_errors_on(ctx); - r = do_compute_signature(card, data, datalen, out, outlen); - sc_ctx_suppress_errors_off(ctx); - if (r >= SC_SUCCESS) - SC_FUNC_RETURN(ctx, 4, r); + + if (ctx->debug >= 3) { + if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED) + sc_debug(ctx, "Forcing RAW_HASH_STRIPPED\n"); + if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH) + sc_debug(ctx, "Forcing RAW_HASH\n"); + } + + if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH))) { + if (ctx->debug >= 3) + sc_debug(ctx, "trying RSA_PURE_SIG (padded DigestInfo)\n"); + sc_ctx_suppress_errors_on(ctx); + r = do_compute_signature(card, data, datalen, out, outlen); + sc_ctx_suppress_errors_off(ctx); + if (r >= SC_SUCCESS) + SC_FUNC_RETURN(ctx, 4, r); + } + if (ctx->debug >= 3) sc_debug(ctx, "trying RSA_SIG (just the DigestInfo)\n"); /* remove padding: first try pkcs1 bt01 padding */ @@ -826,13 +840,24 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, } memcpy(buf, p, tmp_len); } - sc_ctx_suppress_errors_on(ctx); - r = do_compute_signature(card, buf, tmp_len, out, outlen); - sc_ctx_suppress_errors_off(ctx); - if (r >= SC_SUCCESS) - SC_FUNC_RETURN(ctx, 4, r); + + if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH)) || card->caps & SC_CARD_CAP_ONLY_RAW_HASH ) { + if (ctx->debug >= 3) + sc_debug(ctx, "trying to sign raw hash value with prefix\n"); + sc_ctx_suppress_errors_on(ctx); + r = do_compute_signature(card, buf, tmp_len, out, outlen); + sc_ctx_suppress_errors_off(ctx); + if (r >= SC_SUCCESS) + SC_FUNC_RETURN(ctx, 4, r); + } + + if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH) { + sc_debug(ctx, "Failed to sign raw hash value with prefix when forcing\n"); + SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS); + } + if (ctx->debug >= 3) - sc_debug(ctx, "trying to sign raw hash value\n"); + sc_debug(ctx, "trying to sign stripped raw hash value (card is responsible for prefix)\n"); r = sc_pkcs1_strip_digest_info_prefix(NULL,buf,tmp_len,buf,&buf_len); if (r != SC_SUCCESS) SC_FUNC_RETURN(ctx, 4, r); diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index d080dc54..a444411e 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -446,6 +446,10 @@ struct sc_reader_operations { /* The card supports 2048 bit RSA keys */ #define SC_CARD_CAP_RSA_2048 0x00000020 +/* D-TRUST CardOS cards special flags */ +#define SC_CARD_CAP_ONLY_RAW_HASH 0x00000040 +#define SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED 0x00000080 + typedef struct sc_card { struct sc_context *ctx; struct sc_reader *reader; diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index b57dbe06..29297339 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -681,6 +681,38 @@ static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card) || strcmp(p15card->manufacturer_id,"Prime") == 0 )) p15card->flags |= SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT; + /* set special flags based on card meta data */ + if (strcmp(p15card->card->driver->short_name,"cardos") == 0) { + + /* D-Trust cards (D-TRUST, D-SIGN) */ + if (strstr(p15card->label,"D-TRUST") == 0 + || strstr(p15card->label,"D-SIGN") == 0) { + + /* D-TRUST Card 2.0 2cc (standard cards, which always add + * SHA1 prefix itself */ + if (strstr(p15card->label, "2cc") != NULL) { + p15card->card->caps |= SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED; + p15card->flags &= ~SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT; + sc_debug(p15card->card->ctx, "D-TRUST 2cc card detected, only SHA1 works with this card\n"); + /* XXX: add detection when other hash than SHA1 is used with + * such a card, as this produces invalid signatures. + */ + } + + /* D-SIGN multicard 2.0 2ca (cards working with all types of hashes + * and no addition of prefix) */ + else if (strstr(p15card->label, "2ca") != NULL) { + p15card->card->caps |= SC_CARD_CAP_ONLY_RAW_HASH; + p15card->flags &= ~SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT; + sc_debug(p15card->card->ctx, "D-TRUST 2ca card detected\n"); + } + + /* XXX: probably there are more D-Trust card in the wild, + * which also need these flags to produce valid signatures + */ + } + } + ok = 1; end: if(buf != NULL)