Skip to content

Commit

Permalink
minidriver.c - Create shadow MD_ROLE_USER_ALWAYS and MD_ROLE_USER_SI…
Browse files Browse the repository at this point in the history
…GN_ALWAYS

   PKCS11 defines CKA_ALWAYS_AUTHENTICATE attribute for private keys, which is converted
   to `user_consent` for PKCS15 for private keys. Windows has `PinCacheAlwaysPrompt`
   on PINS to accomplish the same thing - prompt user before using a key.

   But a key "is secured by" only one pin, but a pin may secure multiple keys where only
   a subset of keys need `PinCacheAlwaysPrompt`

   Two new pin roles are defined and use a sc_pkcs15_id auth_id of
   auth_id_md_role_user_always = {"MD_ROLE_USER_ALWAYS", 18};
   and
   auth_id_md_role_user_sign_always = {"MD_ROLE_USER_SIGN_ALWAYS", 18};

   When building containers for pkcs15 key objects, if user_consent > 0, the auth_id
   is set to one of the above. Thus when Windows CSP selects a key, it will find
   a pin that matches the correct role for the key.

 On branch minidriver-PinCacheAlwaysPrompt
 Changes to be committed:
	modified:   minidriver/minidriver.c
  • Loading branch information
dengert committed Jun 7, 2024
1 parent 6ceb50e commit 894eafd
Showing 1 changed file with 82 additions and 20 deletions.
102 changes: 82 additions & 20 deletions src/minidriver/minidriver.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ HINSTANCE g_inst;
#define MD_CARDID_SIZE 16

#define MD_ROLE_USER_SIGN (ROLE_ADMIN + 1)
#define MD_ROLE_USER_ALWAYS (ROLE_ADMIN + 2)
#define MD_ROLE_USER_SIGN_ALWAYS (ROLE_ADMIN + 3)
static struct sc_pkcs15_id auth_id_md_role_user_always = {"MD_ROLE_USER_ALWAYS", 18};
static struct sc_pkcs15_id auth_id_md_role_user_sign_always = {"MD_ROLE_USER_SIGN_ALWAYS", 24};

/*
* must be higher than MD_ROLE_USER_SIGN and
* less than or equal MAX_PINS
Expand Down Expand Up @@ -499,12 +504,18 @@ get_pin_by_name(PCARD_DATA pCardData, struct sc_pkcs15_card *p15card, int role,
MD_FUNC_CALLED(pCardData, 1);

switch (role) {
case ROLE_USER:
case ROLE_USER:
pin_type = "user_pin";
break;
case MD_ROLE_USER_ALWAYS:
pin_type = "user_pin_always";
break;
case MD_ROLE_USER_SIGN:
pin_type = "sign_pin";
break;
case MD_ROLE_USER_SIGN_ALWAYS:
pin_type = "sign_pin_always";
break;
default:
MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
}
Expand Down Expand Up @@ -535,6 +546,14 @@ get_pin_by_name(PCARD_DATA pCardData, struct sc_pkcs15_card *p15card, int role,
MD_FUNC_RETURN(pCardData, 1, sc_pkcs15_find_pin_by_auth_id(p15card, &id, ret_obj) ? SCARD_F_INTERNAL_ERROR : SCARD_S_SUCCESS);
}

static
replace_auth_id(struct sc_pkcs15_id *auth_id, struct sc_pkcs15_id *auth_id_replacment)
{
memset(auth_id->value, 0, SC_PKCS15_MAX_ID_SIZE);
auth_id->len = auth_id_replacment->len;
memcpy(auth_id->value, auth_id_replacment->value, auth_id->len);
}

static DWORD
md_get_pin_by_role(PCARD_DATA pCardData, PIN_ID role, struct sc_pkcs15_object **ret_obj)
{
Expand All @@ -555,15 +574,16 @@ md_get_pin_by_role(PCARD_DATA pCardData, PIN_ID role, struct sc_pkcs15_object **
goto out;

/* please keep me in sync with _get_auth_object_by_name() in pkcs11/framework-pkcs15.c */
if (role == ROLE_USER) {
/* ROLE_USER and MD_ROLE_USER_ALWAYS use same PIN - its the key that requires ALWAYS */
if (role == ROLE_USER || role == MD_ROLE_USER_ALWAYS) {
/* Get 'global' User PIN; if no, get the 'local' one */
rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_GLOBAL,
SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj);
SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj);
if (rv)
rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL,
SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj);
SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj);
}
else if (role == MD_ROLE_USER_SIGN) {
else if (role == MD_ROLE_USER_SIGN || role == MD_ROLE_USER_SIGN_ALWAYS) {
int idx = 0;

/* Get the 'global' user PIN */
Expand Down Expand Up @@ -1861,32 +1881,61 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file)
vs->pin_objs[pinidxempty] = keypin_obj;
}

if (sc_pkcs15_compare_id(&key_obj->auth_id, &userpin_info->auth_id)) {
/* in case key_obj->auth_id is already set at auth_id_md_role_user_always */
if (sc_pkcs15_compare_id(&key_obj->auth_id, &userpin_info->auth_id) ||
sc_pkcs15_compare_id(&key_obj->auth_id, &auth_id_md_role_user_always)) {
pin_mode_t pin_mode_n =
cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
SCF_DEFAULT_USER_PIN : SCF_NONDEFAULT_USER_PIN;

logprintf(pCardData, 7,
"Container[%i]%s is secured by User PIN\n",
ii,
cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
" (default)" : "");
/*
* if key has user_consent i.e. CKA_ALWAYS_AUTHENTICATE use MD_ROLE_USER_ALWAYS
* We change the auth_id so it can be found by comparing auth_id of MD_ROLE_USER_ALWAYS
*/
if (key_obj->user_consent) {
replace_auth_id(&key_obj->auth_id, &auth_id_md_role_user_always);
logprintf(pCardData, "Container[%i]%s is secured by MD_ROLE_USER_ALWAYS\n",
ii,
cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
" (default)" : "");
}
else {
logprintf(pCardData, 7,
"Container[%i]%s is secured by User PIN\n",
ii,
cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
" (default)" : "");
}

if (pin_mode < pin_mode_n) {
pin_mode = pin_mode_n;
pin_cont_idx = ii;
}
} else if (signpin_info != NULL &&
sc_pkcs15_compare_id(&key_obj->auth_id, &signpin_info->auth_id)) {
(sc_pkcs15_compare_id(&key_obj->auth_id, &signpin_info->auth_id) ||
sc_pkcs15_compare_id(&key_obj->auth_id, &auth_id_md_role_user_sign_always))) {
pin_mode_t pin_mode_n =
cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
SCF_DEFAULT_SIGN_PIN : SCF_NONDEFAULT_SIGN_PIN;

logprintf(pCardData, 7,
"Container[%i]%s is secured by Sign PIN\n",
ii,
cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
" (default)" : "");
/*
* if key has user_consent i.e. CKA_ALWAYS_AUTHENTICATE use MD_ROLE_USER_SIGN_ALWAYS
* We change the auth_id so it can be found by comparing auth_id of MD_ROLE_USER_ALWAYS
*/
if (key_obj->user_consent) {
replace_auth_id(&key_obj->auth_id, &auth_id_md_role_user_sign_always);
logprintf(pCardData, 7, "Container[%i]%s is secured by MD_ROLE_USER_SIGN_ALWAYS\n",
ii,
cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
" (default)" : "");
}
else {
logprintf(pCardData, 7,
"Container[%i]%s is secured by Sign PIN\n",
ii,
cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
" (default)" : "");
}

if (pin_mode < pin_mode_n) {
pin_mode = pin_mode_n;
Expand Down Expand Up @@ -6475,16 +6524,29 @@ 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->PinPurpose = PrimaryCardPin;
else if (dwFlags == MD_ROLE_USER_SIGN)
p->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
}
else if (dwFlags == MD_ROLE_USER_ALWAYS) {
p->PinPurpose = AuthenticationPin;
p->PinCachePolicy.PinCachePolicyType = PinCacheAlwaysPrompt;
logprintf(pCardData, 1, "setting PinCacheAlwaysPrompt\n");
}
else if (dwFlags == MD_ROLE_USER_SIGN) {
p->PinPurpose = DigitalSignaturePin;
p->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
}
else if (dwFlags == MD_ROLE_USER_SIGN_ALWAYS) {
p->PinPurpose = DigitalSignaturePin;
p->PinCachePolicy.PinCachePolicyType = PinCacheAlwaysPrompt;
logprintf(pCardData, 1, "setting PinCacheAlwaysPrompt\n");
}
else
p->PinPurpose = AuthenticationPin;

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 894eafd

Please sign in to comment.