summaryrefslogtreecommitdiff
path: root/ssh-sk-helper.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2020-01-06 02:00:46 +0000
committerDamien Miller <djm@mindrot.org>2020-01-06 13:12:46 +1100
commitc312ca077cd2a6c15545cd6b4d34ee2f69289174 (patch)
treeb8dd974c55dd0de351dfcbfc4f33fddb935a1c12 /ssh-sk-helper.c
parent2ab335712d084d9ccaf3f53afc3fa9535329da87 (diff)
upstream: Extends the SK API to accept a set of key/value options
for all operations. These are intended to future-proof the API a little by making it easier to specify additional fields for without having to change the API version for each. At present, only two options are defined: one to explicitly specify the device for an operation (rather than accepting the middleware's autoselection) and another to specify the FIDO2 username that may be used when generating a resident key. These new options may be invoked at key generation time via ssh-keygen -O This also implements a suggestion from Markus to avoid "int" in favour of uint32_t for the algorithm argument in the API, to make implementation of ssh-sk-client/helper a little easier. feedback, fixes and ok markus@ OpenBSD-Commit-ID: 973ce11704609022ab36abbdeb6bc23c8001eabc
Diffstat (limited to 'ssh-sk-helper.c')
-rw-r--r--ssh-sk-helper.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/ssh-sk-helper.c b/ssh-sk-helper.c
index 590ff8501..85a461d53 100644
--- a/ssh-sk-helper.c
+++ b/ssh-sk-helper.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-sk-helper.c,v 1.6 2019/12/30 09:23:28 djm Exp $ */ 1/* $OpenBSD: ssh-sk-helper.c,v 1.7 2020/01/06 02:00:46 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Google LLC 3 * Copyright (c) 2019 Google LLC
4 * 4 *
@@ -77,6 +77,17 @@ reply_error(int r, char *fmt, ...)
77 return resp; 77 return resp;
78} 78}
79 79
80/* If the specified string is zero length, then free it and replace with NULL */
81static void
82null_empty(char **s)
83{
84 if (s == NULL || *s == NULL || **s != '\0')
85 return;
86
87 free(*s);
88 *s = NULL;
89}
90
80static struct sshbuf * 91static struct sshbuf *
81process_sign(struct sshbuf *req) 92process_sign(struct sshbuf *req)
82{ 93{
@@ -108,10 +119,7 @@ process_sign(struct sshbuf *req)
108 "msg len %zu, compat 0x%lx", __progname, sshkey_type(key), 119 "msg len %zu, compat 0x%lx", __progname, sshkey_type(key),
109 provider, msglen, (u_long)compat); 120 provider, msglen, (u_long)compat);
110 121
111 if (*pin == 0) { 122 null_empty(&pin);
112 free(pin);
113 pin = NULL;
114 }
115 123
116 if ((r = sshsk_sign(provider, key, &sig, &siglen, 124 if ((r = sshsk_sign(provider, key, &sig, &siglen,
117 message, msglen, compat, pin)) != 0) { 125 message, msglen, compat, pin)) != 0) {
@@ -138,7 +146,7 @@ process_enroll(struct sshbuf *req)
138{ 146{
139 int r; 147 int r;
140 u_int type; 148 u_int type;
141 char *provider, *application, *pin; 149 char *provider, *application, *pin, *device, *userid;
142 uint8_t flags; 150 uint8_t flags;
143 struct sshbuf *challenge, *attest, *kbuf, *resp; 151 struct sshbuf *challenge, *attest, *kbuf, *resp;
144 struct sshkey *key; 152 struct sshkey *key;
@@ -149,7 +157,9 @@ process_enroll(struct sshbuf *req)
149 157
150 if ((r = sshbuf_get_u32(req, &type)) != 0 || 158 if ((r = sshbuf_get_u32(req, &type)) != 0 ||
151 (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || 159 (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
160 (r = sshbuf_get_cstring(req, &device, NULL)) != 0 ||
152 (r = sshbuf_get_cstring(req, &application, NULL)) != 0 || 161 (r = sshbuf_get_cstring(req, &application, NULL)) != 0 ||
162 (r = sshbuf_get_cstring(req, &userid, NULL)) != 0 ||
153 (r = sshbuf_get_u8(req, &flags)) != 0 || 163 (r = sshbuf_get_u8(req, &flags)) != 0 ||
154 (r = sshbuf_get_cstring(req, &pin, NULL)) != 0 || 164 (r = sshbuf_get_cstring(req, &pin, NULL)) != 0 ||
155 (r = sshbuf_froms(req, &challenge)) != 0) 165 (r = sshbuf_froms(req, &challenge)) != 0)
@@ -163,13 +173,12 @@ process_enroll(struct sshbuf *req)
163 sshbuf_free(challenge); 173 sshbuf_free(challenge);
164 challenge = NULL; 174 challenge = NULL;
165 } 175 }
166 if (*pin == 0) { 176 null_empty(&device);
167 free(pin); 177 null_empty(&userid);
168 pin = NULL; 178 null_empty(&pin);
169 }
170 179
171 if ((r = sshsk_enroll((int)type, provider, application, flags, pin, 180 if ((r = sshsk_enroll((int)type, provider, device, application, userid,
172 challenge, &key, attest)) != 0) { 181 flags, pin, challenge, &key, attest)) != 0) {
173 resp = reply_error(r, "Enrollment failed: %s", ssh_err(r)); 182 resp = reply_error(r, "Enrollment failed: %s", ssh_err(r));
174 goto out; 183 goto out;
175 } 184 }
@@ -200,7 +209,7 @@ static struct sshbuf *
200process_load_resident(struct sshbuf *req) 209process_load_resident(struct sshbuf *req)
201{ 210{
202 int r; 211 int r;
203 char *provider, *pin; 212 char *provider, *pin, *device;
204 struct sshbuf *kbuf, *resp; 213 struct sshbuf *kbuf, *resp;
205 struct sshkey **keys = NULL; 214 struct sshkey **keys = NULL;
206 size_t nkeys = 0, i; 215 size_t nkeys = 0, i;
@@ -209,17 +218,17 @@ process_load_resident(struct sshbuf *req)
209 fatal("%s: sshbuf_new failed", __progname); 218 fatal("%s: sshbuf_new failed", __progname);
210 219
211 if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || 220 if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
221 (r = sshbuf_get_cstring(req, &device, NULL)) != 0 ||
212 (r = sshbuf_get_cstring(req, &pin, NULL)) != 0) 222 (r = sshbuf_get_cstring(req, &pin, NULL)) != 0)
213 fatal("%s: buffer error: %s", __progname, ssh_err(r)); 223 fatal("%s: buffer error: %s", __progname, ssh_err(r));
214 if (sshbuf_len(req) != 0) 224 if (sshbuf_len(req) != 0)
215 fatal("%s: trailing data in request", __progname); 225 fatal("%s: trailing data in request", __progname);
216 226
217 if (*pin == 0) { 227 null_empty(&device);
218 free(pin); 228 null_empty(&pin);
219 pin = NULL;
220 }
221 229
222 if ((r = sshsk_load_resident(provider, pin, &keys, &nkeys)) != 0) { 230 if ((r = sshsk_load_resident(provider, device, pin,
231 &keys, &nkeys)) != 0) {
223 resp = reply_error(r, " sshsk_load_resident failed: %s", 232 resp = reply_error(r, " sshsk_load_resident failed: %s",
224 ssh_err(r)); 233 ssh_err(r));
225 goto out; 234 goto out;