From 96abdb1386284da07a7fe129b79d08890949d2ed Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 10 Jul 2009 10:15:33 +0000 Subject: [PATCH] Fix for card keys > 2048 bit. --- scd/ChangeLog | 9 +++++++++ scd/app-dinsig.c | 3 ++- scd/app-nks.c | 3 ++- scd/app-openpgp.c | 34 +++++++++++++++++++++++++++++++--- scd/app-p15.c | 6 +++--- scd/iso7816.c | 34 ++++++++++++++++++++++++++-------- scd/iso7816.h | 6 ++++-- 7 files changed, 77 insertions(+), 18 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 94e1ebd59..27453113b 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,12 @@ +2009-07-10 Werner Koch + + * iso7816.c (iso7816_compute_ds): Add args EXTENDED_MODE and LE. + Change all callers to use 0. + (iso7816_internal_authenticate): Add args EXTENDED_MODE and LE. + * app-openpgp.c (do_sign): Take exmode and Le from card + capabilities and pass them to iso7816_compute_ds. + (do_auth): Ditto for iso7816_internal_authenticate. + 2009-07-09 Werner Koch * app-openpgp.c (change_keyattr): New. diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c index f0655bb2d..46e9a6a9b 100644 --- a/scd/app-dinsig.c +++ b/scd/app-dinsig.c @@ -483,7 +483,8 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, rc = verify_pin (app, pincb, pincb_arg); if (!rc) - rc = iso7816_compute_ds (app->slot, data, datalen, outdata, outdatalen); + rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0, + outdata, outdatalen); return rc; } diff --git a/scd/app-nks.c b/scd/app-nks.c index 53435c360..1f3aad209 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -969,7 +969,8 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, rc = verify_pin (app, 0, NULL, pincb, pincb_arg); /* Compute the signature. */ if (!rc) - rc = iso7816_compute_ds (app->slot, data, datalen, outdata, outdatalen); + rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0, + outdata, outdatalen); return rc; } diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 9620d5b40..134679bfb 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -3008,6 +3008,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, const char *fpr = NULL; unsigned long sigcount; int use_auth = 0; + int exmode, le_value; if (!keyidstr || !*keyidstr) return gpg_error (GPG_ERR_INV_VALUE); @@ -3148,7 +3149,19 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, xfree (pinvalue); } - rc = iso7816_compute_ds (app->slot, data, datalen, outdata, outdatalen); + + if (app->app_local->cardcap.ext_lc_le) + { + exmode = 1; /* Use extended length. */ + le_value = app->app_local->extcap.max_rsp_data; + } + else + { + exmode = 0; + le_value = 0; + } + rc = iso7816_compute_ds (app->slot, exmode, data, datalen, le_value, + outdata, outdatalen); return rc; } @@ -3219,8 +3232,23 @@ do_auth (app_t app, const char *keyidstr, rc = verify_chv2 (app, pincb, pincb_arg); if (!rc) - rc = iso7816_internal_authenticate (app->slot, indata, indatalen, - outdata, outdatalen); + { + int exmode, le_value; + + if (app->app_local->cardcap.ext_lc_le) + { + exmode = 1; /* Use extended length. */ + le_value = app->app_local->extcap.max_rsp_data; + } + else + { + exmode = 0; + le_value = 0; + } + rc = iso7816_internal_authenticate (app->slot, exmode, + indata, indatalen, le_value, + outdata, outdatalen); + } return rc; } diff --git a/scd/app-p15.c b/scd/app-p15.c index 62404bef9..7d8329366 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -3180,11 +3180,11 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, } if (hashalgo == MD_USER_TLS_MD5SHA1) - err = iso7816_compute_ds (app->slot, data, 36, outdata, outdatalen); + err = iso7816_compute_ds (app->slot, 0, data, 36, 0, outdata, outdatalen); else if (no_data_padding) - err = iso7816_compute_ds (app->slot, data+15, 20, outdata, outdatalen); + err = iso7816_compute_ds (app->slot, 0, data+15, 20, 0,outdata,outdatalen); else - err = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); + err = iso7816_compute_ds (app->slot, 0, data, 35, 0, outdata, outdatalen); return err; } diff --git a/scd/iso7816.c b/scd/iso7816.c index 3fea6c79e..f1ee0daef 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -505,9 +505,10 @@ iso7816_manage_security_env (int slot, int p1, int p2, /* Perform the security operation COMPUTE DIGITAL SIGANTURE. On success 0 is returned and the data is availavle in a newly allocated buffer stored at RESULT with its length stored at - RESULTLEN. */ + RESULTLEN. For LE see do_generate_keypair. */ gpg_error_t -iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen, +iso7816_compute_ds (int slot, int extended_mode, + const unsigned char *data, size_t datalen, int le, unsigned char **result, size_t *resultlen) { int sw; @@ -517,9 +518,16 @@ iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen, *result = NULL; *resultlen = 0; - sw = apdu_send (slot, 0, - 0x00, CMD_PSO, 0x9E, 0x9A, datalen, (const char*)data, - result, resultlen); + if (!extended_mode) + le = 256; /* Ignore provided Le and use what apdu_send uses. */ + else if (le >= 0 && le < 256) + le = 256; + + sw = apdu_send_le (slot, extended_mode, + 0x00, CMD_PSO, 0x9E, 0x9A, + datalen, (const char*)data, + le, + result, resultlen); if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ @@ -586,9 +594,11 @@ iso7816_decipher (int slot, int extended_mode, } +/* For LE see do_generate_keypair. */ gpg_error_t -iso7816_internal_authenticate (int slot, +iso7816_internal_authenticate (int slot, int extended_mode, const unsigned char *data, size_t datalen, + int le, unsigned char **result, size_t *resultlen) { int sw; @@ -598,8 +608,16 @@ iso7816_internal_authenticate (int slot, *result = NULL; *resultlen = 0; - sw = apdu_send (slot, 0, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0, - datalen, (const char*)data, result, resultlen); + if (!extended_mode) + le = 256; /* Ignore provided Le and use what apdu_send uses. */ + else if (le >= 0 && le < 256) + le = 256; + + sw = apdu_send_le (slot, extended_mode, + 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0, + datalen, (const char*)data, + le, + result, resultlen); if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ diff --git a/scd/iso7816.h b/scd/iso7816.h index d3deda13d..4e7a344ab 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -93,15 +93,17 @@ gpg_error_t iso7816_put_data_odd (int slot, int extended_mode, int tag, gpg_error_t iso7816_manage_security_env (int slot, int p1, int p2, const unsigned char *data, size_t datalen); -gpg_error_t iso7816_compute_ds (int slot, +gpg_error_t iso7816_compute_ds (int slot, int extended_mode, const unsigned char *data, size_t datalen, + int le, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_decipher (int slot, int extended_mode, const unsigned char *data, size_t datalen, int padind, unsigned char **result, size_t *resultlen); -gpg_error_t iso7816_internal_authenticate (int slot, +gpg_error_t iso7816_internal_authenticate (int slot, int extended_mode, const unsigned char *data, size_t datalen, + int le, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_generate_keypair (int slot, int extended_mode, const unsigned char *data, size_t datalen,