diff options
-rw-r--r-- | ssh-sk.c | 96 |
1 files changed, 59 insertions, 37 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-sk.c,v 1.1 2019/10/31 21:16:20 djm Exp $ */ | 1 | /* $OpenBSD: ssh-sk.c,v 1.2 2019/11/12 19:29:54 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2019 Google LLC | 3 | * Copyright (c) 2019 Google LLC |
4 | * | 4 | * |
@@ -143,6 +143,61 @@ sshsk_free_sign_response(struct sk_sign_response *r) | |||
143 | freezero(r, sizeof(*r)); | 143 | freezero(r, sizeof(*r)); |
144 | }; | 144 | }; |
145 | 145 | ||
146 | /* Assemble key from response */ | ||
147 | static int | ||
148 | sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp) | ||
149 | { | ||
150 | struct sshkey *key = NULL; | ||
151 | struct sshbuf *b = NULL; | ||
152 | EC_POINT *q = NULL; | ||
153 | int r; | ||
154 | |||
155 | *keyp = NULL; | ||
156 | if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) { | ||
157 | error("%s: sshkey_new failed", __func__); | ||
158 | r = SSH_ERR_ALLOC_FAIL; | ||
159 | goto out; | ||
160 | } | ||
161 | key->ecdsa_nid = NID_X9_62_prime256v1; | ||
162 | if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL || | ||
163 | (q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL || | ||
164 | (b = sshbuf_new()) == NULL) { | ||
165 | error("%s: allocation failed", __func__); | ||
166 | r = SSH_ERR_ALLOC_FAIL; | ||
167 | goto out; | ||
168 | } | ||
169 | if ((r = sshbuf_put_string(b, | ||
170 | resp->public_key, resp->public_key_len)) != 0) { | ||
171 | error("%s: buffer error: %s", __func__, ssh_err(r)); | ||
172 | goto out; | ||
173 | } | ||
174 | if ((r = sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa))) != 0) { | ||
175 | error("%s: parse key: %s", __func__, ssh_err(r)); | ||
176 | r = SSH_ERR_INVALID_FORMAT; | ||
177 | goto out; | ||
178 | } | ||
179 | if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) { | ||
180 | error("Security key returned invalid ECDSA key"); | ||
181 | r = SSH_ERR_KEY_INVALID_EC_VALUE; | ||
182 | goto out; | ||
183 | } | ||
184 | if (EC_KEY_set_public_key(key->ecdsa, q) != 1) { | ||
185 | /* XXX assume it is a allocation error */ | ||
186 | error("%s: allocation failed", __func__); | ||
187 | r = SSH_ERR_ALLOC_FAIL; | ||
188 | goto out; | ||
189 | } | ||
190 | /* success */ | ||
191 | *keyp = key; | ||
192 | key = NULL; /* transferred */ | ||
193 | r = 0; | ||
194 | out: | ||
195 | EC_POINT_free(q); | ||
196 | sshkey_free(key); | ||
197 | sshbuf_free(b); | ||
198 | return r; | ||
199 | } | ||
200 | |||
146 | int | 201 | int |
147 | sshsk_enroll(const char *provider_path, const char *application, | 202 | sshsk_enroll(const char *provider_path, const char *application, |
148 | uint8_t flags, struct sshbuf *challenge_buf, struct sshkey **keyp, | 203 | uint8_t flags, struct sshbuf *challenge_buf, struct sshkey **keyp, |
@@ -155,8 +210,6 @@ sshsk_enroll(const char *provider_path, const char *application, | |||
155 | size_t challenge_len; | 210 | size_t challenge_len; |
156 | struct sk_enroll_response *resp = NULL; | 211 | struct sk_enroll_response *resp = NULL; |
157 | int r = SSH_ERR_INTERNAL_ERROR; | 212 | int r = SSH_ERR_INTERNAL_ERROR; |
158 | struct sshbuf *b = NULL; | ||
159 | EC_POINT *q = NULL; | ||
160 | 213 | ||
161 | *keyp = NULL; | 214 | *keyp = NULL; |
162 | if (attest) | 215 | if (attest) |
@@ -206,49 +259,20 @@ sshsk_enroll(const char *provider_path, const char *application, | |||
206 | r = SSH_ERR_INVALID_FORMAT; | 259 | r = SSH_ERR_INVALID_FORMAT; |
207 | goto out; | 260 | goto out; |
208 | } | 261 | } |
209 | /* Assemble key from response */ | 262 | if ((r = sshsk_ecdsa_assemble(resp, &key)) != 0) |
210 | if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) { | ||
211 | error("%s: sshkey_new failed", __func__); | ||
212 | r = SSH_ERR_ALLOC_FAIL; | ||
213 | goto out; | 263 | goto out; |
214 | } | ||
215 | key->ecdsa_nid = NID_X9_62_prime256v1; | ||
216 | key->sk_flags = flags; | 264 | key->sk_flags = flags; |
217 | if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL || | 265 | if ((key->sk_key_handle = sshbuf_new()) == NULL || |
218 | (q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL || | 266 | (key->sk_reserved = sshbuf_new()) == NULL) { |
219 | (key->sk_key_handle = sshbuf_new()) == NULL || | ||
220 | (key->sk_reserved = sshbuf_new()) == NULL || | ||
221 | (b = sshbuf_new()) == NULL) { | ||
222 | error("%s: allocation failed", __func__); | 267 | error("%s: allocation failed", __func__); |
223 | r = SSH_ERR_ALLOC_FAIL; | 268 | r = SSH_ERR_ALLOC_FAIL; |
224 | goto out; | 269 | goto out; |
225 | } | 270 | } |
226 | if ((r = sshbuf_put_string(b, | ||
227 | resp->public_key, resp->public_key_len)) != 0) { | ||
228 | error("%s: buffer error: %s", __func__, ssh_err(r)); | ||
229 | goto out; | ||
230 | } | ||
231 | if ((key->sk_application = strdup(application)) == NULL) { | 271 | if ((key->sk_application = strdup(application)) == NULL) { |
232 | error("%s: strdup application failed", __func__); | 272 | error("%s: strdup application failed", __func__); |
233 | r = SSH_ERR_ALLOC_FAIL; | 273 | r = SSH_ERR_ALLOC_FAIL; |
234 | goto out; | 274 | goto out; |
235 | } | 275 | } |
236 | if ((r = sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa))) != 0) { | ||
237 | error("%s: parse key: %s", __func__, ssh_err(r)); | ||
238 | r = SSH_ERR_INVALID_FORMAT; | ||
239 | goto out; | ||
240 | } | ||
241 | if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) { | ||
242 | error("Security key returned invalid ECDSA key"); | ||
243 | r = SSH_ERR_KEY_INVALID_EC_VALUE; | ||
244 | goto out; | ||
245 | } | ||
246 | if (EC_KEY_set_public_key(key->ecdsa, q) != 1) { | ||
247 | /* XXX assume it is a allocation error */ | ||
248 | error("%s: allocation failed", __func__); | ||
249 | r = SSH_ERR_ALLOC_FAIL; | ||
250 | goto out; | ||
251 | } | ||
252 | if ((r = sshbuf_put(key->sk_key_handle, resp->key_handle, | 276 | if ((r = sshbuf_put(key->sk_key_handle, resp->key_handle, |
253 | resp->key_handle_len)) != 0) { | 277 | resp->key_handle_len)) != 0) { |
254 | error("%s: buffer error: %s", __func__, ssh_err(r)); | 278 | error("%s: buffer error: %s", __func__, ssh_err(r)); |
@@ -273,9 +297,7 @@ sshsk_enroll(const char *provider_path, const char *application, | |||
273 | key = NULL; /* transferred */ | 297 | key = NULL; /* transferred */ |
274 | r = 0; | 298 | r = 0; |
275 | out: | 299 | out: |
276 | EC_POINT_free(q); | ||
277 | sshsk_free(skp); | 300 | sshsk_free(skp); |
278 | sshbuf_free(b); | ||
279 | sshkey_free(key); | 301 | sshkey_free(key); |
280 | sshsk_free_enroll_response(resp); | 302 | sshsk_free_enroll_response(resp); |
281 | explicit_bzero(randchall, sizeof(randchall)); | 303 | explicit_bzero(randchall, sizeof(randchall)); |