diff options
Diffstat (limited to 'sshkey.c')
-rw-r--r-- | sshkey.c | 816 |
1 files changed, 467 insertions, 349 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.66 2018/07/03 13:20:25 djm Exp $ */ | 1 | /* $OpenBSD: sshkey.c,v 1.72 2018/10/11 00:52:46 djm 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. |
@@ -60,6 +60,8 @@ | |||
60 | 60 | ||
61 | #include "xmss_fast.h" | 61 | #include "xmss_fast.h" |
62 | 62 | ||
63 | #include "openbsd-compat/openssl-compat.h" | ||
64 | |||
63 | /* openssh private key file format */ | 65 | /* openssh private key file format */ |
64 | #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" | 66 | #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" |
65 | #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" | 67 | #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" |
@@ -78,6 +80,7 @@ int sshkey_private_serialize_opt(const struct sshkey *key, | |||
78 | struct sshbuf *buf, enum sshkey_serialize_rep); | 80 | struct sshbuf *buf, enum sshkey_serialize_rep); |
79 | static int sshkey_from_blob_internal(struct sshbuf *buf, | 81 | static int sshkey_from_blob_internal(struct sshbuf *buf, |
80 | struct sshkey **keyp, int allow_cert); | 82 | struct sshkey **keyp, int allow_cert); |
83 | static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep); | ||
81 | 84 | ||
82 | /* Supported key types */ | 85 | /* Supported key types */ |
83 | struct keytype { | 86 | struct keytype { |
@@ -116,17 +119,9 @@ static const struct keytype keytypes[] = { | |||
116 | { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL, | 119 | { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL, |
117 | KEY_RSA_CERT, 0, 1, 0 }, | 120 | KEY_RSA_CERT, 0, 1, 0 }, |
118 | { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT", | 121 | { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT", |
119 | "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 }, | 122 | "rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 }, |
120 | { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT", | ||
121 | "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 }, | ||
122 | { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL, | ||
123 | KEY_DSA_CERT, 0, 1, 0 }, | ||
124 | { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL, | ||
125 | KEY_RSA_CERT, 0, 1, 0 }, | ||
126 | { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT", | ||
127 | "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 }, | ||
128 | { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT", | 123 | { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT", |
129 | "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 }, | 124 | "rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 }, |
130 | { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL, | 125 | { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL, |
131 | KEY_DSA_CERT, 0, 1, 0 }, | 126 | KEY_DSA_CERT, 0, 1, 0 }, |
132 | # ifdef OPENSSL_HAS_ECC | 127 | # ifdef OPENSSL_HAS_ECC |
@@ -288,14 +283,24 @@ sshkey_names_valid2(const char *names, int allow_wildcard) | |||
288 | u_int | 283 | u_int |
289 | sshkey_size(const struct sshkey *k) | 284 | sshkey_size(const struct sshkey *k) |
290 | { | 285 | { |
286 | #ifdef WITH_OPENSSL | ||
287 | const BIGNUM *rsa_n, *dsa_p; | ||
288 | #endif /* WITH_OPENSSL */ | ||
289 | |||
291 | switch (k->type) { | 290 | switch (k->type) { |
292 | #ifdef WITH_OPENSSL | 291 | #ifdef WITH_OPENSSL |
293 | case KEY_RSA: | 292 | case KEY_RSA: |
294 | case KEY_RSA_CERT: | 293 | case KEY_RSA_CERT: |
295 | return BN_num_bits(k->rsa->n); | 294 | if (k->rsa == NULL) |
295 | return 0; | ||
296 | RSA_get0_key(k->rsa, &rsa_n, NULL, NULL); | ||
297 | return BN_num_bits(rsa_n); | ||
296 | case KEY_DSA: | 298 | case KEY_DSA: |
297 | case KEY_DSA_CERT: | 299 | case KEY_DSA_CERT: |
298 | return BN_num_bits(k->dsa->p); | 300 | if (k->dsa == NULL) |
301 | return 0; | ||
302 | DSA_get0_pqg(k->dsa, &dsa_p, NULL, NULL); | ||
303 | return BN_num_bits(dsa_p); | ||
299 | case KEY_ECDSA: | 304 | case KEY_ECDSA: |
300 | case KEY_ECDSA_CERT: | 305 | case KEY_ECDSA_CERT: |
301 | return sshkey_curve_nid_to_bits(k->ecdsa_nid); | 306 | return sshkey_curve_nid_to_bits(k->ecdsa_nid); |
@@ -453,6 +458,7 @@ cert_free(struct sshkey_cert *cert) | |||
453 | free(cert->principals[i]); | 458 | free(cert->principals[i]); |
454 | free(cert->principals); | 459 | free(cert->principals); |
455 | sshkey_free(cert->signature_key); | 460 | sshkey_free(cert->signature_key); |
461 | free(cert->signature_type); | ||
456 | freezero(cert, sizeof(*cert)); | 462 | freezero(cert, sizeof(*cert)); |
457 | } | 463 | } |
458 | 464 | ||
@@ -472,6 +478,7 @@ cert_new(void) | |||
472 | cert->key_id = NULL; | 478 | cert->key_id = NULL; |
473 | cert->principals = NULL; | 479 | cert->principals = NULL; |
474 | cert->signature_key = NULL; | 480 | cert->signature_key = NULL; |
481 | cert->signature_type = NULL; | ||
475 | return cert; | 482 | return cert; |
476 | } | 483 | } |
477 | 484 | ||
@@ -500,10 +507,7 @@ sshkey_new(int type) | |||
500 | #ifdef WITH_OPENSSL | 507 | #ifdef WITH_OPENSSL |
501 | case KEY_RSA: | 508 | case KEY_RSA: |
502 | case KEY_RSA_CERT: | 509 | case KEY_RSA_CERT: |
503 | if ((rsa = RSA_new()) == NULL || | 510 | if ((rsa = RSA_new()) == NULL) { |
504 | (rsa->n = BN_new()) == NULL || | ||
505 | (rsa->e = BN_new()) == NULL) { | ||
506 | RSA_free(rsa); | ||
507 | free(k); | 511 | free(k); |
508 | return NULL; | 512 | return NULL; |
509 | } | 513 | } |
@@ -511,12 +515,7 @@ sshkey_new(int type) | |||
511 | break; | 515 | break; |
512 | case KEY_DSA: | 516 | case KEY_DSA: |
513 | case KEY_DSA_CERT: | 517 | case KEY_DSA_CERT: |
514 | if ((dsa = DSA_new()) == NULL || | 518 | if ((dsa = DSA_new()) == NULL) { |
515 | (dsa->p = BN_new()) == NULL || | ||
516 | (dsa->q = BN_new()) == NULL || | ||
517 | (dsa->g = BN_new()) == NULL || | ||
518 | (dsa->pub_key = BN_new()) == NULL) { | ||
519 | DSA_free(dsa); | ||
520 | free(k); | 519 | free(k); |
521 | return NULL; | 520 | return NULL; |
522 | } | 521 | } |
@@ -550,61 +549,6 @@ sshkey_new(int type) | |||
550 | return k; | 549 | return k; |
551 | } | 550 | } |
552 | 551 | ||
553 | int | ||
554 | sshkey_add_private(struct sshkey *k) | ||
555 | { | ||
556 | switch (k->type) { | ||
557 | #ifdef WITH_OPENSSL | ||
558 | case KEY_RSA: | ||
559 | case KEY_RSA_CERT: | ||
560 | #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL) | ||
561 | if (bn_maybe_alloc_failed(k->rsa->d) || | ||
562 | bn_maybe_alloc_failed(k->rsa->iqmp) || | ||
563 | bn_maybe_alloc_failed(k->rsa->q) || | ||
564 | bn_maybe_alloc_failed(k->rsa->p) || | ||
565 | bn_maybe_alloc_failed(k->rsa->dmq1) || | ||
566 | bn_maybe_alloc_failed(k->rsa->dmp1)) | ||
567 | return SSH_ERR_ALLOC_FAIL; | ||
568 | break; | ||
569 | case KEY_DSA: | ||
570 | case KEY_DSA_CERT: | ||
571 | if (bn_maybe_alloc_failed(k->dsa->priv_key)) | ||
572 | return SSH_ERR_ALLOC_FAIL; | ||
573 | break; | ||
574 | #undef bn_maybe_alloc_failed | ||
575 | case KEY_ECDSA: | ||
576 | case KEY_ECDSA_CERT: | ||
577 | /* Cannot do anything until we know the group */ | ||
578 | break; | ||
579 | #endif /* WITH_OPENSSL */ | ||
580 | case KEY_ED25519: | ||
581 | case KEY_ED25519_CERT: | ||
582 | case KEY_XMSS: | ||
583 | case KEY_XMSS_CERT: | ||
584 | /* no need to prealloc */ | ||
585 | break; | ||
586 | case KEY_UNSPEC: | ||
587 | break; | ||
588 | default: | ||
589 | return SSH_ERR_INVALID_ARGUMENT; | ||
590 | } | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | struct sshkey * | ||
595 | sshkey_new_private(int type) | ||
596 | { | ||
597 | struct sshkey *k = sshkey_new(type); | ||
598 | |||
599 | if (k == NULL) | ||
600 | return NULL; | ||
601 | if (sshkey_add_private(k) != 0) { | ||
602 | sshkey_free(k); | ||
603 | return NULL; | ||
604 | } | ||
605 | return k; | ||
606 | } | ||
607 | |||
608 | void | 552 | void |
609 | sshkey_free(struct sshkey *k) | 553 | sshkey_free(struct sshkey *k) |
610 | { | 554 | { |
@@ -683,9 +627,15 @@ cert_compare(struct sshkey_cert *a, struct sshkey_cert *b) | |||
683 | int | 627 | int |
684 | sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) | 628 | sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) |
685 | { | 629 | { |
686 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | 630 | #if defined(WITH_OPENSSL) |
631 | const BIGNUM *rsa_e_a, *rsa_n_a; | ||
632 | const BIGNUM *rsa_e_b, *rsa_n_b; | ||
633 | const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a; | ||
634 | const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b; | ||
635 | # if defined(OPENSSL_HAS_ECC) | ||
687 | BN_CTX *bnctx; | 636 | BN_CTX *bnctx; |
688 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ | 637 | # endif /* OPENSSL_HAS_ECC */ |
638 | #endif /* WITH_OPENSSL */ | ||
689 | 639 | ||
690 | if (a == NULL || b == NULL || | 640 | if (a == NULL || b == NULL || |
691 | sshkey_type_plain(a->type) != sshkey_type_plain(b->type)) | 641 | sshkey_type_plain(a->type) != sshkey_type_plain(b->type)) |
@@ -695,16 +645,24 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) | |||
695 | #ifdef WITH_OPENSSL | 645 | #ifdef WITH_OPENSSL |
696 | case KEY_RSA_CERT: | 646 | case KEY_RSA_CERT: |
697 | case KEY_RSA: | 647 | case KEY_RSA: |
698 | return a->rsa != NULL && b->rsa != NULL && | 648 | if (a->rsa == NULL || b->rsa == NULL) |
699 | BN_cmp(a->rsa->e, b->rsa->e) == 0 && | 649 | return 0; |
700 | BN_cmp(a->rsa->n, b->rsa->n) == 0; | 650 | RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL); |
651 | RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL); | ||
652 | return BN_cmp(rsa_e_a, rsa_e_b) == 0 && | ||
653 | BN_cmp(rsa_n_a, rsa_n_b) == 0; | ||
701 | case KEY_DSA_CERT: | 654 | case KEY_DSA_CERT: |
702 | case KEY_DSA: | 655 | case KEY_DSA: |
703 | return a->dsa != NULL && b->dsa != NULL && | 656 | if (a->dsa == NULL || b->dsa == NULL) |
704 | BN_cmp(a->dsa->p, b->dsa->p) == 0 && | 657 | return 0; |
705 | BN_cmp(a->dsa->q, b->dsa->q) == 0 && | 658 | DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a); |
706 | BN_cmp(a->dsa->g, b->dsa->g) == 0 && | 659 | DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b); |
707 | BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; | 660 | DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL); |
661 | DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL); | ||
662 | return BN_cmp(dsa_p_a, dsa_p_b) == 0 && | ||
663 | BN_cmp(dsa_q_a, dsa_q_b) == 0 && | ||
664 | BN_cmp(dsa_g_a, dsa_g_b) == 0 && | ||
665 | BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 0; | ||
708 | # ifdef OPENSSL_HAS_ECC | 666 | # ifdef OPENSSL_HAS_ECC |
709 | case KEY_ECDSA_CERT: | 667 | case KEY_ECDSA_CERT: |
710 | case KEY_ECDSA: | 668 | case KEY_ECDSA: |
@@ -761,6 +719,9 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, | |||
761 | { | 719 | { |
762 | int type, ret = SSH_ERR_INTERNAL_ERROR; | 720 | int type, ret = SSH_ERR_INTERNAL_ERROR; |
763 | const char *typename; | 721 | const char *typename; |
722 | #ifdef WITH_OPENSSL | ||
723 | const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; | ||
724 | #endif /* WITH_OPENSSL */ | ||
764 | 725 | ||
765 | if (key == NULL) | 726 | if (key == NULL) |
766 | return SSH_ERR_INVALID_ARGUMENT; | 727 | return SSH_ERR_INVALID_ARGUMENT; |
@@ -793,11 +754,13 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, | |||
793 | case KEY_DSA: | 754 | case KEY_DSA: |
794 | if (key->dsa == NULL) | 755 | if (key->dsa == NULL) |
795 | return SSH_ERR_INVALID_ARGUMENT; | 756 | return SSH_ERR_INVALID_ARGUMENT; |
757 | DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g); | ||
758 | DSA_get0_key(key->dsa, &dsa_pub_key, NULL); | ||
796 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || | 759 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || |
797 | (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || | 760 | (ret = sshbuf_put_bignum2(b, dsa_p)) != 0 || |
798 | (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || | 761 | (ret = sshbuf_put_bignum2(b, dsa_q)) != 0 || |
799 | (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || | 762 | (ret = sshbuf_put_bignum2(b, dsa_g)) != 0 || |
800 | (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0) | 763 | (ret = sshbuf_put_bignum2(b, dsa_pub_key)) != 0) |
801 | return ret; | 764 | return ret; |
802 | break; | 765 | break; |
803 | # ifdef OPENSSL_HAS_ECC | 766 | # ifdef OPENSSL_HAS_ECC |
@@ -814,9 +777,10 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, | |||
814 | case KEY_RSA: | 777 | case KEY_RSA: |
815 | if (key->rsa == NULL) | 778 | if (key->rsa == NULL) |
816 | return SSH_ERR_INVALID_ARGUMENT; | 779 | return SSH_ERR_INVALID_ARGUMENT; |
780 | RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL); | ||
817 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || | 781 | if ((ret = sshbuf_put_cstring(b, typename)) != 0 || |
818 | (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || | 782 | (ret = sshbuf_put_bignum2(b, rsa_e)) != 0 || |
819 | (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0) | 783 | (ret = sshbuf_put_bignum2(b, rsa_n)) != 0) |
820 | return ret; | 784 | return ret; |
821 | break; | 785 | break; |
822 | #endif /* WITH_OPENSSL */ | 786 | #endif /* WITH_OPENSSL */ |
@@ -1695,114 +1659,163 @@ sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key) | |||
1695 | u_int i; | 1659 | u_int i; |
1696 | const struct sshkey_cert *from; | 1660 | const struct sshkey_cert *from; |
1697 | struct sshkey_cert *to; | 1661 | struct sshkey_cert *to; |
1698 | int ret = SSH_ERR_INTERNAL_ERROR; | 1662 | int r = SSH_ERR_INTERNAL_ERROR; |
1699 | |||
1700 | if (to_key->cert != NULL) { | ||
1701 | cert_free(to_key->cert); | ||
1702 | to_key->cert = NULL; | ||
1703 | } | ||
1704 | 1663 | ||
1705 | if ((from = from_key->cert) == NULL) | 1664 | if (to_key == NULL || (from = from_key->cert) == NULL) |
1706 | return SSH_ERR_INVALID_ARGUMENT; | 1665 | return SSH_ERR_INVALID_ARGUMENT; |
1707 | 1666 | ||
1708 | if ((to = to_key->cert = cert_new()) == NULL) | 1667 | if ((to = cert_new()) == NULL) |
1709 | return SSH_ERR_ALLOC_FAIL; | 1668 | return SSH_ERR_ALLOC_FAIL; |
1710 | 1669 | ||
1711 | if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 || | 1670 | if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 || |
1712 | (ret = sshbuf_putb(to->critical, from->critical)) != 0 || | 1671 | (r = sshbuf_putb(to->critical, from->critical)) != 0 || |
1713 | (ret = sshbuf_putb(to->extensions, from->extensions)) != 0) | 1672 | (r = sshbuf_putb(to->extensions, from->extensions)) != 0) |
1714 | return ret; | 1673 | goto out; |
1715 | 1674 | ||
1716 | to->serial = from->serial; | 1675 | to->serial = from->serial; |
1717 | to->type = from->type; | 1676 | to->type = from->type; |
1718 | if (from->key_id == NULL) | 1677 | if (from->key_id == NULL) |
1719 | to->key_id = NULL; | 1678 | to->key_id = NULL; |
1720 | else if ((to->key_id = strdup(from->key_id)) == NULL) | 1679 | else if ((to->key_id = strdup(from->key_id)) == NULL) { |
1721 | return SSH_ERR_ALLOC_FAIL; | 1680 | r = SSH_ERR_ALLOC_FAIL; |
1681 | goto out; | ||
1682 | } | ||
1722 | to->valid_after = from->valid_after; | 1683 | to->valid_after = from->valid_after; |
1723 | to->valid_before = from->valid_before; | 1684 | to->valid_before = from->valid_before; |
1724 | if (from->signature_key == NULL) | 1685 | if (from->signature_key == NULL) |
1725 | to->signature_key = NULL; | 1686 | to->signature_key = NULL; |
1726 | else if ((ret = sshkey_from_private(from->signature_key, | 1687 | else if ((r = sshkey_from_private(from->signature_key, |
1727 | &to->signature_key)) != 0) | 1688 | &to->signature_key)) != 0) |
1728 | return ret; | 1689 | goto out; |
1729 | 1690 | if (from->signature_type != NULL && | |
1730 | if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) | 1691 | (to->signature_type = strdup(from->signature_type)) == NULL) { |
1731 | return SSH_ERR_INVALID_ARGUMENT; | 1692 | r = SSH_ERR_ALLOC_FAIL; |
1693 | goto out; | ||
1694 | } | ||
1695 | if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) { | ||
1696 | r = SSH_ERR_INVALID_ARGUMENT; | ||
1697 | goto out; | ||
1698 | } | ||
1732 | if (from->nprincipals > 0) { | 1699 | if (from->nprincipals > 0) { |
1733 | if ((to->principals = calloc(from->nprincipals, | 1700 | if ((to->principals = calloc(from->nprincipals, |
1734 | sizeof(*to->principals))) == NULL) | 1701 | sizeof(*to->principals))) == NULL) { |
1735 | return SSH_ERR_ALLOC_FAIL; | 1702 | r = SSH_ERR_ALLOC_FAIL; |
1703 | goto out; | ||
1704 | } | ||
1736 | for (i = 0; i < from->nprincipals; i++) { | 1705 | for (i = 0; i < from->nprincipals; i++) { |
1737 | to->principals[i] = strdup(from->principals[i]); | 1706 | to->principals[i] = strdup(from->principals[i]); |
1738 | if (to->principals[i] == NULL) { | 1707 | if (to->principals[i] == NULL) { |
1739 | to->nprincipals = i; | 1708 | to->nprincipals = i; |
1740 | return SSH_ERR_ALLOC_FAIL; | 1709 | r = SSH_ERR_ALLOC_FAIL; |
1710 | goto out; | ||
1741 | } | 1711 | } |
1742 | } | 1712 | } |
1743 | } | 1713 | } |
1744 | to->nprincipals = from->nprincipals; | 1714 | to->nprincipals = from->nprincipals; |
1745 | return 0; | 1715 | |
1716 | /* success */ | ||
1717 | cert_free(to_key->cert); | ||
1718 | to_key->cert = to; | ||
1719 | to = NULL; | ||
1720 | r = 0; | ||
1721 | out: | ||
1722 | cert_free(to); | ||
1723 | return r; | ||
1746 | } | 1724 | } |
1747 | 1725 | ||
1748 | int | 1726 | int |
1749 | sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | 1727 | sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) |
1750 | { | 1728 | { |
1751 | struct sshkey *n = NULL; | 1729 | struct sshkey *n = NULL; |
1752 | int ret = SSH_ERR_INTERNAL_ERROR; | 1730 | int r = SSH_ERR_INTERNAL_ERROR; |
1731 | #ifdef WITH_OPENSSL | ||
1732 | const BIGNUM *rsa_n, *rsa_e; | ||
1733 | BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL; | ||
1734 | const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; | ||
1735 | BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL; | ||
1736 | BIGNUM *dsa_pub_key_dup = NULL; | ||
1737 | #endif /* WITH_OPENSSL */ | ||
1753 | 1738 | ||
1754 | *pkp = NULL; | 1739 | *pkp = NULL; |
1755 | switch (k->type) { | 1740 | switch (k->type) { |
1756 | #ifdef WITH_OPENSSL | 1741 | #ifdef WITH_OPENSSL |
1757 | case KEY_DSA: | 1742 | case KEY_DSA: |
1758 | case KEY_DSA_CERT: | 1743 | case KEY_DSA_CERT: |
1759 | if ((n = sshkey_new(k->type)) == NULL) | 1744 | if ((n = sshkey_new(k->type)) == NULL) { |
1760 | return SSH_ERR_ALLOC_FAIL; | 1745 | r = SSH_ERR_ALLOC_FAIL; |
1761 | if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || | 1746 | goto out; |
1762 | (BN_copy(n->dsa->q, k->dsa->q) == NULL) || | ||
1763 | (BN_copy(n->dsa->g, k->dsa->g) == NULL) || | ||
1764 | (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) { | ||
1765 | sshkey_free(n); | ||
1766 | return SSH_ERR_ALLOC_FAIL; | ||
1767 | } | 1747 | } |
1748 | |||
1749 | DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g); | ||
1750 | DSA_get0_key(k->dsa, &dsa_pub_key, NULL); | ||
1751 | if ((dsa_p_dup = BN_dup(dsa_p)) == NULL || | ||
1752 | (dsa_q_dup = BN_dup(dsa_q)) == NULL || | ||
1753 | (dsa_g_dup = BN_dup(dsa_g)) == NULL || | ||
1754 | (dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) { | ||
1755 | r = SSH_ERR_ALLOC_FAIL; | ||
1756 | goto out; | ||
1757 | } | ||
1758 | if (!DSA_set0_pqg(n->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) { | ||
1759 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
1760 | goto out; | ||
1761 | } | ||
1762 | dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */ | ||
1763 | if (!DSA_set0_key(n->dsa, dsa_pub_key_dup, NULL)) { | ||
1764 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
1765 | goto out; | ||
1766 | } | ||
1767 | dsa_pub_key_dup = NULL; /* transferred */ | ||
1768 | |||
1768 | break; | 1769 | break; |
1769 | # ifdef OPENSSL_HAS_ECC | 1770 | # ifdef OPENSSL_HAS_ECC |
1770 | case KEY_ECDSA: | 1771 | case KEY_ECDSA: |
1771 | case KEY_ECDSA_CERT: | 1772 | case KEY_ECDSA_CERT: |
1772 | if ((n = sshkey_new(k->type)) == NULL) | 1773 | if ((n = sshkey_new(k->type)) == NULL) { |
1773 | return SSH_ERR_ALLOC_FAIL; | 1774 | r = SSH_ERR_ALLOC_FAIL; |
1775 | goto out; | ||
1776 | } | ||
1774 | n->ecdsa_nid = k->ecdsa_nid; | 1777 | n->ecdsa_nid = k->ecdsa_nid; |
1775 | n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); | 1778 | n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); |
1776 | if (n->ecdsa == NULL) { | 1779 | if (n->ecdsa == NULL) { |
1777 | sshkey_free(n); | 1780 | r = SSH_ERR_ALLOC_FAIL; |
1778 | return SSH_ERR_ALLOC_FAIL; | 1781 | goto out; |
1779 | } | 1782 | } |
1780 | if (EC_KEY_set_public_key(n->ecdsa, | 1783 | if (EC_KEY_set_public_key(n->ecdsa, |
1781 | EC_KEY_get0_public_key(k->ecdsa)) != 1) { | 1784 | EC_KEY_get0_public_key(k->ecdsa)) != 1) { |
1782 | sshkey_free(n); | 1785 | r = SSH_ERR_LIBCRYPTO_ERROR; |
1783 | return SSH_ERR_LIBCRYPTO_ERROR; | 1786 | goto out; |
1784 | } | 1787 | } |
1785 | break; | 1788 | break; |
1786 | # endif /* OPENSSL_HAS_ECC */ | 1789 | # endif /* OPENSSL_HAS_ECC */ |
1787 | case KEY_RSA: | 1790 | case KEY_RSA: |
1788 | case KEY_RSA_CERT: | 1791 | case KEY_RSA_CERT: |
1789 | if ((n = sshkey_new(k->type)) == NULL) | 1792 | if ((n = sshkey_new(k->type)) == NULL) { |
1790 | return SSH_ERR_ALLOC_FAIL; | 1793 | r = SSH_ERR_ALLOC_FAIL; |
1791 | if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || | 1794 | goto out; |
1792 | (BN_copy(n->rsa->e, k->rsa->e) == NULL)) { | ||
1793 | sshkey_free(n); | ||
1794 | return SSH_ERR_ALLOC_FAIL; | ||
1795 | } | 1795 | } |
1796 | RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL); | ||
1797 | if ((rsa_n_dup = BN_dup(rsa_n)) == NULL || | ||
1798 | (rsa_e_dup = BN_dup(rsa_e)) == NULL) { | ||
1799 | r = SSH_ERR_ALLOC_FAIL; | ||
1800 | goto out; | ||
1801 | } | ||
1802 | if (!RSA_set0_key(n->rsa, rsa_n_dup, rsa_e_dup, NULL)) { | ||
1803 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
1804 | goto out; | ||
1805 | } | ||
1806 | rsa_n_dup = rsa_e_dup = NULL; /* transferred */ | ||
1796 | break; | 1807 | break; |
1797 | #endif /* WITH_OPENSSL */ | 1808 | #endif /* WITH_OPENSSL */ |
1798 | case KEY_ED25519: | 1809 | case KEY_ED25519: |
1799 | case KEY_ED25519_CERT: | 1810 | case KEY_ED25519_CERT: |
1800 | if ((n = sshkey_new(k->type)) == NULL) | 1811 | if ((n = sshkey_new(k->type)) == NULL) { |
1801 | return SSH_ERR_ALLOC_FAIL; | 1812 | r = SSH_ERR_ALLOC_FAIL; |
1813 | goto out; | ||
1814 | } | ||
1802 | if (k->ed25519_pk != NULL) { | 1815 | if (k->ed25519_pk != NULL) { |
1803 | if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { | 1816 | if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { |
1804 | sshkey_free(n); | 1817 | r = SSH_ERR_ALLOC_FAIL; |
1805 | return SSH_ERR_ALLOC_FAIL; | 1818 | goto out; |
1806 | } | 1819 | } |
1807 | memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); | 1820 | memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); |
1808 | } | 1821 | } |
@@ -1810,37 +1823,48 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | |||
1810 | #ifdef WITH_XMSS | 1823 | #ifdef WITH_XMSS |
1811 | case KEY_XMSS: | 1824 | case KEY_XMSS: |
1812 | case KEY_XMSS_CERT: | 1825 | case KEY_XMSS_CERT: |
1813 | if ((n = sshkey_new(k->type)) == NULL) | 1826 | if ((n = sshkey_new(k->type)) == NULL) { |
1814 | return SSH_ERR_ALLOC_FAIL; | 1827 | r = SSH_ERR_ALLOC_FAIL; |
1815 | if ((ret = sshkey_xmss_init(n, k->xmss_name)) != 0) { | 1828 | goto out; |
1816 | sshkey_free(n); | ||
1817 | return ret; | ||
1818 | } | 1829 | } |
1830 | if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0) | ||
1831 | goto out; | ||
1819 | if (k->xmss_pk != NULL) { | 1832 | if (k->xmss_pk != NULL) { |
1820 | size_t pklen = sshkey_xmss_pklen(k); | 1833 | size_t pklen = sshkey_xmss_pklen(k); |
1821 | if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) { | 1834 | if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) { |
1822 | sshkey_free(n); | 1835 | r = SSH_ERR_INTERNAL_ERROR; |
1823 | return SSH_ERR_INTERNAL_ERROR; | 1836 | goto out; |
1824 | } | 1837 | } |
1825 | if ((n->xmss_pk = malloc(pklen)) == NULL) { | 1838 | if ((n->xmss_pk = malloc(pklen)) == NULL) { |
1826 | sshkey_free(n); | 1839 | r = SSH_ERR_ALLOC_FAIL; |
1827 | return SSH_ERR_ALLOC_FAIL; | 1840 | goto out; |
1828 | } | 1841 | } |
1829 | memcpy(n->xmss_pk, k->xmss_pk, pklen); | 1842 | memcpy(n->xmss_pk, k->xmss_pk, pklen); |
1830 | } | 1843 | } |
1831 | break; | 1844 | break; |
1832 | #endif /* WITH_XMSS */ | 1845 | #endif /* WITH_XMSS */ |
1833 | default: | 1846 | default: |
1834 | return SSH_ERR_KEY_TYPE_UNKNOWN; | 1847 | r = SSH_ERR_KEY_TYPE_UNKNOWN; |
1835 | } | 1848 | goto out; |
1836 | if (sshkey_is_cert(k)) { | ||
1837 | if ((ret = sshkey_cert_copy(k, n)) != 0) { | ||
1838 | sshkey_free(n); | ||
1839 | return ret; | ||
1840 | } | ||
1841 | } | 1849 | } |
1850 | if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0) | ||
1851 | goto out; | ||
1852 | /* success */ | ||
1842 | *pkp = n; | 1853 | *pkp = n; |
1843 | return 0; | 1854 | n = NULL; |
1855 | r = 0; | ||
1856 | out: | ||
1857 | sshkey_free(n); | ||
1858 | #ifdef WITH_OPENSSL | ||
1859 | BN_clear_free(rsa_n_dup); | ||
1860 | BN_clear_free(rsa_e_dup); | ||
1861 | BN_clear_free(dsa_p_dup); | ||
1862 | BN_clear_free(dsa_q_dup); | ||
1863 | BN_clear_free(dsa_g_dup); | ||
1864 | BN_clear_free(dsa_pub_key_dup); | ||
1865 | #endif | ||
1866 | |||
1867 | return r; | ||
1844 | } | 1868 | } |
1845 | 1869 | ||
1846 | static int | 1870 | static int |
@@ -1954,6 +1978,8 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) | |||
1954 | if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, | 1978 | if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, |
1955 | sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0) | 1979 | sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0) |
1956 | goto out; | 1980 | goto out; |
1981 | if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0) | ||
1982 | goto out; | ||
1957 | 1983 | ||
1958 | /* Success */ | 1984 | /* Success */ |
1959 | ret = 0; | 1985 | ret = 0; |
@@ -1966,6 +1992,19 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) | |||
1966 | return ret; | 1992 | return ret; |
1967 | } | 1993 | } |
1968 | 1994 | ||
1995 | #ifdef WITH_OPENSSL | ||
1996 | static int | ||
1997 | check_rsa_length(const RSA *rsa) | ||
1998 | { | ||
1999 | const BIGNUM *rsa_n; | ||
2000 | |||
2001 | RSA_get0_key(rsa, &rsa_n, NULL, NULL); | ||
2002 | if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) | ||
2003 | return SSH_ERR_KEY_LENGTH; | ||
2004 | return 0; | ||
2005 | } | ||
2006 | #endif | ||
2007 | |||
1969 | static int | 2008 | static int |
1970 | sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | 2009 | sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, |
1971 | int allow_cert) | 2010 | int allow_cert) |
@@ -1976,9 +2015,13 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
1976 | size_t len; | 2015 | size_t len; |
1977 | u_char *pk = NULL; | 2016 | u_char *pk = NULL; |
1978 | struct sshbuf *copy; | 2017 | struct sshbuf *copy; |
1979 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | 2018 | #if defined(WITH_OPENSSL) |
2019 | BIGNUM *rsa_n = NULL, *rsa_e = NULL; | ||
2020 | BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL; | ||
2021 | # if defined(OPENSSL_HAS_ECC) | ||
1980 | EC_POINT *q = NULL; | 2022 | EC_POINT *q = NULL; |
1981 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ | 2023 | # endif /* OPENSSL_HAS_ECC */ |
2024 | #endif /* WITH_OPENSSL */ | ||
1982 | 2025 | ||
1983 | #ifdef DEBUG_PK /* XXX */ | 2026 | #ifdef DEBUG_PK /* XXX */ |
1984 | sshbuf_dump(b, stderr); | 2027 | sshbuf_dump(b, stderr); |
@@ -2013,15 +2056,23 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2013 | ret = SSH_ERR_ALLOC_FAIL; | 2056 | ret = SSH_ERR_ALLOC_FAIL; |
2014 | goto out; | 2057 | goto out; |
2015 | } | 2058 | } |
2016 | if (sshbuf_get_bignum2(b, key->rsa->e) != 0 || | 2059 | if ((rsa_e = BN_new()) == NULL || |
2017 | sshbuf_get_bignum2(b, key->rsa->n) != 0) { | 2060 | (rsa_n = BN_new()) == NULL) { |
2061 | ret = SSH_ERR_ALLOC_FAIL; | ||
2062 | goto out; | ||
2063 | } | ||
2064 | if (sshbuf_get_bignum2(b, rsa_e) != 0 || | ||
2065 | sshbuf_get_bignum2(b, rsa_n) != 0) { | ||
2018 | ret = SSH_ERR_INVALID_FORMAT; | 2066 | ret = SSH_ERR_INVALID_FORMAT; |
2019 | goto out; | 2067 | goto out; |
2020 | } | 2068 | } |
2021 | if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { | 2069 | if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) { |
2022 | ret = SSH_ERR_KEY_LENGTH; | 2070 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
2023 | goto out; | 2071 | goto out; |
2024 | } | 2072 | } |
2073 | rsa_n = rsa_e = NULL; /* transferred */ | ||
2074 | if ((ret = check_rsa_length(key->rsa)) != 0) | ||
2075 | goto out; | ||
2025 | #ifdef DEBUG_PK | 2076 | #ifdef DEBUG_PK |
2026 | RSA_print_fp(stderr, key->rsa, 8); | 2077 | RSA_print_fp(stderr, key->rsa, 8); |
2027 | #endif | 2078 | #endif |
@@ -2038,13 +2089,30 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2038 | ret = SSH_ERR_ALLOC_FAIL; | 2089 | ret = SSH_ERR_ALLOC_FAIL; |
2039 | goto out; | 2090 | goto out; |
2040 | } | 2091 | } |
2041 | if (sshbuf_get_bignum2(b, key->dsa->p) != 0 || | 2092 | if ((dsa_p = BN_new()) == NULL || |
2042 | sshbuf_get_bignum2(b, key->dsa->q) != 0 || | 2093 | (dsa_q = BN_new()) == NULL || |
2043 | sshbuf_get_bignum2(b, key->dsa->g) != 0 || | 2094 | (dsa_g = BN_new()) == NULL || |
2044 | sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) { | 2095 | (dsa_pub_key = BN_new()) == NULL) { |
2096 | ret = SSH_ERR_ALLOC_FAIL; | ||
2097 | goto out; | ||
2098 | } | ||
2099 | if (sshbuf_get_bignum2(b, dsa_p) != 0 || | ||
2100 | sshbuf_get_bignum2(b, dsa_q) != 0 || | ||
2101 | sshbuf_get_bignum2(b, dsa_g) != 0 || | ||
2102 | sshbuf_get_bignum2(b, dsa_pub_key) != 0) { | ||
2045 | ret = SSH_ERR_INVALID_FORMAT; | 2103 | ret = SSH_ERR_INVALID_FORMAT; |
2046 | goto out; | 2104 | goto out; |
2047 | } | 2105 | } |
2106 | if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) { | ||
2107 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
2108 | goto out; | ||
2109 | } | ||
2110 | dsa_p = dsa_q = dsa_g = NULL; /* transferred */ | ||
2111 | if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) { | ||
2112 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
2113 | goto out; | ||
2114 | } | ||
2115 | dsa_pub_key = NULL; /* transferred */ | ||
2048 | #ifdef DEBUG_PK | 2116 | #ifdef DEBUG_PK |
2049 | DSA_print_fp(stderr, key->dsa, 8); | 2117 | DSA_print_fp(stderr, key->dsa, 8); |
2050 | #endif | 2118 | #endif |
@@ -2178,9 +2246,17 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2178 | free(ktype); | 2246 | free(ktype); |
2179 | free(curve); | 2247 | free(curve); |
2180 | free(pk); | 2248 | free(pk); |
2181 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | 2249 | #if defined(WITH_OPENSSL) |
2250 | BN_clear_free(rsa_n); | ||
2251 | BN_clear_free(rsa_e); | ||
2252 | BN_clear_free(dsa_p); | ||
2253 | BN_clear_free(dsa_q); | ||
2254 | BN_clear_free(dsa_g); | ||
2255 | BN_clear_free(dsa_pub_key); | ||
2256 | # if defined(OPENSSL_HAS_ECC) | ||
2182 | EC_POINT_free(q); | 2257 | EC_POINT_free(q); |
2183 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ | 2258 | # endif /* OPENSSL_HAS_ECC */ |
2259 | #endif /* WITH_OPENSSL */ | ||
2184 | return ret; | 2260 | return ret; |
2185 | } | 2261 | } |
2186 | 2262 | ||
@@ -2242,6 +2318,27 @@ get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) | |||
2242 | } | 2318 | } |
2243 | 2319 | ||
2244 | /* | 2320 | /* |
2321 | * | ||
2322 | * Checks whether a certificate's signature type is allowed. | ||
2323 | * Returns 0 (success) if the certificate signature type appears in the | ||
2324 | * "allowed" pattern-list, or the key is not a certificate to begin with. | ||
2325 | * Otherwise returns a ssherr.h code. | ||
2326 | */ | ||
2327 | int | ||
2328 | sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed) | ||
2329 | { | ||
2330 | if (key == NULL || allowed == NULL) | ||
2331 | return SSH_ERR_INVALID_ARGUMENT; | ||
2332 | if (!sshkey_type_is_cert(key->type)) | ||
2333 | return 0; | ||
2334 | if (key->cert == NULL || key->cert->signature_type == NULL) | ||
2335 | return SSH_ERR_INVALID_ARGUMENT; | ||
2336 | if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1) | ||
2337 | return SSH_ERR_SIGN_ALG_UNSUPPORTED; | ||
2338 | return 0; | ||
2339 | } | ||
2340 | |||
2341 | /* | ||
2245 | * Returns the expected signature algorithm for a given public key algorithm. | 2342 | * Returns the expected signature algorithm for a given public key algorithm. |
2246 | */ | 2343 | */ |
2247 | const char * | 2344 | const char * |
@@ -2361,120 +2458,6 @@ sshkey_verify(const struct sshkey *key, | |||
2361 | } | 2458 | } |
2362 | } | 2459 | } |
2363 | 2460 | ||
2364 | /* Converts a private to a public key */ | ||
2365 | int | ||
2366 | sshkey_demote(const struct sshkey *k, struct sshkey **dkp) | ||
2367 | { | ||
2368 | struct sshkey *pk; | ||
2369 | int ret = SSH_ERR_INTERNAL_ERROR; | ||
2370 | |||
2371 | *dkp = NULL; | ||
2372 | if ((pk = calloc(1, sizeof(*pk))) == NULL) | ||
2373 | return SSH_ERR_ALLOC_FAIL; | ||
2374 | pk->type = k->type; | ||
2375 | pk->flags = k->flags; | ||
2376 | pk->ecdsa_nid = k->ecdsa_nid; | ||
2377 | pk->dsa = NULL; | ||
2378 | pk->ecdsa = NULL; | ||
2379 | pk->rsa = NULL; | ||
2380 | pk->ed25519_pk = NULL; | ||
2381 | pk->ed25519_sk = NULL; | ||
2382 | pk->xmss_pk = NULL; | ||
2383 | pk->xmss_sk = NULL; | ||
2384 | |||
2385 | switch (k->type) { | ||
2386 | #ifdef WITH_OPENSSL | ||
2387 | case KEY_RSA_CERT: | ||
2388 | if ((ret = sshkey_cert_copy(k, pk)) != 0) | ||
2389 | goto fail; | ||
2390 | /* FALLTHROUGH */ | ||
2391 | case KEY_RSA: | ||
2392 | if ((pk->rsa = RSA_new()) == NULL || | ||
2393 | (pk->rsa->e = BN_dup(k->rsa->e)) == NULL || | ||
2394 | (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) { | ||
2395 | ret = SSH_ERR_ALLOC_FAIL; | ||
2396 | goto fail; | ||
2397 | } | ||
2398 | break; | ||
2399 | case KEY_DSA_CERT: | ||
2400 | if ((ret = sshkey_cert_copy(k, pk)) != 0) | ||
2401 | goto fail; | ||
2402 | /* FALLTHROUGH */ | ||
2403 | case KEY_DSA: | ||
2404 | if ((pk->dsa = DSA_new()) == NULL || | ||
2405 | (pk->dsa->p = BN_dup(k->dsa->p)) == NULL || | ||
2406 | (pk->dsa->q = BN_dup(k->dsa->q)) == NULL || | ||
2407 | (pk->dsa->g = BN_dup(k->dsa->g)) == NULL || | ||
2408 | (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) { | ||
2409 | ret = SSH_ERR_ALLOC_FAIL; | ||
2410 | goto fail; | ||
2411 | } | ||
2412 | break; | ||
2413 | case KEY_ECDSA_CERT: | ||
2414 | if ((ret = sshkey_cert_copy(k, pk)) != 0) | ||
2415 | goto fail; | ||
2416 | /* FALLTHROUGH */ | ||
2417 | # ifdef OPENSSL_HAS_ECC | ||
2418 | case KEY_ECDSA: | ||
2419 | pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid); | ||
2420 | if (pk->ecdsa == NULL) { | ||
2421 | ret = SSH_ERR_ALLOC_FAIL; | ||
2422 | goto fail; | ||
2423 | } | ||
2424 | if (EC_KEY_set_public_key(pk->ecdsa, | ||
2425 | EC_KEY_get0_public_key(k->ecdsa)) != 1) { | ||
2426 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
2427 | goto fail; | ||
2428 | } | ||
2429 | break; | ||
2430 | # endif /* OPENSSL_HAS_ECC */ | ||
2431 | #endif /* WITH_OPENSSL */ | ||
2432 | case KEY_ED25519_CERT: | ||
2433 | if ((ret = sshkey_cert_copy(k, pk)) != 0) | ||
2434 | goto fail; | ||
2435 | /* FALLTHROUGH */ | ||
2436 | case KEY_ED25519: | ||
2437 | if (k->ed25519_pk != NULL) { | ||
2438 | if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { | ||
2439 | ret = SSH_ERR_ALLOC_FAIL; | ||
2440 | goto fail; | ||
2441 | } | ||
2442 | memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); | ||
2443 | } | ||
2444 | break; | ||
2445 | #ifdef WITH_XMSS | ||
2446 | case KEY_XMSS_CERT: | ||
2447 | if ((ret = sshkey_cert_copy(k, pk)) != 0) | ||
2448 | goto fail; | ||
2449 | /* FALLTHROUGH */ | ||
2450 | case KEY_XMSS: | ||
2451 | if ((ret = sshkey_xmss_init(pk, k->xmss_name)) != 0) | ||
2452 | goto fail; | ||
2453 | if (k->xmss_pk != NULL) { | ||
2454 | size_t pklen = sshkey_xmss_pklen(k); | ||
2455 | |||
2456 | if (pklen == 0 || sshkey_xmss_pklen(pk) != pklen) { | ||
2457 | ret = SSH_ERR_INTERNAL_ERROR; | ||
2458 | goto fail; | ||
2459 | } | ||
2460 | if ((pk->xmss_pk = malloc(pklen)) == NULL) { | ||
2461 | ret = SSH_ERR_ALLOC_FAIL; | ||
2462 | goto fail; | ||
2463 | } | ||
2464 | memcpy(pk->xmss_pk, k->xmss_pk, pklen); | ||
2465 | } | ||
2466 | break; | ||
2467 | #endif /* WITH_XMSS */ | ||
2468 | default: | ||
2469 | ret = SSH_ERR_KEY_TYPE_UNKNOWN; | ||
2470 | fail: | ||
2471 | sshkey_free(pk); | ||
2472 | return ret; | ||
2473 | } | ||
2474 | *dkp = pk; | ||
2475 | return 0; | ||
2476 | } | ||
2477 | |||
2478 | /* Convert a plain key to their _CERT equivalent */ | 2461 | /* Convert a plain key to their _CERT equivalent */ |
2479 | int | 2462 | int |
2480 | sshkey_to_certified(struct sshkey *k) | 2463 | sshkey_to_certified(struct sshkey *k) |
@@ -2531,7 +2514,11 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, | |||
2531 | u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; | 2514 | u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; |
2532 | size_t i, ca_len, sig_len; | 2515 | size_t i, ca_len, sig_len; |
2533 | int ret = SSH_ERR_INTERNAL_ERROR; | 2516 | int ret = SSH_ERR_INTERNAL_ERROR; |
2534 | struct sshbuf *cert; | 2517 | struct sshbuf *cert = NULL; |
2518 | char *sigtype = NULL; | ||
2519 | #ifdef WITH_OPENSSL | ||
2520 | const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; | ||
2521 | #endif /* WITH_OPENSSL */ | ||
2535 | 2522 | ||
2536 | if (k == NULL || k->cert == NULL || | 2523 | if (k == NULL || k->cert == NULL || |
2537 | k->cert->certblob == NULL || ca == NULL) | 2524 | k->cert->certblob == NULL || ca == NULL) |
@@ -2541,6 +2528,16 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, | |||
2541 | if (!sshkey_type_is_valid_ca(ca->type)) | 2528 | if (!sshkey_type_is_valid_ca(ca->type)) |
2542 | return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; | 2529 | return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
2543 | 2530 | ||
2531 | /* | ||
2532 | * If no alg specified as argument but a signature_type was set, | ||
2533 | * then prefer that. If both were specified, then they must match. | ||
2534 | */ | ||
2535 | if (alg == NULL) | ||
2536 | alg = k->cert->signature_type; | ||
2537 | else if (k->cert->signature_type != NULL && | ||
2538 | strcmp(alg, k->cert->signature_type) != 0) | ||
2539 | return SSH_ERR_INVALID_ARGUMENT; | ||
2540 | |||
2544 | if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) | 2541 | if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) |
2545 | return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; | 2542 | return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
2546 | 2543 | ||
@@ -2558,10 +2555,12 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, | |||
2558 | switch (k->type) { | 2555 | switch (k->type) { |
2559 | #ifdef WITH_OPENSSL | 2556 | #ifdef WITH_OPENSSL |
2560 | case KEY_DSA_CERT: | 2557 | case KEY_DSA_CERT: |
2561 | if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 || | 2558 | DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g); |
2562 | (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 || | 2559 | DSA_get0_key(k->dsa, &dsa_pub_key, NULL); |
2563 | (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 || | 2560 | if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 || |
2564 | (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0) | 2561 | (ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 || |
2562 | (ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 || | ||
2563 | (ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0) | ||
2565 | goto out; | 2564 | goto out; |
2566 | break; | 2565 | break; |
2567 | # ifdef OPENSSL_HAS_ECC | 2566 | # ifdef OPENSSL_HAS_ECC |
@@ -2575,8 +2574,9 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, | |||
2575 | break; | 2574 | break; |
2576 | # endif /* OPENSSL_HAS_ECC */ | 2575 | # endif /* OPENSSL_HAS_ECC */ |
2577 | case KEY_RSA_CERT: | 2576 | case KEY_RSA_CERT: |
2578 | if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 || | 2577 | RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL); |
2579 | (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0) | 2578 | if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 || |
2579 | (ret = sshbuf_put_bignum2(cert, rsa_n)) != 0) | ||
2580 | goto out; | 2580 | goto out; |
2581 | break; | 2581 | break; |
2582 | #endif /* WITH_OPENSSL */ | 2582 | #endif /* WITH_OPENSSL */ |
@@ -2629,7 +2629,17 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, | |||
2629 | if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), | 2629 | if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), |
2630 | sshbuf_len(cert), alg, 0, signer_ctx)) != 0) | 2630 | sshbuf_len(cert), alg, 0, signer_ctx)) != 0) |
2631 | goto out; | 2631 | goto out; |
2632 | 2632 | /* Check and update signature_type against what was actually used */ | |
2633 | if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0) | ||
2634 | goto out; | ||
2635 | if (alg != NULL && strcmp(alg, sigtype) != 0) { | ||
2636 | ret = SSH_ERR_SIGN_ALG_UNSUPPORTED; | ||
2637 | goto out; | ||
2638 | } | ||
2639 | if (k->cert->signature_type == NULL) { | ||
2640 | k->cert->signature_type = sigtype; | ||
2641 | sigtype = NULL; | ||
2642 | } | ||
2633 | /* Append signature and we are done */ | 2643 | /* Append signature and we are done */ |
2634 | if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0) | 2644 | if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0) |
2635 | goto out; | 2645 | goto out; |
@@ -2639,6 +2649,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, | |||
2639 | sshbuf_reset(cert); | 2649 | sshbuf_reset(cert); |
2640 | free(sig_blob); | 2650 | free(sig_blob); |
2641 | free(ca_blob); | 2651 | free(ca_blob); |
2652 | free(sigtype); | ||
2642 | sshbuf_free(principals); | 2653 | sshbuf_free(principals); |
2643 | return ret; | 2654 | return ret; |
2644 | } | 2655 | } |
@@ -2758,18 +2769,25 @@ sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b, | |||
2758 | enum sshkey_serialize_rep opts) | 2769 | enum sshkey_serialize_rep opts) |
2759 | { | 2770 | { |
2760 | int r = SSH_ERR_INTERNAL_ERROR; | 2771 | int r = SSH_ERR_INTERNAL_ERROR; |
2772 | #ifdef WITH_OPENSSL | ||
2773 | const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q; | ||
2774 | const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key; | ||
2775 | #endif /* WITH_OPENSSL */ | ||
2761 | 2776 | ||
2762 | if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) | 2777 | if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) |
2763 | goto out; | 2778 | goto out; |
2764 | switch (key->type) { | 2779 | switch (key->type) { |
2765 | #ifdef WITH_OPENSSL | 2780 | #ifdef WITH_OPENSSL |
2766 | case KEY_RSA: | 2781 | case KEY_RSA: |
2767 | if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 || | 2782 | RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d); |
2768 | (r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || | 2783 | RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); |
2769 | (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || | 2784 | RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp); |
2770 | (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || | 2785 | if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 || |
2771 | (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || | 2786 | (r = sshbuf_put_bignum2(b, rsa_e)) != 0 || |
2772 | (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) | 2787 | (r = sshbuf_put_bignum2(b, rsa_d)) != 0 || |
2788 | (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 || | ||
2789 | (r = sshbuf_put_bignum2(b, rsa_p)) != 0 || | ||
2790 | (r = sshbuf_put_bignum2(b, rsa_q)) != 0) | ||
2773 | goto out; | 2791 | goto out; |
2774 | break; | 2792 | break; |
2775 | case KEY_RSA_CERT: | 2793 | case KEY_RSA_CERT: |
@@ -2777,19 +2795,24 @@ sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b, | |||
2777 | r = SSH_ERR_INVALID_ARGUMENT; | 2795 | r = SSH_ERR_INVALID_ARGUMENT; |
2778 | goto out; | 2796 | goto out; |
2779 | } | 2797 | } |
2798 | RSA_get0_key(key->rsa, NULL, NULL, &rsa_d); | ||
2799 | RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); | ||
2800 | RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp); | ||
2780 | if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || | 2801 | if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || |
2781 | (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || | 2802 | (r = sshbuf_put_bignum2(b, rsa_d)) != 0 || |
2782 | (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || | 2803 | (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 || |
2783 | (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || | 2804 | (r = sshbuf_put_bignum2(b, rsa_p)) != 0 || |
2784 | (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) | 2805 | (r = sshbuf_put_bignum2(b, rsa_q)) != 0) |
2785 | goto out; | 2806 | goto out; |
2786 | break; | 2807 | break; |
2787 | case KEY_DSA: | 2808 | case KEY_DSA: |
2788 | if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || | 2809 | DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g); |
2789 | (r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || | 2810 | DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key); |
2790 | (r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || | 2811 | if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 || |
2791 | (r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 || | 2812 | (r = sshbuf_put_bignum2(b, dsa_q)) != 0 || |
2792 | (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) | 2813 | (r = sshbuf_put_bignum2(b, dsa_g)) != 0 || |
2814 | (r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0 || | ||
2815 | (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) | ||
2793 | goto out; | 2816 | goto out; |
2794 | break; | 2817 | break; |
2795 | case KEY_DSA_CERT: | 2818 | case KEY_DSA_CERT: |
@@ -2797,8 +2820,9 @@ sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b, | |||
2797 | r = SSH_ERR_INVALID_ARGUMENT; | 2820 | r = SSH_ERR_INVALID_ARGUMENT; |
2798 | goto out; | 2821 | goto out; |
2799 | } | 2822 | } |
2823 | DSA_get0_key(key->dsa, NULL, &dsa_priv_key); | ||
2800 | if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || | 2824 | if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || |
2801 | (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) | 2825 | (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) |
2802 | goto out; | 2826 | goto out; |
2803 | break; | 2827 | break; |
2804 | # ifdef OPENSSL_HAS_ECC | 2828 | # ifdef OPENSSL_HAS_ECC |
@@ -2899,6 +2923,10 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2899 | u_char *xmss_pk = NULL, *xmss_sk = NULL; | 2923 | u_char *xmss_pk = NULL, *xmss_sk = NULL; |
2900 | #ifdef WITH_OPENSSL | 2924 | #ifdef WITH_OPENSSL |
2901 | BIGNUM *exponent = NULL; | 2925 | BIGNUM *exponent = NULL; |
2926 | BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; | ||
2927 | BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL; | ||
2928 | BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; | ||
2929 | BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; | ||
2902 | #endif /* WITH_OPENSSL */ | 2930 | #endif /* WITH_OPENSSL */ |
2903 | 2931 | ||
2904 | if (kp != NULL) | 2932 | if (kp != NULL) |
@@ -2909,26 +2937,52 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2909 | switch (type) { | 2937 | switch (type) { |
2910 | #ifdef WITH_OPENSSL | 2938 | #ifdef WITH_OPENSSL |
2911 | case KEY_DSA: | 2939 | case KEY_DSA: |
2912 | if ((k = sshkey_new_private(type)) == NULL) { | 2940 | if ((k = sshkey_new(type)) == NULL) { |
2913 | r = SSH_ERR_ALLOC_FAIL; | 2941 | r = SSH_ERR_ALLOC_FAIL; |
2914 | goto out; | 2942 | goto out; |
2915 | } | 2943 | } |
2916 | if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 || | 2944 | if ((dsa_p = BN_new()) == NULL || |
2917 | (r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 || | 2945 | (dsa_q = BN_new()) == NULL || |
2918 | (r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 || | 2946 | (dsa_g = BN_new()) == NULL || |
2919 | (r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 || | 2947 | (dsa_pub_key = BN_new()) == NULL || |
2920 | (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) | 2948 | (dsa_priv_key = BN_new()) == NULL) { |
2949 | r = SSH_ERR_ALLOC_FAIL; | ||
2921 | goto out; | 2950 | goto out; |
2951 | } | ||
2952 | if ((r = sshbuf_get_bignum2(buf, dsa_p)) != 0 || | ||
2953 | (r = sshbuf_get_bignum2(buf, dsa_q)) != 0 || | ||
2954 | (r = sshbuf_get_bignum2(buf, dsa_g)) != 0 || | ||
2955 | (r = sshbuf_get_bignum2(buf, dsa_pub_key)) != 0 || | ||
2956 | (r = sshbuf_get_bignum2(buf, dsa_priv_key)) != 0) | ||
2957 | goto out; | ||
2958 | if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) { | ||
2959 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
2960 | goto out; | ||
2961 | } | ||
2962 | dsa_p = dsa_q = dsa_g = NULL; /* transferred */ | ||
2963 | if (!DSA_set0_key(k->dsa, dsa_pub_key, dsa_priv_key)) { | ||
2964 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
2965 | goto out; | ||
2966 | } | ||
2967 | dsa_pub_key = dsa_priv_key = NULL; /* transferred */ | ||
2922 | break; | 2968 | break; |
2923 | case KEY_DSA_CERT: | 2969 | case KEY_DSA_CERT: |
2970 | if ((dsa_priv_key = BN_new()) == NULL) { | ||
2971 | r = SSH_ERR_ALLOC_FAIL; | ||
2972 | goto out; | ||
2973 | } | ||
2924 | if ((r = sshkey_froms(buf, &k)) != 0 || | 2974 | if ((r = sshkey_froms(buf, &k)) != 0 || |
2925 | (r = sshkey_add_private(k)) != 0 || | 2975 | (r = sshbuf_get_bignum2(buf, dsa_priv_key)) != 0) |
2926 | (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) | 2976 | goto out; |
2977 | if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) { | ||
2978 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
2927 | goto out; | 2979 | goto out; |
2980 | } | ||
2981 | dsa_priv_key = NULL; /* transferred */ | ||
2928 | break; | 2982 | break; |
2929 | # ifdef OPENSSL_HAS_ECC | 2983 | # ifdef OPENSSL_HAS_ECC |
2930 | case KEY_ECDSA: | 2984 | case KEY_ECDSA: |
2931 | if ((k = sshkey_new_private(type)) == NULL) { | 2985 | if ((k = sshkey_new(type)) == NULL) { |
2932 | r = SSH_ERR_ALLOC_FAIL; | 2986 | r = SSH_ERR_ALLOC_FAIL; |
2933 | goto out; | 2987 | goto out; |
2934 | } | 2988 | } |
@@ -2965,7 +3019,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2965 | goto out; | 3019 | goto out; |
2966 | } | 3020 | } |
2967 | if ((r = sshkey_froms(buf, &k)) != 0 || | 3021 | if ((r = sshkey_froms(buf, &k)) != 0 || |
2968 | (r = sshkey_add_private(k)) != 0 || | ||
2969 | (r = sshbuf_get_bignum2(buf, exponent)) != 0) | 3022 | (r = sshbuf_get_bignum2(buf, exponent)) != 0) |
2970 | goto out; | 3023 | goto out; |
2971 | if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { | 3024 | if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { |
@@ -2979,40 +3032,73 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2979 | break; | 3032 | break; |
2980 | # endif /* OPENSSL_HAS_ECC */ | 3033 | # endif /* OPENSSL_HAS_ECC */ |
2981 | case KEY_RSA: | 3034 | case KEY_RSA: |
2982 | if ((k = sshkey_new_private(type)) == NULL) { | 3035 | if ((k = sshkey_new(type)) == NULL) { |
2983 | r = SSH_ERR_ALLOC_FAIL; | 3036 | r = SSH_ERR_ALLOC_FAIL; |
2984 | goto out; | 3037 | goto out; |
2985 | } | 3038 | } |
2986 | if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 || | 3039 | if ((rsa_n = BN_new()) == NULL || |
2987 | (r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 || | 3040 | (rsa_e = BN_new()) == NULL || |
2988 | (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || | 3041 | (rsa_d = BN_new()) == NULL || |
2989 | (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || | 3042 | (rsa_iqmp = BN_new()) == NULL || |
2990 | (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || | 3043 | (rsa_p = BN_new()) == NULL || |
2991 | (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || | 3044 | (rsa_q = BN_new()) == NULL) { |
2992 | (r = ssh_rsa_generate_additional_parameters(k)) != 0) | 3045 | r = SSH_ERR_ALLOC_FAIL; |
2993 | goto out; | 3046 | goto out; |
2994 | if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { | 3047 | } |
2995 | r = SSH_ERR_KEY_LENGTH; | 3048 | if ((r = sshbuf_get_bignum2(buf, rsa_n)) != 0 || |
3049 | (r = sshbuf_get_bignum2(buf, rsa_e)) != 0 || | ||
3050 | (r = sshbuf_get_bignum2(buf, rsa_d)) != 0 || | ||
3051 | (r = sshbuf_get_bignum2(buf, rsa_iqmp)) != 0 || | ||
3052 | (r = sshbuf_get_bignum2(buf, rsa_p)) != 0 || | ||
3053 | (r = sshbuf_get_bignum2(buf, rsa_q)) != 0) | ||
3054 | goto out; | ||
3055 | if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, rsa_d)) { | ||
3056 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
2996 | goto out; | 3057 | goto out; |
2997 | } | 3058 | } |
3059 | rsa_n = rsa_e = rsa_d = NULL; /* transferred */ | ||
3060 | if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) { | ||
3061 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3062 | goto out; | ||
3063 | } | ||
3064 | rsa_p = rsa_q = NULL; /* transferred */ | ||
3065 | if ((r = check_rsa_length(k->rsa)) != 0) | ||
3066 | goto out; | ||
3067 | if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) | ||
3068 | goto out; | ||
2998 | break; | 3069 | break; |
2999 | case KEY_RSA_CERT: | 3070 | case KEY_RSA_CERT: |
3071 | if ((rsa_d = BN_new()) == NULL || | ||
3072 | (rsa_iqmp = BN_new()) == NULL || | ||
3073 | (rsa_p = BN_new()) == NULL || | ||
3074 | (rsa_q = BN_new()) == NULL) { | ||
3075 | r = SSH_ERR_ALLOC_FAIL; | ||
3076 | goto out; | ||
3077 | } | ||
3000 | if ((r = sshkey_froms(buf, &k)) != 0 || | 3078 | if ((r = sshkey_froms(buf, &k)) != 0 || |
3001 | (r = sshkey_add_private(k)) != 0 || | 3079 | (r = sshbuf_get_bignum2(buf, rsa_d)) != 0 || |
3002 | (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || | 3080 | (r = sshbuf_get_bignum2(buf, rsa_iqmp)) != 0 || |
3003 | (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || | 3081 | (r = sshbuf_get_bignum2(buf, rsa_p)) != 0 || |
3004 | (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || | 3082 | (r = sshbuf_get_bignum2(buf, rsa_q)) != 0) |
3005 | (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || | ||
3006 | (r = ssh_rsa_generate_additional_parameters(k)) != 0) | ||
3007 | goto out; | 3083 | goto out; |
3008 | if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { | 3084 | if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) { |
3009 | r = SSH_ERR_KEY_LENGTH; | 3085 | r = SSH_ERR_LIBCRYPTO_ERROR; |
3086 | goto out; | ||
3087 | } | ||
3088 | rsa_d = NULL; /* transferred */ | ||
3089 | if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) { | ||
3090 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3010 | goto out; | 3091 | goto out; |
3011 | } | 3092 | } |
3093 | rsa_p = rsa_q = NULL; /* transferred */ | ||
3094 | if ((r = check_rsa_length(k->rsa)) != 0) | ||
3095 | goto out; | ||
3096 | if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) | ||
3097 | goto out; | ||
3012 | break; | 3098 | break; |
3013 | #endif /* WITH_OPENSSL */ | 3099 | #endif /* WITH_OPENSSL */ |
3014 | case KEY_ED25519: | 3100 | case KEY_ED25519: |
3015 | if ((k = sshkey_new_private(type)) == NULL) { | 3101 | if ((k = sshkey_new(type)) == NULL) { |
3016 | r = SSH_ERR_ALLOC_FAIL; | 3102 | r = SSH_ERR_ALLOC_FAIL; |
3017 | goto out; | 3103 | goto out; |
3018 | } | 3104 | } |
@@ -3029,7 +3115,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
3029 | break; | 3115 | break; |
3030 | case KEY_ED25519_CERT: | 3116 | case KEY_ED25519_CERT: |
3031 | if ((r = sshkey_froms(buf, &k)) != 0 || | 3117 | if ((r = sshkey_froms(buf, &k)) != 0 || |
3032 | (r = sshkey_add_private(k)) != 0 || | ||
3033 | (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || | 3118 | (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || |
3034 | (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) | 3119 | (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) |
3035 | goto out; | 3120 | goto out; |
@@ -3043,7 +3128,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
3043 | break; | 3128 | break; |
3044 | #ifdef WITH_XMSS | 3129 | #ifdef WITH_XMSS |
3045 | case KEY_XMSS: | 3130 | case KEY_XMSS: |
3046 | if ((k = sshkey_new_private(type)) == NULL) { | 3131 | if ((k = sshkey_new(type)) == NULL) { |
3047 | r = SSH_ERR_ALLOC_FAIL; | 3132 | r = SSH_ERR_ALLOC_FAIL; |
3048 | goto out; | 3133 | goto out; |
3049 | } | 3134 | } |
@@ -3066,7 +3151,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
3066 | break; | 3151 | break; |
3067 | case KEY_XMSS_CERT: | 3152 | case KEY_XMSS_CERT: |
3068 | if ((r = sshkey_froms(buf, &k)) != 0 || | 3153 | if ((r = sshkey_froms(buf, &k)) != 0 || |
3069 | (r = sshkey_add_private(k)) != 0 || | ||
3070 | (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 || | 3154 | (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 || |
3071 | (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 || | 3155 | (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 || |
3072 | (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0) | 3156 | (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0) |
@@ -3115,6 +3199,17 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
3115 | free(curve); | 3199 | free(curve); |
3116 | #ifdef WITH_OPENSSL | 3200 | #ifdef WITH_OPENSSL |
3117 | BN_clear_free(exponent); | 3201 | BN_clear_free(exponent); |
3202 | BN_clear_free(dsa_p); | ||
3203 | BN_clear_free(dsa_q); | ||
3204 | BN_clear_free(dsa_g); | ||
3205 | BN_clear_free(dsa_pub_key); | ||
3206 | BN_clear_free(dsa_priv_key); | ||
3207 | BN_clear_free(rsa_n); | ||
3208 | BN_clear_free(rsa_e); | ||
3209 | BN_clear_free(rsa_d); | ||
3210 | BN_clear_free(rsa_p); | ||
3211 | BN_clear_free(rsa_q); | ||
3212 | BN_clear_free(rsa_iqmp); | ||
3118 | #endif /* WITH_OPENSSL */ | 3213 | #endif /* WITH_OPENSSL */ |
3119 | sshkey_free(k); | 3214 | sshkey_free(k); |
3120 | freezero(ed25519_pk, pklen); | 3215 | freezero(ed25519_pk, pklen); |
@@ -3769,7 +3864,9 @@ translate_libcrypto_error(unsigned long pem_err) | |||
3769 | switch (pem_reason) { | 3864 | switch (pem_reason) { |
3770 | case EVP_R_BAD_DECRYPT: | 3865 | case EVP_R_BAD_DECRYPT: |
3771 | return SSH_ERR_KEY_WRONG_PASSPHRASE; | 3866 | return SSH_ERR_KEY_WRONG_PASSPHRASE; |
3867 | #ifdef EVP_R_BN_DECODE_ERROR | ||
3772 | case EVP_R_BN_DECODE_ERROR: | 3868 | case EVP_R_BN_DECODE_ERROR: |
3869 | #endif | ||
3773 | case EVP_R_DECODE_ERROR: | 3870 | case EVP_R_DECODE_ERROR: |
3774 | #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR | 3871 | #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR |
3775 | case EVP_R_PRIVATE_KEY_DECODE_ERROR: | 3872 | case EVP_R_PRIVATE_KEY_DECODE_ERROR: |
@@ -3809,6 +3906,20 @@ convert_libcrypto_error(void) | |||
3809 | } | 3906 | } |
3810 | 3907 | ||
3811 | static int | 3908 | static int |
3909 | pem_passphrase_cb(char *buf, int size, int rwflag, void *u) | ||
3910 | { | ||
3911 | char *p = (char *)u; | ||
3912 | size_t len; | ||
3913 | |||
3914 | if (p == NULL || (len = strlen(p)) == 0) | ||
3915 | return -1; | ||
3916 | if (size < 0 || len > (size_t)size) | ||
3917 | return -1; | ||
3918 | memcpy(buf, p, len); | ||
3919 | return (int)len; | ||
3920 | } | ||
3921 | |||
3922 | static int | ||
3812 | sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | 3923 | sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, |
3813 | const char *passphrase, struct sshkey **keyp) | 3924 | const char *passphrase, struct sshkey **keyp) |
3814 | { | 3925 | { |
@@ -3829,12 +3940,21 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | |||
3829 | } | 3940 | } |
3830 | 3941 | ||
3831 | clear_libcrypto_errors(); | 3942 | clear_libcrypto_errors(); |
3832 | if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, | 3943 | if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb, |
3833 | (char *)passphrase)) == NULL) { | 3944 | (char *)passphrase)) == NULL) { |
3834 | r = convert_libcrypto_error(); | 3945 | /* |
3946 | * libcrypto may return various ASN.1 errors when attempting | ||
3947 | * to parse a key with an incorrect passphrase. | ||
3948 | * Treat all format errors as "incorrect passphrase" if a | ||
3949 | * passphrase was supplied. | ||
3950 | */ | ||
3951 | if (passphrase != NULL && *passphrase != '\0') | ||
3952 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3953 | else | ||
3954 | r = convert_libcrypto_error(); | ||
3835 | goto out; | 3955 | goto out; |
3836 | } | 3956 | } |
3837 | if (pk->type == EVP_PKEY_RSA && | 3957 | if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA && |
3838 | (type == KEY_UNSPEC || type == KEY_RSA)) { | 3958 | (type == KEY_UNSPEC || type == KEY_RSA)) { |
3839 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { | 3959 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { |
3840 | r = SSH_ERR_ALLOC_FAIL; | 3960 | r = SSH_ERR_ALLOC_FAIL; |
@@ -3849,11 +3969,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | |||
3849 | r = SSH_ERR_LIBCRYPTO_ERROR; | 3969 | r = SSH_ERR_LIBCRYPTO_ERROR; |
3850 | goto out; | 3970 | goto out; |
3851 | } | 3971 | } |
3852 | if (BN_num_bits(prv->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { | 3972 | if ((r = check_rsa_length(prv->rsa)) != 0) |
3853 | r = SSH_ERR_KEY_LENGTH; | ||
3854 | goto out; | 3973 | goto out; |
3855 | } | 3974 | } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA && |
3856 | } else if (pk->type == EVP_PKEY_DSA && | ||
3857 | (type == KEY_UNSPEC || type == KEY_DSA)) { | 3975 | (type == KEY_UNSPEC || type == KEY_DSA)) { |
3858 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { | 3976 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { |
3859 | r = SSH_ERR_ALLOC_FAIL; | 3977 | r = SSH_ERR_ALLOC_FAIL; |
@@ -3865,7 +3983,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | |||
3865 | DSA_print_fp(stderr, prv->dsa, 8); | 3983 | DSA_print_fp(stderr, prv->dsa, 8); |
3866 | #endif | 3984 | #endif |
3867 | #ifdef OPENSSL_HAS_ECC | 3985 | #ifdef OPENSSL_HAS_ECC |
3868 | } else if (pk->type == EVP_PKEY_EC && | 3986 | } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC && |
3869 | (type == KEY_UNSPEC || type == KEY_ECDSA)) { | 3987 | (type == KEY_UNSPEC || type == KEY_ECDSA)) { |
3870 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { | 3988 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { |
3871 | r = SSH_ERR_ALLOC_FAIL; | 3989 | r = SSH_ERR_ALLOC_FAIL; |