diff --git a/backport-upstream-Refactor-private-key-parsing.-Eliminates-a-.patch b/backport-upstream-Refactor-private-key-parsing.-Eliminates-a-.patch new file mode 100644 index 0000000000000000000000000000000000000000..5ba6ff30c889ba1f6c80092f1c0d5630c69d9bdb --- /dev/null +++ b/backport-upstream-Refactor-private-key-parsing.-Eliminates-a-.patch @@ -0,0 +1,322 @@ +From 3779b50ee952078018a5d9e1df20977f4355df17 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Sat, 11 Apr 2020 10:16:11 +0000 +Subject: [PATCH] upstream: Refactor private key parsing. Eliminates a fair bit + of + +duplicated code and fixes oss-fuzz#20074 (NULL deref) caused by a missing key +type check in the ECDSA_CERT parsing path. + +feedback and ok markus@ + +OpenBSD-Commit-ID: 4711981d88afb7196d228f7baad9be1d3b20f9c9 +Conflict:NA +Reference: https://github.com/openssh/openssh-portable/commit/3779b50ee952078018a5d9e1df20977f4355df17 +--- + sshkey.c | 187 ++++++++++++++------------------------------------------------- + 1 file changed, 40 insertions(+), 147 deletions(-) + +diff --git a/sshkey.c b/sshkey.c +index 3a9e0f3..96be57e 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: sshkey.c,v 1.99 2020/01/21 05:56:56 djm Exp $ */ ++/* $OpenBSD: sshkey.c,v 1.108 2020/04/11 10:16:11 djm Exp $ */ + /* + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2008 Alexander von Gernler. All rights reserved. +@@ -3512,38 +3512,52 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0) + goto out; + type = sshkey_type_from_name(tname); +- switch (type) { +-#ifdef WITH_OPENSSL +- case KEY_DSA: ++ if (sshkey_type_is_cert(type)) { ++ /* ++ * Certificate key private keys begin with the certificate ++ * itself. Make sure this matches the type of the enclosing ++ * private key. ++ */ ++ if ((r = sshkey_froms(buf, &k)) != 0) ++ goto out; ++ if (k->type != type) { ++ r = SSH_ERR_KEY_CERT_MISMATCH; ++ goto out; ++ } ++ /* For ECDSA keys, the group must match too */ ++ if (k->type == KEY_ECDSA && ++ k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) { ++ r = SSH_ERR_KEY_CERT_MISMATCH; ++ goto out; ++ } ++ } else { + if ((k = sshkey_new(type)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } ++ } ++ switch (type) { ++#ifdef WITH_OPENSSL ++ case KEY_DSA: + if ((r = sshbuf_get_bignum2(buf, &dsa_p)) != 0 || + (r = sshbuf_get_bignum2(buf, &dsa_q)) != 0 || + (r = sshbuf_get_bignum2(buf, &dsa_g)) != 0 || +- (r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0 || +- (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0) ++ (r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0) + goto out; + if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + dsa_p = dsa_q = dsa_g = NULL; /* transferred */ +- if (!DSA_set0_key(k->dsa, dsa_pub_key, dsa_priv_key)) { ++ if (!DSA_set0_key(k->dsa, dsa_pub_key, NULL)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- dsa_pub_key = dsa_priv_key = NULL; /* transferred */ +- break; ++ dsa_pub_key = NULL; /* transferred */ ++ /* FALLTHROUGH */ + case KEY_DSA_CERT: +- if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0) ++ if ((r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0) + goto out; +- if (k->type != type) { +- r = SSH_ERR_INVALID_FORMAT; +- goto out; +- } + if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; +@@ -3552,10 +3566,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + break; + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: +- if ((k = sshkey_new(type)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } + if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; +@@ -3571,27 +3581,12 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 || +- (r = sshbuf_get_bignum2(buf, &exponent))) +- goto out; +- if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { +- r = SSH_ERR_LIBCRYPTO_ERROR; +- goto out; +- } +- if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa), +- EC_KEY_get0_public_key(k->ecdsa))) != 0 || +- (r = sshkey_ec_validate_private(k->ecdsa)) != 0) ++ if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0) + goto out; +- break; ++ /* FALLTHROUGH */ + case KEY_ECDSA_CERT: +- if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshbuf_get_bignum2(buf, &exponent)) != 0) +- goto out; +- if (k->type != type || +- k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) { +- r = SSH_ERR_INVALID_FORMAT; ++ if ((r = sshbuf_get_bignum2(buf, &exponent)) != 0) + goto out; +- } + if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; +@@ -3602,10 +3597,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + goto out; + break; + case KEY_ECDSA_SK: +- if ((k = sshkey_new(type)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } + if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; +@@ -3638,8 +3629,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + goto out; + break; + case KEY_ECDSA_SK_CERT: +- if ((r = sshkey_froms(buf, &k)) != 0) +- goto out; + if ((k->sk_key_handle = sshbuf_new()) == NULL || + (k->sk_reserved = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; +@@ -3657,43 +3646,21 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + break; + # endif /* OPENSSL_HAS_ECC */ + case KEY_RSA: +- if ((k = sshkey_new(type)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } + if ((r = sshbuf_get_bignum2(buf, &rsa_n)) != 0 || +- (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0 || +- (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 || +- (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 || +- (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 || +- (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0) +- goto out; +- if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, rsa_d)) { +- r = SSH_ERR_LIBCRYPTO_ERROR; ++ (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0) + goto out; +- } +- rsa_n = rsa_e = rsa_d = NULL; /* transferred */ +- if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) { ++ if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, NULL)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- rsa_p = rsa_q = NULL; /* transferred */ +- if ((r = check_rsa_length(k->rsa)) != 0) +- goto out; +- if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) +- goto out; +- break; ++ rsa_n = rsa_e = NULL; /* transferred */ ++ /* FALLTHROUGH */ + case KEY_RSA_CERT: +- if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 || ++ if ((r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 || + (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 || + (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 || + (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0) + goto out; +- if (k->type != type) { +- r = SSH_ERR_INVALID_FORMAT; +- goto out; +- } + if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; +@@ -3711,30 +3678,10 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + break; + #endif /* WITH_OPENSSL */ + case KEY_ED25519: +- if ((k = sshkey_new(type)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } +- if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || +- (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) +- goto out; +- if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) { +- r = SSH_ERR_INVALID_FORMAT; +- goto out; +- } +- k->ed25519_pk = ed25519_pk; +- k->ed25519_sk = ed25519_sk; +- ed25519_pk = ed25519_sk = NULL; +- break; + case KEY_ED25519_CERT: +- if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || ++ if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || + (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) + goto out; +- if (k->type != type) { +- r = SSH_ERR_INVALID_FORMAT; +- goto out; +- } + if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto out; +@@ -3744,38 +3691,9 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + ed25519_pk = ed25519_sk = NULL; /* transferred */ + break; + case KEY_ED25519_SK: +- if ((k = sshkey_new(type)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } +- if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0) +- goto out; +- if (pklen != ED25519_PK_SZ) { +- r = SSH_ERR_INVALID_FORMAT; +- goto out; +- } +- if ((k->sk_key_handle = sshbuf_new()) == NULL || +- (k->sk_reserved = sshbuf_new()) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } +- if ((r = sshbuf_get_cstring(buf, &k->sk_application, +- NULL)) != 0 || +- (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || +- (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || +- (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) +- goto out; +- k->ed25519_pk = ed25519_pk; +- ed25519_pk = NULL; +- break; + case KEY_ED25519_SK_CERT: +- if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0) +- goto out; +- if (k->type != type) { +- r = SSH_ERR_INVALID_FORMAT; ++ if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0) + goto out; +- } + if (pklen != ED25519_PK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto out; +@@ -3796,10 +3714,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + break; + #ifdef WITH_XMSS + case KEY_XMSS: +- if ((k = sshkey_new(type)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } ++ case KEY_XMSS_CERT: + if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 || + (r = sshkey_xmss_init(k, xmss_name)) != 0 || + (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 || +@@ -3817,28 +3732,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0) + goto out; + break; +- case KEY_XMSS_CERT: +- if ((r = sshkey_froms(buf, &k)) != 0 || +- (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 || +- (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 || +- (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0) +- goto out; +- if (k->type != type || strcmp(xmss_name, k->xmss_name) != 0) { +- r = SSH_ERR_INVALID_FORMAT; +- goto out; +- } +- if (pklen != sshkey_xmss_pklen(k) || +- sklen != sshkey_xmss_sklen(k)) { +- r = SSH_ERR_INVALID_FORMAT; +- goto out; +- } +- k->xmss_pk = xmss_pk; +- k->xmss_sk = xmss_sk; +- xmss_pk = xmss_sk = NULL; +- /* optional internal state */ +- if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0) +- goto out; +- break; + #endif /* WITH_XMSS */ + default: + r = SSH_ERR_KEY_TYPE_UNKNOWN; +-- +1.8.3.1 + diff --git a/openssh.spec b/openssh.spec index ff62f21587c0127c7e8abd8b163d083846b81f1f..b96cecb93824cce292704af4c460f1ed9a467cb8 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 14 +%global openssh_release 15 Name: openssh Version: 8.2p1 @@ -94,6 +94,7 @@ Patch61: add-strict-scp-check-for-CVE-2020-15778.patch Patch62: backport-move-closefrom-to-before-first-malloc.patch Patch63: backport-CVE-2021-41617-1.patch Patch64: backport-CVE-2021-41617-2.patch +Patch65: backport-upstream-Refactor-private-key-parsing.-Eliminates-a-.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -260,6 +261,7 @@ popd %patch62 -p1 %patch63 -p1 %patch64 -p1 +%patch65 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -471,6 +473,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Sat Oct 30 2021 kircher - 8.2P1-15 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:backport patch frpom github to fix NULL ref + * Sat Oct 09 2021 renmingshuai - 8.2P1-14 - Type:bugfix - CVE:CVE-2021-41617