From b16400e22c48f3c6ee3f6efca792bd011c798c5f Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 8 Jun 2024 11:26:47 -0500 Subject: [PATCH] Minidriver.c sign_pin and user_consent - PinCacheAlwaysPrompt At least 5 card drivers set user_consent on a sign pin The user_consent indicates a prompt for the pin should always be done by minidriver. PKCS15 can also set user_consent and PKCS11 sets key attribute CKA_ALWAYS_AUTHENTICATE when key has user_consent, but windows need the PinCacheAlwaysPrompt flag set on the pin. pkcs15-piv.c now defines a sign pin which is used only with the 9C key. ======= On branch minidriver-PinCacheAlwaysPrompt Changes to be committed: modified: libopensc/pkcs15-piv.c modified: minidriver/minidriver.c --- src/libopensc/pkcs15-piv.c | 32 ++++++++++++++++++++++++------ src/minidriver/minidriver.c | 39 +++++++++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c index db7e21decb..71fc2839f4 100644 --- a/src/libopensc/pkcs15-piv.c +++ b/src/libopensc/pkcs15-piv.c @@ -385,16 +385,29 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_LOCAL, -1, 0xFF, - SC_PKCS15_CO_FLAG_PRIVATE }, + SC_PKCS15_CO_FLAG_PRIVATE}, + { "02", "PIV PUK", "", 0x81, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_INITIALIZED | - SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN | + SC_PKCS15_PIN_FLAG_SO_PIN | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, + + /* only used with minidriver */ + { "03", "PIN", "", 0x80, + /* used in minidriver as the sign key and for 9C key */ + /* label, flag and ref will change if using global pin */ + SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, + 8, 4, 8, + SC_PKCS15_PIN_FLAG_NEEDS_PADDING | + SC_PKCS15_PIN_FLAG_INITIALIZED | + SC_PKCS15_PIN_FLAG_LOCAL, + -1, 0xFF, + SC_PKCS15_CO_FLAG_PRIVATE}, { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; // clang-format on @@ -540,7 +553,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, /*EC*/SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, - "", 0x9C, "01", SC_PKCS15_CO_FLAG_PRIVATE, 1}, + "", 0x9C, "01", SC_PKCS15_CO_FLAG_PRIVATE, 1}, /* use sign pin and user_consent */ { "03", "KEY MAN key", /*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, @@ -952,6 +965,10 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) const char * label; int pin_ref; + /* the SignPIN is only used with minidriver */ + if ((i == 2) && strcmp(card->ctx->app_name, "cardmod")) + continue; + memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); @@ -968,17 +985,16 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) sc_format_path(pins[i].path, &pin_info.path); label = pins[i].label; - if (i == 0 && + if ((i == 0 || i == 2) && sc_card_ctl(card, SC_CARDCTL_PIV_PIN_PREFERENCE, &pin_ref) == 0 && pin_ref == 0x00) { /* must be 80 for PIV pin, or 00 for Global PIN */ pin_info.attrs.pin.reference = pin_ref; - pin_info.attrs.pin.flags &= ~SC_PKCS15_PIN_FLAG_LOCAL; label = "Global PIN"; } strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1); pin_obj.flags = pins[i].obj_flags; - if (i == 0 && pin_info.attrs.pin.reference == 0x80) { + if ((i == 0 || i == 2) && pin_info.attrs.pin.reference == 0x80) { /* * according to description of "RESET RETRY COUNTER" * command in specs PUK can only unblock PIV PIN @@ -1169,6 +1185,10 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) if (prkeys[i].auth_id) sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id); + /* If using minidriver, use Sign PIN for 9C key */ + if (prkey_obj.user_consent && !strcmp(card->ctx->app_name, "cardmod")) + sc_pkcs15_format_id("03", &prkey_obj.auth_id); + /* * When no cert is present and a pubkey in a file was found, * means the caller is initializing a card. A sign operation diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 10da7dba43..de0a73bfdf 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -233,6 +233,9 @@ typedef struct _VENDOR_SPECIFIC struct md_dh_agreement* dh_agreements; BYTE allocatedAgreements; + /* if any key used with the MD_ROLE_USER_SIGN has user_consent set PinCacheAlwaysPrompt */ + int need_pin_always; + CRITICAL_SECTION hScard_lock; } VENDOR_SPECIFIC; @@ -1888,6 +1891,12 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file) cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ? " (default)" : ""); + /* set flag that at least one key that uses the sign key needs PinCacheAlwaysPrompt */ + logprintf(pCardData, 7, "key_obj->user_consent: %d\n", (int) key_obj->user_consent); + if (key_obj->user_consent) + vs->need_pin_always = 1; + logprintf(pCardData, 7, "vs->need_pin_always %d\n", (int) vs->need_pin_always); + if (pin_mode < pin_mode_n) { pin_mode = pin_mode_n; pin_cont_idx = ii; @@ -5999,6 +6008,16 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, if (pcbSessionPin) *pcbSessionPin = 0; if (ppbSessionPin) *ppbSessionPin = NULL; logprintf(pCardData, 2, "standard pin verification"); + /* + * TODO the use of auth_method being overridden to do session pin + * conflicts with framework-pkcs15.c use of auth_method SC_AC_CONTEXT_SPECIFIC + * for a different porpose. But needs to be reviewed + */ + if (PinId == MD_ROLE_USER_SIGN && vs->need_pin_always) { + logprintf(pCardData, 7, "Setting SC_AC_CONTEXT_SPECIFIC cbPinData: %lu old auth_method: %0x auth_id:%x \n", + (unsigned long) cbPinData, (unsigned int) auth_info->auth_method, (unsigned char) auth_info->auth_id.value[0]); + auth_info->auth_method = SC_AC_CONTEXT_SPECIFIC; + } r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_VERIFY, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData, NULL, NULL, DisplayPinpadUI, PinId); } @@ -6475,16 +6494,28 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, "returning info on normal PIN [%lu]\n", (unsigned long)dwFlags); - if (dwFlags == ROLE_USER) + if (dwFlags == ROLE_USER) { + p->PinCachePolicy.PinCachePolicyType = PinCacheNormal; p->PinPurpose = PrimaryCardPin; - else if (dwFlags == MD_ROLE_USER_SIGN) + } + else if (dwFlags == MD_ROLE_USER_SIGN) { + logprintf(pCardData, 7, "vs->need_pin_always %d\n", (int) vs->need_pin_always); + if (vs->need_pin_always) { + p->PinCachePolicy.PinCachePolicyType = PinCacheAlwaysPrompt; + logprintf(pCardData, 7, "Setting PinCacheAlwaysPrompt\n"); + } + else + p->PinCachePolicy.PinCachePolicyType = PinCacheNormal; + p->PinPurpose = DigitalSignaturePin; - else + } + else { p->PinPurpose = AuthenticationPin; + p->PinCachePolicy.PinCachePolicyType = PinCacheNormal; + } p->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION; p->PinCachePolicy.dwPinCachePolicyInfo = 0; - p->PinCachePolicy.PinCachePolicyType = PinCacheNormal; p->dwChangePermission = CREATE_PIN_SET(dwFlags); p->dwUnblockPermission = CREATE_PIN_SET(ROLE_ADMIN); break;