diff options
Diffstat (limited to 'sshkey.c')
-rw-r--r-- | sshkey.c | 444 |
1 files changed, 378 insertions, 66 deletions
@@ -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 | ||
79 | int 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 | |||
90 | int sshkey_private_serialize_opt(struct sshkey *key, | ||
80 | struct sshbuf *buf, enum sshkey_serialize_rep); | 91 | struct sshbuf *buf, enum sshkey_serialize_rep); |
81 | static int sshkey_from_blob_internal(struct sshbuf *buf, | 92 | static int sshkey_from_blob_internal(struct sshbuf *buf, |
82 | struct sshkey **keyp, int allow_cert); | 93 | struct sshkey **keyp, int allow_cert); |
83 | static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep); | ||
84 | 94 | ||
85 | /* Supported key types */ | 95 | /* Supported key types */ |
86 | struct keytype { | 96 | struct 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 | ||
1881 | int | ||
1882 | sshkey_is_shielded(struct sshkey *k) | ||
1883 | { | ||
1884 | return k != NULL && k->shielded_private != NULL; | ||
1885 | } | ||
1886 | |||
1887 | int | ||
1888 | sshkey_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 | |||
1996 | int | ||
1997 | sshkey_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 | |||
1871 | static int | 2093 | static int |
1872 | cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) | 2094 | cert_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 | ||
2284 | static int | 2507 | int |
2285 | get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) | 2508 | sshkey_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 | ||
2374 | int | 2597 | int |
2375 | sshkey_sign(const struct sshkey *key, | 2598 | sshkey_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 | ||
2646 | static int | 2890 | static int |
2647 | default_key_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | 2891 | default_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 | ||
2756 | int | 3000 | int |
2757 | sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b, | 3001 | sshkey_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 | ||
2897 | int | 3156 | int |
2898 | sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b) | 3157 | sshkey_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 | ||
3352 | static int | 3628 | static int |
3353 | sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob, | 3629 | sshkey_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 */ |
3722 | static int | 3986 | static int |
3723 | sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob, | 3987 | sshkey_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, | |||
3775 | int | 4078 | int |
3776 | sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, | 4079 | sshkey_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 | */ |
4042 | int | 4354 | int |
4043 | sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b, | 4355 | sshkey_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 |
4096 | int | 4408 | int |
4097 | sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b, | 4409 | sshkey_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); |