diff options
-rw-r--r-- | sshkey.c | 98 |
1 files changed, 47 insertions, 51 deletions
@@ -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 | |||
1769 | cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob, | 1769 | cert_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 */ |