[PATCH 1/1] Support PKCS#11 URI keys vi libp11

James Bottomley James.Bottomley at HansenPartnership.com
Thu Jun 11 04:15:48 AEST 2020


PKCS#11 URIs are an RFC7512 scheme for naming individual token based
keys.  In a system which supports them (Such as via p11-kit), every
key may be uniquely specified via such a URI (so you can add specific
keys from token which have more than one).  libp11 is a project that
installs an openssl engine which supports PKCS#11 URIs via modules
installed in the p11-kit directory.

Support is simple in that the OpenSSL libp11 engine already supports
the URI scheme, so all that has to be done is to add extra code to try
the engines anyway, even if a file corresponding to the ssh-add can't
be found.  The only problem with this scheme is that it can't return a
meaningful error if there's a problem with the PKCS#11 URI.  This will
be fixed in the provider architecture, but it's a historical remnant
of the way the engine keys work (returning NULL for every error).

The key can be inserted by URI:

> ssh-add 'pkcs11:token=id_rsa_new'

And when successfully added, it will be shown by URI:

> ssh-add -l
2048 SHA256:6q8CFWO4m3Ky99h+Mp9b6KEBTdobxUZQGzd0Sgxilpg pkcs11:token=id_rsa_new (RSA)

Signed-off-by: James Bottomley <James.Bottomley at HansenPartnership.com>
---
 ssh-add.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/ssh-add.c b/ssh-add.c
index b0ce393c7..017dea228 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -227,13 +227,19 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag,
 	int r, fd, ret = -1;
 	size_t i;
 	u_int32_t left;
-	struct sshbuf *keyblob;
+	struct sshbuf *keyblob = NULL;
 	struct ssh_identitylist *idlist;
 
 	if (strcmp(filename, "-") == 0) {
 		fd = STDIN_FILENO;
 		filename = "(stdin)";
 	} else if ((fd = open(filename, O_RDONLY)) == -1) {
+#ifdef USE_OPENSSL_ENGINE
+		if (errno == ENOENT) {
+			r = 0;
+			goto engine;
+		}
+#endif
 		perror(filename);
 		return -1;
 	}
@@ -261,12 +267,17 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag,
 	if ((r = sshkey_parse_private_fileblob(keyblob, "", &private,
 	    &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
 #ifdef USE_OPENSSL_ENGINE
-		int n_r = add_engine_key(agent_fd, filename);
+		int n_r;
 
+	engine:
+		n_r = add_engine_key(agent_fd, filename);
 		if (n_r == SSH_AGENT_SUCCESS) {
 			clear_pass();
 			sshbuf_free(keyblob);
 			return 0;
+		} else if (r == 0 && n_r == SSH_ERR_INTERNAL_ERROR) {
+			perror(filename);
+			return -1;
 		} else if (n_r != SSH_ERR_INTERNAL_ERROR) {
 			r = n_r;
 		}
-- 
2.26.2



More information about the openssh-unix-dev mailing list