Skip to content

Commit bc0b511

Browse files
committed
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
1 parent 6ceb50e commit bc0b511

File tree

2 files changed

+65
-13
lines changed

2 files changed

+65
-13
lines changed

src/libopensc/pkcs15-piv.c

+30-9
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ typedef struct pdata_st {
7171
int tries_left;
7272
const unsigned char pad_char;
7373
int obj_flags;
74+
int cardmod; /* only use with cardmod minidriver */
7475
} pindata;
7576

7677
typedef struct pubdata_st {
@@ -385,17 +386,30 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
385386
SC_PKCS15_PIN_FLAG_INITIALIZED |
386387
SC_PKCS15_PIN_FLAG_LOCAL,
387388
-1, 0xFF,
388-
SC_PKCS15_CO_FLAG_PRIVATE },
389+
SC_PKCS15_CO_FLAG_PRIVATE, 0},
390+
389391
{ "02", "PIV PUK", "", 0x81,
390392
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
391393
8, 4, 8,
392394
SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
393395
SC_PKCS15_PIN_FLAG_INITIALIZED |
394-
SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN |
396+
SC_PKCS15_PIN_FLAG_SO_PIN |
395397
SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN,
396398
-1, 0xFF,
397-
SC_PKCS15_CO_FLAG_PRIVATE },
398-
{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
399+
SC_PKCS15_CO_FLAG_PRIVATE, 0},
400+
401+
/* only used with minidriver */
402+
{ "03", "PIN", "", 0x80,
403+
/* used in minidriver as the sign key and for 9C key */
404+
/* label, flag and ref will change if using global pin */
405+
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
406+
8, 4, 8,
407+
SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
408+
SC_PKCS15_PIN_FLAG_INITIALIZED |
409+
SC_PKCS15_PIN_FLAG_LOCAL,
410+
-1, 0xFF,
411+
SC_PKCS15_CO_FLAG_PRIVATE, 1}, /* only use if cardmod */
412+
{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
399413
};
400414
// clang-format on
401415

@@ -540,7 +554,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
540554
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
541555
/*EC*/SC_PKCS15_PRKEY_USAGE_SIGN |
542556
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
543-
"", 0x9C, "01", SC_PKCS15_CO_FLAG_PRIVATE, 1},
557+
"", 0x9C, "01", SC_PKCS15_CO_FLAG_PRIVATE, 1}, /* use sign pin and user_consent */
544558
{ "03", "KEY MAN key",
545559
/*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP,
546560
/*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE,
@@ -952,6 +966,10 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
952966
const char * label;
953967
int pin_ref;
954968

969+
/* the SignPIN is only used with minidriver */
970+
if (pins[i].cardmod && (strcmp(card->ctx->app_name, "cardmod") != 0))
971+
continue;
972+
955973
memset(&pin_info, 0, sizeof(pin_info));
956974
memset(&pin_obj, 0, sizeof(pin_obj));
957975

@@ -968,17 +986,17 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
968986
sc_format_path(pins[i].path, &pin_info.path);
969987

970988
label = pins[i].label;
971-
if (i == 0 &&
989+
if ((i == 0 || pins[i].cardmod) &&
972990
sc_card_ctl(card, SC_CARDCTL_PIV_PIN_PREFERENCE,
973991
&pin_ref) == 0 &&
974992
pin_ref == 0x00) { /* must be 80 for PIV pin, or 00 for Global PIN */
975993
pin_info.attrs.pin.reference = pin_ref;
976-
pin_info.attrs.pin.flags &= ~SC_PKCS15_PIN_FLAG_LOCAL;
977994
label = "Global PIN";
978995
}
996+
979997
strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1);
980998
pin_obj.flags = pins[i].obj_flags;
981-
if (i == 0 && pin_info.attrs.pin.reference == 0x80) {
999+
if ((i == 0 || pins[i].cardmod)) {
9821000
/*
9831001
* according to description of "RESET RETRY COUNTER"
9841002
* command in specs PUK can only unblock PIV PIN
@@ -1016,7 +1034,6 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
10161034

10171035
pubkey_obj.flags = pubkeys[i].obj_flags;
10181036

1019-
10201037
if (pubkeys[i].auth_id)
10211038
sc_pkcs15_format_id(pubkeys[i].auth_id, &pubkey_obj.auth_id);
10221039

@@ -1169,6 +1186,10 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
11691186
if (prkeys[i].auth_id)
11701187
sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id);
11711188

1189+
/* If using minidriver, use Sign PIN for 9C key */
1190+
if (prkey_obj.user_consent && (strcmp(card->ctx->app_name, "cardmod") == 0))
1191+
sc_pkcs15_format_id("03", &prkey_obj.auth_id);
1192+
11721193
/*
11731194
* When no cert is present and a pubkey in a file was found,
11741195
* means the caller is initializing a card. A sign operation

src/minidriver/minidriver.c

+35-4
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ typedef struct _VENDOR_SPECIFIC
233233
struct md_dh_agreement* dh_agreements;
234234
BYTE allocatedAgreements;
235235

236+
/* if any key used with the MD_ROLE_USER_SIGN has user_consent set PinCacheAlwaysPrompt */
237+
int need_pin_always;
238+
236239
CRITICAL_SECTION hScard_lock;
237240
} VENDOR_SPECIFIC;
238241

@@ -1888,6 +1891,12 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file)
18881891
cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
18891892
" (default)" : "");
18901893

1894+
/* set flag that at least one key that uses the sign key needs PinCacheAlwaysPrompt */
1895+
logprintf(pCardData, 7, "key_obj->user_consent: %d\n", (int) key_obj->user_consent);
1896+
if (key_obj->user_consent)
1897+
vs->need_pin_always = 1;
1898+
logprintf(pCardData, 7, "vs->need_pin_always %d\n", (int) vs->need_pin_always);
1899+
18911900
if (pin_mode < pin_mode_n) {
18921901
pin_mode = pin_mode_n;
18931902
pin_cont_idx = ii;
@@ -5999,6 +6008,16 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData,
59996008
if (pcbSessionPin) *pcbSessionPin = 0;
60006009
if (ppbSessionPin) *ppbSessionPin = NULL;
60016010
logprintf(pCardData, 2, "standard pin verification");
6011+
/*
6012+
* TODO the use of auth_method being overridden to do session pin
6013+
* conflicts with framework-pkcs15.c use of auth_method SC_AC_CONTEXT_SPECIFIC
6014+
* for a different purpose. But needs to be reviewed
6015+
*/
6016+
if (PinId == MD_ROLE_USER_SIGN && vs->need_pin_always) {
6017+
logprintf(pCardData, 7, "Setting SC_AC_CONTEXT_SPECIFIC cbPinData: %lu old auth_method: %0x auth_id:%x \n",
6018+
(unsigned long) cbPinData, (unsigned int) auth_info->auth_method, (unsigned char) auth_info->auth_id.value[0]);
6019+
auth_info->auth_method = SC_AC_CONTEXT_SPECIFIC;
6020+
}
60026021
r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_VERIFY, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData, NULL, NULL, DisplayPinpadUI, PinId);
60036022
}
60046023

@@ -6475,16 +6494,28 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData,
64756494
"returning info on normal PIN [%lu]\n",
64766495
(unsigned long)dwFlags);
64776496

6478-
if (dwFlags == ROLE_USER)
6497+
if (dwFlags == ROLE_USER) {
6498+
p->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
64796499
p->PinPurpose = PrimaryCardPin;
6480-
else if (dwFlags == MD_ROLE_USER_SIGN)
6500+
}
6501+
else if (dwFlags == MD_ROLE_USER_SIGN) {
6502+
logprintf(pCardData, 7, "vs->need_pin_always %d\n", (int) vs->need_pin_always);
6503+
if (vs->need_pin_always) {
6504+
p->PinCachePolicy.PinCachePolicyType = PinCacheAlwaysPrompt;
6505+
logprintf(pCardData, 7, "Setting PinCacheAlwaysPrompt\n");
6506+
}
6507+
else
6508+
p->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
6509+
64816510
p->PinPurpose = DigitalSignaturePin;
6482-
else
6511+
}
6512+
else {
64836513
p->PinPurpose = AuthenticationPin;
6514+
p->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
6515+
}
64846516

64856517
p->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
64866518
p->PinCachePolicy.dwPinCachePolicyInfo = 0;
6487-
p->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
64886519
p->dwChangePermission = CREATE_PIN_SET(dwFlags);
64896520
p->dwUnblockPermission = CREATE_PIN_SET(ROLE_ADMIN);
64906521
break;

0 commit comments

Comments
 (0)