Re: Outstanding PKCS#11 issues

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

 





On 2/26/2018 12:00 PM, Jakub Jelen wrote:
Hello everyone,

as you could have noticed over the years, there are several bugs for
PKCS#11 improvement and integration which are slipping under the radar
for several releases, but the most painful ones are constantly updated
by community to build, work and make our lives better.

I wrote some of the patches, provided feedback to others, or offered
other help here on mailing list, but did not get quite much any
feedback, none of the patches (excluding some one-liners) are not
incorporated, but usually not yet even reviewed or considered.

I believe using PKCS#11 as a store for private keys is a good practice
and making OpenSSH work with it is a must. So again, I offering my help
  in this area not limited to the following bugs (according to
complexity and priority):

Bug 2430 - ssh-keygen should allow to login before reading public key
from smart card
Bug 2652 - PKCS11 login skipped if login required and no pin set
Bug 2638 - Honor PKCS#11 CKA_ALWAYS_AUTHENTICATE attribute of the
private objects
Bug 2474 - Enabling ECDSA in PKCS#11 support for ssh-agent
Bug 2817 - Add support for PKCS#11 URIs (RFC 7512)
Bug 2472 - Add support to load additional certificates
Bug 2075 - [PATCH] Enable key pair generation on a PCKS#11 device

Namely, the #2638 one will be a big problem after the release of OpenSC
0.18.0 [1], which is no longer allowing the workflow OpenSSH is using.


In response to #2638, Attached are changes to 7.7p1 so the pin is used
for both the C_Login(CKU_USER) and C_Login(CKU_CONTEXT_SPECIFIC)
It can also work with a pin pad reader if [2] is applied but requires
user to enter pin twice.

Tested with NIST Demo card using AUTH key and SIGN Key.

PIV card enforces "PIN Always" for the SIGN key and OpenSC supports
this by returning CKA_ALWAYS_AUTHENTICATE=True for the SIGN key. The
Application requests this attribute and if True and does
C_Login(CKU_CONTEXT_SPECIFIC) just before the the C_Sign operation.







[1] https://github.com/OpenSC/OpenSC/pull/1256

[2] https://github.com/OpenSC/OpenSC/commit/dac9634d87e38ec899713d36a389816b0435b767


--

 Douglas E. Engert  <DEEngert@xxxxxxxxx>

From 981d0914d919afb56f452ba0507ddfaf7c99387a Mon Sep 17 00:00:00 2001
From: Doug Engert <deengert@xxxxxxxxx>
Date: Wed, 18 Apr 2018 09:09:05 -0500
Subject: [PATCH] PKCS11  Better C_Login to handle CKA_ALWAYS_AUTHENTICATE

 On branch pkcs11-c_login
 Changes to be committed:
	modified:   ssh-pkcs11.c
---
 ssh-pkcs11.c | 98 +++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 68 insertions(+), 30 deletions(-)

diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index 65a7b58..5b53f8e 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -216,6 +216,37 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
 	return (ret);
 }
 
+/* read pin and do C_Login of type CKU_USER or CKU_CONTEXT_SPECIFIC */
+static int
+pkcs11_c_login(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, int cku, char **pin)
+{
+	CK_FUNCTION_LIST        *f;
+	CK_RV                   rv;
+	char			prompt[1041];
+
+	f = provider->function_list;
+	if (*pin == NULL) {
+		if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
+			verbose("Deferring PIN entry to reader keypad.");
+		else {
+			snprintf(prompt, sizeof(prompt),
+			    "Enter%s PIN for '%s': ", cku==CKU_CONTEXT_SPECIFIC?" Context Specific":"", si->token.label);
+			*pin = read_passphrase(prompt, RP_ALLOW_EOF);
+			if (*pin == NULL)
+				return (-1);	/* bail out */
+		}
+	}
+	rv = f->C_Login(si->session, cku, (u_char *)*pin,
+	    (*pin != NULL) ? strlen(*pin) : 0);
+	    /* caller must zero out pin */
+	if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
+		error("C_Login failed: %lu", rv);
+		return (-1);
+	}
+	return 0;
+}
+
+
 /* openssl callback doing the actual signing operation */
 static int
 pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
@@ -237,7 +268,12 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
 		{CKA_ID, NULL, 0},
 		{CKA_SIGN, NULL, sizeof(true_val) }
 	};
-	char			*pin = NULL, prompt[1024];
+	CK_BBOOL		cka_always_authenticate = CK_FALSE;
+	CK_ATTRIBUTE		key_cka_always_authenticate[] = {
+		{CKA_ALWAYS_AUTHENTICATE, &cka_always_authenticate, sizeof(cka_always_authenticate) }
+	};
+		 
+	char			*pin = NULL;
 	int			rval = -1;
 
 	key_filter[0].pValue = &private_key_class;
@@ -260,25 +296,9 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
 			    " 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);
-			return (-1);
-		}
+		rv = pkcs11_c_login(k11->provider, si, CKU_USER, &pin);
+		if (rv  != 0)
+		    return (-1);
 		si->logged_in = 1;
 	}
 	key_filter[1].pValue = k11->keyid;
@@ -287,16 +307,34 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
 	if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 &&
 	    pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) {
 		error("cannot find private key");
-	} else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
-		error("C_SignInit failed: %lu", rv);
-	} else {
-		/* XXX handle CKR_BUFFER_TOO_SMALL */
-		tlen = RSA_size(rsa);
-		rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen);
-		if (rv == CKR_OK) 
-			rval = tlen;
-		else 
-			error("C_Sign failed: %lu", rv);
+		goto fail;
+	}
+	/* If pkcs11 lib does support this, assume false get before C_SignInit */
+	f->C_GetAttributeValue(si->session, obj, key_cka_always_authenticate, 1);
+	if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
+			error("C_SignInit failed: %lu", rv);
+			goto fail;
+	}
+	if (cka_always_authenticate) {
+		/* if we have the PIN from above use it, or get it now */
+		rv = pkcs11_c_login(k11->provider, si, CKU_CONTEXT_SPECIFIC, &pin);
+		if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
+		    error("Context specific login failed %lu", rv);
+		    goto fail;
+		}
+	}
+	/* XXX handle CKR_BUFFER_TOO_SMALL */
+	tlen = RSA_size(rsa);
+	rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen);
+	if (rv == CKR_OK)
+		rval = tlen;
+	else
+		error("C_Sign failed: %lu", rv);
+fail:
+	if (pin != NULL) {
+		explicit_bzero(pin, strlen(pin));
+		free(pin);
+		pin = NULL;
 	}
 	return (rval);
 }
-- 
2.7.4

_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@xxxxxxxxxxx
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux