Dear Developers, this series of patches adds ECC support for the D-Trust 4.1/4.4 cards. All the code was already there. Just the security environment parameters had to be confirmed which I now successfully did with my test cards.
The patches further allow keys with the derive usage-flag to be used for decryption and fixes certificate import for duplicate certificate IDs. These issues were already addressed in separate threads on this list. I am unsure whether patch nr. 0003 is necessary. Feel free to either omit it or to squash it with 0002. Mario Haustein (3): scd:p15: Take derive usage into account for decryption. scd:p15: Fix typo in a comment scd:p15: Add ECC support for D-Trust Card 4.1/4.4 Werner Koch (2): scd:p15: Handle duplicate certificate ids. scd:p15: Take derive usage into account for decryption. scd/app-p15.c | 96 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 25 deletions(-) -- 2.43.0 Kind regards -- Mario Haustein Facharbeitsgruppe Anwendungen Universitätsrechenzentrum Technische Universität Chemnitz Straße der Nationen 62 | R. 1/B303 (neu: A11.303) 09111 Chemnitz Germany Tel: +49 371 531-36606 Fax: +49 371 531-836606 [email protected] www.tu-chemnitz.de
>From f7b706b0e78cc7415cd2e512ed4a9731b355078f Mon Sep 17 00:00:00 2001 From: Werner Koch <[email protected]> Date: Mon, 19 Feb 2024 14:45:06 +0100 Subject: [PATCH GnuPG 1/5] scd:p15: Handle duplicate certificate ids. * scd/app-p15.c (struct app_local_s): Add field cdf_dup_counter. (objid_in_cdflist_p): New. (read_p15_info): Clear the counter. (read_ef_cdf): Detect and fix duplicate IDs. -- GnuPG-bug-id: 7001 Reported-by: Mario Haustein <[email protected]> --- scd/app-p15.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/scd/app-p15.c b/scd/app-p15.c index 2bb90beaa..eb9c53465 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -520,6 +520,9 @@ struct app_local_s /* Information on all useful certificates. */ cdf_object_t useful_certificate_info; + /* Counter to make object ids of certificates unique. */ + unsigned int cdf_dup_counter; + /* Information on all public keys. */ prkdf_object_t public_key_info; @@ -2419,6 +2422,22 @@ read_ef_pukdf (app_t app, unsigned short fid, pukdf_object_t *result) } +/* Return true id CDFLIST has the given object id. */ +static int +objid_in_cdflist_p (cdf_object_t cdflist, + const unsigned char *objid, size_t objidlen) +{ + cdf_object_t cdf; + + if (!objid || !objidlen) + return 0; + for (cdf = cdflist; cdf; cdf = cdf->next) + if (cdf->objidlen == objidlen && !memcmp (cdf->objid, objid, objidlen)) + return 1; + return 0; +} + + /* Read and parse the Certificate Directory Files identified by FID. On success a newlist of CDF object gets stored at RESULT and the caller is then responsible of releasing this list. On error a @@ -2464,6 +2483,7 @@ read_ef_cdf (app_t app, unsigned short fid, int cdftype, cdf_object_t *result) unsigned long ul; const unsigned char *objid; size_t objidlen; + int objidextralen; err = parse_ber_header (&p, &n, &class, &tag, &constructed, &ndef, &objlen, &hdrlen); @@ -2588,8 +2608,19 @@ read_ef_cdf (app_t app, unsigned short fid, int cdftype, cdf_object_t *result) label = NULL; } - cdf->objidlen = objidlen; - cdf->objid = xtrymalloc (objidlen); + /* Card's have been found in the wild which do not have unique + * IDs for their certificate objects. If we detect this we + * append a counter to the ID. */ + objidextralen = + (objid_in_cdflist_p (cdflist, objid, objidlen) + || objid_in_cdflist_p (app->app_local->certificate_info, + objid, objidlen) + || objid_in_cdflist_p (app->app_local->trusted_certificate_info, + objid, objidlen) + || objid_in_cdflist_p (app->app_local->useful_certificate_info, + objid, objidlen)); + cdf->objidlen = objidlen + objidextralen; + cdf->objid = xtrymalloc (objidlen + objidextralen); if (!cdf->objid) { err = gpg_error_from_syserror (); @@ -2597,6 +2628,16 @@ read_ef_cdf (app_t app, unsigned short fid, int cdftype, cdf_object_t *result) goto leave; } memcpy (cdf->objid, objid, objidlen); + if (objidextralen) + { + if (app->app_local->cdf_dup_counter == 255) + { + log_error ("p15: too many duplicate certificate ids\n"); + err = gpg_error (GPG_ERR_TOO_MANY); + goto parse_error; + } + cdf->objid[objidlen] = ++app->app_local->cdf_dup_counter; + } cdf->pathlen = objlen/2; for (i=0; i < cdf->pathlen; i++, pp += 2, nn -= 2) @@ -3664,6 +3705,7 @@ read_p15_info (app_t app) log_assert (!app->app_local->certificate_info); log_assert (!app->app_local->trusted_certificate_info); log_assert (!app->app_local->useful_certificate_info); + app->app_local->cdf_dup_counter = 0; err = read_ef_cdf (app, app->app_local->odf.certificates, 'c', &app->app_local->certificate_info); if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA) -- 2.43.0
>From 057a668a7994dfb4ad3dcde7d40337cd34bded64 Mon Sep 17 00:00:00 2001 From: Werner Koch <[email protected]> Date: Mon, 19 Feb 2024 13:51:02 +0100 Subject: [PATCH GnuPG 2/5] scd:p15: Take derive usage into account for decryption. * scd/app-p15.c (set_usage_string): Map usageflags.derive also to 'e'. (do_auth): Allow usageflags.sign_recover. (do_decipher): Allow usageflags.derive. (do_with_keygrip): Take usageflags.derive into account. (do_decipher): Take a missing AODF for authentication not needed. -- This is required for D-Trust ECC cards. The AODF thing is unrelated but seems to be a good idea. GnuPG-bug-id: 7000 --- scd/app-p15.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/scd/app-p15.c b/scd/app-p15.c index eb9c53465..8a869279d 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -305,7 +305,7 @@ struct prkdf_object_s keyaccess_flags_t accessflags; /* Extended key usage flags. Only used if .valid is set. This - * information is computed from an associated certificate15. */ + * information is computed from an associated certificate. */ struct { unsigned int valid:1; unsigned int sign:1; @@ -4256,7 +4256,8 @@ set_usage_string (char usage[5], prkdf_object_t prkdf) && (!prkdf->extusage.valid || prkdf->extusage.sign)) usage[usagelen++] = 'c'; if ((prkdf->usageflags.decrypt - || prkdf->usageflags.unwrap) + || prkdf->usageflags.unwrap + || prkdf->usageflags.derive) && (!prkdf->extusage.valid || prkdf->extusage.encr)) usage[usagelen++] = 'e'; if ((prkdf->usageflags.sign @@ -5969,7 +5970,8 @@ do_auth (app_t app, ctrl_t ctrl, const char *keyidstr, err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf); if (err) return err; - if (!(prkdf->usageflags.sign || prkdf->gpgusage.auth)) + if (!(prkdf->usageflags.sign || prkdf->usageflags.sign_recover + || prkdf->gpgusage.auth)) { log_error ("p15: key %s may not be used for authentication\n", keyidstr); return gpg_error (GPG_ERR_WRONG_KEY_USAGE); @@ -6012,6 +6014,7 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr, return err; if (!(prkdf->usageflags.decrypt || prkdf->usageflags.unwrap + || prkdf->usageflags.derive || prkdf->gpgusage.encr )) { log_error ("p15: key %s may not be used for decryption\n", keyidstr); @@ -6021,17 +6024,18 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr, /* Find the authentication object to this private key object. */ if (!prkdf->authid) { - log_error ("p15: no authentication object defined for %s\n", keyidstr); - /* fixme: we might want to go ahead and do without PIN - verification. */ - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + log_info ("p15: no authentication object defined for %s\n", keyidstr); + aodf = NULL; + } + else + { + for (aodf = app->app_local->auth_object_info; aodf; aodf = aodf->next) + if (aodf->objidlen == prkdf->authidlen + && !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen)) + break; + if (!aodf) + log_info ("p15: no authentication for %s needed\n", keyidstr); } - for (aodf = app->app_local->auth_object_info; aodf; aodf = aodf->next) - if (aodf->objidlen == prkdf->authidlen - && !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen)) - break; - if (!aodf) - log_info ("p15: no authentication for %s needed\n", keyidstr); /* We need some more info about the key - get the keygrip to * populate these fields. */ @@ -6316,7 +6320,8 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action, } else if (capability == GCRY_PK_USAGE_ENCR) { - if (!(prkdf->usageflags.decrypt || prkdf->usageflags.unwrap)) + if (!(prkdf->usageflags.decrypt || prkdf->usageflags.unwrap + || prkdf->usageflags.derive)) continue; } else if (capability == GCRY_PK_USAGE_AUTH) -- 2.43.0
>From 3c61ac16e8b6a90f3efeb917bd20612660755c54 Mon Sep 17 00:00:00 2001 From: Mario Haustein <[email protected]> Date: Mon, 19 Feb 2024 10:22:08 +0100 Subject: [PATCH GnuPG 4/5] scd:p15: Fix typo in a comment --- scd/app-p15.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scd/app-p15.c b/scd/app-p15.c index 4ad3bc3b7..fb1b67c21 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -4704,7 +4704,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) /* We return the ID of the first private key capable of the * requested action. If any gpgusage flag has been set for the - * card we consult the gpgusage flags and not the regualr usage + * card we consult the gpgusage flags and not the regular usage * flags. */ /* FIXME: This changed: Note that we do not yet return -- 2.43.0
>From c944a0cb15a332426105a33bf01d4f301b60cbe7 Mon Sep 17 00:00:00 2001 From: Mario Haustein <[email protected]> Date: Mon, 19 Feb 2024 10:21:24 +0100 Subject: [PATCH GnuPG 3/5] scd:p15: Take derive usage into account for decryption. * scd/app-p15.c (do_getattr): Map usageflags.derive also to 'e'. --- scd/app-p15.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scd/app-p15.c b/scd/app-p15.c index 8a869279d..4ad3bc3b7 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -4726,7 +4726,8 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) if ((name[1] == 'A' && (prkdf->usageflags.sign || prkdf->usageflags.sign_recover)) || (name[1] == 'E' && (prkdf->usageflags.decrypt - || prkdf->usageflags.unwrap)) + || prkdf->usageflags.unwrap + || prkdf->usageflags.derive)) || (name[1] == 'S' && (prkdf->usageflags.sign || prkdf->usageflags.sign_recover))) break; @@ -4935,7 +4936,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) } else { - if (prkdf->usageflags.decrypt || prkdf->usageflags.unwrap) + if (prkdf->usageflags.decrypt || prkdf->usageflags.unwrap || prkdf->usageflags.derive) break; } } -- 2.43.0
>From 5fecff0baed5d8b7ef0f53a08a75976794dd739e Mon Sep 17 00:00:00 2001 From: Mario Haustein <[email protected]> Date: Mon, 19 Feb 2024 10:22:35 +0100 Subject: [PATCH GnuPG 5/5] scd:p15: Add ECC support for D-Trust Card 4.1/4.4 * scd/app-p15.c (do_sign): Add MSE RESTORE parameters for D-Trust ECC cards. (do_decipher): Ditto. --- scd/app-p15.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/scd/app-p15.c b/scd/app-p15.c index fb1b67c21..877db8bfc 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -5828,9 +5828,8 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo, { if (prkdf->is_ecc) { - /* Not implemented due to lacking test hardware. */ - log_info ("Note: ECC is not yet implemented for DTRUST 4 cards\n"); - err = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + err = iso7816_manage_security_env (app_get_slot (app), + 0xf3, 0x21, NULL, 0); } else { @@ -6089,9 +6088,8 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr, { if (prkdf->is_ecc) { - /* Not implemented due to lacking test hardware. */ - log_info ("Note: ECC is not yet implemented for DTRUST 4 cards\n"); - err = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + err = iso7816_manage_security_env (app_get_slot (app), + 0xF3, 0x39, NULL, 0); } else { -- 2.43.0
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ Gnupg-devel mailing list [email protected] https://lists.gnupg.org/mailman/listinfo/gnupg-devel
