summaryrefslogtreecommitdiff
path: root/ssh-pkcs11.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-01-22 12:00:50 +0000
committerDamien Miller <djm@mindrot.org>2019-01-22 23:04:54 +1100
commit2162171ad517501ba511fa9f8191945d01857bb4 (patch)
tree9cfd9baea34f5f110d01ea97ded5238bcb3d0639 /ssh-pkcs11.c
parent7a2cb18a215b2cb335da3dc99489c52a91f4925b (diff)
downloadopenssh-git-2162171ad517501ba511fa9f8191945d01857bb4.tar.gz
upstream: Support keys that set the CKA_ALWAYS_AUTHENTICATE by
requring a fresh login after the C_SignInit operation. based on patch from Jakub Jelen in bz#2638; ok markus OpenBSD-Commit-ID: a76e66996ba7c0923b46b74d46d499b811786661
Diffstat (limited to 'ssh-pkcs11.c')
-rw-r--r--ssh-pkcs11.c121
1 files changed, 95 insertions, 26 deletions
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index 036ee811..384ac1ed 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-pkcs11.c,v 1.39 2019/01/21 02:05:38 djm Exp $ */
+/* $OpenBSD: ssh-pkcs11.c,v 1.40 2019/01/22 12:00:50 djm Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
* Copyright (c) 2014 Pedro Martelletto. All rights reserved.
@@ -240,6 +240,85 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
}
static int
+pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type)
+{
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ char *pin = NULL, prompt[1024];
+ CK_RV rv;
+
+ if (!k11->provider || !k11->provider->valid) {
+ error("no pkcs11 (valid) provider found");
+ return (-1);
+ }
+
+ f = k11->provider->function_list;
+ si = &k11->provider->slotinfo[k11->slotidx];
+
+ if (!pkcs11_interactive) {
+ error("need pin entry%s",
+ (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ?
+ " on reader keypad" : "");
+ return (-1);
+ }
+ if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
+ verbose("Deferring PIN entry to reader keypad.");
+ else {
+ snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
+ si->token.label);
+ if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) {
+ debug("%s: no pin specified", __func__);
+ return (-1); /* bail out */
+ }
+ }
+ rv = f->C_Login(si->session, type, (u_char *)pin,
+ (pin != NULL) ? strlen(pin) : 0);
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
+ if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
+ error("C_Login failed: %lu", rv);
+ return (-1);
+ }
+ si->logged_in = 1;
+ return (0);
+}
+
+static int
+pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_TYPE type, int *val)
+{
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_BBOOL flag = 0;
+ CK_ATTRIBUTE attr;
+ CK_RV rv;
+
+ *val = 0;
+
+ if (!k11->provider || !k11->provider->valid) {
+ error("no pkcs11 (valid) provider found");
+ return (-1);
+ }
+
+ f = k11->provider->function_list;
+ si = &k11->provider->slotinfo[k11->slotidx];
+
+ attr.type = type;
+ attr.pValue = &flag;
+ attr.ulValueLen = sizeof(flag);
+
+ rv = f->C_GetAttributeValue(si->session, obj, &attr, 1);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ return (-1);
+ }
+ *val = flag != 0;
+ debug("%s: provider %p slot %lu object %lu: attrib %lu = %d",
+ __func__, k11->provider, k11->slotidx, obj, type, *val);
+ return (0);
+}
+
+static int
pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
{
struct pkcs11_slotinfo *si;
@@ -250,7 +329,8 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
CK_BBOOL true_val;
CK_MECHANISM mech;
CK_ATTRIBUTE key_filter[3];
- char *pin = NULL, prompt[1024];
+ int always_auth = 0;
+ int did_login = 0;
if (!k11->provider || !k11->provider->valid) {
error("no pkcs11 (valid) provider found");
@@ -261,32 +341,11 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
si = &k11->provider->slotinfo[k11->slotidx];
if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
- if (!pkcs11_interactive) {
- error("need pin entry%s", (si->token.flags &
- CKF_PROTECTED_AUTHENTICATION_PATH) ?
- " on reader keypad" : "");
- return (-1);
- }
- if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
- verbose("Deferring PIN entry to reader keypad.");
- else {
- snprintf(prompt, sizeof(prompt),
- "Enter PIN for '%s': ", si->token.label);
- pin = read_passphrase(prompt, RP_ALLOW_EOF);
- if (pin == NULL)
- return (-1); /* bail out */
- }
- rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,
- (pin != NULL) ? strlen(pin) : 0);
- if (pin != NULL) {
- explicit_bzero(pin, strlen(pin));
- free(pin);
- }
- if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
- error("C_Login failed: %lu", rv);
+ if (pkcs11_login(k11, CKU_USER) < 0) {
+ error("login failed");
return (-1);
}
- si->logged_in = 1;
+ did_login = 1;
}
memset(&key_filter, 0, sizeof(key_filter));
@@ -321,6 +380,16 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
return (-1);
}
+ pkcs11_check_obj_bool_attrib(k11, obj, CKA_ALWAYS_AUTHENTICATE,
+ &always_auth); /* ignore errors here */
+ if (always_auth && !did_login) {
+ debug("%s: always-auth key", __func__);
+ if (pkcs11_login(k11, CKU_CONTEXT_SPECIFIC) < 0) {
+ error("login failed for always-auth key");
+ return (-1);
+ }
+ }
+
return (0);
}