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