summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-06-21 04:21:04 +0000
committerDamien Miller <djm@mindrot.org>2019-06-21 14:24:35 +1000
commit4f7a56d5e02e3d04ab69eac1213817a7536d0562 (patch)
treeb17da67f20831b53f9b00c6647c5eb1bdf88d626 /sshkey.c
parent4cd6b12cc9c10bf59c8b425041f3ea5091285a0f (diff)
upstream: Add protection for private keys at rest in RAM against
speculation and memory sidechannel attacks like Spectre, Meltdown, Rowhammer and Rambleed. This change encrypts private keys when they are not in use with a symmetic key that is derived from a relatively large "prekey" consisting of random data (currently 16KB). Attackers must recover the entire prekey with high accuracy before they can attempt to decrypt the shielded private key, but the current generation of attacks have bit error rates that, when applied cumulatively to the entire prekey, make this unlikely. Implementation-wise, keys are encrypted "shielded" when loaded and then automatically and transparently unshielded when used for signatures or when being saved/serialised. Hopefully we can remove this in a few years time when computer architecture has become less unsafe. been in snaps for a bit already; thanks deraadt@ ok dtucker@ deraadt@ OpenBSD-Commit-ID: 19767213c312e46f94b303a512ef8e9218a39bd4
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c299
1 files changed, 282 insertions, 17 deletions
diff --git a/sshkey.c b/sshkey.c
index 379a579cf..7aa7e772c 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.75 2019/05/20 00:20:35 djm Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.76 2019/06/21 04:21:05 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.
@@ -78,7 +78,15 @@
78/* Version identification string for SSH v1 identity files. */ 78/* Version identification string for SSH v1 identity files. */
79#define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n" 79#define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
80 80
81int sshkey_private_serialize_opt(const struct sshkey *key, 81/*
82 * Constants relating to "shielding" support; protection of keys expected
83 * to remain in memory for long durations
84 */
85#define SSHKEY_SHIELD_PREKEY_LEN (16 * 1024)
86#define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */
87#define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512
88
89int sshkey_private_serialize_opt(struct sshkey *key,
82 struct sshbuf *buf, enum sshkey_serialize_rep); 90 struct sshbuf *buf, enum sshkey_serialize_rep);
83static int sshkey_from_blob_internal(struct sshbuf *buf, 91static int sshkey_from_blob_internal(struct sshbuf *buf,
84 struct sshkey **keyp, int allow_cert); 92 struct sshkey **keyp, int allow_cert);
@@ -604,6 +612,8 @@ sshkey_free(struct sshkey *k)
604 } 612 }
605 if (sshkey_is_cert(k)) 613 if (sshkey_is_cert(k))
606 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);
607 freezero(k, sizeof(*k)); 617 freezero(k, sizeof(*k));
608} 618}
609 619
@@ -1869,6 +1879,218 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1869 return r; 1879 return r;
1870} 1880}
1871 1881
1882int
1883sshkey_is_shielded(struct sshkey *k)
1884{
1885 return k != NULL && k->shielded_private != NULL;
1886}
1887
1888int
1889sshkey_shield_private(struct sshkey *k)
1890{
1891 struct sshbuf *prvbuf = NULL;
1892 u_char *prekey = NULL, *enc = NULL, keyiv[SSH_DIGEST_MAX_LENGTH];
1893 struct sshcipher_ctx *cctx = NULL;
1894 const struct sshcipher *cipher;
1895 size_t i, enclen = 0;
1896 struct sshkey *kswap = NULL, tmp;
1897 int r = SSH_ERR_INTERNAL_ERROR;
1898
1899#ifdef DEBUG_PK
1900 fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
1901#endif
1902 if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
1903 r = SSH_ERR_INVALID_ARGUMENT;
1904 goto out;
1905 }
1906 if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
1907 ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
1908 r = SSH_ERR_INTERNAL_ERROR;
1909 goto out;
1910 }
1911
1912 /* Prepare a random pre-key, and from it an ephemeral key */
1913 if ((prekey = malloc(SSHKEY_SHIELD_PREKEY_LEN)) == NULL) {
1914 r = SSH_ERR_ALLOC_FAIL;
1915 goto out;
1916 }
1917 arc4random_buf(prekey, SSHKEY_SHIELD_PREKEY_LEN);
1918 if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
1919 prekey, SSHKEY_SHIELD_PREKEY_LEN,
1920 keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
1921 goto out;
1922#ifdef DEBUG_PK
1923 fprintf(stderr, "%s: key+iv\n", __func__);
1924 sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
1925 stderr);
1926#endif
1927 if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
1928 keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 1)) != 0)
1929 goto out;
1930
1931 /* Serialise and encrypt the private key using the ephemeral key */
1932 if ((prvbuf = sshbuf_new()) == NULL) {
1933 r = SSH_ERR_ALLOC_FAIL;
1934 goto out;
1935 }
1936 if (sshkey_is_shielded(k) && (r = sshkey_unshield_private(k)) != 0)
1937 goto out;
1938 if ((r = sshkey_private_serialize_opt(k, prvbuf,
1939 SSHKEY_SERIALIZE_FULL)) != 0)
1940 goto out;
1941 /* pad to cipher blocksize */
1942 i = 0;
1943 while (sshbuf_len(prvbuf) % cipher_blocksize(cipher)) {
1944 if ((r = sshbuf_put_u8(prvbuf, ++i & 0xff)) != 0)
1945 goto out;
1946 }
1947#ifdef DEBUG_PK
1948 fprintf(stderr, "%s: serialised\n", __func__);
1949 sshbuf_dump(prvbuf, stderr);
1950#endif
1951 /* encrypt */
1952 enclen = sshbuf_len(prvbuf);
1953 if ((enc = malloc(enclen)) == NULL) {
1954 r = SSH_ERR_ALLOC_FAIL;
1955 goto out;
1956 }
1957 if ((r = cipher_crypt(cctx, 0, enc,
1958 sshbuf_ptr(prvbuf), sshbuf_len(prvbuf), 0, 0)) != 0)
1959 goto out;
1960#ifdef DEBUG_PK
1961 fprintf(stderr, "%s: encrypted\n", __func__);
1962 sshbuf_dump_data(enc, enclen, stderr);
1963#endif
1964
1965 /* Make a scrubbed, public-only copy of our private key argument */
1966 if ((r = sshkey_from_private(k, &kswap)) != 0)
1967 goto out;
1968
1969 /* Swap the private key out (it will be destroyed below) */
1970 tmp = *kswap;
1971 *kswap = *k;
1972 *k = tmp;
1973
1974 /* Insert the shielded key into our argument */
1975 k->shielded_private = enc;
1976 k->shielded_len = enclen;
1977 k->shield_prekey = prekey;
1978 k->shield_prekey_len = SSHKEY_SHIELD_PREKEY_LEN;
1979 enc = prekey = NULL; /* transferred */
1980 enclen = 0;
1981
1982 /* success */
1983 r = 0;
1984
1985 out:
1986 /* XXX behaviour on error - invalidate original private key? */
1987 cipher_free(cctx);
1988 explicit_bzero(enc, enclen);
1989 explicit_bzero(keyiv, sizeof(keyiv));
1990 explicit_bzero(&tmp, sizeof(tmp));
1991 freezero(prekey, SSHKEY_SHIELD_PREKEY_LEN);
1992 sshkey_free(kswap);
1993 sshbuf_free(prvbuf);
1994 return r;
1995}
1996
1997int
1998sshkey_unshield_private(struct sshkey *k)
1999{
2000 struct sshbuf *prvbuf = NULL;
2001 u_char pad, *cp, keyiv[SSH_DIGEST_MAX_LENGTH];
2002 struct sshcipher_ctx *cctx = NULL;
2003 const struct sshcipher *cipher;
2004 size_t i;
2005 struct sshkey *kswap = NULL, tmp;
2006 int r = SSH_ERR_INTERNAL_ERROR;
2007
2008#ifdef DEBUG_PK
2009 fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k));
2010#endif
2011 if (!sshkey_is_shielded(k))
2012 return 0; /* nothing to do */
2013
2014 if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) {
2015 r = SSH_ERR_INVALID_ARGUMENT;
2016 goto out;
2017 }
2018 if (cipher_keylen(cipher) + cipher_ivlen(cipher) >
2019 ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) {
2020 r = SSH_ERR_INTERNAL_ERROR;
2021 goto out;
2022 }
2023 /* check size of shielded key blob */
2024 if (k->shielded_len < cipher_blocksize(cipher) ||
2025 (k->shielded_len % cipher_blocksize(cipher)) != 0) {
2026 r = SSH_ERR_INVALID_FORMAT;
2027 goto out;
2028 }
2029
2030 /* Calculate the ephemeral key from the prekey */
2031 if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH,
2032 k->shield_prekey, k->shield_prekey_len,
2033 keyiv, SSH_DIGEST_MAX_LENGTH)) != 0)
2034 goto out;
2035 if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher),
2036 keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 0)) != 0)
2037 goto out;
2038#ifdef DEBUG_PK
2039 fprintf(stderr, "%s: key+iv\n", __func__);
2040 sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH),
2041 stderr);
2042#endif
2043
2044 /* Decrypt and parse the shielded private key using the ephemeral key */
2045 if ((prvbuf = sshbuf_new()) == NULL) {
2046 r = SSH_ERR_ALLOC_FAIL;
2047 goto out;
2048 }
2049 if ((r = sshbuf_reserve(prvbuf, k->shielded_len, &cp)) != 0)
2050 goto out;
2051 /* decrypt */
2052#ifdef DEBUG_PK
2053 fprintf(stderr, "%s: encrypted\n", __func__);
2054 sshbuf_dump_data(k->shielded_private, k->shielded_len, stderr);
2055#endif
2056 if ((r = cipher_crypt(cctx, 0, cp,
2057 k->shielded_private, k->shielded_len, 0, 0)) != 0)
2058 goto out;
2059#ifdef DEBUG_PK
2060 fprintf(stderr, "%s: serialised\n", __func__);
2061 sshbuf_dump(prvbuf, stderr);
2062#endif
2063 /* Parse private key */
2064 if ((r = sshkey_private_deserialize(prvbuf, &kswap)) != 0)
2065 goto out;
2066 /* Check deterministic padding */
2067 i = 0;
2068 while (sshbuf_len(prvbuf)) {
2069 if ((r = sshbuf_get_u8(prvbuf, &pad)) != 0)
2070 goto out;
2071 if (pad != (++i & 0xff)) {
2072 r = SSH_ERR_INVALID_FORMAT;
2073 goto out;
2074 }
2075 }
2076
2077 /* Swap the parsed key back into place */
2078 tmp = *kswap;
2079 *kswap = *k;
2080 *k = tmp;
2081
2082 /* success */
2083 r = 0;
2084
2085 out:
2086 cipher_free(cctx);
2087 explicit_bzero(keyiv, sizeof(keyiv));
2088 explicit_bzero(&tmp, sizeof(tmp));
2089 sshkey_free(kswap);
2090 sshbuf_free(prvbuf);
2091 return r;
2092}
2093
1872static int 2094static int
1873cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) 2095cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1874{ 2096{
@@ -2373,41 +2595,55 @@ sshkey_check_sigtype(const u_char *sig, size_t siglen,
2373} 2595}
2374 2596
2375int 2597int
2376sshkey_sign(const struct sshkey *key, 2598sshkey_sign(struct sshkey *key,
2377 u_char **sigp, size_t *lenp, 2599 u_char **sigp, size_t *lenp,
2378 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)
2379{ 2601{
2602 int was_shielded = sshkey_is_shielded(key);
2603 int r2, r = SSH_ERR_INTERNAL_ERROR;
2604
2380 if (sigp != NULL) 2605 if (sigp != NULL)
2381 *sigp = NULL; 2606 *sigp = NULL;
2382 if (lenp != NULL) 2607 if (lenp != NULL)
2383 *lenp = 0; 2608 *lenp = 0;
2384 if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) 2609 if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2385 return SSH_ERR_INVALID_ARGUMENT; 2610 return SSH_ERR_INVALID_ARGUMENT;
2611 if ((r = sshkey_unshield_private(key)) != 0)
2612 return r;
2386 switch (key->type) { 2613 switch (key->type) {
2387#ifdef WITH_OPENSSL 2614#ifdef WITH_OPENSSL
2388 case KEY_DSA_CERT: 2615 case KEY_DSA_CERT:
2389 case KEY_DSA: 2616 case KEY_DSA:
2390 return ssh_dss_sign(key, sigp, lenp, data, datalen, compat); 2617 r = ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
2618 break;
2391# ifdef OPENSSL_HAS_ECC 2619# ifdef OPENSSL_HAS_ECC
2392 case KEY_ECDSA_CERT: 2620 case KEY_ECDSA_CERT:
2393 case KEY_ECDSA: 2621 case KEY_ECDSA:
2394 return ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat); 2622 r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
2623 break;
2395# endif /* OPENSSL_HAS_ECC */ 2624# endif /* OPENSSL_HAS_ECC */
2396 case KEY_RSA_CERT: 2625 case KEY_RSA_CERT:
2397 case KEY_RSA: 2626 case KEY_RSA:
2398 return ssh_rsa_sign(key, sigp, lenp, data, datalen, alg); 2627 r = ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
2628 break;
2399#endif /* WITH_OPENSSL */ 2629#endif /* WITH_OPENSSL */
2400 case KEY_ED25519: 2630 case KEY_ED25519:
2401 case KEY_ED25519_CERT: 2631 case KEY_ED25519_CERT:
2402 return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat); 2632 r = ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
2633 break;
2403#ifdef WITH_XMSS 2634#ifdef WITH_XMSS
2404 case KEY_XMSS: 2635 case KEY_XMSS:
2405 case KEY_XMSS_CERT: 2636 case KEY_XMSS_CERT:
2406 return ssh_xmss_sign(key, sigp, lenp, data, datalen, compat); 2637 r = ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
2638 break;
2407#endif /* WITH_XMSS */ 2639#endif /* WITH_XMSS */
2408 default: 2640 default:
2409 return SSH_ERR_KEY_TYPE_UNKNOWN; 2641 r = SSH_ERR_KEY_TYPE_UNKNOWN;
2642 break;
2410 } 2643 }
2644 if (was_shielded && (r2 = sshkey_shield_private(key)) != 0)
2645 return r2;
2646 return r;
2411} 2647}
2412 2648
2413/* 2649/*
@@ -2652,7 +2888,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2652} 2888}
2653 2889
2654static int 2890static int
2655default_key_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 2891default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
2656 const u_char *data, size_t datalen, 2892 const u_char *data, size_t datalen,
2657 const char *alg, u_int compat, void *ctx) 2893 const char *alg, u_int compat, void *ctx)
2658{ 2894{
@@ -2762,15 +2998,21 @@ sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
2762} 2998}
2763 2999
2764int 3000int
2765sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b, 3001sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
2766 enum sshkey_serialize_rep opts) 3002 enum sshkey_serialize_rep opts)
2767{ 3003{
2768 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;
2769#ifdef WITH_OPENSSL 3007#ifdef WITH_OPENSSL
2770 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;
2771 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;
2772#endif /* WITH_OPENSSL */ 3010#endif /* WITH_OPENSSL */
2773 3011
3012 if ((r = sshkey_unshield_private(key)) != 0)
3013 return r;
3014 if ((b = sshbuf_new()) == NULL)
3015 return SSH_ERR_ALLOC_FAIL;
2774 if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) 3016 if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
2775 goto out; 3017 goto out;
2776 switch (key->type) { 3018 switch (key->type) {
@@ -2896,14 +3138,23 @@ sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b,
2896 r = SSH_ERR_INVALID_ARGUMENT; 3138 r = SSH_ERR_INVALID_ARGUMENT;
2897 goto out; 3139 goto out;
2898 } 3140 }
2899 /* success */ 3141 /*
3142 * success (but we still need to append the output to buf after
3143 * possibly re-shielding the private key)
3144 */
2900 r = 0; 3145 r = 0;
2901 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
2902 return r; 3153 return r;
2903} 3154}
2904 3155
2905int 3156int
2906sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b) 3157sshkey_private_serialize(struct sshkey *key, struct sshbuf *b)
2907{ 3158{
2908 return sshkey_private_serialize_opt(key, b, 3159 return sshkey_private_serialize_opt(key, b,
2909 SSHKEY_SERIALIZE_DEFAULT); 3160 SSHKEY_SERIALIZE_DEFAULT);
@@ -3358,7 +3609,7 @@ sshkey_dump_ec_key(const EC_KEY *key)
3358#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ 3609#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
3359 3610
3360static int 3611static int
3361sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob, 3612sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob,
3362 const char *passphrase, const char *comment, const char *ciphername, 3613 const char *passphrase, const char *comment, const char *ciphername,
3363 int rounds) 3614 int rounds)
3364{ 3615{
@@ -3728,20 +3979,28 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3728#ifdef WITH_OPENSSL 3979#ifdef WITH_OPENSSL
3729/* convert SSH v2 key in OpenSSL PEM format */ 3980/* convert SSH v2 key in OpenSSL PEM format */
3730static int 3981static int
3731sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob, 3982sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf,
3732 const char *_passphrase, const char *comment) 3983 const char *_passphrase, const char *comment)
3733{ 3984{
3985 int was_shielded = sshkey_is_shielded(key);
3734 int success, r; 3986 int success, r;
3735 int blen, len = strlen(_passphrase); 3987 int blen, len = strlen(_passphrase);
3736 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; 3988 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
3737 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; 3989 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
3738 char *bptr; 3990 char *bptr;
3739 BIO *bio = NULL; 3991 BIO *bio = NULL;
3992 struct sshbuf *blob;
3740 3993
3741 if (len > 0 && len <= 4) 3994 if (len > 0 && len <= 4)
3742 return SSH_ERR_PASSPHRASE_TOO_SHORT; 3995 return SSH_ERR_PASSPHRASE_TOO_SHORT;
3743 if ((bio = BIO_new(BIO_s_mem())) == NULL) 3996 if ((blob = sshbuf_new()) == NULL)
3744 return SSH_ERR_ALLOC_FAIL; 3997 return SSH_ERR_ALLOC_FAIL;
3998 if ((bio = BIO_new(BIO_s_mem())) == NULL) {
3999 sshbuf_free(blob);
4000 return SSH_ERR_ALLOC_FAIL;
4001 }
4002 if ((r = sshkey_unshield_private(key)) != 0)
4003 goto out;
3745 4004
3746 switch (key->type) { 4005 switch (key->type) {
3747 case KEY_DSA: 4006 case KEY_DSA:
@@ -3774,6 +4033,12 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
3774 goto out; 4033 goto out;
3775 r = 0; 4034 r = 0;
3776 out: 4035 out:
4036 if (was_shielded)
4037 r = sshkey_shield_private(key);
4038 if (r == 0)
4039 r = sshbuf_putb(buf, blob);
4040 sshbuf_free(blob);
4041
3777 BIO_free(bio); 4042 BIO_free(bio);
3778 return r; 4043 return r;
3779} 4044}
@@ -4102,7 +4367,7 @@ sshkey_set_filename(struct sshkey *k, const char *filename)
4102} 4367}
4103#else 4368#else
4104int 4369int
4105sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b, 4370sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
4106 u_int32_t maxsign, sshkey_printfn *pr) 4371 u_int32_t maxsign, sshkey_printfn *pr)
4107{ 4372{
4108 return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT); 4373 return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);