summaryrefslogtreecommitdiff
path: root/ssh-sk-helper.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-12-30 09:23:28 +0000
committerDamien Miller <djm@mindrot.org>2019-12-30 20:59:33 +1100
commitc54cd1892c3e7f268b21e1f07ada9f0d9816ffc0 (patch)
tree71f801c4734b81311ec04f8bba13376c0d6591b0 /ssh-sk-helper.c
parent79fe22d9bc2868c5118f032ec1200ac9c2e3aaef (diff)
upstream: SK API and sk-helper error/PIN passing
Allow passing a PIN via the SK API (API major crank) and let the ssh-sk-helper API follow. Also enhance the ssh-sk-helper API to support passing back an error code instead of a complete reply. Will be used to signal "wrong PIN", etc. feedback and ok markus@ OpenBSD-Commit-ID: a1bd6b0a2421646919a0c139b8183ad76d28fb71
Diffstat (limited to 'ssh-sk-helper.c')
-rw-r--r--ssh-sk-helper.c106
1 files changed, 84 insertions, 22 deletions
diff --git a/ssh-sk-helper.c b/ssh-sk-helper.c
index ac528cfcf..590ff8501 100644
--- a/ssh-sk-helper.c
+++ b/ssh-sk-helper.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-sk-helper.c,v 1.5 2019/12/30 09:21:59 djm Exp $ */ 1/* $OpenBSD: ssh-sk-helper.c,v 1.6 2019/12/30 09:23:28 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2019 Google LLC 3 * Copyright (c) 2019 Google LLC
4 * 4 *
@@ -50,6 +50,33 @@
50#ifdef ENABLE_SK 50#ifdef ENABLE_SK
51extern char *__progname; 51extern char *__progname;
52 52
53static struct sshbuf *reply_error(int r, char *fmt, ...)
54 __attribute__((__format__ (printf, 2, 3)));
55
56static struct sshbuf *
57reply_error(int r, char *fmt, ...)
58{
59 char *msg;
60 va_list ap;
61 struct sshbuf *resp;
62
63 va_start(ap, fmt);
64 xvasprintf(&msg, fmt, ap);
65 va_end(ap);
66 error("%s: %s", __progname, msg);
67 free(msg);
68
69 if (r >= 0)
70 fatal("%s: invalid error code %d", __func__, r);
71
72 if ((resp = sshbuf_new()) == NULL)
73 fatal("%s: sshbuf_new failed", __progname);
74 if (sshbuf_put_u32(resp, SSH_SK_HELPER_ERROR) != 0 ||
75 sshbuf_put_u32(resp, (u_int)-r) != 0)
76 fatal("%s: buffer error", __progname);
77 return resp;
78}
79
53static struct sshbuf * 80static struct sshbuf *
54process_sign(struct sshbuf *req) 81process_sign(struct sshbuf *req)
55{ 82{
@@ -60,13 +87,14 @@ process_sign(struct sshbuf *req)
60 const u_char *message; 87 const u_char *message;
61 u_char *sig; 88 u_char *sig;
62 size_t msglen, siglen; 89 size_t msglen, siglen;
63 char *provider; 90 char *provider, *pin;
64 91
65 if ((r = sshbuf_froms(req, &kbuf)) != 0 || 92 if ((r = sshbuf_froms(req, &kbuf)) != 0 ||
66 (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || 93 (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
67 (r = sshbuf_get_string_direct(req, &message, &msglen)) != 0 || 94 (r = sshbuf_get_string_direct(req, &message, &msglen)) != 0 ||
68 (r = sshbuf_get_cstring(req, NULL, NULL)) != 0 || /* alg */ 95 (r = sshbuf_get_cstring(req, NULL, NULL)) != 0 || /* alg */
69 (r = sshbuf_get_u32(req, &compat)) != 0) 96 (r = sshbuf_get_u32(req, &compat)) != 0 ||
97 (r = sshbuf_get_cstring(req, &pin, NULL)) != 0)
70 fatal("%s: buffer error: %s", __progname, ssh_err(r)); 98 fatal("%s: buffer error: %s", __progname, ssh_err(r));
71 if (sshbuf_len(req) != 0) 99 if (sshbuf_len(req) != 0)
72 fatal("%s: trailing data in request", __progname); 100 fatal("%s: trailing data in request", __progname);
@@ -80,19 +108,28 @@ process_sign(struct sshbuf *req)
80 "msg len %zu, compat 0x%lx", __progname, sshkey_type(key), 108 "msg len %zu, compat 0x%lx", __progname, sshkey_type(key),
81 provider, msglen, (u_long)compat); 109 provider, msglen, (u_long)compat);
82 110
111 if (*pin == 0) {
112 free(pin);
113 pin = NULL;
114 }
115
83 if ((r = sshsk_sign(provider, key, &sig, &siglen, 116 if ((r = sshsk_sign(provider, key, &sig, &siglen,
84 message, msglen, compat)) != 0) 117 message, msglen, compat, pin)) != 0) {
85 fatal("Signing failed: %s", ssh_err(r)); 118 resp = reply_error(r, "Signing failed: %s", ssh_err(r));
119 goto out;
120 }
86 121
87 if ((resp = sshbuf_new()) == NULL) 122 if ((resp = sshbuf_new()) == NULL)
88 fatal("%s: sshbuf_new failed", __progname); 123 fatal("%s: sshbuf_new failed", __progname);
89 124
90 if ((r = sshbuf_put_string(resp, sig, siglen)) != 0) 125 if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_SIGN)) != 0 ||
126 (r = sshbuf_put_string(resp, sig, siglen)) != 0)
91 fatal("%s: buffer error: %s", __progname, ssh_err(r)); 127 fatal("%s: buffer error: %s", __progname, ssh_err(r));
92 128 out:
93 sshbuf_free(kbuf); 129 sshbuf_free(kbuf);
94 free(provider); 130 free(provider);
95 131 if (pin != NULL)
132 freezero(pin, strlen(pin));
96 return resp; 133 return resp;
97} 134}
98 135
@@ -101,14 +138,12 @@ process_enroll(struct sshbuf *req)
101{ 138{
102 int r; 139 int r;
103 u_int type; 140 u_int type;
104 char *provider; 141 char *provider, *application, *pin;
105 char *application;
106 uint8_t flags; 142 uint8_t flags;
107 struct sshbuf *challenge, *attest, *kbuf, *resp; 143 struct sshbuf *challenge, *attest, *kbuf, *resp;
108 struct sshkey *key; 144 struct sshkey *key;
109 145
110 if ((resp = sshbuf_new()) == NULL || 146 if ((attest = sshbuf_new()) == NULL ||
111 (attest = sshbuf_new()) == NULL ||
112 (kbuf = sshbuf_new()) == NULL) 147 (kbuf = sshbuf_new()) == NULL)
113 fatal("%s: sshbuf_new failed", __progname); 148 fatal("%s: sshbuf_new failed", __progname);
114 149
@@ -116,6 +151,7 @@ process_enroll(struct sshbuf *req)
116 (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || 151 (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
117 (r = sshbuf_get_cstring(req, &application, NULL)) != 0 || 152 (r = sshbuf_get_cstring(req, &application, NULL)) != 0 ||
118 (r = sshbuf_get_u8(req, &flags)) != 0 || 153 (r = sshbuf_get_u8(req, &flags)) != 0 ||
154 (r = sshbuf_get_cstring(req, &pin, NULL)) != 0 ||
119 (r = sshbuf_froms(req, &challenge)) != 0) 155 (r = sshbuf_froms(req, &challenge)) != 0)
120 fatal("%s: buffer error: %s", __progname, ssh_err(r)); 156 fatal("%s: buffer error: %s", __progname, ssh_err(r));
121 if (sshbuf_len(req) != 0) 157 if (sshbuf_len(req) != 0)
@@ -127,23 +163,35 @@ process_enroll(struct sshbuf *req)
127 sshbuf_free(challenge); 163 sshbuf_free(challenge);
128 challenge = NULL; 164 challenge = NULL;
129 } 165 }
166 if (*pin == 0) {
167 free(pin);
168 pin = NULL;
169 }
130 170
131 if ((r = sshsk_enroll((int)type, provider, application, flags, 171 if ((r = sshsk_enroll((int)type, provider, application, flags, pin,
132 challenge, &key, attest)) != 0) 172 challenge, &key, attest)) != 0) {
133 fatal("%s: sshsk_enroll failed: %s", __progname, ssh_err(r)); 173 resp = reply_error(r, "Enrollment failed: %s", ssh_err(r));
174 goto out;
175 }
134 176
177 if ((resp = sshbuf_new()) == NULL)
178 fatal("%s: sshbuf_new failed", __progname);
135 if ((r = sshkey_private_serialize(key, kbuf)) != 0) 179 if ((r = sshkey_private_serialize(key, kbuf)) != 0)
136 fatal("%s: serialize private key: %s", __progname, ssh_err(r)); 180 fatal("%s: serialize private key: %s", __progname, ssh_err(r));
137 if ((r = sshbuf_put_stringb(resp, kbuf)) != 0 || 181 if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_ENROLL)) != 0 ||
182 (r = sshbuf_put_stringb(resp, kbuf)) != 0 ||
138 (r = sshbuf_put_stringb(resp, attest)) != 0) 183 (r = sshbuf_put_stringb(resp, attest)) != 0)
139 fatal("%s: buffer error: %s", __progname, ssh_err(r)); 184 fatal("%s: buffer error: %s", __progname, ssh_err(r));
140 185
186 out:
141 sshkey_free(key); 187 sshkey_free(key);
142 sshbuf_free(kbuf); 188 sshbuf_free(kbuf);
143 sshbuf_free(attest); 189 sshbuf_free(attest);
144 sshbuf_free(challenge); 190 sshbuf_free(challenge);
145 free(provider); 191 free(provider);
146 free(application); 192 free(application);
193 if (pin != NULL)
194 freezero(pin, strlen(pin));
147 195
148 return resp; 196 return resp;
149} 197}
@@ -157,8 +205,7 @@ process_load_resident(struct sshbuf *req)
157 struct sshkey **keys = NULL; 205 struct sshkey **keys = NULL;
158 size_t nkeys = 0, i; 206 size_t nkeys = 0, i;
159 207
160 if ((resp = sshbuf_new()) == NULL || 208 if ((kbuf = sshbuf_new()) == NULL)
161 (kbuf = sshbuf_new()) == NULL)
162 fatal("%s: sshbuf_new failed", __progname); 209 fatal("%s: sshbuf_new failed", __progname);
163 210
164 if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || 211 if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
@@ -167,9 +214,22 @@ process_load_resident(struct sshbuf *req)
167 if (sshbuf_len(req) != 0) 214 if (sshbuf_len(req) != 0)
168 fatal("%s: trailing data in request", __progname); 215 fatal("%s: trailing data in request", __progname);
169 216
170 if ((r = sshsk_load_resident(provider, pin, &keys, &nkeys)) != 0) 217 if (*pin == 0) {
171 fatal("%s: sshsk_load_resident failed: %s", 218 free(pin);
172 __progname, ssh_err(r)); 219 pin = NULL;
220 }
221
222 if ((r = sshsk_load_resident(provider, pin, &keys, &nkeys)) != 0) {
223 resp = reply_error(r, " sshsk_load_resident failed: %s",
224 ssh_err(r));
225 goto out;
226 }
227
228 if ((resp = sshbuf_new()) == NULL)
229 fatal("%s: sshbuf_new failed", __progname);
230
231 if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0)
232 fatal("%s: buffer error: %s", __progname, ssh_err(r));
173 233
174 for (i = 0; i < nkeys; i++) { 234 for (i = 0; i < nkeys; i++) {
175 debug("%s: key %zu %s %s", __func__, i, 235 debug("%s: key %zu %s %s", __func__, i,
@@ -183,12 +243,14 @@ process_load_resident(struct sshbuf *req)
183 fatal("%s: buffer error: %s", __progname, ssh_err(r)); 243 fatal("%s: buffer error: %s", __progname, ssh_err(r));
184 } 244 }
185 245
246 out:
186 for (i = 0; i < nkeys; i++) 247 for (i = 0; i < nkeys; i++)
187 sshkey_free(keys[i]); 248 sshkey_free(keys[i]);
188 free(keys); 249 free(keys);
189 sshbuf_free(kbuf); 250 sshbuf_free(kbuf);
190 free(provider); 251 free(provider);
191 freezero(pin, strlen(pin)); 252 if (pin != NULL)
253 freezero(pin, strlen(pin));
192 return resp; 254 return resp;
193} 255}
194 256