]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: Support keys that set the CKA_ALWAYS_AUTHENTICATE by
authordjm@openbsd.org <djm@openbsd.org>
Tue, 22 Jan 2019 12:00:50 +0000 (12:00 +0000)
committerDamien Miller <djm@mindrot.org>
Tue, 22 Jan 2019 12:04:54 +0000 (23:04 +1100)
requring a fresh login after the C_SignInit operation.

based on patch from Jakub Jelen in bz#2638; ok markus

OpenBSD-Commit-ID: a76e66996ba7c0923b46b74d46d499b811786661

ssh-pkcs11.c

index 036ee8115657511fc2def40e16317235afbbd3ad..384ac1edb5d21cfa9d9cfdc58e5538a45c9a145e 100644 (file)
@@ -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.
@@ -239,6 +239,85 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
        return (ret);
 }
 
+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)
 {
@@ -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);
 }