Mercurial > dropbear
comparison signkey.c @ 1855:35d504d59c05
Implement server-side support for sk-ecdsa U2F-backed keys (#142)
* Implement server-side support for sk-ecdsa U2F-backed keys
* Fix out-of-bounds read on normal ecdsa-sha2-[identifier] keys
* Fix one more potential out-of-bounds read
* Check if nistp256 curve is used in sk-ecdsa-sha2- key
It's the only allowed curve per PROTOCOL.u2f specification
* Implement server-side support for sk-ed25519 FIDO2-backed keys
* Keys with type sk-* make no sense as host keys, so they should be
disabled
* fix typo
* Make sk-ecdsa call buf_ecdsa_verify
This reduces code duplication, the SK code just handles the
different message format.
* Reduce sk specific code
The application id can be stored in signkey, then we don't need
to call sk-specific functions from svr-authpubkey
* Remove debugging output, which causes compilation errors with DEBUG_TRACE disabled
* Proper cleanup of sk_app
Co-authored-by: Matt Johnston <[email protected]>
author | egor-duda <egor-duda@users.noreply.github.com> |
---|---|
date | Sat, 22 Jan 2022 16:53:04 +0300 |
parents | fa6ff07dcc77 |
children | 3f4cdf839a1a |
comparison
equal
deleted
inserted
replaced
1854:cba37fe1ddc8 | 1855:35d504d59c05 |
---|---|
26 #include "dbutil.h" | 26 #include "dbutil.h" |
27 #include "signkey.h" | 27 #include "signkey.h" |
28 #include "buffer.h" | 28 #include "buffer.h" |
29 #include "ssh.h" | 29 #include "ssh.h" |
30 #include "ecdsa.h" | 30 #include "ecdsa.h" |
31 #include "sk-ecdsa.h" | |
32 #include "sk-ed25519.h" | |
31 #include "rsa.h" | 33 #include "rsa.h" |
32 #include "dss.h" | 34 #include "dss.h" |
33 #include "ed25519.h" | 35 #include "ed25519.h" |
34 | 36 |
35 static const char * const signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = { | 37 static const char * const signkey_names[DROPBEAR_SIGNKEY_NUM_NAMED] = { |
41 #endif | 43 #endif |
42 #if DROPBEAR_ECDSA | 44 #if DROPBEAR_ECDSA |
43 "ecdsa-sha2-nistp256", | 45 "ecdsa-sha2-nistp256", |
44 "ecdsa-sha2-nistp384", | 46 "ecdsa-sha2-nistp384", |
45 "ecdsa-sha2-nistp521", | 47 "ecdsa-sha2-nistp521", |
48 #if DROPBEAR_SK_ECDSA | |
49 "[email protected]", | |
50 #endif /* DROPBEAR_SK_ECDSA */ | |
46 #endif /* DROPBEAR_ECDSA */ | 51 #endif /* DROPBEAR_ECDSA */ |
47 #if DROPBEAR_ED25519 | 52 #if DROPBEAR_ED25519 |
48 "ssh-ed25519", | 53 "ssh-ed25519", |
54 #if DROPBEAR_SK_ED25519 | |
55 "[email protected]", | |
56 #endif /* DROPBEAR_SK_ED25519 */ | |
49 #endif /* DROPBEAR_ED25519 */ | 57 #endif /* DROPBEAR_ED25519 */ |
50 /* "rsa-sha2-256" is special-cased below since it is only a signature name, not key type */ | 58 /* "rsa-sha2-256" is special-cased below since it is only a signature name, not key type */ |
51 }; | 59 }; |
52 | 60 |
53 /* malloc a new sign_key and set the dss and rsa keys to NULL */ | 61 /* malloc a new sign_key and set the dss and rsa keys to NULL */ |
178 void ** | 186 void ** |
179 signkey_key_ptr(sign_key *key, enum signkey_type type) { | 187 signkey_key_ptr(sign_key *key, enum signkey_type type) { |
180 switch (type) { | 188 switch (type) { |
181 #if DROPBEAR_ED25519 | 189 #if DROPBEAR_ED25519 |
182 case DROPBEAR_SIGNKEY_ED25519: | 190 case DROPBEAR_SIGNKEY_ED25519: |
191 #if DROPBEAR_SK_ED25519 | |
192 case DROPBEAR_SIGNKEY_SK_ED25519: | |
193 #endif | |
183 return (void**)&key->ed25519key; | 194 return (void**)&key->ed25519key; |
184 #endif | 195 #endif |
185 #if DROPBEAR_ECDSA | 196 #if DROPBEAR_ECDSA |
186 #if DROPBEAR_ECC_256 | 197 #if DROPBEAR_ECC_256 |
187 case DROPBEAR_SIGNKEY_ECDSA_NISTP256: | 198 case DROPBEAR_SIGNKEY_ECDSA_NISTP256: |
199 #if DROPBEAR_SK_ECDSA | |
200 case DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256: | |
201 #endif | |
188 return (void**)&key->ecckey256; | 202 return (void**)&key->ecckey256; |
189 #endif | 203 #endif |
190 #if DROPBEAR_ECC_384 | 204 #if DROPBEAR_ECC_384 |
191 case DROPBEAR_SIGNKEY_ECDSA_NISTP384: | 205 case DROPBEAR_SIGNKEY_ECDSA_NISTP384: |
192 return (void**)&key->ecckey384; | 206 return (void**)&key->ecckey384; |
258 key->rsakey = NULL; | 272 key->rsakey = NULL; |
259 } | 273 } |
260 } | 274 } |
261 #endif | 275 #endif |
262 #if DROPBEAR_ECDSA | 276 #if DROPBEAR_ECDSA |
263 if (signkey_is_ecdsa(keytype)) { | 277 if (signkey_is_ecdsa(keytype) |
278 #if DROPBEAR_SK_ECDSA | |
279 || keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256 | |
280 #endif | |
281 ) { | |
264 ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype); | 282 ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype); |
265 if (eck) { | 283 if (eck) { |
266 if (*eck) { | 284 if (*eck) { |
267 ecc_free(*eck); | 285 ecc_free(*eck); |
268 m_free(*eck); | 286 m_free(*eck); |
274 } | 292 } |
275 } | 293 } |
276 } | 294 } |
277 #endif | 295 #endif |
278 #if DROPBEAR_ED25519 | 296 #if DROPBEAR_ED25519 |
279 if (keytype == DROPBEAR_SIGNKEY_ED25519) { | 297 if (keytype == DROPBEAR_SIGNKEY_ED25519 |
298 #if DROPBEAR_SK_ED25519 | |
299 || keytype == DROPBEAR_SIGNKEY_SK_ED25519 | |
300 #endif | |
301 ) { | |
280 ed25519_key_free(key->ed25519key); | 302 ed25519_key_free(key->ed25519key); |
281 key->ed25519key = m_malloc(sizeof(*key->ed25519key)); | 303 key->ed25519key = m_malloc(sizeof(*key->ed25519key)); |
282 ret = buf_get_ed25519_pub_key(buf, key->ed25519key); | 304 ret = buf_get_ed25519_pub_key(buf, key->ed25519key, keytype); |
283 if (ret == DROPBEAR_FAILURE) { | 305 if (ret == DROPBEAR_FAILURE) { |
284 m_free(key->ed25519key); | 306 m_free(key->ed25519key); |
285 key->ed25519key = NULL; | 307 key->ed25519key = NULL; |
286 } | 308 } |
309 } | |
310 #endif | |
311 | |
312 #if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519 | |
313 if (0 | |
314 #if DROPBEAR_SK_ED25519 | |
315 || keytype == DROPBEAR_SIGNKEY_SK_ED25519 | |
316 #endif | |
317 #if DROPBEAR_SK_ECDSA | |
318 || keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256 | |
319 #endif | |
320 ) { | |
321 key->sk_app = buf_getstring(buf, &key->sk_applen); | |
287 } | 322 } |
288 #endif | 323 #endif |
289 | 324 |
290 TRACE2(("leave buf_get_pub_key")) | 325 TRACE2(("leave buf_get_pub_key")) |
291 | 326 |
399 buf_put_ecdsa_pub_key(pubkeys, *eck); | 434 buf_put_ecdsa_pub_key(pubkeys, *eck); |
400 } | 435 } |
401 } | 436 } |
402 #endif | 437 #endif |
403 #if DROPBEAR_ED25519 | 438 #if DROPBEAR_ED25519 |
404 if (type == DROPBEAR_SIGNKEY_ED25519) { | 439 if (type == DROPBEAR_SIGNKEY_ED25519 |
440 #if DROPBEAR_SK_ED25519 | |
441 || type == DROPBEAR_SIGNKEY_SK_ED25519 | |
442 #endif | |
443 ) { | |
405 buf_put_ed25519_pub_key(pubkeys, key->ed25519key); | 444 buf_put_ed25519_pub_key(pubkeys, key->ed25519key); |
406 } | 445 } |
407 #endif | 446 #endif |
408 if (pubkeys->len == 0) { | 447 if (pubkeys->len == 0) { |
409 dropbear_exit("Bad key types in buf_put_pub_key"); | 448 dropbear_exit("Bad key types in buf_put_pub_key"); |
493 ed25519_key_free(key->ed25519key); | 532 ed25519_key_free(key->ed25519key); |
494 key->ed25519key = NULL; | 533 key->ed25519key = NULL; |
495 #endif | 534 #endif |
496 | 535 |
497 m_free(key->filename); | 536 m_free(key->filename); |
537 #if DROPBEAR_SK_ECDSA || DROPBEAR_SK_ED25519 | |
538 if (key->sk_app) { | |
539 m_free(key->sk_app); | |
540 } | |
541 #endif | |
498 | 542 |
499 m_free(key); | 543 m_free(key); |
500 TRACE2(("leave sign_key_free")) | 544 TRACE2(("leave sign_key_free")) |
501 } | 545 } |
502 | 546 |
637 buf_free(sigblob); | 681 buf_free(sigblob); |
638 | 682 |
639 } | 683 } |
640 | 684 |
641 #if DROPBEAR_SIGNKEY_VERIFY | 685 #if DROPBEAR_SIGNKEY_VERIFY |
686 | |
642 /* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE. | 687 /* Return DROPBEAR_SUCCESS or DROPBEAR_FAILURE. |
643 * If FAILURE is returned, the position of | 688 * If FAILURE is returned, the position of |
644 * buf is undefined. If SUCCESS is returned, buf will be positioned after the | 689 * buf is undefined. If SUCCESS is returned, buf will be positioned after the |
645 * signature blob */ | 690 * signature blob */ |
646 int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf) { | 691 int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf) { |
693 dropbear_exit("No Ed25519 key to verify signature"); | 738 dropbear_exit("No Ed25519 key to verify signature"); |
694 } | 739 } |
695 return buf_ed25519_verify(buf, key->ed25519key, data_buf); | 740 return buf_ed25519_verify(buf, key->ed25519key, data_buf); |
696 } | 741 } |
697 #endif | 742 #endif |
743 #if DROPBEAR_SK_ECDSA | |
744 if (keytype == DROPBEAR_SIGNKEY_SK_ECDSA_NISTP256) { | |
745 ecc_key **eck = (ecc_key**)signkey_key_ptr(key, keytype); | |
746 if (eck && *eck) { | |
747 return buf_sk_ecdsa_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen); | |
748 } | |
749 } | |
750 #endif | |
751 #if DROPBEAR_SK_ED25519 | |
752 if (keytype == DROPBEAR_SIGNKEY_SK_ED25519) { | |
753 dropbear_ed25519_key **eck = (dropbear_ed25519_key**)signkey_key_ptr(key, keytype); | |
754 if (eck && *eck) { | |
755 return buf_sk_ed25519_verify(buf, *eck, data_buf, key->sk_app, key->sk_applen); | |
756 } | |
757 } | |
758 #endif | |
698 | 759 |
699 dropbear_exit("Non-matching signing type"); | 760 dropbear_exit("Non-matching signing type"); |
700 return DROPBEAR_FAILURE; | 761 return DROPBEAR_FAILURE; |
701 } | 762 } |
702 #endif /* DROPBEAR_SIGNKEY_VERIFY */ | 763 #endif /* DROPBEAR_SIGNKEY_VERIFY */ |