diff options
author | djm@openbsd.org <djm@openbsd.org> | 2020-01-06 02:00:46 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2020-01-06 13:12:46 +1100 |
commit | c312ca077cd2a6c15545cd6b4d34ee2f69289174 (patch) | |
tree | b8dd974c55dd0de351dfcbfc4f33fddb935a1c12 /ssh-sk-helper.c | |
parent | 2ab335712d084d9ccaf3f53afc3fa9535329da87 (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.c | 45 |
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 */ | ||
81 | static void | ||
82 | null_empty(char **s) | ||
83 | { | ||
84 | if (s == NULL || *s == NULL || **s != '\0') | ||
85 | return; | ||
86 | |||
87 | free(*s); | ||
88 | *s = NULL; | ||
89 | } | ||
90 | |||
80 | static struct sshbuf * | 91 | static struct sshbuf * |
81 | process_sign(struct sshbuf *req) | 92 | process_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 * | |||
200 | process_load_resident(struct sshbuf *req) | 209 | process_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; |