summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-09-12 01:31:30 +0000
committerDamien Miller <djm@mindrot.org>2018-09-12 16:49:21 +1000
commita70fd4ad7bd9f2ed223ff635a3d41e483057f23b (patch)
tree06f3d604918320a7b28474377c5a65b4bddca9f4 /sshkey.c
parent357128ac48630a9970e3af0e6ff820300a28da47 (diff)
upstream: add cert->signature_type field and keep it in sync with
certificate signature wrt loading and certification operations; ok markus@ OpenBSD-Commit-ID: e8b8b9f76b66707a0cd926109c4383db8f664df3
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c93
1 files changed, 67 insertions, 26 deletions
diff --git a/sshkey.c b/sshkey.c
index 72c08c7e0..b467571fd 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -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.67 2018/09/12 01:31:30 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.
@@ -78,6 +78,7 @@ int sshkey_private_serialize_opt(const struct sshkey *key,
78 struct sshbuf *buf, enum sshkey_serialize_rep); 78 struct sshbuf *buf, enum sshkey_serialize_rep);
79static int sshkey_from_blob_internal(struct sshbuf *buf, 79static int sshkey_from_blob_internal(struct sshbuf *buf,
80 struct sshkey **keyp, int allow_cert); 80 struct sshkey **keyp, int allow_cert);
81static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep);
81 82
82/* Supported key types */ 83/* Supported key types */
83struct keytype { 84struct keytype {
@@ -453,6 +454,7 @@ cert_free(struct sshkey_cert *cert)
453 free(cert->principals[i]); 454 free(cert->principals[i]);
454 free(cert->principals); 455 free(cert->principals);
455 sshkey_free(cert->signature_key); 456 sshkey_free(cert->signature_key);
457 free(cert->signature_type);
456 freezero(cert, sizeof(*cert)); 458 freezero(cert, sizeof(*cert));
457} 459}
458 460
@@ -472,6 +474,7 @@ cert_new(void)
472 cert->key_id = NULL; 474 cert->key_id = NULL;
473 cert->principals = NULL; 475 cert->principals = NULL;
474 cert->signature_key = NULL; 476 cert->signature_key = NULL;
477 cert->signature_type = NULL;
475 return cert; 478 return cert;
476} 479}
477 480
@@ -1695,54 +1698,68 @@ sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
1695 u_int i; 1698 u_int i;
1696 const struct sshkey_cert *from; 1699 const struct sshkey_cert *from;
1697 struct sshkey_cert *to; 1700 struct sshkey_cert *to;
1698 int ret = SSH_ERR_INTERNAL_ERROR; 1701 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 1702
1705 if ((from = from_key->cert) == NULL) 1703 if (to_key == NULL || (from = from_key->cert) == NULL)
1706 return SSH_ERR_INVALID_ARGUMENT; 1704 return SSH_ERR_INVALID_ARGUMENT;
1707 1705
1708 if ((to = to_key->cert = cert_new()) == NULL) 1706 if ((to = cert_new()) == NULL)
1709 return SSH_ERR_ALLOC_FAIL; 1707 return SSH_ERR_ALLOC_FAIL;
1710 1708
1711 if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 || 1709 if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
1712 (ret = sshbuf_putb(to->critical, from->critical)) != 0 || 1710 (r = sshbuf_putb(to->critical, from->critical)) != 0 ||
1713 (ret = sshbuf_putb(to->extensions, from->extensions)) != 0) 1711 (r = sshbuf_putb(to->extensions, from->extensions)) != 0)
1714 return ret; 1712 goto out;
1715 1713
1716 to->serial = from->serial; 1714 to->serial = from->serial;
1717 to->type = from->type; 1715 to->type = from->type;
1718 if (from->key_id == NULL) 1716 if (from->key_id == NULL)
1719 to->key_id = NULL; 1717 to->key_id = NULL;
1720 else if ((to->key_id = strdup(from->key_id)) == NULL) 1718 else if ((to->key_id = strdup(from->key_id)) == NULL) {
1721 return SSH_ERR_ALLOC_FAIL; 1719 r = SSH_ERR_ALLOC_FAIL;
1720 goto out;
1721 }
1722 to->valid_after = from->valid_after; 1722 to->valid_after = from->valid_after;
1723 to->valid_before = from->valid_before; 1723 to->valid_before = from->valid_before;
1724 if (from->signature_key == NULL) 1724 if (from->signature_key == NULL)
1725 to->signature_key = NULL; 1725 to->signature_key = NULL;
1726 else if ((ret = sshkey_from_private(from->signature_key, 1726 else if ((r = sshkey_from_private(from->signature_key,
1727 &to->signature_key)) != 0) 1727 &to->signature_key)) != 0)
1728 return ret; 1728 goto out;
1729 1729 if (from->signature_type != NULL &&
1730 if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) 1730 (to->signature_type = strdup(from->signature_type)) == NULL) {
1731 return SSH_ERR_INVALID_ARGUMENT; 1731 r = SSH_ERR_ALLOC_FAIL;
1732 goto out;
1733 }
1734 if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) {
1735 r = SSH_ERR_INVALID_ARGUMENT;
1736 goto out;
1737 }
1732 if (from->nprincipals > 0) { 1738 if (from->nprincipals > 0) {
1733 if ((to->principals = calloc(from->nprincipals, 1739 if ((to->principals = calloc(from->nprincipals,
1734 sizeof(*to->principals))) == NULL) 1740 sizeof(*to->principals))) == NULL) {
1735 return SSH_ERR_ALLOC_FAIL; 1741 r = SSH_ERR_ALLOC_FAIL;
1742 goto out;
1743 }
1736 for (i = 0; i < from->nprincipals; i++) { 1744 for (i = 0; i < from->nprincipals; i++) {
1737 to->principals[i] = strdup(from->principals[i]); 1745 to->principals[i] = strdup(from->principals[i]);
1738 if (to->principals[i] == NULL) { 1746 if (to->principals[i] == NULL) {
1739 to->nprincipals = i; 1747 to->nprincipals = i;
1740 return SSH_ERR_ALLOC_FAIL; 1748 r = SSH_ERR_ALLOC_FAIL;
1749 goto out;
1741 } 1750 }
1742 } 1751 }
1743 } 1752 }
1744 to->nprincipals = from->nprincipals; 1753 to->nprincipals = from->nprincipals;
1745 return 0; 1754
1755 /* success */
1756 cert_free(to_key->cert);
1757 to_key->cert = to;
1758 to = NULL;
1759 r = 0;
1760 out:
1761 cert_free(to);
1762 return r;
1746} 1763}
1747 1764
1748int 1765int
@@ -1954,6 +1971,8 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1954 if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, 1971 if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1955 sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0) 1972 sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
1956 goto out; 1973 goto out;
1974 if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0)
1975 goto out;
1957 1976
1958 /* Success */ 1977 /* Success */
1959 ret = 0; 1978 ret = 0;
@@ -2531,7 +2550,8 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2531 u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; 2550 u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
2532 size_t i, ca_len, sig_len; 2551 size_t i, ca_len, sig_len;
2533 int ret = SSH_ERR_INTERNAL_ERROR; 2552 int ret = SSH_ERR_INTERNAL_ERROR;
2534 struct sshbuf *cert; 2553 struct sshbuf *cert = NULL;
2554 char *sigtype = NULL;
2535 2555
2536 if (k == NULL || k->cert == NULL || 2556 if (k == NULL || k->cert == NULL ||
2537 k->cert->certblob == NULL || ca == NULL) 2557 k->cert->certblob == NULL || ca == NULL)
@@ -2541,6 +2561,16 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2541 if (!sshkey_type_is_valid_ca(ca->type)) 2561 if (!sshkey_type_is_valid_ca(ca->type))
2542 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; 2562 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2543 2563
2564 /*
2565 * If no alg specified as argument but a signature_type was set,
2566 * then prefer that. If both were specified, then they must match.
2567 */
2568 if (alg == NULL)
2569 alg = k->cert->signature_type;
2570 else if (k->cert->signature_type != NULL &&
2571 strcmp(alg, k->cert->signature_type) != 0)
2572 return SSH_ERR_INVALID_ARGUMENT;
2573
2544 if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) 2574 if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
2545 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; 2575 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2546 2576
@@ -2629,7 +2659,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), 2659 if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
2630 sshbuf_len(cert), alg, 0, signer_ctx)) != 0) 2660 sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
2631 goto out; 2661 goto out;
2632 2662 /* Check and update signature_type against what was actually used */
2663 if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
2664 goto out;
2665 if (alg != NULL && strcmp(alg, sigtype) != 0) {
2666 ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
2667 goto out;
2668 }
2669 if (k->cert->signature_type == NULL) {
2670 k->cert->signature_type = sigtype;
2671 sigtype = NULL;
2672 }
2633 /* Append signature and we are done */ 2673 /* Append signature and we are done */
2634 if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0) 2674 if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
2635 goto out; 2675 goto out;
@@ -2639,6 +2679,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2639 sshbuf_reset(cert); 2679 sshbuf_reset(cert);
2640 free(sig_blob); 2680 free(sig_blob);
2641 free(ca_blob); 2681 free(ca_blob);
2682 free(sigtype);
2642 sshbuf_free(principals); 2683 sshbuf_free(principals);
2643 return ret; 2684 return ret;
2644} 2685}