summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ssh-agent.c19
-rw-r--r--ssh-keygen.c14
-rw-r--r--ssh-pkcs11-client.c14
-rw-r--r--ssh-pkcs11-helper.c21
-rw-r--r--ssh-pkcs11.c142
-rw-r--r--ssh-pkcs11.h4
-rw-r--r--ssh.c12
7 files changed, 144 insertions, 82 deletions
diff --git a/ssh-agent.c b/ssh-agent.c
index dd5d21d5a..6092f19dc 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-agent.c,v 1.252 2020/01/23 07:10:22 dtucker Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.253 2020/01/25 00:03:36 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -633,6 +633,7 @@ static void
633process_add_smartcard_key(SocketEntry *e) 633process_add_smartcard_key(SocketEntry *e)
634{ 634{
635 char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; 635 char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
636 char **comments = NULL;
636 int r, i, count = 0, success = 0, confirm = 0; 637 int r, i, count = 0, success = 0, confirm = 0;
637 u_int seconds; 638 u_int seconds;
638 time_t death = 0; 639 time_t death = 0;
@@ -682,28 +683,34 @@ process_add_smartcard_key(SocketEntry *e)
682 if (lifetime && !death) 683 if (lifetime && !death)
683 death = monotime() + lifetime; 684 death = monotime() + lifetime;
684 685
685 count = pkcs11_add_provider(canonical_provider, pin, &keys); 686 count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments);
686 for (i = 0; i < count; i++) { 687 for (i = 0; i < count; i++) {
687 k = keys[i]; 688 k = keys[i];
688 if (lookup_identity(k) == NULL) { 689 if (lookup_identity(k) == NULL) {
689 id = xcalloc(1, sizeof(Identity)); 690 id = xcalloc(1, sizeof(Identity));
690 id->key = k; 691 id->key = k;
692 keys[i] = NULL; /* transferred */
691 id->provider = xstrdup(canonical_provider); 693 id->provider = xstrdup(canonical_provider);
692 id->comment = xstrdup(canonical_provider); /* XXX */ 694 if (*comments[i] != '\0') {
695 id->comment = comments[i];
696 comments[i] = NULL; /* transferred */
697 } else {
698 id->comment = xstrdup(canonical_provider);
699 }
693 id->death = death; 700 id->death = death;
694 id->confirm = confirm; 701 id->confirm = confirm;
695 TAILQ_INSERT_TAIL(&idtab->idlist, id, next); 702 TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
696 idtab->nentries++; 703 idtab->nentries++;
697 success = 1; 704 success = 1;
698 } else {
699 sshkey_free(k);
700 } 705 }
701 keys[i] = NULL; 706 sshkey_free(keys[i]);
707 free(comments[i]);
702 } 708 }
703send: 709send:
704 free(pin); 710 free(pin);
705 free(provider); 711 free(provider);
706 free(keys); 712 free(keys);
713 free(comments);
707 send_status(e, success); 714 send_status(e, success);
708} 715}
709 716
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 2c9f67862..14d2357a7 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.391 2020/01/24 05:33:01 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.392 2020/01/25 00:03:36 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -829,13 +829,13 @@ do_download(struct passwd *pw)
829 int i, nkeys; 829 int i, nkeys;
830 enum sshkey_fp_rep rep; 830 enum sshkey_fp_rep rep;
831 int fptype; 831 int fptype;
832 char *fp, *ra; 832 char *fp, *ra, **comments = NULL;
833 833
834 fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; 834 fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
835 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; 835 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
836 836
837 pkcs11_init(1); 837 pkcs11_init(1);
838 nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys); 838 nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys, &comments);
839 if (nkeys <= 0) 839 if (nkeys <= 0)
840 fatal("cannot read public key from pkcs11"); 840 fatal("cannot read public key from pkcs11");
841 for (i = 0; i < nkeys; i++) { 841 for (i = 0; i < nkeys; i++) {
@@ -853,10 +853,13 @@ do_download(struct passwd *pw)
853 free(fp); 853 free(fp);
854 } else { 854 } else {
855 (void) sshkey_write(keys[i], stdout); /* XXX check */ 855 (void) sshkey_write(keys[i], stdout); /* XXX check */
856 fprintf(stdout, "\n"); 856 fprintf(stdout, "%s%s\n",
857 *(comments[i]) == '\0' ? "" : " ", comments[i]);
857 } 858 }
859 free(comments[i]);
858 sshkey_free(keys[i]); 860 sshkey_free(keys[i]);
859 } 861 }
862 free(comments);
860 free(keys); 863 free(keys);
861 pkcs11_terminate(); 864 pkcs11_terminate();
862 exit(0); 865 exit(0);
@@ -1703,7 +1706,8 @@ load_pkcs11_key(char *path)
1703 fatal("Couldn't load CA public key \"%s\": %s", 1706 fatal("Couldn't load CA public key \"%s\": %s",
1704 path, ssh_err(r)); 1707 path, ssh_err(r));
1705 1708
1706 nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys); 1709 nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase,
1710 &keys, NULL);
1707 debug3("%s: %d keys", __func__, nkeys); 1711 debug3("%s: %d keys", __func__, nkeys);
1708 if (nkeys <= 0) 1712 if (nkeys <= 0)
1709 fatal("cannot read public key from pkcs11"); 1713 fatal("cannot read public key from pkcs11");
diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
index e7860de89..8a0ffef5d 100644
--- a/ssh-pkcs11-client.c
+++ b/ssh-pkcs11-client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11-client.c,v 1.15 2019/01/21 12:53:35 djm Exp $ */ 1/* $OpenBSD: ssh-pkcs11-client.c,v 1.16 2020/01/25 00:03:36 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved. 4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
@@ -312,11 +312,13 @@ pkcs11_start_helper(void)
312} 312}
313 313
314int 314int
315pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp) 315pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
316 char ***labelsp)
316{ 317{
317 struct sshkey *k; 318 struct sshkey *k;
318 int r, type; 319 int r, type;
319 u_char *blob; 320 u_char *blob;
321 char *label;
320 size_t blen; 322 size_t blen;
321 u_int nkeys, i; 323 u_int nkeys, i;
322 struct sshbuf *msg; 324 struct sshbuf *msg;
@@ -338,16 +340,22 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp)
338 if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) 340 if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
339 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 341 fatal("%s: buffer error: %s", __func__, ssh_err(r));
340 *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); 342 *keysp = xcalloc(nkeys, sizeof(struct sshkey *));
343 if (labelsp)
344 *labelsp = xcalloc(nkeys, sizeof(char *));
341 for (i = 0; i < nkeys; i++) { 345 for (i = 0; i < nkeys; i++) {
342 /* XXX clean up properly instead of fatal() */ 346 /* XXX clean up properly instead of fatal() */
343 if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || 347 if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 ||
344 (r = sshbuf_skip_string(msg)) != 0) 348 (r = sshbuf_get_cstring(msg, &label, NULL)) != 0)
345 fatal("%s: buffer error: %s", 349 fatal("%s: buffer error: %s",
346 __func__, ssh_err(r)); 350 __func__, ssh_err(r));
347 if ((r = sshkey_from_blob(blob, blen, &k)) != 0) 351 if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
348 fatal("%s: bad key: %s", __func__, ssh_err(r)); 352 fatal("%s: bad key: %s", __func__, ssh_err(r));
349 wrap_key(k); 353 wrap_key(k);
350 (*keysp)[i] = k; 354 (*keysp)[i] = k;
355 if (labelsp)
356 (*labelsp)[i] = label;
357 else
358 free(label);
351 free(blob); 359 free(blob);
352 } 360 }
353 } else if (type == SSH2_AGENT_FAILURE) { 361 } else if (type == SSH2_AGENT_FAILURE) {
diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c
index 219ce9b5d..17220d624 100644
--- a/ssh-pkcs11-helper.c
+++ b/ssh-pkcs11-helper.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11-helper.c,v 1.21 2019/09/06 05:23:55 djm Exp $ */ 1/* $OpenBSD: ssh-pkcs11-helper.c,v 1.22 2020/01/25 00:03:36 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * 4 *
@@ -50,7 +50,7 @@
50 50
51struct pkcs11_keyinfo { 51struct pkcs11_keyinfo {
52 struct sshkey *key; 52 struct sshkey *key;
53 char *providername; 53 char *providername, *label;
54 TAILQ_ENTRY(pkcs11_keyinfo) next; 54 TAILQ_ENTRY(pkcs11_keyinfo) next;
55}; 55};
56 56
@@ -63,13 +63,14 @@ struct sshbuf *iqueue;
63struct sshbuf *oqueue; 63struct sshbuf *oqueue;
64 64
65static void 65static void
66add_key(struct sshkey *k, char *name) 66add_key(struct sshkey *k, char *name, char *label)
67{ 67{
68 struct pkcs11_keyinfo *ki; 68 struct pkcs11_keyinfo *ki;
69 69
70 ki = xcalloc(1, sizeof(*ki)); 70 ki = xcalloc(1, sizeof(*ki));
71 ki->providername = xstrdup(name); 71 ki->providername = xstrdup(name);
72 ki->key = k; 72 ki->key = k;
73 ki->label = xstrdup(label);
73 TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next); 74 TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next);
74} 75}
75 76
@@ -83,6 +84,7 @@ del_keys_by_name(char *name)
83 if (!strcmp(ki->providername, name)) { 84 if (!strcmp(ki->providername, name)) {
84 TAILQ_REMOVE(&pkcs11_keylist, ki, next); 85 TAILQ_REMOVE(&pkcs11_keylist, ki, next);
85 free(ki->providername); 86 free(ki->providername);
87 free(ki->label);
86 sshkey_free(ki->key); 88 sshkey_free(ki->key);
87 free(ki); 89 free(ki);
88 } 90 }
@@ -96,7 +98,7 @@ lookup_key(struct sshkey *k)
96 struct pkcs11_keyinfo *ki; 98 struct pkcs11_keyinfo *ki;
97 99
98 TAILQ_FOREACH(ki, &pkcs11_keylist, next) { 100 TAILQ_FOREACH(ki, &pkcs11_keylist, next) {
99 debug("check %p %s", ki, ki->providername); 101 debug("check %p %s %s", ki, ki->providername, ki->label);
100 if (sshkey_equal(k, ki->key)) 102 if (sshkey_equal(k, ki->key))
101 return (ki->key); 103 return (ki->key);
102 } 104 }
@@ -121,13 +123,14 @@ process_add(void)
121 u_char *blob; 123 u_char *blob;
122 size_t blen; 124 size_t blen;
123 struct sshbuf *msg; 125 struct sshbuf *msg;
126 char **labels = NULL;
124 127
125 if ((msg = sshbuf_new()) == NULL) 128 if ((msg = sshbuf_new()) == NULL)
126 fatal("%s: sshbuf_new failed", __func__); 129 fatal("%s: sshbuf_new failed", __func__);
127 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || 130 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
128 (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0) 131 (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
129 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 132 fatal("%s: buffer error: %s", __func__, ssh_err(r));
130 if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) { 133 if ((nkeys = pkcs11_add_provider(name, pin, &keys, &labels)) > 0) {
131 if ((r = sshbuf_put_u8(msg, 134 if ((r = sshbuf_put_u8(msg,
132 SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || 135 SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
133 (r = sshbuf_put_u32(msg, nkeys)) != 0) 136 (r = sshbuf_put_u32(msg, nkeys)) != 0)
@@ -139,11 +142,12 @@ process_add(void)
139 continue; 142 continue;
140 } 143 }
141 if ((r = sshbuf_put_string(msg, blob, blen)) != 0 || 144 if ((r = sshbuf_put_string(msg, blob, blen)) != 0 ||
142 (r = sshbuf_put_cstring(msg, name)) != 0) 145 (r = sshbuf_put_cstring(msg, labels[i])) != 0)
143 fatal("%s: buffer error: %s", 146 fatal("%s: buffer error: %s",
144 __func__, ssh_err(r)); 147 __func__, ssh_err(r));
145 free(blob); 148 free(blob);
146 add_key(keys[i], name); 149 add_key(keys[i], name, labels[i]);
150 free(labels[i]);
147 } 151 }
148 } else { 152 } else {
149 if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) 153 if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
@@ -151,7 +155,8 @@ process_add(void)
151 if ((r = sshbuf_put_u32(msg, -nkeys)) != 0) 155 if ((r = sshbuf_put_u32(msg, -nkeys)) != 0)
152 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 156 fatal("%s: buffer error: %s", __func__, ssh_err(r));
153 } 157 }
154 free(keys); 158 free(labels);
159 free(keys); /* keys themselves are transferred to pkcs11_keylist */
155 free(pin); 160 free(pin);
156 free(name); 161 free(name);
157 send_msg(msg); 162 send_msg(msg);
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index 09f1ea347..a302c79c0 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11.c,v 1.46 2019/10/01 10:22:53 djm Exp $ */ 1/* $OpenBSD: ssh-pkcs11.c,v 1.47 2020/01/25 00:03:36 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved. 4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
@@ -893,15 +893,16 @@ fail:
893 return (key); 893 return (key);
894} 894}
895 895
896static struct sshkey * 896static int
897pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, 897pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
898 CK_OBJECT_HANDLE *obj) 898 CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp)
899{ 899{
900 CK_ATTRIBUTE cert_attr[3]; 900 CK_ATTRIBUTE cert_attr[3];
901 CK_SESSION_HANDLE session; 901 CK_SESSION_HANDLE session;
902 CK_FUNCTION_LIST *f = NULL; 902 CK_FUNCTION_LIST *f = NULL;
903 CK_RV rv; 903 CK_RV rv;
904 X509 *x509 = NULL; 904 X509 *x509 = NULL;
905 X509_NAME *x509_name = NULL;
905 EVP_PKEY *evp; 906 EVP_PKEY *evp;
906 RSA *rsa = NULL; 907 RSA *rsa = NULL;
907#ifdef OPENSSL_HAS_ECC 908#ifdef OPENSSL_HAS_ECC
@@ -912,7 +913,11 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
912#ifdef HAVE_EC_KEY_METHOD_NEW 913#ifdef HAVE_EC_KEY_METHOD_NEW
913 int nid; 914 int nid;
914#endif 915#endif
915 const u_char *cp; 916 const u_char *cp;
917 char *subject = NULL;
918
919 *keyp = NULL;
920 *labelp = NULL;
916 921
917 memset(&cert_attr, 0, sizeof(cert_attr)); 922 memset(&cert_attr, 0, sizeof(cert_attr));
918 cert_attr[0].type = CKA_ID; 923 cert_attr[0].type = CKA_ID;
@@ -926,7 +931,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
926 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); 931 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
927 if (rv != CKR_OK) { 932 if (rv != CKR_OK) {
928 error("C_GetAttributeValue failed: %lu", rv); 933 error("C_GetAttributeValue failed: %lu", rv);
929 return (NULL); 934 return -1;
930 } 935 }
931 936
932 /* 937 /*
@@ -937,7 +942,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
937 if (cert_attr[1].ulValueLen == 0 || 942 if (cert_attr[1].ulValueLen == 0 ||
938 cert_attr[2].ulValueLen == 0) { 943 cert_attr[2].ulValueLen == 0) {
939 error("invalid attribute length"); 944 error("invalid attribute length");
940 return (NULL); 945 return -1;
941 } 946 }
942 947
943 /* allocate buffers for attributes */ 948 /* allocate buffers for attributes */
@@ -949,44 +954,45 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
949 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); 954 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
950 if (rv != CKR_OK) { 955 if (rv != CKR_OK) {
951 error("C_GetAttributeValue failed: %lu", rv); 956 error("C_GetAttributeValue failed: %lu", rv);
952 goto fail; 957 goto out;
953 } 958 }
954 959
955 x509 = X509_new(); 960 /* Decode DER-encoded cert subject */
956 if (x509 == NULL) { 961 cp = cert_attr[2].pValue;
957 error("x509_new failed"); 962 if ((x509_name = d2i_X509_NAME(NULL, &cp,
958 goto fail; 963 cert_attr[1].ulValueLen)) == NULL ||
959 } 964 (subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL)
965 subject = xstrdup("invalid subject");
966 X509_NAME_free(x509_name);
960 967
961 cp = cert_attr[2].pValue; 968 cp = cert_attr[2].pValue;
962 if (d2i_X509(&x509, &cp, cert_attr[2].ulValueLen) == NULL) { 969 if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) {
963 error("d2i_x509 failed"); 970 error("d2i_x509 failed");
964 goto fail; 971 goto out;
965 } 972 }
966 973
967 evp = X509_get_pubkey(x509); 974 if ((evp = X509_get_pubkey(x509)) == NULL) {
968 if (evp == NULL) {
969 error("X509_get_pubkey failed"); 975 error("X509_get_pubkey failed");
970 goto fail; 976 goto out;
971 } 977 }
972 978
973 if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) { 979 if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {
974 if (EVP_PKEY_get0_RSA(evp) == NULL) { 980 if (EVP_PKEY_get0_RSA(evp) == NULL) {
975 error("invalid x509; no rsa key"); 981 error("invalid x509; no rsa key");
976 goto fail; 982 goto out;
977 } 983 }
978 if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) { 984 if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {
979 error("RSAPublicKey_dup failed"); 985 error("RSAPublicKey_dup failed");
980 goto fail; 986 goto out;
981 } 987 }
982 988
983 if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) 989 if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa))
984 goto fail; 990 goto out;
985 991
986 key = sshkey_new(KEY_UNSPEC); 992 key = sshkey_new(KEY_UNSPEC);
987 if (key == NULL) { 993 if (key == NULL) {
988 error("sshkey_new failed"); 994 error("sshkey_new failed");
989 goto fail; 995 goto out;
990 } 996 }
991 997
992 key->rsa = rsa; 998 key->rsa = rsa;
@@ -997,26 +1003,26 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
997 } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) { 1003 } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
998 if (EVP_PKEY_get0_EC_KEY(evp) == NULL) { 1004 if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
999 error("invalid x509; no ec key"); 1005 error("invalid x509; no ec key");
1000 goto fail; 1006 goto out;
1001 } 1007 }
1002 if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) { 1008 if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {
1003 error("EC_KEY_dup failed"); 1009 error("EC_KEY_dup failed");
1004 goto fail; 1010 goto out;
1005 } 1011 }
1006 1012
1007 nid = sshkey_ecdsa_key_to_nid(ec); 1013 nid = sshkey_ecdsa_key_to_nid(ec);
1008 if (nid < 0) { 1014 if (nid < 0) {
1009 error("couldn't get curve nid"); 1015 error("couldn't get curve nid");
1010 goto fail; 1016 goto out;
1011 } 1017 }
1012 1018
1013 if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) 1019 if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec))
1014 goto fail; 1020 goto out;
1015 1021
1016 key = sshkey_new(KEY_UNSPEC); 1022 key = sshkey_new(KEY_UNSPEC);
1017 if (key == NULL) { 1023 if (key == NULL) {
1018 error("sshkey_new failed"); 1024 error("sshkey_new failed");
1019 goto fail; 1025 goto out;
1020 } 1026 }
1021 1027
1022 key->ecdsa = ec; 1028 key->ecdsa = ec;
@@ -1025,10 +1031,11 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
1025 key->flags |= SSHKEY_FLAG_EXT; 1031 key->flags |= SSHKEY_FLAG_EXT;
1026 ec = NULL; /* now owned by key */ 1032 ec = NULL; /* now owned by key */
1027#endif /* HAVE_EC_KEY_METHOD_NEW */ 1033#endif /* HAVE_EC_KEY_METHOD_NEW */
1028 } else 1034 } else {
1029 error("unknown certificate key type"); 1035 error("unknown certificate key type");
1030 1036 goto out;
1031fail: 1037 }
1038 out:
1032 for (i = 0; i < 3; i++) 1039 for (i = 0; i < 3; i++)
1033 free(cert_attr[i].pValue); 1040 free(cert_attr[i].pValue);
1034 X509_free(x509); 1041 X509_free(x509);
@@ -1036,8 +1043,14 @@ fail:
1036#ifdef OPENSSL_HAS_ECC 1043#ifdef OPENSSL_HAS_ECC
1037 EC_KEY_free(ec); 1044 EC_KEY_free(ec);
1038#endif 1045#endif
1039 1046 if (key == NULL) {
1040 return (key); 1047 free(subject);
1048 return -1;
1049 }
1050 /* success */
1051 *keyp = key;
1052 *labelp = subject;
1053 return 0;
1041} 1054}
1042 1055
1043#if 0 1056#if 0
@@ -1058,7 +1071,7 @@ have_rsa_key(const RSA *rsa)
1058 */ 1071 */
1059static int 1072static int
1060pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, 1073pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1061 struct sshkey ***keysp, int *nkeys) 1074 struct sshkey ***keysp, char ***labelsp, int *nkeys)
1062{ 1075{
1063 struct sshkey *key = NULL; 1076 struct sshkey *key = NULL;
1064 CK_OBJECT_CLASS key_class; 1077 CK_OBJECT_CLASS key_class;
@@ -1069,6 +1082,7 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1069 CK_OBJECT_HANDLE obj; 1082 CK_OBJECT_HANDLE obj;
1070 CK_ULONG n = 0; 1083 CK_ULONG n = 0;
1071 int ret = -1; 1084 int ret = -1;
1085 char *label;
1072 1086
1073 memset(&key_attr, 0, sizeof(key_attr)); 1087 memset(&key_attr, 0, sizeof(key_attr));
1074 memset(&obj, 0, sizeof(obj)); 1088 memset(&obj, 0, sizeof(obj));
@@ -1110,18 +1124,19 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1110 goto fail; 1124 goto fail;
1111 } 1125 }
1112 1126
1127 key = NULL;
1128 label = NULL;
1113 switch (ck_cert_type) { 1129 switch (ck_cert_type) {
1114 case CKC_X_509: 1130 case CKC_X_509:
1115 key = pkcs11_fetch_x509_pubkey(p, slotidx, &obj); 1131 if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj,
1132 &key, &label) != 0) {
1133 error("failed to fetch key");
1134 continue;
1135 }
1116 break; 1136 break;
1117 default: 1137 default:
1118 /* XXX print key type? */ 1138 error("skipping unsupported certificate type %lu",
1119 key = NULL; 1139 ck_cert_type);
1120 error("skipping unsupported certificate type");
1121 }
1122
1123 if (key == NULL) {
1124 error("failed to fetch key");
1125 continue; 1140 continue;
1126 } 1141 }
1127 1142
@@ -1132,6 +1147,11 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1132 *keysp = xrecallocarray(*keysp, *nkeys, 1147 *keysp = xrecallocarray(*keysp, *nkeys,
1133 *nkeys + 1, sizeof(struct sshkey *)); 1148 *nkeys + 1, sizeof(struct sshkey *));
1134 (*keysp)[*nkeys] = key; 1149 (*keysp)[*nkeys] = key;
1150 if (labelsp != NULL) {
1151 *labelsp = xrecallocarray(*labelsp, *nkeys,
1152 *nkeys + 1, sizeof(char *));
1153 (*labelsp)[*nkeys] = xstrdup((char *)label);
1154 }
1135 *nkeys = *nkeys + 1; 1155 *nkeys = *nkeys + 1;
1136 debug("have %d keys", *nkeys); 1156 debug("have %d keys", *nkeys);
1137 } 1157 }
@@ -1155,11 +1175,11 @@ fail:
1155 */ 1175 */
1156static int 1176static int
1157pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, 1177pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1158 struct sshkey ***keysp, int *nkeys) 1178 struct sshkey ***keysp, char ***labelsp, int *nkeys)
1159{ 1179{
1160 struct sshkey *key = NULL; 1180 struct sshkey *key = NULL;
1161 CK_OBJECT_CLASS key_class; 1181 CK_OBJECT_CLASS key_class;
1162 CK_ATTRIBUTE key_attr[1]; 1182 CK_ATTRIBUTE key_attr[2];
1163 CK_SESSION_HANDLE session; 1183 CK_SESSION_HANDLE session;
1164 CK_FUNCTION_LIST *f = NULL; 1184 CK_FUNCTION_LIST *f = NULL;
1165 CK_RV rv; 1185 CK_RV rv;
@@ -1186,6 +1206,7 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1186 1206
1187 while (1) { 1207 while (1) {
1188 CK_KEY_TYPE ck_key_type; 1208 CK_KEY_TYPE ck_key_type;
1209 CK_UTF8CHAR label[256];
1189 1210
1190 rv = f->C_FindObjects(session, &obj, 1, &n); 1211 rv = f->C_FindObjects(session, &obj, 1, &n);
1191 if (rv != CKR_OK) { 1212 if (rv != CKR_OK) {
@@ -1200,13 +1221,18 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1200 key_attr[0].type = CKA_KEY_TYPE; 1221 key_attr[0].type = CKA_KEY_TYPE;
1201 key_attr[0].pValue = &ck_key_type; 1222 key_attr[0].pValue = &ck_key_type;
1202 key_attr[0].ulValueLen = sizeof(ck_key_type); 1223 key_attr[0].ulValueLen = sizeof(ck_key_type);
1224 key_attr[1].type = CKA_LABEL;
1225 key_attr[1].pValue = &label;
1226 key_attr[1].ulValueLen = sizeof(label) - 1;
1203 1227
1204 rv = f->C_GetAttributeValue(session, obj, key_attr, 1); 1228 rv = f->C_GetAttributeValue(session, obj, key_attr, 2);
1205 if (rv != CKR_OK) { 1229 if (rv != CKR_OK) {
1206 error("C_GetAttributeValue failed: %lu", rv); 1230 error("C_GetAttributeValue failed: %lu", rv);
1207 goto fail; 1231 goto fail;
1208 } 1232 }
1209 1233
1234 label[key_attr[1].ulValueLen] = '\0';
1235
1210 switch (ck_key_type) { 1236 switch (ck_key_type) {
1211 case CKK_RSA: 1237 case CKK_RSA:
1212 key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); 1238 key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
@@ -1234,6 +1260,11 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1234 *keysp = xrecallocarray(*keysp, *nkeys, 1260 *keysp = xrecallocarray(*keysp, *nkeys,
1235 *nkeys + 1, sizeof(struct sshkey *)); 1261 *nkeys + 1, sizeof(struct sshkey *));
1236 (*keysp)[*nkeys] = key; 1262 (*keysp)[*nkeys] = key;
1263 if (labelsp != NULL) {
1264 *labelsp = xrecallocarray(*labelsp, *nkeys,
1265 *nkeys + 1, sizeof(char *));
1266 (*labelsp)[*nkeys] = xstrdup((char *)label);
1267 }
1237 *nkeys = *nkeys + 1; 1268 *nkeys = *nkeys + 1;
1238 debug("have %d keys", *nkeys); 1269 debug("have %d keys", *nkeys);
1239 } 1270 }
@@ -1440,7 +1471,8 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
1440 * keyp is provided, fetch keys. 1471 * keyp is provided, fetch keys.
1441 */ 1472 */
1442static int 1473static int
1443pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, 1474pkcs11_register_provider(char *provider_id, char *pin,
1475 struct sshkey ***keyp, char ***labelsp,
1444 struct pkcs11_provider **providerp, CK_ULONG user) 1476 struct pkcs11_provider **providerp, CK_ULONG user)
1445{ 1477{
1446 int nkeys, need_finalize = 0; 1478 int nkeys, need_finalize = 0;
@@ -1459,6 +1491,8 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1459 1491
1460 if (keyp != NULL) 1492 if (keyp != NULL)
1461 *keyp = NULL; 1493 *keyp = NULL;
1494 if (labelsp != NULL)
1495 *labelsp = NULL;
1462 1496
1463 if (pkcs11_provider_lookup(provider_id) != NULL) { 1497 if (pkcs11_provider_lookup(provider_id) != NULL) {
1464 debug("%s: provider already registered: %s", 1498 debug("%s: provider already registered: %s",
@@ -1556,8 +1590,8 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1556 if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || 1590 if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 ||
1557 keyp == NULL) 1591 keyp == NULL)
1558 continue; 1592 continue;
1559 pkcs11_fetch_keys(p, i, keyp, &nkeys); 1593 pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1560 pkcs11_fetch_certs(p, i, keyp, &nkeys); 1594 pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1561 if (nkeys == 0 && !p->slotinfo[i].logged_in && 1595 if (nkeys == 0 && !p->slotinfo[i].logged_in &&
1562 pkcs11_interactive) { 1596 pkcs11_interactive) {
1563 /* 1597 /*
@@ -1569,8 +1603,8 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1569 error("login failed"); 1603 error("login failed");
1570 continue; 1604 continue;
1571 } 1605 }
1572 pkcs11_fetch_keys(p, i, keyp, &nkeys); 1606 pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1573 pkcs11_fetch_certs(p, i, keyp, &nkeys); 1607 pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1574 } 1608 }
1575 } 1609 }
1576 1610
@@ -1601,12 +1635,14 @@ fail:
1601 * fails if provider already exists 1635 * fails if provider already exists
1602 */ 1636 */
1603int 1637int
1604pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) 1638pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1639 char ***labelsp)
1605{ 1640{
1606 struct pkcs11_provider *p = NULL; 1641 struct pkcs11_provider *p = NULL;
1607 int nkeys; 1642 int nkeys;
1608 1643
1609 nkeys = pkcs11_register_provider(provider_id, pin, keyp, &p, CKU_USER); 1644 nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp,
1645 &p, CKU_USER);
1610 1646
1611 /* no keys found or some other error, de-register provider */ 1647 /* no keys found or some other error, de-register provider */
1612 if (nkeys <= 0 && p != NULL) { 1648 if (nkeys <= 0 && p != NULL) {
@@ -1638,8 +1674,8 @@ pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
1638 1674
1639 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) 1675 if ((p = pkcs11_provider_lookup(provider_id)) != NULL)
1640 debug("%s: provider \"%s\" available", __func__, provider_id); 1676 debug("%s: provider \"%s\" available", __func__, provider_id);
1641 else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, &p, 1677 else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL,
1642 CKU_SO)) < 0) { 1678 &p, CKU_SO)) < 0) {
1643 debug("%s: could not register provider %s", __func__, 1679 debug("%s: could not register provider %s", __func__,
1644 provider_id); 1680 provider_id);
1645 goto out; 1681 goto out;
@@ -1710,7 +1746,7 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
1710 1746
1711 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { 1747 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
1712 debug("%s: using provider \"%s\"", __func__, provider_id); 1748 debug("%s: using provider \"%s\"", __func__, provider_id);
1713 } else if (pkcs11_register_provider(provider_id, pin, NULL, &p, 1749 } else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p,
1714 CKU_SO) < 0) { 1750 CKU_SO) < 0) {
1715 debug("%s: could not register provider %s", __func__, 1751 debug("%s: could not register provider %s", __func__,
1716 provider_id); 1752 provider_id);
diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h
index b9038450d..81f1d7c5d 100644
--- a/ssh-pkcs11.h
+++ b/ssh-pkcs11.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11.h,v 1.5 2019/01/20 22:51:37 djm Exp $ */ 1/* $OpenBSD: ssh-pkcs11.h,v 1.6 2020/01/25 00:03:36 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * 4 *
@@ -24,7 +24,7 @@
24 24
25int pkcs11_init(int); 25int pkcs11_init(int);
26void pkcs11_terminate(void); 26void pkcs11_terminate(void);
27int pkcs11_add_provider(char *, char *, struct sshkey ***); 27int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***);
28int pkcs11_del_provider(char *); 28int pkcs11_del_provider(char *);
29#ifdef WITH_PKCS11_KEYGEN 29#ifdef WITH_PKCS11_KEYGEN
30struct sshkey * 30struct sshkey *
diff --git a/ssh.c b/ssh.c
index 851d85b50..8931ecf81 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.513 2020/01/23 10:24:29 dtucker Exp $ */ 1/* $OpenBSD: ssh.c,v 1.514 2020/01/25 00:03:36 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2072,7 +2072,8 @@ load_public_identity_files(struct passwd *pw)
2072 struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; 2072 struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
2073 int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; 2073 int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES];
2074#ifdef ENABLE_PKCS11 2074#ifdef ENABLE_PKCS11
2075 struct sshkey **keys; 2075 struct sshkey **keys = NULL;
2076 char **comments = NULL;
2076 int nkeys; 2077 int nkeys;
2077#endif /* PKCS11 */ 2078#endif /* PKCS11 */
2078 2079
@@ -2091,18 +2092,19 @@ load_public_identity_files(struct passwd *pw)
2091 options.num_identity_files < SSH_MAX_IDENTITY_FILES && 2092 options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
2092 (pkcs11_init(!options.batch_mode) == 0) && 2093 (pkcs11_init(!options.batch_mode) == 0) &&
2093 (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, 2094 (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
2094 &keys)) > 0) { 2095 &keys, &comments)) > 0) {
2095 for (i = 0; i < nkeys; i++) { 2096 for (i = 0; i < nkeys; i++) {
2096 if (n_ids >= SSH_MAX_IDENTITY_FILES) { 2097 if (n_ids >= SSH_MAX_IDENTITY_FILES) {
2097 sshkey_free(keys[i]); 2098 sshkey_free(keys[i]);
2099 free(comments[i]);
2098 continue; 2100 continue;
2099 } 2101 }
2100 identity_keys[n_ids] = keys[i]; 2102 identity_keys[n_ids] = keys[i];
2101 identity_files[n_ids] = 2103 identity_files[n_ids] = comments[i]; /* transferred */
2102 xstrdup(options.pkcs11_provider); /* XXX */
2103 n_ids++; 2104 n_ids++;
2104 } 2105 }
2105 free(keys); 2106 free(keys);
2107 free(comments);
2106 } 2108 }
2107#endif /* ENABLE_PKCS11 */ 2109#endif /* ENABLE_PKCS11 */
2108 for (i = 0; i < options.num_identity_files; i++) { 2110 for (i = 0; i < options.num_identity_files; i++) {