summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c444
1 files changed, 378 insertions, 66 deletions
diff --git a/sshkey.c b/sshkey.c
index 789cd61ef..4d2048b6a 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.73 2019/01/21 09:54:11 djm Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.84 2019/10/09 00:04:42 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.
@@ -43,6 +43,7 @@
43#include <stdio.h> 43#include <stdio.h>
44#include <string.h> 44#include <string.h>
45#include <resolv.h> 45#include <resolv.h>
46#include <time.h>
46#ifdef HAVE_UTIL_H 47#ifdef HAVE_UTIL_H
47#include <util.h> 48#include <util.h>
48#endif /* HAVE_UTIL_H */ 49#endif /* HAVE_UTIL_H */
@@ -55,10 +56,12 @@
55#include "digest.h" 56#include "digest.h"
56#define SSHKEY_INTERNAL 57#define SSHKEY_INTERNAL
57#include "sshkey.h" 58#include "sshkey.h"
58#include "sshkey-xmss.h"
59#include "match.h" 59#include "match.h"
60 60
61#ifdef WITH_XMSS
62#include "sshkey-xmss.h"
61#include "xmss_fast.h" 63#include "xmss_fast.h"
64#endif
62 65
63#include "openbsd-compat/openssl-compat.h" 66#include "openbsd-compat/openssl-compat.h"
64 67
@@ -76,11 +79,18 @@
76/* Version identification string for SSH v1 identity files. */ 79/* Version identification string for SSH v1 identity files. */
77#define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n" 80#define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
78 81
79int sshkey_private_serialize_opt(const struct sshkey *key, 82/*
83 * Constants relating to "shielding" support; protection of keys expected
84 * to remain in memory for long durations
85 */
86#define SSHKEY_SHIELD_PREKEY_LEN (16 * 1024)
87#define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */
88#define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512
89
90int sshkey_private_serialize_opt(struct sshkey *key,
80 struct sshbuf *buf, enum sshkey_serialize_rep); 91 struct sshbuf *buf, enum sshkey_serialize_rep);
81static int sshkey_from_blob_internal(struct sshbuf *buf, 92static int sshkey_from_blob_internal(struct sshbuf *buf,
82 struct sshkey **keyp, int allow_cert); 93 struct sshkey **keyp, int allow_cert);
83static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep);
84 94
85/* Supported key types */ 95/* Supported key types */
86struct keytype { 96struct keytype {
@@ -603,6 +613,8 @@ sshkey_free(struct sshkey *k)
603 } 613 }
604 if (sshkey_is_cert(k)) 614 if (sshkey_is_cert(k))
605 cert_free(k->cert); 615 cert_free(k->cert);
616 freezero(k->shielded_private, k->shielded_len);
617 freezero(k->shield_prekey, k->shield_prekey_len);
606 freezero(k, sizeof(*k)); 618 freezero(k, sizeof(*k));
607} 619}
608 620
@@ -939,7 +951,6 @@ fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
939 char *ret; 951 char *ret;
940 size_t plen = strlen(alg) + 1; 952 size_t plen = strlen(alg) + 1;
941 size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1; 953 size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
942 int r;
943 954
944 if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL) 955 if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
945 return NULL; 956 return NULL;
@@ -947,8 +958,7 @@ fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
947 strlcat(ret, ":", rlen); 958 strlcat(ret, ":", rlen);
948 if (dgst_raw_len == 0) 959 if (dgst_raw_len == 0)
949 return ret; 960 return ret;
950 if ((r = b64_ntop(dgst_raw, dgst_raw_len, 961 if (b64_ntop(dgst_raw, dgst_raw_len, ret + plen, rlen - plen) == -1) {
951 ret + plen, rlen - plen)) == -1) {
952 freezero(ret, rlen); 962 freezero(ret, rlen);
953 return NULL; 963 return NULL;
954 } 964 }
@@ -1393,7 +1403,7 @@ sshkey_to_base64(const struct sshkey *key, char **b64p)
1393 return SSH_ERR_ALLOC_FAIL; 1403 return SSH_ERR_ALLOC_FAIL;
1394 if ((r = sshkey_putb(key, b)) != 0) 1404 if ((r = sshkey_putb(key, b)) != 0)
1395 goto out; 1405 goto out;
1396 if ((uu = sshbuf_dtob64(b)) == NULL) { 1406 if ((uu = sshbuf_dtob64_string(b, 0)) == NULL) {
1397 r = SSH_ERR_ALLOC_FAIL; 1407 r = SSH_ERR_ALLOC_FAIL;
1398 goto out; 1408 goto out;
1399 } 1409 }
@@ -1868,6 +1878,218 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1868 return r; 1878 return r;
1869} 1879}
1870 1880
1881int
1882sshkey_is_shielded(struct sshkey *k)
1883{
1884 return k != NULL && k->shielded_private != NULL;
1885}
1886
1887int
1888sshkey_shield_private(struct sshkey *k)
1889{
1890 struct sshbuf *prvbuf = NULL;
1891 u_char *prekey = NULL, *enc = NULL, keyiv[SSH_DIGEST_MAX_LENGTH];
1892 struct sshcipher_ctx *cctx = NULL;
1893 const struct sshcipher *cipher;
1894 size_t i, enclen = 0;
1895 struct sshkey *kswap = NULL, tmp;
1896 int r = SSH_ERR_INTERNAL_ERROR;
1897
1898#ifdef DEBUG_PK
1899 fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
1900#endif
1901 if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
1902 r = SSH_ERR_INVALID_ARGUMENT;
1903 goto out;
1904 }
1905 if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
1906 ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
1907 r = SSH_ERR_INTERNAL_ERROR;
1908 goto out;
1909 }
1910
1911 /* Prepare a random pre-key, and from it an ephemeral key */
1912 if ((prekey = malloc(SSHKEY_SHIELD_PREKEY_LEN)) == NULL) {
1913 r = SSH_ERR_ALLOC_FAIL;
1914 goto out;
1915 }
1916 arc4random_buf(prekey, SSHKEY_SHIELD_PREKEY_LEN);
1917 if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
1918 prekey, SSHKEY_SHIELD_PREKEY_LEN,
1919 keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
1920 goto out;
1921#ifdef DEBUG_PK
1922 fprintf(stderr, "%s: key+iv\n", __func__);
1923 sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
1924 stderr);
1925#endif
1926 if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
1927 keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 1)) != 0)
1928 goto out;
1929
1930 /* Serialise and encrypt the private key using the ephemeral key */
1931 if ((prvbuf = sshbuf_new()) == NULL) {
1932 r = SSH_ERR_ALLOC_FAIL;
1933 goto out;
1934 }
1935 if (sshkey_is_shielded(k) && (r = sshkey_unshield_private(k)) != 0)
1936 goto out;
1937 if ((r = sshkey_private_serialize_opt(k, prvbuf,
1938 SSHKEY_SERIALIZE_FULL)) != 0)
1939 goto out;
1940 /* pad to cipher blocksize */
1941 i = 0;
1942 while (sshbuf_len(prvbuf) % cipher_blocksize(cipher)) {
1943 if ((r = sshbuf_put_u8(prvbuf, ++i & 0xff)) != 0)
1944 goto out;
1945 }
1946#ifdef DEBUG_PK
1947 fprintf(stderr, "%s: serialised\n", __func__);
1948 sshbuf_dump(prvbuf, stderr);
1949#endif
1950 /* encrypt */
1951 enclen = sshbuf_len(prvbuf);
1952 if ((enc = malloc(enclen)) == NULL) {
1953 r = SSH_ERR_ALLOC_FAIL;
1954 goto out;
1955 }
1956 if ((r = cipher_crypt(cctx, 0, enc,
1957 sshbuf_ptr(prvbuf), sshbuf_len(prvbuf), 0, 0)) != 0)
1958 goto out;
1959#ifdef DEBUG_PK
1960 fprintf(stderr, "%s: encrypted\n", __func__);
1961 sshbuf_dump_data(enc, enclen, stderr);
1962#endif
1963
1964 /* Make a scrubbed, public-only copy of our private key argument */
1965 if ((r = sshkey_from_private(k, &kswap)) != 0)
1966 goto out;
1967
1968 /* Swap the private key out (it will be destroyed below) */
1969 tmp = *kswap;
1970 *kswap = *k;
1971 *k = tmp;
1972
1973 /* Insert the shielded key into our argument */
1974 k->shielded_private = enc;
1975 k->shielded_len = enclen;
1976 k->shield_prekey = prekey;
1977 k->shield_prekey_len = SSHKEY_SHIELD_PREKEY_LEN;
1978 enc = prekey = NULL; /* transferred */
1979 enclen = 0;
1980
1981 /* success */
1982 r = 0;
1983
1984 out:
1985 /* XXX behaviour on error - invalidate original private key? */
1986 cipher_free(cctx);
1987 explicit_bzero(keyiv, sizeof(keyiv));
1988 explicit_bzero(&tmp, sizeof(tmp));
1989 freezero(enc, enclen);
1990 freezero(prekey, SSHKEY_SHIELD_PREKEY_LEN);
1991 sshkey_free(kswap);
1992 sshbuf_free(prvbuf);
1993 return r;
1994}
1995
1996int
1997sshkey_unshield_private(struct sshkey *k)
1998{
1999 struct sshbuf *prvbuf = NULL;
2000 u_char pad, *cp, keyiv[SSH_DIGEST_MAX_LENGTH];
2001 struct sshcipher_ctx *cctx = NULL;
2002 const struct sshcipher *cipher;
2003 size_t i;
2004 struct sshkey *kswap = NULL, tmp;
2005 int r = SSH_ERR_INTERNAL_ERROR;
2006
2007#ifdef DEBUG_PK
2008 fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
2009#endif
2010 if (!sshkey_is_shielded(k))
2011 return 0; /* nothing to do */
2012
2013 if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
2014 r = SSH_ERR_INVALID_ARGUMENT;
2015 goto out;
2016 }
2017 if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
2018 ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
2019 r = SSH_ERR_INTERNAL_ERROR;
2020 goto out;
2021 }
2022 /* check size of shielded key blob */
2023 if (k->shielded_len < cipher_blocksize(cipher) ||
2024 (k->shielded_len % cipher_blocksize(cipher)) != 0) {
2025 r = SSH_ERR_INVALID_FORMAT;
2026 goto out;
2027 }
2028
2029 /* Calculate the ephemeral key from the prekey */
2030 if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
2031 k->shield_prekey, k->shield_prekey_len,
2032 keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
2033 goto out;
2034 if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
2035 keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 0)) != 0)
2036 goto out;
2037#ifdef DEBUG_PK
2038 fprintf(stderr, "%s: key+iv\n", __func__);
2039 sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
2040 stderr);
2041#endif
2042
2043 /* Decrypt and parse the shielded private key using the ephemeral key */
2044 if ((prvbuf = sshbuf_new()) == NULL) {
2045 r = SSH_ERR_ALLOC_FAIL;
2046 goto out;
2047 }
2048 if ((r = sshbuf_reserve(prvbuf, k->shielded_len, &cp)) != 0)
2049 goto out;
2050 /* decrypt */
2051#ifdef DEBUG_PK
2052 fprintf(stderr, "%s: encrypted\n", __func__);
2053 sshbuf_dump_data(k->shielded_private, k->shielded_len, stderr);
2054#endif
2055 if ((r = cipher_crypt(cctx, 0, cp,
2056 k->shielded_private, k->shielded_len, 0, 0)) != 0)
2057 goto out;
2058#ifdef DEBUG_PK
2059 fprintf(stderr, "%s: serialised\n", __func__);
2060 sshbuf_dump(prvbuf, stderr);
2061#endif
2062 /* Parse private key */
2063 if ((r = sshkey_private_deserialize(prvbuf, &kswap)) != 0)
2064 goto out;
2065 /* Check deterministic padding */
2066 i = 0;
2067 while (sshbuf_len(prvbuf)) {
2068 if ((r = sshbuf_get_u8(prvbuf, &pad)) != 0)
2069 goto out;
2070 if (pad != (++i & 0xff)) {
2071 r = SSH_ERR_INVALID_FORMAT;
2072 goto out;
2073 }
2074 }
2075
2076 /* Swap the parsed key back into place */
2077 tmp = *kswap;
2078 *kswap = *k;
2079 *k = tmp;
2080
2081 /* success */
2082 r = 0;
2083
2084 out:
2085 cipher_free(cctx);
2086 explicit_bzero(keyiv, sizeof(keyiv));
2087 explicit_bzero(&tmp, sizeof(tmp));
2088 sshkey_free(kswap);
2089 sshbuf_free(prvbuf);
2090 return r;
2091}
2092
1871static int 2093static int
1872cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) 2094cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1873{ 2095{
@@ -1979,7 +2201,8 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1979 if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, 2201 if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1980 sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0) 2202 sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
1981 goto out; 2203 goto out;
1982 if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0) 2204 if ((ret = sshkey_get_sigtype(sig, slen,
2205 &key->cert->signature_type)) != 0)
1983 goto out; 2206 goto out;
1984 2207
1985 /* Success */ 2208 /* Success */
@@ -2281,8 +2504,8 @@ sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
2281 return r; 2504 return r;
2282} 2505}
2283 2506
2284static int 2507int
2285get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) 2508sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
2286{ 2509{
2287 int r; 2510 int r;
2288 struct sshbuf *b = NULL; 2511 struct sshbuf *b = NULL;
@@ -2364,7 +2587,7 @@ sshkey_check_sigtype(const u_char *sig, size_t siglen,
2364 return 0; 2587 return 0;
2365 if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL) 2588 if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
2366 return SSH_ERR_INVALID_ARGUMENT; 2589 return SSH_ERR_INVALID_ARGUMENT;
2367 if ((r = get_sigtype(sig, siglen, &sigtype)) != 0) 2590 if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0)
2368 return r; 2591 return r;
2369 r = strcmp(expected_alg, sigtype) == 0; 2592 r = strcmp(expected_alg, sigtype) == 0;
2370 free(sigtype); 2593 free(sigtype);
@@ -2372,41 +2595,55 @@ sshkey_check_sigtype(const u_char *sig, size_t siglen,
2372} 2595}
2373 2596
2374int 2597int
2375sshkey_sign(const struct sshkey *key, 2598sshkey_sign(struct sshkey *key,
2376 u_char **sigp, size_t *lenp, 2599 u_char **sigp, size_t *lenp,
2377 const u_char *data, size_t datalen, const char *alg, u_int compat) 2600 const u_char *data, size_t datalen, const char *alg, u_int compat)
2378{ 2601{
2602 int was_shielded = sshkey_is_shielded(key);
2603 int r2, r = SSH_ERR_INTERNAL_ERROR;
2604
2379 if (sigp != NULL) 2605 if (sigp != NULL)
2380 *sigp = NULL; 2606 *sigp = NULL;
2381 if (lenp != NULL) 2607 if (lenp != NULL)
2382 *lenp = 0; 2608 *lenp = 0;
2383 if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) 2609 if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2384 return SSH_ERR_INVALID_ARGUMENT; 2610 return SSH_ERR_INVALID_ARGUMENT;
2611 if ((r = sshkey_unshield_private(key)) != 0)
2612 return r;
2385 switch (key->type) { 2613 switch (key->type) {
2386#ifdef WITH_OPENSSL 2614#ifdef WITH_OPENSSL
2387 case KEY_DSA_CERT: 2615 case KEY_DSA_CERT:
2388 case KEY_DSA: 2616 case KEY_DSA:
2389 return ssh_dss_sign(key, sigp, lenp, data, datalen, compat); 2617 r = ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
2618 break;
2390# ifdef OPENSSL_HAS_ECC 2619# ifdef OPENSSL_HAS_ECC
2391 case KEY_ECDSA_CERT: 2620 case KEY_ECDSA_CERT:
2392 case KEY_ECDSA: 2621 case KEY_ECDSA:
2393 return ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat); 2622 r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
2623 break;
2394# endif /* OPENSSL_HAS_ECC */ 2624# endif /* OPENSSL_HAS_ECC */
2395 case KEY_RSA_CERT: 2625 case KEY_RSA_CERT:
2396 case KEY_RSA: 2626 case KEY_RSA:
2397 return ssh_rsa_sign(key, sigp, lenp, data, datalen, alg); 2627 r = ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
2628 break;
2398#endif /* WITH_OPENSSL */ 2629#endif /* WITH_OPENSSL */
2399 case KEY_ED25519: 2630 case KEY_ED25519:
2400 case KEY_ED25519_CERT: 2631 case KEY_ED25519_CERT:
2401 return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat); 2632 r = ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
2633 break;
2402#ifdef WITH_XMSS 2634#ifdef WITH_XMSS
2403 case KEY_XMSS: 2635 case KEY_XMSS:
2404 case KEY_XMSS_CERT: 2636 case KEY_XMSS_CERT:
2405 return ssh_xmss_sign(key, sigp, lenp, data, datalen, compat); 2637 r = ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
2638 break;
2406#endif /* WITH_XMSS */ 2639#endif /* WITH_XMSS */
2407 default: 2640 default:
2408 return SSH_ERR_KEY_TYPE_UNKNOWN; 2641 r = SSH_ERR_KEY_TYPE_UNKNOWN;
2642 break;
2409 } 2643 }
2644 if (was_shielded && (r2 = sshkey_shield_private(key)) != 0)
2645 return r2;
2646 return r;
2410} 2647}
2411 2648
2412/* 2649/*
@@ -2527,6 +2764,13 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2527 strcmp(alg, k->cert->signature_type) != 0) 2764 strcmp(alg, k->cert->signature_type) != 0)
2528 return SSH_ERR_INVALID_ARGUMENT; 2765 return SSH_ERR_INVALID_ARGUMENT;
2529 2766
2767 /*
2768 * If no signing algorithm or signature_type was specified and we're
2769 * using a RSA key, then default to a good signature algorithm.
2770 */
2771 if (alg == NULL && ca->type == KEY_RSA)
2772 alg = "rsa-sha2-512";
2773
2530 if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) 2774 if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
2531 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; 2775 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2532 2776
@@ -2619,7 +2863,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2619 sshbuf_len(cert), alg, 0, signer_ctx)) != 0) 2863 sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
2620 goto out; 2864 goto out;
2621 /* Check and update signature_type against what was actually used */ 2865 /* Check and update signature_type against what was actually used */
2622 if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0) 2866 if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
2623 goto out; 2867 goto out;
2624 if (alg != NULL && strcmp(alg, sigtype) != 0) { 2868 if (alg != NULL && strcmp(alg, sigtype) != 0) {
2625 ret = SSH_ERR_SIGN_ALG_UNSUPPORTED; 2869 ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
@@ -2644,7 +2888,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2644} 2888}
2645 2889
2646static int 2890static int
2647default_key_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 2891default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
2648 const u_char *data, size_t datalen, 2892 const u_char *data, size_t datalen,
2649 const char *alg, u_int compat, void *ctx) 2893 const char *alg, u_int compat, void *ctx)
2650{ 2894{
@@ -2754,15 +2998,21 @@ sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
2754} 2998}
2755 2999
2756int 3000int
2757sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b, 3001sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
2758 enum sshkey_serialize_rep opts) 3002 enum sshkey_serialize_rep opts)
2759{ 3003{
2760 int r = SSH_ERR_INTERNAL_ERROR; 3004 int r = SSH_ERR_INTERNAL_ERROR;
3005 int was_shielded = sshkey_is_shielded(key);
3006 struct sshbuf *b = NULL;
2761#ifdef WITH_OPENSSL 3007#ifdef WITH_OPENSSL
2762 const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q; 3008 const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
2763 const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key; 3009 const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key;
2764#endif /* WITH_OPENSSL */ 3010#endif /* WITH_OPENSSL */
2765 3011
3012 if ((r = sshkey_unshield_private(key)) != 0)
3013 return r;
3014 if ((b = sshbuf_new()) == NULL)
3015 return SSH_ERR_ALLOC_FAIL;
2766 if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) 3016 if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
2767 goto out; 3017 goto out;
2768 switch (key->type) { 3018 switch (key->type) {
@@ -2888,14 +3138,23 @@ sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b,
2888 r = SSH_ERR_INVALID_ARGUMENT; 3138 r = SSH_ERR_INVALID_ARGUMENT;
2889 goto out; 3139 goto out;
2890 } 3140 }
2891 /* success */ 3141 /*
3142 * success (but we still need to append the output to buf after
3143 * possibly re-shielding the private key)
3144 */
2892 r = 0; 3145 r = 0;
2893 out: 3146 out:
3147 if (was_shielded)
3148 r = sshkey_shield_private(key);
3149 if (r == 0)
3150 r = sshbuf_putb(buf, b);
3151 sshbuf_free(b);
3152
2894 return r; 3153 return r;
2895} 3154}
2896 3155
2897int 3156int
2898sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b) 3157sshkey_private_serialize(struct sshkey *key, struct sshbuf *b)
2899{ 3158{
2900 return sshkey_private_serialize_opt(key, b, 3159 return sshkey_private_serialize_opt(key, b,
2901 SSHKEY_SERIALIZE_DEFAULT); 3160 SSHKEY_SERIALIZE_DEFAULT);
@@ -2951,6 +3210,10 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
2951 if ((r = sshkey_froms(buf, &k)) != 0 || 3210 if ((r = sshkey_froms(buf, &k)) != 0 ||
2952 (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0) 3211 (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
2953 goto out; 3212 goto out;
3213 if (k->type != type) {
3214 r = SSH_ERR_INVALID_FORMAT;
3215 goto out;
3216 }
2954 if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) { 3217 if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) {
2955 r = SSH_ERR_LIBCRYPTO_ERROR; 3218 r = SSH_ERR_LIBCRYPTO_ERROR;
2956 goto out; 3219 goto out;
@@ -2994,6 +3257,11 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
2994 if ((r = sshkey_froms(buf, &k)) != 0 || 3257 if ((r = sshkey_froms(buf, &k)) != 0 ||
2995 (r = sshbuf_get_bignum2(buf, &exponent)) != 0) 3258 (r = sshbuf_get_bignum2(buf, &exponent)) != 0)
2996 goto out; 3259 goto out;
3260 if (k->type != type ||
3261 k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) {
3262 r = SSH_ERR_INVALID_FORMAT;
3263 goto out;
3264 }
2997 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { 3265 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
2998 r = SSH_ERR_LIBCRYPTO_ERROR; 3266 r = SSH_ERR_LIBCRYPTO_ERROR;
2999 goto out; 3267 goto out;
@@ -3038,6 +3306,10 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3038 (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 || 3306 (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
3039 (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0) 3307 (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
3040 goto out; 3308 goto out;
3309 if (k->type != type) {
3310 r = SSH_ERR_INVALID_FORMAT;
3311 goto out;
3312 }
3041 if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) { 3313 if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) {
3042 r = SSH_ERR_LIBCRYPTO_ERROR; 3314 r = SSH_ERR_LIBCRYPTO_ERROR;
3043 goto out; 3315 goto out;
@@ -3075,13 +3347,17 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3075 (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || 3347 (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3076 (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) 3348 (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3077 goto out; 3349 goto out;
3350 if (k->type != type) {
3351 r = SSH_ERR_INVALID_FORMAT;
3352 goto out;
3353 }
3078 if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) { 3354 if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3079 r = SSH_ERR_INVALID_FORMAT; 3355 r = SSH_ERR_INVALID_FORMAT;
3080 goto out; 3356 goto out;
3081 } 3357 }
3082 k->ed25519_pk = ed25519_pk; 3358 k->ed25519_pk = ed25519_pk;
3083 k->ed25519_sk = ed25519_sk; 3359 k->ed25519_sk = ed25519_sk;
3084 ed25519_pk = ed25519_sk = NULL; 3360 ed25519_pk = ed25519_sk = NULL; /* transferred */
3085 break; 3361 break;
3086#ifdef WITH_XMSS 3362#ifdef WITH_XMSS
3087 case KEY_XMSS: 3363 case KEY_XMSS:
@@ -3112,7 +3388,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3112 (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 || 3388 (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3113 (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0) 3389 (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
3114 goto out; 3390 goto out;
3115 if (strcmp(xmss_name, k->xmss_name)) { 3391 if (k->type != type || strcmp(xmss_name, k->xmss_name) != 0) {
3116 r = SSH_ERR_INVALID_FORMAT; 3392 r = SSH_ERR_INVALID_FORMAT;
3117 goto out; 3393 goto out;
3118 } 3394 }
@@ -3350,7 +3626,7 @@ sshkey_dump_ec_key(const EC_KEY *key)
3350#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ 3626#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
3351 3627
3352static int 3628static int
3353sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob, 3629sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob,
3354 const char *passphrase, const char *comment, const char *ciphername, 3630 const char *passphrase, const char *comment, const char *ciphername,
3355 int rounds) 3631 int rounds)
3356{ 3632{
@@ -3452,25 +3728,12 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
3452 sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0) 3728 sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
3453 goto out; 3729 goto out;
3454 3730
3455 /* uuencode */
3456 if ((b64 = sshbuf_dtob64(encoded)) == NULL) {
3457 r = SSH_ERR_ALLOC_FAIL;
3458 goto out;
3459 }
3460
3461 sshbuf_reset(blob); 3731 sshbuf_reset(blob);
3462 if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0) 3732
3463 goto out; 3733 /* assemble uuencoded key */
3464 for (i = 0; i < strlen(b64); i++) { 3734 if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0 ||
3465 if ((r = sshbuf_put_u8(blob, b64[i])) != 0) 3735 (r = sshbuf_dtob64(encoded, blob, 1)) != 0 ||
3466 goto out; 3736 (r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
3467 /* insert line breaks */
3468 if (i % 70 == 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
3469 goto out;
3470 }
3471 if (i % 70 != 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
3472 goto out;
3473 if ((r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
3474 goto out; 3737 goto out;
3475 3738
3476 /* success */ 3739 /* success */
@@ -3632,7 +3895,8 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3632 } 3895 }
3633 3896
3634 /* check that an appropriate amount of auth data is present */ 3897 /* check that an appropriate amount of auth data is present */
3635 if (sshbuf_len(decoded) < encrypted_len + authlen) { 3898 if (sshbuf_len(decoded) < authlen ||
3899 sshbuf_len(decoded) - authlen < encrypted_len) {
3636 r = SSH_ERR_INVALID_FORMAT; 3900 r = SSH_ERR_INVALID_FORMAT;
3637 goto out; 3901 goto out;
3638 } 3902 }
@@ -3718,37 +3982,62 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3718 3982
3719 3983
3720#ifdef WITH_OPENSSL 3984#ifdef WITH_OPENSSL
3721/* convert SSH v2 key in OpenSSL PEM format */ 3985/* convert SSH v2 key to PEM or PKCS#8 format */
3722static int 3986static int
3723sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob, 3987sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
3724 const char *_passphrase, const char *comment) 3988 int format, const char *_passphrase, const char *comment)
3725{ 3989{
3990 int was_shielded = sshkey_is_shielded(key);
3726 int success, r; 3991 int success, r;
3727 int blen, len = strlen(_passphrase); 3992 int blen, len = strlen(_passphrase);
3728 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; 3993 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
3729 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; 3994 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
3730 char *bptr; 3995 char *bptr;
3731 BIO *bio = NULL; 3996 BIO *bio = NULL;
3997 struct sshbuf *blob;
3998 EVP_PKEY *pkey = NULL;
3732 3999
3733 if (len > 0 && len <= 4) 4000 if (len > 0 && len <= 4)
3734 return SSH_ERR_PASSPHRASE_TOO_SHORT; 4001 return SSH_ERR_PASSPHRASE_TOO_SHORT;
3735 if ((bio = BIO_new(BIO_s_mem())) == NULL) 4002 if ((blob = sshbuf_new()) == NULL)
3736 return SSH_ERR_ALLOC_FAIL; 4003 return SSH_ERR_ALLOC_FAIL;
4004 if ((bio = BIO_new(BIO_s_mem())) == NULL) {
4005 r = SSH_ERR_ALLOC_FAIL;
4006 goto out;
4007 }
4008 if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
4009 r = SSH_ERR_ALLOC_FAIL;
4010 goto out;
4011 }
4012 if ((r = sshkey_unshield_private(key)) != 0)
4013 goto out;
3737 4014
3738 switch (key->type) { 4015 switch (key->type) {
3739 case KEY_DSA: 4016 case KEY_DSA:
3740 success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, 4017 if (format == SSHKEY_PRIVATE_PEM) {
3741 cipher, passphrase, len, NULL, NULL); 4018 success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
4019 cipher, passphrase, len, NULL, NULL);
4020 } else {
4021 success = EVP_PKEY_set1_DSA(pkey, key->dsa);
4022 }
3742 break; 4023 break;
3743#ifdef OPENSSL_HAS_ECC 4024#ifdef OPENSSL_HAS_ECC
3744 case KEY_ECDSA: 4025 case KEY_ECDSA:
3745 success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, 4026 if (format == SSHKEY_PRIVATE_PEM) {
3746 cipher, passphrase, len, NULL, NULL); 4027 success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
4028 cipher, passphrase, len, NULL, NULL);
4029 } else {
4030 success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
4031 }
3747 break; 4032 break;
3748#endif 4033#endif
3749 case KEY_RSA: 4034 case KEY_RSA:
3750 success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, 4035 if (format == SSHKEY_PRIVATE_PEM) {
3751 cipher, passphrase, len, NULL, NULL); 4036 success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
4037 cipher, passphrase, len, NULL, NULL);
4038 } else {
4039 success = EVP_PKEY_set1_RSA(pkey, key->rsa);
4040 }
3752 break; 4041 break;
3753 default: 4042 default:
3754 success = 0; 4043 success = 0;
@@ -3758,6 +4047,13 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
3758 r = SSH_ERR_LIBCRYPTO_ERROR; 4047 r = SSH_ERR_LIBCRYPTO_ERROR;
3759 goto out; 4048 goto out;
3760 } 4049 }
4050 if (format == SSHKEY_PRIVATE_PKCS8) {
4051 if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher,
4052 passphrase, len, NULL, NULL)) == 0) {
4053 r = SSH_ERR_LIBCRYPTO_ERROR;
4054 goto out;
4055 }
4056 }
3761 if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) { 4057 if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
3762 r = SSH_ERR_INTERNAL_ERROR; 4058 r = SSH_ERR_INTERNAL_ERROR;
3763 goto out; 4059 goto out;
@@ -3766,6 +4062,13 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
3766 goto out; 4062 goto out;
3767 r = 0; 4063 r = 0;
3768 out: 4064 out:
4065 if (was_shielded)
4066 r = sshkey_shield_private(key);
4067 if (r == 0)
4068 r = sshbuf_putb(buf, blob);
4069
4070 EVP_PKEY_free(pkey);
4071 sshbuf_free(blob);
3769 BIO_free(bio); 4072 BIO_free(bio);
3770 return r; 4073 return r;
3771} 4074}
@@ -3775,29 +4078,38 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
3775int 4078int
3776sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, 4079sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
3777 const char *passphrase, const char *comment, 4080 const char *passphrase, const char *comment,
3778 int force_new_format, const char *new_format_cipher, int new_format_rounds) 4081 int format, const char *openssh_format_cipher, int openssh_format_rounds)
3779{ 4082{
3780 switch (key->type) { 4083 switch (key->type) {
3781#ifdef WITH_OPENSSL 4084#ifdef WITH_OPENSSL
3782 case KEY_DSA: 4085 case KEY_DSA:
3783 case KEY_ECDSA: 4086 case KEY_ECDSA:
3784 case KEY_RSA: 4087 case KEY_RSA:
3785 if (force_new_format) { 4088 break; /* see below */
3786 return sshkey_private_to_blob2(key, blob, passphrase,
3787 comment, new_format_cipher, new_format_rounds);
3788 }
3789 return sshkey_private_pem_to_blob(key, blob,
3790 passphrase, comment);
3791#endif /* WITH_OPENSSL */ 4089#endif /* WITH_OPENSSL */
3792 case KEY_ED25519: 4090 case KEY_ED25519:
3793#ifdef WITH_XMSS 4091#ifdef WITH_XMSS
3794 case KEY_XMSS: 4092 case KEY_XMSS:
3795#endif /* WITH_XMSS */ 4093#endif /* WITH_XMSS */
3796 return sshkey_private_to_blob2(key, blob, passphrase, 4094 return sshkey_private_to_blob2(key, blob, passphrase,
3797 comment, new_format_cipher, new_format_rounds); 4095 comment, openssh_format_cipher, openssh_format_rounds);
3798 default: 4096 default:
3799 return SSH_ERR_KEY_TYPE_UNKNOWN; 4097 return SSH_ERR_KEY_TYPE_UNKNOWN;
3800 } 4098 }
4099
4100#ifdef WITH_OPENSSL
4101 switch (format) {
4102 case SSHKEY_PRIVATE_OPENSSH:
4103 return sshkey_private_to_blob2(key, blob, passphrase,
4104 comment, openssh_format_cipher, openssh_format_rounds);
4105 case SSHKEY_PRIVATE_PEM:
4106 case SSHKEY_PRIVATE_PKCS8:
4107 return sshkey_private_to_blob_pem_pkcs8(key, blob,
4108 format, passphrase, comment);
4109 default:
4110 return SSH_ERR_INVALID_ARGUMENT;
4111 }
4112#endif /* WITH_OPENSSL */
3801} 4113}
3802 4114
3803 4115
@@ -4040,7 +4352,7 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
4040 * maxsign times. 4352 * maxsign times.
4041 */ 4353 */
4042int 4354int
4043sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b, 4355sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
4044 u_int32_t maxsign, sshkey_printfn *pr) 4356 u_int32_t maxsign, sshkey_printfn *pr)
4045{ 4357{
4046 int r, rupdate; 4358 int r, rupdate;
@@ -4094,7 +4406,7 @@ sshkey_set_filename(struct sshkey *k, const char *filename)
4094} 4406}
4095#else 4407#else
4096int 4408int
4097sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b, 4409sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
4098 u_int32_t maxsign, sshkey_printfn *pr) 4410 u_int32_t maxsign, sshkey_printfn *pr)
4099{ 4411{
4100 return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT); 4412 return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);