summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--authfd.c4
-rw-r--r--authfd.h4
-rw-r--r--krl.c4
-rw-r--r--krl.h4
-rw-r--r--ssh-agent.c7
-rw-r--r--ssh-keygen.c4
-rw-r--r--sshconnect.c4
-rw-r--r--sshconnect.h4
-rw-r--r--sshd.c10
-rw-r--r--sshkey.c299
-rw-r--r--sshkey.h21
11 files changed, 324 insertions, 41 deletions
diff --git a/authfd.c b/authfd.c
index 95348abfc..327a333d2 100644
--- a/authfd.c
+++ b/authfd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfd.c,v 1.113 2018/12/27 23:02:11 djm Exp $ */ 1/* $OpenBSD: authfd.c,v 1.114 2019/06/21 04:21:04 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -423,7 +423,7 @@ encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign)
423 * This call is intended only for use by ssh-add(1) and like applications. 423 * This call is intended only for use by ssh-add(1) and like applications.
424 */ 424 */
425int 425int
426ssh_add_identity_constrained(int sock, const struct sshkey *key, 426ssh_add_identity_constrained(int sock, struct sshkey *key,
427 const char *comment, u_int life, u_int confirm, u_int maxsign) 427 const char *comment, u_int life, u_int confirm, u_int maxsign)
428{ 428{
429 struct sshbuf *msg; 429 struct sshbuf *msg;
diff --git a/authfd.h b/authfd.h
index a032fd542..060bed63f 100644
--- a/authfd.h
+++ b/authfd.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfd.h,v 1.44 2018/07/12 04:35:25 djm Exp $ */ 1/* $OpenBSD: authfd.h,v 1.45 2019/06/21 04:21:04 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -29,7 +29,7 @@ void ssh_close_authentication_socket(int sock);
29int ssh_lock_agent(int sock, int lock, const char *password); 29int ssh_lock_agent(int sock, int lock, const char *password);
30int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp); 30int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp);
31void ssh_free_identitylist(struct ssh_identitylist *idl); 31void ssh_free_identitylist(struct ssh_identitylist *idl);
32int ssh_add_identity_constrained(int sock, const struct sshkey *key, 32int ssh_add_identity_constrained(int sock, struct sshkey *key,
33 const char *comment, u_int life, u_int confirm, u_int maxsign); 33 const char *comment, u_int life, u_int confirm, u_int maxsign);
34int ssh_remove_identity(int sock, struct sshkey *key); 34int ssh_remove_identity(int sock, struct sshkey *key);
35int ssh_update_card(int sock, int add, const char *reader_id, 35int ssh_update_card(int sock, int add, const char *reader_id,
diff --git a/krl.c b/krl.c
index 8e2d5d5df..bb960882f 100644
--- a/krl.c
+++ b/krl.c
@@ -14,7 +14,7 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17/* $OpenBSD: krl.c,v 1.42 2018/09/12 01:21:34 djm Exp $ */ 17/* $OpenBSD: krl.c,v 1.43 2019/06/21 04:21:04 djm Exp $ */
18 18
19#include "includes.h" 19#include "includes.h"
20 20
@@ -732,7 +732,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
732 732
733int 733int
734ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, 734ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
735 const struct sshkey **sign_keys, u_int nsign_keys) 735 struct sshkey **sign_keys, u_int nsign_keys)
736{ 736{
737 int r = SSH_ERR_INTERNAL_ERROR; 737 int r = SSH_ERR_INTERNAL_ERROR;
738 struct revoked_certs *rc; 738 struct revoked_certs *rc;
diff --git a/krl.h b/krl.h
index 815a1df4e..ce534a111 100644
--- a/krl.h
+++ b/krl.h
@@ -14,7 +14,7 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17/* $OpenBSD: krl.h,v 1.6 2018/09/12 01:21:34 djm Exp $ */ 17/* $OpenBSD: krl.h,v 1.7 2019/06/21 04:21:04 djm Exp $ */
18 18
19#ifndef _KRL_H 19#ifndef _KRL_H
20#define _KRL_H 20#define _KRL_H
@@ -56,7 +56,7 @@ int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len);
56int ssh_krl_revoke_key_sha256(struct ssh_krl *krl, const u_char *p, size_t len); 56int ssh_krl_revoke_key_sha256(struct ssh_krl *krl, const u_char *p, size_t len);
57int ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key); 57int ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key);
58int ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, 58int ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
59 const struct sshkey **sign_keys, u_int nsign_keys); 59 struct sshkey **sign_keys, u_int nsign_keys);
60int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, 60int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
61 const struct sshkey **sign_ca_keys, size_t nsign_ca_keys); 61 const struct sshkey **sign_ca_keys, size_t nsign_ca_keys);
62int ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key); 62int ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key);
diff --git a/ssh-agent.c b/ssh-agent.c
index 4669b679c..4d7ab225f 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-agent.c,v 1.235 2019/06/14 03:51:47 djm Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.236 2019/06/21 04:21:04 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -423,7 +423,10 @@ process_add_identity(SocketEntry *e)
423 error("%s: decode private key: %s", __func__, ssh_err(r)); 423 error("%s: decode private key: %s", __func__, ssh_err(r));
424 goto err; 424 goto err;
425 } 425 }
426 426 if ((r = sshkey_shield_private(k)) != 0) {
427 error("%s: shield private key: %s", __func__, ssh_err(r));
428 goto err;
429 }
427 while (sshbuf_len(e->request)) { 430 while (sshbuf_len(e->request)) {
428 if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) { 431 if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) {
429 error("%s: buffer error: %s", __func__, ssh_err(r)); 432 error("%s: buffer error: %s", __func__, ssh_err(r));
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 010667157..c95bc15cf 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.331 2019/06/06 05:13:13 otto Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.332 2019/06/21 04:21:04 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1654,7 +1654,7 @@ load_pkcs11_key(char *path)
1654 1654
1655/* Signer for sshkey_certify_custom that uses the agent */ 1655/* Signer for sshkey_certify_custom that uses the agent */
1656static int 1656static int
1657agent_signer(const struct sshkey *key, u_char **sigp, size_t *lenp, 1657agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp,
1658 const u_char *data, size_t datalen, 1658 const u_char *data, size_t datalen,
1659 const char *alg, u_int compat, void *ctx) 1659 const char *alg, u_int compat, void *ctx)
1660{ 1660{
diff --git a/sshconnect.c b/sshconnect.c
index c57f1a0ff..2dc500b47 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect.c,v 1.315 2019/05/03 03:27:38 dtucker Exp $ */ 1/* $OpenBSD: sshconnect.c,v 1.316 2019/06/21 04:21:04 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1401,7 +1401,7 @@ ssh_local_cmd(const char *args)
1401} 1401}
1402 1402
1403void 1403void
1404maybe_add_key_to_agent(char *authfile, const struct sshkey *private, 1404maybe_add_key_to_agent(char *authfile, struct sshkey *private,
1405 char *comment, char *passphrase) 1405 char *comment, char *passphrase)
1406{ 1406{
1407 int auth_sock = -1, r; 1407 int auth_sock = -1, r;
diff --git a/sshconnect.h b/sshconnect.h
index 6e8989b27..b455d7c20 100644
--- a/sshconnect.h
+++ b/sshconnect.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect.h,v 1.37 2019/01/19 21:36:38 djm Exp $ */ 1/* $OpenBSD: sshconnect.h,v 1.38 2019/06/21 04:21:05 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -52,4 +52,4 @@ void ssh_userauth2(struct ssh *ssh, const char *, const char *,
52 52
53int ssh_local_cmd(const char *); 53int ssh_local_cmd(const char *);
54 54
55void maybe_add_key_to_agent(char *, const struct sshkey *, char *, char *); 55void maybe_add_key_to_agent(char *, struct sshkey *, char *, char *);
diff --git a/sshd.c b/sshd.c
index be23fbc80..735a11060 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.535 2019/06/06 05:13:13 otto Exp $ */ 1/* $OpenBSD: sshd.c,v 1.536 2019/06/21 04:21:05 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1375,7 +1375,7 @@ set_process_rdomain(struct ssh *ssh, const char *name)
1375 1375
1376static void 1376static void
1377accumulate_host_timing_secret(struct sshbuf *server_cfg, 1377accumulate_host_timing_secret(struct sshbuf *server_cfg,
1378 const struct sshkey *key) 1378 struct sshkey *key)
1379{ 1379{
1380 static struct ssh_digest_ctx *ctx; 1380 static struct ssh_digest_ctx *ctx;
1381 u_char *hash; 1381 u_char *hash;
@@ -1723,6 +1723,12 @@ main(int ac, char **av)
1723 &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) 1723 &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
1724 do_log2(ll, "Unable to load host key \"%s\": %s", 1724 do_log2(ll, "Unable to load host key \"%s\": %s",
1725 options.host_key_files[i], ssh_err(r)); 1725 options.host_key_files[i], ssh_err(r));
1726 if (r == 0 && (r = sshkey_shield_private(key)) != 0) {
1727 do_log2(ll, "Unable to shield host key \"%s\": %s",
1728 options.host_key_files[i], ssh_err(r));
1729 sshkey_free(key);
1730 key = NULL;
1731 }
1726 if ((r = sshkey_load_public(options.host_key_files[i], 1732 if ((r = sshkey_load_public(options.host_key_files[i],
1727 &pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) 1733 &pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
1728 do_log2(ll, "Unable to load host key \"%s\": %s", 1734 do_log2(ll, "Unable to load host key \"%s\": %s",
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);
diff --git a/sshkey.h b/sshkey.h
index a91e60436..41d159a1b 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.h,v 1.31 2019/01/20 22:51:37 djm Exp $ */ 1/* $OpenBSD: sshkey.h,v 1.32 2019/06/21 04:21:05 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -123,6 +123,10 @@ struct sshkey {
123 u_char *xmss_sk; 123 u_char *xmss_sk;
124 u_char *xmss_pk; 124 u_char *xmss_pk;
125 struct sshkey_cert *cert; 125 struct sshkey_cert *cert;
126 u_char *shielded_private;
127 size_t shielded_len;
128 u_char *shield_prekey;
129 size_t shield_prekey_len;
126}; 130};
127 131
128#define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES 132#define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES
@@ -146,6 +150,11 @@ u_int sshkey_size(const struct sshkey *);
146 150
147int sshkey_generate(int type, u_int bits, struct sshkey **keyp); 151int sshkey_generate(int type, u_int bits, struct sshkey **keyp);
148int sshkey_from_private(const struct sshkey *, struct sshkey **); 152int sshkey_from_private(const struct sshkey *, struct sshkey **);
153
154int sshkey_is_shielded(struct sshkey *);
155int sshkey_shield_private(struct sshkey *);
156int sshkey_unshield_private(struct sshkey *);
157
149int sshkey_type_from_name(const char *); 158int sshkey_type_from_name(const char *);
150int sshkey_is_cert(const struct sshkey *); 159int sshkey_is_cert(const struct sshkey *);
151int sshkey_type_is_cert(int); 160int sshkey_type_is_cert(int);
@@ -161,7 +170,7 @@ int sshkey_check_cert_sigtype(const struct sshkey *, const char *);
161 170
162int sshkey_certify(struct sshkey *, struct sshkey *, const char *); 171int sshkey_certify(struct sshkey *, struct sshkey *, const char *);
163/* Variant allowing use of a custom signature function (e.g. for ssh-agent) */ 172/* Variant allowing use of a custom signature function (e.g. for ssh-agent) */
164typedef int sshkey_certify_signer(const struct sshkey *, u_char **, size_t *, 173typedef int sshkey_certify_signer(struct sshkey *, u_char **, size_t *,
165 const u_char *, size_t, const char *, u_int, void *); 174 const u_char *, size_t, const char *, u_int, void *);
166int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *, 175int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *,
167 sshkey_certify_signer *, void *); 176 sshkey_certify_signer *, void *);
@@ -192,7 +201,7 @@ int sshkey_puts_opts(const struct sshkey *, struct sshbuf *,
192int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *); 201int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
193int sshkey_putb_plain(const struct sshkey *, struct sshbuf *); 202int sshkey_putb_plain(const struct sshkey *, struct sshbuf *);
194 203
195int sshkey_sign(const struct sshkey *, u_char **, size_t *, 204int sshkey_sign(struct sshkey *, u_char **, size_t *,
196 const u_char *, size_t, const char *, u_int); 205 const u_char *, size_t, const char *, u_int);
197int sshkey_verify(const struct sshkey *, const u_char *, size_t, 206int sshkey_verify(const struct sshkey *, const u_char *, size_t,
198 const u_char *, size_t, const char *, u_int); 207 const u_char *, size_t, const char *, u_int);
@@ -204,8 +213,8 @@ void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *);
204void sshkey_dump_ec_key(const EC_KEY *); 213void sshkey_dump_ec_key(const EC_KEY *);
205 214
206/* private key parsing and serialisation */ 215/* private key parsing and serialisation */
207int sshkey_private_serialize(const struct sshkey *key, struct sshbuf *buf); 216int sshkey_private_serialize(struct sshkey *key, struct sshbuf *buf);
208int sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *buf, 217int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
209 enum sshkey_serialize_rep); 218 enum sshkey_serialize_rep);
210int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp); 219int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp);
211 220
@@ -231,7 +240,7 @@ int sshkey_set_filename(struct sshkey *, const char *);
231int sshkey_enable_maxsign(struct sshkey *, u_int32_t); 240int sshkey_enable_maxsign(struct sshkey *, u_int32_t);
232u_int32_t sshkey_signatures_left(const struct sshkey *); 241u_int32_t sshkey_signatures_left(const struct sshkey *);
233int sshkey_forward_state(const struct sshkey *, u_int32_t, sshkey_printfn *); 242int sshkey_forward_state(const struct sshkey *, u_int32_t, sshkey_printfn *);
234int sshkey_private_serialize_maxsign(const struct sshkey *key, struct sshbuf *buf, 243int sshkey_private_serialize_maxsign(struct sshkey *key, struct sshbuf *buf,
235 u_int32_t maxsign, sshkey_printfn *pr); 244 u_int32_t maxsign, sshkey_printfn *pr);
236 245
237#ifdef SSHKEY_INTERNAL 246#ifdef SSHKEY_INTERNAL