diff options
author | markus@openbsd.org <markus@openbsd.org> | 2019-11-12 19:33:08 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2019-11-13 08:54:09 +1100 |
commit | 2c55744a56de0ffc81fe445a1e7fc5cd308712b3 (patch) | |
tree | 349cdc436823354aca60031358a6030313b6002d /sshkey.c | |
parent | fd1a3b5e38721b1d69aae2d9de1a1d9155dfa5c7 (diff) |
upstream: enable ed25519 support; ok djm
OpenBSD-Commit-ID: 1a399c5b3ef15bd8efb916110cf5a9e0b554ab7e
Diffstat (limited to 'sshkey.c')
-rw-r--r-- | sshkey.c | 154 |
1 files changed, 153 insertions, 1 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.89 2019/11/12 19:31:18 markus Exp $ */ | 1 | /* $OpenBSD: sshkey.c,v 1.90 2019/11/12 19:33:08 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. | 4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. |
@@ -107,6 +107,10 @@ static const struct keytype keytypes[] = { | |||
107 | { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 }, | 107 | { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 }, |
108 | { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL, | 108 | { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL, |
109 | KEY_ED25519_CERT, 0, 1, 0 }, | 109 | KEY_ED25519_CERT, 0, 1, 0 }, |
110 | { "sk-ssh-ed25519@openssh.com", "ED25519-SK", NULL, | ||
111 | KEY_ED25519_SK, 0, 0, 0 }, | ||
112 | { "sk-ssh-ed25519-cert-v01@openssh.com", "ED25519-SK-CERT", NULL, | ||
113 | KEY_ED25519_SK_CERT, 0, 1, 0 }, | ||
110 | #ifdef WITH_XMSS | 114 | #ifdef WITH_XMSS |
111 | { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 }, | 115 | { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 }, |
112 | { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL, | 116 | { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL, |
@@ -337,6 +341,8 @@ sshkey_size(const struct sshkey *k) | |||
337 | #endif /* WITH_OPENSSL */ | 341 | #endif /* WITH_OPENSSL */ |
338 | case KEY_ED25519: | 342 | case KEY_ED25519: |
339 | case KEY_ED25519_CERT: | 343 | case KEY_ED25519_CERT: |
344 | case KEY_ED25519_SK: | ||
345 | case KEY_ED25519_SK_CERT: | ||
340 | case KEY_XMSS: | 346 | case KEY_XMSS: |
341 | case KEY_XMSS_CERT: | 347 | case KEY_XMSS_CERT: |
342 | return 256; /* XXX */ | 348 | return 256; /* XXX */ |
@@ -353,6 +359,7 @@ sshkey_type_is_valid_ca(int type) | |||
353 | case KEY_ECDSA: | 359 | case KEY_ECDSA: |
354 | case KEY_ECDSA_SK: | 360 | case KEY_ECDSA_SK: |
355 | case KEY_ED25519: | 361 | case KEY_ED25519: |
362 | case KEY_ED25519_SK: | ||
356 | case KEY_XMSS: | 363 | case KEY_XMSS: |
357 | return 1; | 364 | return 1; |
358 | default: | 365 | default: |
@@ -368,6 +375,20 @@ sshkey_is_cert(const struct sshkey *k) | |||
368 | return sshkey_type_is_cert(k->type); | 375 | return sshkey_type_is_cert(k->type); |
369 | } | 376 | } |
370 | 377 | ||
378 | int | ||
379 | sshkey_is_sk(const struct sshkey *k) | ||
380 | { | ||
381 | if (k == NULL) | ||
382 | return 0; | ||
383 | switch (sshkey_type_plain(k->type)) { | ||
384 | case KEY_ECDSA_SK: | ||
385 | case KEY_ED25519_SK: | ||
386 | return 1; | ||
387 | default: | ||
388 | return 0; | ||
389 | } | ||
390 | } | ||
391 | |||
371 | /* Return the cert-less equivalent to a certified key type */ | 392 | /* Return the cert-less equivalent to a certified key type */ |
372 | int | 393 | int |
373 | sshkey_type_plain(int type) | 394 | sshkey_type_plain(int type) |
@@ -383,6 +404,8 @@ sshkey_type_plain(int type) | |||
383 | return KEY_ECDSA_SK; | 404 | return KEY_ECDSA_SK; |
384 | case KEY_ED25519_CERT: | 405 | case KEY_ED25519_CERT: |
385 | return KEY_ED25519; | 406 | return KEY_ED25519; |
407 | case KEY_ED25519_SK_CERT: | ||
408 | return KEY_ED25519_SK; | ||
386 | case KEY_XMSS_CERT: | 409 | case KEY_XMSS_CERT: |
387 | return KEY_XMSS; | 410 | return KEY_XMSS; |
388 | default: | 411 | default: |
@@ -563,6 +586,8 @@ sshkey_new(int type) | |||
563 | #endif /* WITH_OPENSSL */ | 586 | #endif /* WITH_OPENSSL */ |
564 | case KEY_ED25519: | 587 | case KEY_ED25519: |
565 | case KEY_ED25519_CERT: | 588 | case KEY_ED25519_CERT: |
589 | case KEY_ED25519_SK: | ||
590 | case KEY_ED25519_SK_CERT: | ||
566 | case KEY_XMSS: | 591 | case KEY_XMSS: |
567 | case KEY_XMSS_CERT: | 592 | case KEY_XMSS_CERT: |
568 | /* no need to prealloc */ | 593 | /* no need to prealloc */ |
@@ -615,6 +640,12 @@ sshkey_free(struct sshkey *k) | |||
615 | break; | 640 | break; |
616 | # endif /* OPENSSL_HAS_ECC */ | 641 | # endif /* OPENSSL_HAS_ECC */ |
617 | #endif /* WITH_OPENSSL */ | 642 | #endif /* WITH_OPENSSL */ |
643 | case KEY_ED25519_SK: | ||
644 | case KEY_ED25519_SK_CERT: | ||
645 | free(k->sk_application); | ||
646 | sshbuf_free(k->sk_key_handle); | ||
647 | sshbuf_free(k->sk_reserved); | ||
648 | /* FALLTHROUGH */ | ||
618 | case KEY_ED25519: | 649 | case KEY_ED25519: |
619 | case KEY_ED25519_CERT: | 650 | case KEY_ED25519_CERT: |
620 | freezero(k->ed25519_pk, ED25519_PK_SZ); | 651 | freezero(k->ed25519_pk, ED25519_PK_SZ); |
@@ -734,6 +765,13 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) | |||
734 | return 1; | 765 | return 1; |
735 | # endif /* OPENSSL_HAS_ECC */ | 766 | # endif /* OPENSSL_HAS_ECC */ |
736 | #endif /* WITH_OPENSSL */ | 767 | #endif /* WITH_OPENSSL */ |
768 | case KEY_ED25519_SK: | ||
769 | case KEY_ED25519_SK_CERT: | ||
770 | if (a->sk_application == NULL || b->sk_application == NULL) | ||
771 | return 0; | ||
772 | if (strcmp(a->sk_application, b->sk_application) != 0) | ||
773 | return 0; | ||
774 | /* FALLTHROUGH */ | ||
737 | case KEY_ED25519: | 775 | case KEY_ED25519: |
738 | case KEY_ED25519_CERT: | 776 | case KEY_ED25519_CERT: |
739 | return a->ed25519_pk != NULL && b->ed25519_pk != NULL && | 777 | return a->ed25519_pk != NULL && b->ed25519_pk != NULL && |
@@ -842,12 +880,18 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, | |||
842 | break; | 880 | break; |
843 | #endif /* WITH_OPENSSL */ | 881 | #endif /* WITH_OPENSSL */ |
844 | case KEY_ED25519: | 882 | case KEY_ED25519: |
883 | case KEY_ED25519_SK: | ||
845 | if (key->ed25519_pk == NULL) | 884 | if (key->ed25519_pk == NULL) |
846 | return SSH_ERR_INVALID_ARGUMENT; | 885 | return SSH_ERR_INVALID_ARGUMENT; |
847 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || | 886 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || |
848 | (ret = sshbuf_put_string(b, | 887 | (ret = sshbuf_put_string(b, |
849 | key->ed25519_pk, ED25519_PK_SZ)) != 0) | 888 | key->ed25519_pk, ED25519_PK_SZ)) != 0) |
850 | return ret; | 889 | return ret; |
890 | if (type == KEY_ED25519_SK) { | ||
891 | if ((ret = sshbuf_put_cstring(b, | ||
892 | key->sk_application)) != 0) | ||
893 | return ret; | ||
894 | } | ||
851 | break; | 895 | break; |
852 | #ifdef WITH_XMSS | 896 | #ifdef WITH_XMSS |
853 | case KEY_XMSS: | 897 | case KEY_XMSS: |
@@ -1290,11 +1334,13 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1290 | case KEY_ECDSA: | 1334 | case KEY_ECDSA: |
1291 | case KEY_ECDSA_SK: | 1335 | case KEY_ECDSA_SK: |
1292 | case KEY_ED25519: | 1336 | case KEY_ED25519: |
1337 | case KEY_ED25519_SK: | ||
1293 | case KEY_DSA_CERT: | 1338 | case KEY_DSA_CERT: |
1294 | case KEY_ECDSA_CERT: | 1339 | case KEY_ECDSA_CERT: |
1295 | case KEY_ECDSA_SK_CERT: | 1340 | case KEY_ECDSA_SK_CERT: |
1296 | case KEY_RSA_CERT: | 1341 | case KEY_RSA_CERT: |
1297 | case KEY_ED25519_CERT: | 1342 | case KEY_ED25519_CERT: |
1343 | case KEY_ED25519_SK_CERT: | ||
1298 | #ifdef WITH_XMSS | 1344 | #ifdef WITH_XMSS |
1299 | case KEY_XMSS: | 1345 | case KEY_XMSS: |
1300 | case KEY_XMSS_CERT: | 1346 | case KEY_XMSS_CERT: |
@@ -1418,6 +1464,13 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1418 | /* XXX */ | 1464 | /* XXX */ |
1419 | #endif | 1465 | #endif |
1420 | break; | 1466 | break; |
1467 | case KEY_ED25519_SK: | ||
1468 | freezero(ret->ed25519_pk, ED25519_PK_SZ); | ||
1469 | ret->ed25519_pk = k->ed25519_pk; | ||
1470 | ret->sk_application = k->sk_application; | ||
1471 | k->ed25519_pk = NULL; | ||
1472 | k->sk_application = NULL; | ||
1473 | break; | ||
1421 | #ifdef WITH_XMSS | 1474 | #ifdef WITH_XMSS |
1422 | case KEY_XMSS: | 1475 | case KEY_XMSS: |
1423 | free(ret->xmss_pk); | 1476 | free(ret->xmss_pk); |
@@ -1876,6 +1929,8 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | |||
1876 | #endif /* WITH_OPENSSL */ | 1929 | #endif /* WITH_OPENSSL */ |
1877 | case KEY_ED25519: | 1930 | case KEY_ED25519: |
1878 | case KEY_ED25519_CERT: | 1931 | case KEY_ED25519_CERT: |
1932 | case KEY_ED25519_SK: | ||
1933 | case KEY_ED25519_SK_CERT: | ||
1879 | if (k->ed25519_pk != NULL) { | 1934 | if (k->ed25519_pk != NULL) { |
1880 | if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { | 1935 | if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { |
1881 | r = SSH_ERR_ALLOC_FAIL; | 1936 | r = SSH_ERR_ALLOC_FAIL; |
@@ -1883,6 +1938,12 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | |||
1883 | } | 1938 | } |
1884 | memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); | 1939 | memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); |
1885 | } | 1940 | } |
1941 | if (k->type != KEY_ED25519_SK && | ||
1942 | k->type != KEY_ED25519_SK_CERT) | ||
1943 | break; | ||
1944 | /* Append security-key application string */ | ||
1945 | if ((n->sk_application = strdup(k->sk_application)) == NULL) | ||
1946 | goto out; | ||
1886 | break; | 1947 | break; |
1887 | #ifdef WITH_XMSS | 1948 | #ifdef WITH_XMSS |
1888 | case KEY_XMSS: | 1949 | case KEY_XMSS: |
@@ -2444,6 +2505,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2444 | # endif /* OPENSSL_HAS_ECC */ | 2505 | # endif /* OPENSSL_HAS_ECC */ |
2445 | #endif /* WITH_OPENSSL */ | 2506 | #endif /* WITH_OPENSSL */ |
2446 | case KEY_ED25519_CERT: | 2507 | case KEY_ED25519_CERT: |
2508 | case KEY_ED25519_SK_CERT: | ||
2447 | /* Skip nonce */ | 2509 | /* Skip nonce */ |
2448 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { | 2510 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { |
2449 | ret = SSH_ERR_INVALID_FORMAT; | 2511 | ret = SSH_ERR_INVALID_FORMAT; |
@@ -2451,6 +2513,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2451 | } | 2513 | } |
2452 | /* FALLTHROUGH */ | 2514 | /* FALLTHROUGH */ |
2453 | case KEY_ED25519: | 2515 | case KEY_ED25519: |
2516 | case KEY_ED25519_SK: | ||
2454 | if ((ret = sshbuf_get_string(b, &pk, &len)) != 0) | 2517 | if ((ret = sshbuf_get_string(b, &pk, &len)) != 0) |
2455 | goto out; | 2518 | goto out; |
2456 | if (len != ED25519_PK_SZ) { | 2519 | if (len != ED25519_PK_SZ) { |
@@ -2461,6 +2524,17 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2461 | ret = SSH_ERR_ALLOC_FAIL; | 2524 | ret = SSH_ERR_ALLOC_FAIL; |
2462 | goto out; | 2525 | goto out; |
2463 | } | 2526 | } |
2527 | if (type == KEY_ED25519_SK || type == KEY_ED25519_SK_CERT) { | ||
2528 | /* Parse additional security-key application string */ | ||
2529 | if (sshbuf_get_cstring(b, &key->sk_application, | ||
2530 | NULL) != 0) { | ||
2531 | ret = SSH_ERR_INVALID_FORMAT; | ||
2532 | goto out; | ||
2533 | } | ||
2534 | #ifdef DEBUG_PK | ||
2535 | fprintf(stderr, "App: %s\n", key->sk_application); | ||
2536 | #endif | ||
2537 | } | ||
2464 | key->ed25519_pk = pk; | 2538 | key->ed25519_pk = pk; |
2465 | pk = NULL; | 2539 | pk = NULL; |
2466 | break; | 2540 | break; |
@@ -2790,6 +2864,9 @@ sshkey_to_certified(struct sshkey *k) | |||
2790 | newtype = KEY_ECDSA_SK_CERT; | 2864 | newtype = KEY_ECDSA_SK_CERT; |
2791 | break; | 2865 | break; |
2792 | #endif /* WITH_OPENSSL */ | 2866 | #endif /* WITH_OPENSSL */ |
2867 | case KEY_ED25519_SK: | ||
2868 | newtype = KEY_ED25519_SK_CERT; | ||
2869 | break; | ||
2793 | case KEY_ED25519: | 2870 | case KEY_ED25519: |
2794 | newtype = KEY_ED25519_CERT; | 2871 | newtype = KEY_ED25519_CERT; |
2795 | break; | 2872 | break; |
@@ -3223,6 +3300,29 @@ sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, | |||
3223 | ED25519_SK_SZ)) != 0) | 3300 | ED25519_SK_SZ)) != 0) |
3224 | goto out; | 3301 | goto out; |
3225 | break; | 3302 | break; |
3303 | case KEY_ED25519_SK: | ||
3304 | if ((r = sshbuf_put_string(b, key->ed25519_pk, | ||
3305 | ED25519_PK_SZ)) != 0 || | ||
3306 | (r = sshbuf_put_cstring(b, key->sk_application)) != 0 || | ||
3307 | (r = sshbuf_put_u8(b, key->sk_flags)) != 0 || | ||
3308 | (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 || | ||
3309 | (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0) | ||
3310 | goto out; | ||
3311 | break; | ||
3312 | case KEY_ED25519_SK_CERT: | ||
3313 | if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { | ||
3314 | r = SSH_ERR_INVALID_ARGUMENT; | ||
3315 | goto out; | ||
3316 | } | ||
3317 | if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || | ||
3318 | (r = sshbuf_put_string(b, key->ed25519_pk, | ||
3319 | ED25519_PK_SZ)) != 0 || | ||
3320 | (r = sshbuf_put_cstring(b, key->sk_application)) != 0 || | ||
3321 | (r = sshbuf_put_u8(b, key->sk_flags)) != 0 || | ||
3322 | (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 || | ||
3323 | (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0) | ||
3324 | goto out; | ||
3325 | break; | ||
3226 | #ifdef WITH_XMSS | 3326 | #ifdef WITH_XMSS |
3227 | case KEY_XMSS: | 3327 | case KEY_XMSS: |
3228 | if (key->xmss_name == NULL) { | 3328 | if (key->xmss_name == NULL) { |
@@ -3532,6 +3632,57 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
3532 | k->ed25519_sk = ed25519_sk; | 3632 | k->ed25519_sk = ed25519_sk; |
3533 | ed25519_pk = ed25519_sk = NULL; /* transferred */ | 3633 | ed25519_pk = ed25519_sk = NULL; /* transferred */ |
3534 | break; | 3634 | break; |
3635 | case KEY_ED25519_SK: | ||
3636 | if ((k = sshkey_new(type)) == NULL) { | ||
3637 | r = SSH_ERR_ALLOC_FAIL; | ||
3638 | goto out; | ||
3639 | } | ||
3640 | if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0) | ||
3641 | goto out; | ||
3642 | if (pklen != ED25519_PK_SZ) { | ||
3643 | r = SSH_ERR_INVALID_FORMAT; | ||
3644 | goto out; | ||
3645 | } | ||
3646 | if ((k->sk_key_handle = sshbuf_new()) == NULL || | ||
3647 | (k->sk_reserved = sshbuf_new()) == NULL) { | ||
3648 | r = SSH_ERR_ALLOC_FAIL; | ||
3649 | goto out; | ||
3650 | } | ||
3651 | if ((r = sshbuf_get_cstring(buf, &k->sk_application, | ||
3652 | NULL)) != 0 || | ||
3653 | (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || | ||
3654 | (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || | ||
3655 | (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) | ||
3656 | goto out; | ||
3657 | k->ed25519_pk = ed25519_pk; | ||
3658 | ed25519_pk = NULL; | ||
3659 | break; | ||
3660 | case KEY_ED25519_SK_CERT: | ||
3661 | if ((r = sshkey_froms(buf, &k)) != 0 || | ||
3662 | (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0) | ||
3663 | goto out; | ||
3664 | if (k->type != type) { | ||
3665 | r = SSH_ERR_INVALID_FORMAT; | ||
3666 | goto out; | ||
3667 | } | ||
3668 | if (pklen != ED25519_PK_SZ) { | ||
3669 | r = SSH_ERR_INVALID_FORMAT; | ||
3670 | goto out; | ||
3671 | } | ||
3672 | if ((k->sk_key_handle = sshbuf_new()) == NULL || | ||
3673 | (k->sk_reserved = sshbuf_new()) == NULL) { | ||
3674 | r = SSH_ERR_ALLOC_FAIL; | ||
3675 | goto out; | ||
3676 | } | ||
3677 | if ((r = sshbuf_get_cstring(buf, &k->sk_application, | ||
3678 | NULL)) != 0 || | ||
3679 | (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || | ||
3680 | (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || | ||
3681 | (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) | ||
3682 | goto out; | ||
3683 | k->ed25519_pk = ed25519_pk; | ||
3684 | ed25519_pk = NULL; /* transferred */ | ||
3685 | break; | ||
3535 | #ifdef WITH_XMSS | 3686 | #ifdef WITH_XMSS |
3536 | case KEY_XMSS: | 3687 | case KEY_XMSS: |
3537 | if ((k = sshkey_new(type)) == NULL) { | 3688 | if ((k = sshkey_new(type)) == NULL) { |
@@ -4261,6 +4412,7 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, | |||
4261 | break; /* see below */ | 4412 | break; /* see below */ |
4262 | #endif /* WITH_OPENSSL */ | 4413 | #endif /* WITH_OPENSSL */ |
4263 | case KEY_ED25519: | 4414 | case KEY_ED25519: |
4415 | case KEY_ED25519_SK: | ||
4264 | #ifdef WITH_XMSS | 4416 | #ifdef WITH_XMSS |
4265 | case KEY_XMSS: | 4417 | case KEY_XMSS: |
4266 | #endif /* WITH_XMSS */ | 4418 | #endif /* WITH_XMSS */ |