Skip to content

Instantly share code, notes, and snippets.

@apatard
Created April 26, 2023 13:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save apatard/2049a50505a482c3e1e7906cba40fd72 to your computer and use it in GitHub Desktop.
Save apatard/2049a50505a482c3e1e7906cba40fd72 to your computer and use it in GitHub Desktop.
scdaemon: Allow to switch between piv and openpgp apps for Nitrokey 3
Nitrokey 3 token have a piv and openpgp applications, like Yubikey.
So add minimal glue to allow switching between them.
Tested with Nitrokey 3 firmware v1.3.1-test.20230417 and
gpg --card-status && pkcs11-tool --list-slots && gpg --card-status.
The scdaemon configuration was:
debug-all
debug-ccid-driver
log-file /root/scdaemon.log
disable-ccid
pcsc-shared
pcsc-driver /usr/lib/x86_64-linux-gnu/libpcsclite.so.1
[ The adding certs to the PIV application has not tested. Only pkcs15-tool
list commands like --list-pins or -C has been used ]
Signed-off-by: Arnaud Patard <apatard@hupstream.com>
Index: gnupg2/scd/app-common.h
===================================================================
--- gnupg2.orig/scd/app-common.h
+++ gnupg2/scd/app-common.h
@@ -55,6 +55,7 @@ typedef enum
{
CARDTYPE_GENERIC = 0,
CARDTYPE_GNUK,
+ CARDTYPE_NK3,
CARDTYPE_YUBIKEY,
CARDTYPE_ZEITCONTROL
Index: gnupg2/scd/app.c
===================================================================
--- gnupg2.orig/scd/app.c
+++ gnupg2/scd/app.c
@@ -110,6 +110,7 @@ strcardtype (cardtype_t t)
{
case CARDTYPE_GENERIC: return "generic";
case CARDTYPE_GNUK: return "gnuk";
+ case CARDTYPE_NK3: return "nitrokey3";
case CARDTYPE_YUBIKEY: return "yubikey";
case CARDTYPE_ZEITCONTROL: return "zeitcontrol";
}
@@ -509,7 +510,7 @@ check_application_conflict (card_t card,
if (card->app->apptype == APPTYPE_UNDEFINED)
return 0;
- if (card->cardtype == CARDTYPE_YUBIKEY)
+ if (card->cardtype == CARDTYPE_YUBIKEY || card->cardtype == CARDTYPE_NK3)
{
if (card->app->apptype == APPTYPE_OPENPGP)
{
@@ -680,6 +681,8 @@ app_new_register (int slot, ctrl_t ctrl,
card->cardtype = CARDTYPE_GNUK;
else if (atrlen == 21 && atr[7] == 0x75)
card->cardtype = CARDTYPE_ZEITCONTROL;
+ else if (atrlen >= 16 && !memcmp(&atr[5], "Nitrokey", 8))
+ card->cardtype = CARDTYPE_NK3;
xfree (atr);
}
}
@@ -1031,7 +1034,7 @@ select_all_additional_applications_inter
int i, j;
int any_new = 0;
- if (card->cardtype == CARDTYPE_YUBIKEY)
+ if (card->cardtype == CARDTYPE_YUBIKEY || card->cardtype == CARDTYPE_NK3)
{
candidates[0] = APPTYPE_OPENPGP;
candidates[1] = APPTYPE_PIV;
@@ -1610,9 +1613,7 @@ check_external_interference (app_t app,
* APDU command has been used we better also check whether the AID
* is still valid.
*/
- if (app && app->card && app->card->maybe_check_aid)
- app->card->maybe_check_aid = 0;
- else if (!opt.pcsc_shared || app->card->cardtype != CARDTYPE_YUBIKEY)
+ if (!opt.pcsc_shared || (app->card->cardtype != CARDTYPE_YUBIKEY && app->card->cardtype != CARDTYPE_NK3))
return 0;
if (app->fnc.check_aid)
@@ -1651,7 +1652,7 @@ maybe_switch_app (ctrl_t ctrl, card_t ca
if (!card->app)
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
- if (card->maybe_check_aid && card->app->fnc.reselect
+ if (card->app->fnc.reselect
&& check_external_interference (card->app, ctrl))
{
if (DBG_APP)
Index: gnupg2/scd/app-openpgp.c
===================================================================
--- gnupg2.orig/scd/app-openpgp.c
+++ gnupg2/scd/app-openpgp.c
@@ -6350,7 +6350,7 @@ do_reselect (app_t app, ctrl_t ctrl)
/* An extra check which should not be necessary because the caller
* should have made sure that a re-select is only called for
* appropriate cards. */
- if (APP_CARD(app)->cardtype != CARDTYPE_YUBIKEY)
+ if (APP_CARD(app)->cardtype != CARDTYPE_YUBIKEY && APP_CARD(app)->cardtype != CARDTYPE_NK3)
return gpg_error (GPG_ERR_NOT_SUPPORTED);
/* Note that the card can't cope with P2=0xCO, thus we need to pass
Index: gnupg2/scd/app-piv.c
===================================================================
--- gnupg2.orig/scd/app-piv.c
+++ gnupg2/scd/app-piv.c
@@ -211,6 +211,7 @@ struct app_local_s {
struct
{
unsigned int yubikey:1; /* This is on a Yubikey. */
+ unsigned int nk3:1; /* This is on a Nitrokey3. */
} flags;
/* Keep track on whether we cache a certain PIN so that we get it
@@ -3607,7 +3608,7 @@ do_reselect (app_t app, ctrl_t ctrl)
/* An extra check which should not be necessary because the caller
* should have made sure that a re-select is only called for
* appropriate cards. */
- if (!app->app_local->flags.yubikey)
+ if (!app->app_local->flags.yubikey && !app->app_local->flags.nk3)
return gpg_error (GPG_ERR_NOT_SUPPORTED);
err = iso7816_select_application (app_get_slot (app),
@@ -3711,6 +3712,8 @@ app_select_piv (app_t app)
if (app->card->cardtype == CARDTYPE_YUBIKEY)
app->app_local->flags.yubikey = 1;
+ if (app->card->cardtype == CARDTYPE_NK3)
+ app->app_local->flags.nk3 = 1;
/* FIXME: Parse the optional and conditional DOs in the APT. */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment