summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2014-10-08 21:45:48 +0000
committerDamien Miller <djm@mindrot.org>2014-10-13 11:39:11 +1100
commit3cc1fbb4fb0e804bfb873fd363cea91b27fc8188 (patch)
tree51f2098e67c3ceb4301080b0525099236882e1d6 /sshkey.c
parent4a45922aebf99164e2fc83d34fe55b11ae1866ef (diff)
upstream commit
parse cert sections using nested buffers to reduce copies; ok markus
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c98
1 files changed, 47 insertions, 51 deletions
diff --git a/sshkey.c b/sshkey.c
index fdd0c8a89..cbf3c2d03 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.3 2014/07/03 01:45:38 djm Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.4 2014/10/08 21:45:48 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.
@@ -181,12 +181,12 @@ sshkey_ecdsa_nid_from_name(const char *name)
181{ 181{
182 const struct keytype *kt; 182 const struct keytype *kt;
183 183
184 for (kt = keytypes; kt->type != -1; kt++) { 184 for (kt = keytypes; kt->type != -1; kt++) {
185 if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) 185 if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
186 continue; 186 continue;
187 if (kt->name != NULL && strcmp(name, kt->name) == 0) 187 if (kt->name != NULL && strcmp(name, kt->name) == 0)
188 return kt->nid; 188 return kt->nid;
189 } 189 }
190 return -1; 190 return -1;
191} 191}
192 192
@@ -1769,32 +1769,24 @@ static int
1769cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob, 1769cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob,
1770 size_t blen) 1770 size_t blen)
1771{ 1771{
1772 u_char *principals = NULL, *critical = NULL, *exts = NULL; 1772 struct sshbuf *principals = NULL, *crit = NULL, *exts = NULL;
1773 u_char *sig_key = NULL, *sig = NULL; 1773 u_char *sig_key = NULL, *sig = NULL;
1774 size_t signed_len, plen, clen, sklen, slen, kidlen, elen; 1774 size_t signed_len = 0, sklen = 0, slen = 0, kidlen = 0;
1775 struct sshbuf *tmp;
1776 char *principal;
1777 int ret = SSH_ERR_INTERNAL_ERROR; 1775 int ret = SSH_ERR_INTERNAL_ERROR;
1778 int v00 = sshkey_cert_is_legacy(key); 1776 int v00 = sshkey_cert_is_legacy(key);
1779 char **oprincipals;
1780
1781 if ((tmp = sshbuf_new()) == NULL)
1782 return SSH_ERR_ALLOC_FAIL;
1783 1777
1784 /* Copy the entire key blob for verification and later serialisation */ 1778 /* Copy the entire key blob for verification and later serialisation */
1785 if ((ret = sshbuf_put(key->cert->certblob, blob, blen)) != 0) 1779 if ((ret = sshbuf_put(key->cert->certblob, blob, blen)) != 0)
1786 return ret; 1780 return ret;
1787 1781
1788 elen = 0; /* Not touched for v00 certs */
1789 principals = exts = critical = sig_key = sig = NULL;
1790 if ((!v00 && (ret = sshbuf_get_u64(b, &key->cert->serial)) != 0) || 1782 if ((!v00 && (ret = sshbuf_get_u64(b, &key->cert->serial)) != 0) ||
1791 (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 || 1783 (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
1792 (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 || 1784 (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
1793 (ret = sshbuf_get_string(b, &principals, &plen)) != 0 || 1785 (ret = sshbuf_froms(b, &principals)) != 0 ||
1794 (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 || 1786 (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
1795 (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 || 1787 (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
1796 (ret = sshbuf_get_string(b, &critical, &clen)) != 0 || 1788 (ret = sshbuf_froms(b, &crit)) != 0 ||
1797 (!v00 && (ret = sshbuf_get_string(b, &exts, &elen)) != 0) || 1789 (!v00 && (ret = sshbuf_froms(b, &exts)) != 0) ||
1798 (v00 && (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0) || 1790 (v00 && (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0) ||
1799 (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || 1791 (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
1800 (ret = sshbuf_get_string(b, &sig_key, &sklen)) != 0) { 1792 (ret = sshbuf_get_string(b, &sig_key, &sklen)) != 0) {
@@ -1817,14 +1809,17 @@ cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob,
1817 goto out; 1809 goto out;
1818 } 1810 }
1819 1811
1820 if ((ret = sshbuf_put(tmp, principals, plen)) != 0) 1812 /* Parse principals section */
1821 goto out; 1813 while (sshbuf_len(principals) > 0) {
1822 while (sshbuf_len(tmp) > 0) { 1814 char *principal = NULL;
1815 char **oprincipals = NULL;
1816
1823 if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) { 1817 if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) {
1824 ret = SSH_ERR_INVALID_FORMAT; 1818 ret = SSH_ERR_INVALID_FORMAT;
1825 goto out; 1819 goto out;
1826 } 1820 }
1827 if ((ret = sshbuf_get_cstring(tmp, &principal, &plen)) != 0) { 1821 if ((ret = sshbuf_get_cstring(principals, &principal,
1822 NULL)) != 0) {
1828 ret = SSH_ERR_INVALID_FORMAT; 1823 ret = SSH_ERR_INVALID_FORMAT;
1829 goto out; 1824 goto out;
1830 } 1825 }
@@ -1841,36 +1836,37 @@ cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob,
1841 key->cert->principals[key->cert->nprincipals++] = principal; 1836 key->cert->principals[key->cert->nprincipals++] = principal;
1842 } 1837 }
1843 1838
1844 sshbuf_reset(tmp); 1839 /*
1845 1840 * Stash a copies of the critical options and extensions sections
1846 if ((ret = sshbuf_put(key->cert->critical, critical, clen)) != 0 || 1841 * for later use.
1847 (ret = sshbuf_put(tmp, critical, clen)) != 0) 1842 */
1843 if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 ||
1844 (exts != NULL &&
1845 (ret = sshbuf_putb(key->cert->extensions, exts)) != 0))
1848 goto out; 1846 goto out;
1849 1847
1850 /* validate structure */ 1848 /*
1851 while (sshbuf_len(tmp) != 0) { 1849 * Validate critical options and extensions sections format.
1852 if ((ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0 || 1850 * NB. extensions are not present in v00 certs.
1853 (ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0) { 1851 */
1852 while (sshbuf_len(crit) != 0) {
1853 if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 ||
1854 (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) {
1855 sshbuf_reset(key->cert->critical);
1854 ret = SSH_ERR_INVALID_FORMAT; 1856 ret = SSH_ERR_INVALID_FORMAT;
1855 goto out; 1857 goto out;
1856 } 1858 }
1857 } 1859 }
1858 sshbuf_reset(tmp); 1860 while (exts != NULL && sshbuf_len(exts) != 0) {
1859 1861 if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 ||
1860 if ((ret = sshbuf_put(key->cert->extensions, exts, elen)) != 0 || 1862 (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) {
1861 (ret = sshbuf_put(tmp, exts, elen)) != 0) 1863 sshbuf_reset(key->cert->extensions);
1862 goto out;
1863
1864 /* validate structure */
1865 while (sshbuf_len(tmp) != 0) {
1866 if ((ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0 ||
1867 (ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0) {
1868 ret = SSH_ERR_INVALID_FORMAT; 1864 ret = SSH_ERR_INVALID_FORMAT;
1869 goto out; 1865 goto out;
1870 } 1866 }
1871 } 1867 }
1872 sshbuf_reset(tmp);
1873 1868
1869 /* Parse CA key and check signature */
1874 if (sshkey_from_blob_internal(sig_key, sklen, 1870 if (sshkey_from_blob_internal(sig_key, sklen,
1875 &key->cert->signature_key, 0) != 0) { 1871 &key->cert->signature_key, 0) != 0) {
1876 ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; 1872 ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
@@ -1880,17 +1876,16 @@ cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob,
1880 ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; 1876 ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1881 goto out; 1877 goto out;
1882 } 1878 }
1883
1884 if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, 1879 if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1885 sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0) 1880 sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0)
1886 goto out; 1881 goto out;
1887 ret = 0;
1888 1882
1883 /* Success */
1884 ret = 0;
1889 out: 1885 out:
1890 sshbuf_free(tmp); 1886 sshbuf_free(crit);
1891 free(principals); 1887 sshbuf_free(exts);
1892 free(critical); 1888 sshbuf_free(principals);
1893 free(exts);
1894 free(sig_key); 1889 free(sig_key);
1895 free(sig); 1890 free(sig);
1896 return ret; 1891 return ret;
@@ -2952,8 +2947,9 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
2952 const char *passphrase, const char *comment, const char *ciphername, 2947 const char *passphrase, const char *comment, const char *ciphername,
2953 int rounds) 2948 int rounds)
2954{ 2949{
2955 u_char *cp, *b64 = NULL, *key = NULL, *pubkeyblob = NULL; 2950 u_char *cp, *key = NULL, *pubkeyblob = NULL;
2956 u_char salt[SALT_LEN]; 2951 u_char salt[SALT_LEN];
2952 char *b64 = NULL;
2957 size_t i, pubkeylen, keylen, ivlen, blocksize, authlen; 2953 size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
2958 u_int check; 2954 u_int check;
2959 int r = SSH_ERR_INTERNAL_ERROR; 2955 int r = SSH_ERR_INTERNAL_ERROR;
@@ -3165,7 +3161,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3165 } 3161 }
3166 3162
3167 /* decode base64 */ 3163 /* decode base64 */
3168 if ((r = sshbuf_b64tod(decoded, sshbuf_ptr(encoded))) != 0) 3164 if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0)
3169 goto out; 3165 goto out;
3170 3166
3171 /* check magic */ 3167 /* check magic */