Skip to content

Commit

Permalink
Minidriver.c sign_pin and user_consent - PinCacheAlwaysPrompt
Browse files Browse the repository at this point in the history
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
  • Loading branch information
dengert committed Jun 15, 2024
1 parent 6ceb50e commit bc0b511
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 13 deletions.
39 changes: 30 additions & 9 deletions src/libopensc/pkcs15-piv.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ typedef struct pdata_st {
int tries_left;
const unsigned char pad_char;
int obj_flags;
int cardmod; /* only use with cardmod minidriver */
} pindata;

typedef struct pubdata_st {
Expand Down Expand Up @@ -385,17 +386,30 @@ 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, 0},

{ "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 },
{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
SC_PKCS15_CO_FLAG_PRIVATE, 0},

/* 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, 1}, /* only use if cardmod */
{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
// clang-format on

Expand Down Expand Up @@ -540,7 +554,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,
Expand Down Expand Up @@ -952,6 +966,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 (pins[i].cardmod && (strcmp(card->ctx->app_name, "cardmod") != 0))
continue;

memset(&pin_info, 0, sizeof(pin_info));
memset(&pin_obj, 0, sizeof(pin_obj));

Expand All @@ -968,17 +986,17 @@ 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 || pins[i].cardmod) &&
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 || pins[i].cardmod)) {
/*
* according to description of "RESET RETRY COUNTER"
* command in specs PUK can only unblock PIV PIN
Expand Down Expand Up @@ -1016,7 +1034,6 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)

pubkey_obj.flags = pubkeys[i].obj_flags;


if (pubkeys[i].auth_id)
sc_pkcs15_format_id(pubkeys[i].auth_id, &pubkey_obj.auth_id);

Expand Down Expand Up @@ -1169,6 +1186,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") == 0))
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
Expand Down
39 changes: 35 additions & 4 deletions src/minidriver/minidriver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 purpose. 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);
}

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit bc0b511

Please sign in to comment.