From 60bf9d85b2d1f1b246663cd34bb9c278b4058037 Mon Sep 17 00:00:00 2001 From: eaglegai Date: Wed, 18 Nov 2020 17:32:11 +0800 Subject: [PATCH 01/22] keep pam_ssh_agent_auth change release number with openssh --- openssh.spec | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 202886e..b20b2b2 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,10 +6,11 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 +%global openssh_release 7 Name: openssh Version: 8.2p1 -Release: 6 +Release: %{openssh_release} URL: http://www.openssh.com/portable.html License: BSD Summary: An open source implementation of SSH protocol version 2 @@ -136,7 +137,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: 0.10.3 -Release: 9.1 +Release: 9.%{openssh_release} License: BSD %description @@ -461,6 +462,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Wed Nov 18 2020 gaihuiying - 8.2P1-7 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:keep pam_ssh_agent_auth change release number with openssh + * Mon Nov 09 2020 xihaochen - 8.2P1-6 - Type:requirement - CVE:NA -- Gitee From cf0b4522835e20380c6f4b0152496434a2692e2a Mon Sep 17 00:00:00 2001 From: quanhongfei <2506045831@qq.com> Date: Wed, 9 Dec 2020 21:44:36 +0800 Subject: [PATCH 02/22] fix ssh key file access permission error --- openssh.spec | 8 +++++++- sshd-keygen | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/openssh.spec b/openssh.spec index b20b2b2..d3eb54c 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 7 +%global openssh_release 8 Name: openssh Version: 8.2p1 @@ -462,6 +462,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Wed Dec 09 2020 quanhongfei - 8.2P1-8 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:fix /etc/ssh/ generate key file access premission error + * Wed Nov 18 2020 gaihuiying - 8.2P1-7 - Type:bugfix - CVE:NA diff --git a/sshd-keygen b/sshd-keygen index efd876c..141814c 100644 --- a/sshd-keygen +++ b/sshd-keygen @@ -31,8 +31,8 @@ fi # sanitize permissions /usr/bin/chgrp ssh_keys $KEY -/usr/bin/chmod 400 $KEY -/usr/bin/chmod 400 $KEY.pub +/usr/bin/chmod 640 $KEY +/usr/bin/chmod 644 $KEY.pub if [[ -x /usr/sbin/restorecon ]]; then /usr/sbin/restorecon $KEY{,.pub} fi -- Gitee From 01598604276fbb2d07e06d6349489b54bad8d947 Mon Sep 17 00:00:00 2001 From: eaglegai Date: Fri, 18 Dec 2020 10:24:55 +0800 Subject: [PATCH 03/22] update key file permissions to 600 --- openssh.spec | 8 +++++++- sshd-keygen | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index d3eb54c..94031d7 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 8 +%global openssh_release 9 Name: openssh Version: 8.2p1 @@ -462,6 +462,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Fri Dec 18 2020 gaihuiying - 8.2P1-9 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:update key file permissions to 600 + * Wed Dec 09 2020 quanhongfei - 8.2P1-8 - Type:bugfix - CVE:NA diff --git a/sshd-keygen b/sshd-keygen index 141814c..11b818a 100644 --- a/sshd-keygen +++ b/sshd-keygen @@ -31,7 +31,7 @@ fi # sanitize permissions /usr/bin/chgrp ssh_keys $KEY -/usr/bin/chmod 640 $KEY +/usr/bin/chmod 600 $KEY /usr/bin/chmod 644 $KEY.pub if [[ -x /usr/sbin/restorecon ]]; then /usr/sbin/restorecon $KEY{,.pub} -- Gitee From 844733ce5c431fe5affd68a8f574131e4585520f Mon Sep 17 00:00:00 2001 From: yu_boyun <1215979730@qq.com> Date: Tue, 12 Jan 2021 16:29:18 +0800 Subject: [PATCH 04/22] Fix CVE-2020-14145 --- CVE-2020-14145.patch | 92 ++++++++++++++++++++++++++++++++++++++++++++ openssh.spec | 10 ++++- 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 CVE-2020-14145.patch diff --git a/CVE-2020-14145.patch b/CVE-2020-14145.patch new file mode 100644 index 0000000..76fb3e8 --- /dev/null +++ b/CVE-2020-14145.patch @@ -0,0 +1,92 @@ +From b3855ff053f5078ec3d3c653cdaedefaa5fc362d Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Fri, 18 Sep 2020 05:23:03 +0000 +Subject: upstream: tweak the client hostkey preference ordering algorithm to + +prefer the default ordering if the user has a key that matches the +best-preference default algorithm. + +feedback and ok markus@ + +OpenBSD-Commit-ID: a92dd7d7520ddd95c0a16786a7519e6d0167d35f +--- + sshconnect2.c | 41 ++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 38 insertions(+), 3 deletions(-) + +diff --git a/sshconnect2.c b/sshconnect2.c +index 347e348c..f64aae66 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: sshconnect2.c,v 1.320 2020/02/06 22:48:23 djm Exp $ */ ++/* $OpenBSD: sshconnect2.c,v 1.326 2020/09/18 05:23:03 djm Exp $ */ + /* + * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2008 Damien Miller. All rights reserved. +@@ -102,12 +102,25 @@ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) + return 0; + } + ++/* Returns the first item from a comma-separated algorithm list */ ++static char * ++first_alg(const char *algs) ++{ ++ char *ret, *cp; ++ ++ ret = xstrdup(algs); ++ if ((cp = strchr(ret, ',')) != NULL) ++ *cp = '\0'; ++ return ret; ++} ++ + static char * + order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) + { +- char *oavail, *avail, *first, *last, *alg, *hostname, *ret; ++ char *oavail = NULL, *avail = NULL, *first = NULL, *last = NULL; ++ char *alg = NULL, *hostname = NULL, *ret = NULL, *best = NULL; + size_t maxlen; +- struct hostkeys *hostkeys; ++ struct hostkeys *hostkeys = NULL; + int ktype; + u_int i; + +@@ -119,6 +132,26 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) + for (i = 0; i < options.num_system_hostfiles; i++) + load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]); + ++ /* ++ * If a plain public key exists that matches the type of the best ++ * preference HostkeyAlgorithms, then use the whole list as is. ++ * Note that we ignore whether the best preference algorithm is a ++ * certificate type, as sshconnect.c will downgrade certs to ++ * plain keys if necessary. ++ */ ++ best = first_alg(options.hostkeyalgorithms); ++ if (lookup_key_in_hostkeys_by_type(hostkeys, ++ sshkey_type_plain(sshkey_type_from_name(best)), NULL)) { ++ debug3("%s: have matching best-preference key type %s, " ++ "using HostkeyAlgorithms verbatim", __func__, best); ++ ret = xstrdup(options.hostkeyalgorithms); ++ goto out; ++ } ++ ++ /* ++ * Otherwise, prefer the host key algorithms that match known keys ++ * while keeping the ordering of HostkeyAlgorithms as much as possible. ++ */ + oavail = avail = xstrdup(options.hostkeyalgorithms); + maxlen = strlen(avail) + 1; + first = xmalloc(maxlen); +@@ -159,6 +192,8 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) + if (*first != '\0') + debug3("%s: prefer hostkeyalgs: %s", __func__, first); + ++ out: ++ free(best); + free(first); + free(last); + free(hostname); +-- +cgit v1.2.3 + diff --git a/openssh.spec b/openssh.spec index 94031d7..d1ee182 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 9 +%global openssh_release 10 Name: openssh Version: 8.2p1 @@ -89,6 +89,7 @@ Patch56: set-sshd-config.patch Patch57: CVE-2020-12062-1.patch Patch58: CVE-2020-12062-2.patch Patch59: upstream-expose-vasnmprintf.patch +Patch60: CVE-2020-14145.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -250,6 +251,7 @@ popd %patch57 -p1 %patch58 -p1 %patch59 -p1 +%patch60 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -462,6 +464,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Tue Jan 12 2021 yuboyun - 8.2P1-10 +- Type:cves +- ID:CVE-2020-14145 +- SUG:NA +- DESC:Fix CVE-2020-14145 + * Fri Dec 18 2020 gaihuiying - 8.2P1-9 - Type:bugfix - CVE:NA -- Gitee From fc269c323c17cb2c0dd4d5641c3c745cefc6aea1 Mon Sep 17 00:00:00 2001 From: panchenbo Date: Mon, 12 Jul 2021 18:28:17 +0800 Subject: [PATCH 05/22] fix pam_ssh_agent_auth.8.gz conflicts --- openssh.spec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index d1ee182..f66e6de 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 10 +%global openssh_release 11 Name: openssh Version: 8.2p1 @@ -449,7 +449,6 @@ getent passwd sshd >/dev/null || \ %files -n pam_ssh_agent_auth %license pam_ssh_agent_auth-0.10.3/OPENSSH_LICENSE %attr(0755,root,root) %{_libdir}/security/pam_ssh_agent_auth.so -%attr(0644,root,root) %{_mandir}/man8/pam_ssh_agent_auth.8* %files help %doc ChangeLog OVERVIEW PROTOCOL* README README.privsep README.tun README.dns TODO openssh-lpk-openldap.schema @@ -464,6 +463,9 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Tue Jul 12 2021 panchenbo - 8.2P1-11 +- fix pam_ssh_agent_auth.8.gz conflicts + * Tue Jan 12 2021 yuboyun - 8.2P1-10 - Type:cves - ID:CVE-2020-14145 -- Gitee From e4f81efb0d948293537ba26e93a79200b8723a0f Mon Sep 17 00:00:00 2001 From: wei dong Date: Tue, 3 Aug 2021 09:48:09 +0800 Subject: [PATCH 06/22] add strict-scp-check for check command injection --- add-strict-scp-check-for-CVE-2020-15778.patch | 159 ++++++++++++++++++ openssh.spec | 10 +- 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 add-strict-scp-check-for-CVE-2020-15778.patch diff --git a/add-strict-scp-check-for-CVE-2020-15778.patch b/add-strict-scp-check-for-CVE-2020-15778.patch new file mode 100644 index 0000000..7dfd9d2 --- /dev/null +++ b/add-strict-scp-check-for-CVE-2020-15778.patch @@ -0,0 +1,159 @@ +From 2e0b74242220a97926d006719d1ac6e113918e2b Mon Sep 17 00:00:00 2001 +From: seuzw <930zhaowei@163.com> +Date: Thu, 20 May 2021 20:23:30 +0800 +Subject: [PATCH] add strict-scp-check for CVE-2020-15778 + +--- + servconf.c | 12 ++++++++++++ + servconf.h | 1 + + session.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 63 insertions(+) + +diff --git a/servconf.c b/servconf.c +index 76147f9..4e0401f 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -90,6 +90,7 @@ initialize_server_options(ServerOptions *options) + { + memset(options, 0, sizeof(*options)); + ++ options->strict_scp_check = -1; + /* Portable-specific options */ + options->use_pam = -1; + +@@ -330,6 +331,8 @@ fill_default_server_options(ServerOptions *options) + _PATH_HOST_XMSS_KEY_FILE, 0); + #endif /* WITH_XMSS */ + } ++ if (options->strict_scp_check == -1) ++ options->strict_scp_check = 0; + /* No certificates by default */ + if (options->num_ports == 0) + options->ports[options->num_ports++] = SSH_DEFAULT_PORT; +@@ -540,6 +543,7 @@ fill_default_server_options(ServerOptions *options) + /* Keyword tokens. */ + typedef enum { + sBadOption, /* == unknown option */ ++ sStrictScpCheck, + /* Portable-specific options */ + sUsePAM, + /* Standard Options */ +@@ -598,6 +602,7 @@ static struct { + #else + { "usepam", sUnsupported, SSHCFG_GLOBAL }, + #endif ++ { "strictscpcheck", sStrictScpCheck, SSHCFG_GLOBAL }, + { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, + /* Standard Options */ + { "port", sPort, SSHCFG_GLOBAL }, +@@ -1372,6 +1377,11 @@ process_server_config_line_depth(ServerOptions *options, char *line, + /* Standard Options */ + case sBadOption: + return -1; ++ ++ case sStrictScpCheck: ++ intptr = &options->strict_scp_check; ++ goto parse_flag; ++ + case sPort: + /* ignore ports from configfile if cmdline specifies ports */ + if (options->ports_from_cmdline) +@@ -2556,6 +2566,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) + dst->n = src->n; \ + } while (0) + ++ M_CP_INTOPT(strict_scp_check); + M_CP_INTOPT(password_authentication); + M_CP_INTOPT(gss_authentication); + M_CP_INTOPT(pubkey_authentication); +@@ -2846,6 +2857,7 @@ dump_config(ServerOptions *o) + #ifdef USE_PAM + dump_cfg_fmtint(sUsePAM, o->use_pam); + #endif ++ dump_cfg_fmtint(sStrictScpCheck, o->strict_scp_check); + dump_cfg_int(sLoginGraceTime, o->login_grace_time); + dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); + dump_cfg_int(sX11MaxDisplays, o->x11_max_displays); +diff --git a/servconf.h b/servconf.h +index 2c16b5a..e37dc25 100644 +--- a/servconf.h ++++ b/servconf.h +@@ -192,6 +192,7 @@ typedef struct { + * disconnect the session + */ + ++ int strict_scp_check; + u_int num_authkeys_files; /* Files containing public keys */ + char **authorized_keys_files; + +diff --git a/session.c b/session.c +index 607f17a..383c8ee 100644 +--- a/session.c ++++ b/session.c +@@ -175,6 +175,50 @@ static char *auth_sock_dir = NULL; + + /* removes the agent forwarding socket */ + ++int scp_check(const char *command) ++{ ++ debug("Entering scp check"); ++ int check = 0; ++ if (command == NULL) { ++ debug("scp check succeeded for shell mode"); ++ return check; ++ } ++ int lc = strlen(command); ++ char special_characters[] = "|;&$><`\\!\n"; ++ int ls = strlen(special_characters); ++ int count_char[128] = {0}; ++ ++ for (int i = 0; i < ls; i++) { ++ count_char[special_characters[i]] = 1; ++ } ++ ++ char scp_prefix[6] = "scp -"; ++ int lp = 5; ++ ++ if (lc <= lp) { ++ debug("scp check succeeded for length"); ++ return check; ++ } ++ ++ for (int i = 0; i < lp; i++) { ++ if (command[i] - scp_prefix[i]) { ++ debug("scp check succeeded for prefix"); ++ return check; ++ } ++ } ++ ++ for (int i = lp; i < lc; i++) { ++ if (command[i] > 0 && command[i] < 128) { ++ if (count_char[command[i]]) { ++ check = 1; ++ debug("scp check failed at %d: %c", i, command[i]); ++ break; ++ } ++ } ++ } ++ return check; ++} ++ + static void + auth_sock_cleanup_proc(struct passwd *pw) + { +@@ -696,6 +740,12 @@ do_exec(struct ssh *ssh, Session *s, const char *command) + command = auth_opts->force_command; + forced = "(key-option)"; + } ++ ++ if (options.strict_scp_check && scp_check(command)) { ++ verbose("Special characters not allowed in scp"); ++ return 1; ++ } ++ + #ifdef GSSAPI + #ifdef KRB5 /* k5users_allowed_cmds only available w/ GSSAPI+KRB5 */ + else if (k5users_allowed_cmds) { +-- +2.23.0 + diff --git a/openssh.spec b/openssh.spec index f66e6de..8535b52 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 11 +%global openssh_release 12 Name: openssh Version: 8.2p1 @@ -90,6 +90,7 @@ Patch57: CVE-2020-12062-1.patch Patch58: CVE-2020-12062-2.patch Patch59: upstream-expose-vasnmprintf.patch Patch60: CVE-2020-14145.patch +Patch61: add-strict-scp-check-for-CVE-2020-15778.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -252,6 +253,7 @@ popd %patch58 -p1 %patch59 -p1 %patch60 -p1 +%patch61 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -463,6 +465,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Tue Aug 03 2021 weidong - 8.2P1-12 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:add strict-scp-check for check command injection + * Tue Jul 12 2021 panchenbo - 8.2P1-11 - fix pam_ssh_agent_auth.8.gz conflicts -- Gitee From c75589174a7cd28c94b45eeabef1b01445c2261b Mon Sep 17 00:00:00 2001 From: chxssg Date: Mon, 9 Aug 2021 14:37:47 +0800 Subject: [PATCH 07/22] move closefrom to before first malloc --- ...ove-closefrom-to-before-first-malloc.patch | 46 +++++++++++++++++++ openssh.spec | 14 ++++-- 2 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 backport-move-closefrom-to-before-first-malloc.patch diff --git a/backport-move-closefrom-to-before-first-malloc.patch b/backport-move-closefrom-to-before-first-malloc.patch new file mode 100644 index 0000000..b94c365 --- /dev/null +++ b/backport-move-closefrom-to-before-first-malloc.patch @@ -0,0 +1,46 @@ +From c9f7bba2e6f70b7ac1f5ea190d890cb5162ce127 Mon Sep 17 00:00:00 2001 +From: Darren Tucker +Date: Fri, 25 Jun 2021 15:08:18 +1000 +Subject: Move closefrom() to before first malloc. + +When built against tcmalloc, tcmalloc allocates a descriptor for its +internal use, so calling closefrom() afterward causes the descriptor +number to be reused resulting in a corrupted connection. Moving the +closefrom a little earlier should resolve this. From kircherlike at +outlook.com via bz#3321, ok djm@ +--- + ssh.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/ssh.c b/ssh.c +index cf8c018e..0343cba3 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -609,6 +609,12 @@ main(int ac, char **av) + /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ + sanitise_stdfd(); + ++ /* ++ * Discard other fds that are hanging around. These can cause problem ++ * with backgrounded ssh processes started by ControlPersist. ++ */ ++ closefrom(STDERR_FILENO + 1); ++ + __progname = ssh_get_progname(av[0]); + #if OPENSSL_VERSION_NUMBER < 0x10100000L + SSLeay_add_all_algorithms(); +@@ -638,12 +644,6 @@ main(int ac, char **av) + debug("FIPS mode initialized"); + } + +- /* +- * Discard other fds that are hanging around. These can cause problem +- * with backgrounded ssh processes started by ControlPersist. +- */ +- closefrom(STDERR_FILENO + 1); +- + /* Get user data. */ + pw = getpwuid(getuid()); + if (!pw) { +-- +cgit v1.2.3 diff --git a/openssh.spec b/openssh.spec index 8535b52..f0ecd1b 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 12 +%global openssh_release 13 Name: openssh Version: 8.2p1 @@ -89,8 +89,9 @@ Patch56: set-sshd-config.patch Patch57: CVE-2020-12062-1.patch Patch58: CVE-2020-12062-2.patch Patch59: upstream-expose-vasnmprintf.patch -Patch60: CVE-2020-14145.patch -Patch61: add-strict-scp-check-for-CVE-2020-15778.patch +Patch60: CVE-2020-14145.patch +Patch61: add-strict-scp-check-for-CVE-2020-15778.patch +Patch62: backport-move-closefrom-to-before-first-malloc.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -254,6 +255,7 @@ popd %patch59 -p1 %patch60 -p1 %patch61 -p1 +%patch62 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -465,6 +467,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Mon Aug 09 2021 chxssg - 8.2P1-13 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:move closefrom to before first malloc + * Tue Aug 03 2021 weidong - 8.2P1-12 - Type:bugfix - CVE:NA -- Gitee From cfaaaa1eeb7b1c2c3d69e0b756f3b4dd543a6903 Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Sat, 9 Oct 2021 09:52:09 +0800 Subject: [PATCH 08/22] fix CVE-2021-41617 --- backport-CVE-2021-41617-1.patch | 34 +++++++++++++++++++++++++++++++++ backport-CVE-2021-41617-2.patch | 28 +++++++++++++++++++++++++++ openssh.spec | 12 +++++++++++- 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2021-41617-1.patch create mode 100644 backport-CVE-2021-41617-2.patch diff --git a/backport-CVE-2021-41617-1.patch b/backport-CVE-2021-41617-1.patch new file mode 100644 index 0000000..31159d9 --- /dev/null +++ b/backport-CVE-2021-41617-1.patch @@ -0,0 +1,34 @@ +From f3cbe43e28fe71427d41cfe3a17125b972710455 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Sun, 26 Sep 2021 14:01:03 +0000 +Subject: upstream: need initgroups() before setresgid(); reported by anton@, + +ok deraadt@ + +OpenBSD-Commit-ID: 6aa003ee658b316960d94078f2a16edbc25087ce + +--- + auth.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/auth.c b/auth.c +index c73444a..e510a05 100644 +--- a/auth.c ++++ b/auth.c +@@ -852,6 +852,13 @@ subprocess(const char *tag, struct passwd *pw, const char *command, + } + closefrom(STDERR_FILENO + 1); + ++ if (geteuid() == 0 && ++ initgroups(pw->pw_name, pw->pw_gid) == -1) { ++ error("%s: initgroups(%s, %u): %s", tag, ++ pw->pw_name, (u_int)pw->pw_gid, strerror(errno)); ++ _exit(1); ++ } ++ + /* Don't use permanently_set_uid() here to avoid fatal() */ + if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) { + error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid, +-- +1.8.3.1 + diff --git a/backport-CVE-2021-41617-2.patch b/backport-CVE-2021-41617-2.patch new file mode 100644 index 0000000..93871b1 --- /dev/null +++ b/backport-CVE-2021-41617-2.patch @@ -0,0 +1,28 @@ +From f3cbe43e28fe71427d41cfe3a17125b972710455 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Sun, 26 Sep 2021 14:01:03 +0000 +Subject: upstream: need initgroups() before setresgid(); reported by anton@, + +ok deraadt@ + +OpenBSD-Commit-ID: 6aa003ee658b316960d94078f2a16edbc25087ce + +--- + auth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/auth.c b/auth.c +index e510a05..46b56cf 100644 +--- a/auth.c ++++ b/auth.c +@@ -39,6 +39,7 @@ + # include + #endif + #include ++#include + #ifdef HAVE_LOGIN_H + #include + #endif +-- +1.8.3.1 + diff --git a/openssh.spec b/openssh.spec index f0ecd1b..b16b081 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 13 +%global openssh_release 14 Name: openssh Version: 8.2p1 @@ -92,6 +92,8 @@ Patch59: upstream-expose-vasnmprintf.patch Patch60: CVE-2020-14145.patch 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 Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -256,6 +258,8 @@ popd %patch60 -p1 %patch61 -p1 %patch62 -p1 +%patch63 -p1 +%patch64 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -467,6 +471,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Sat Oct 09 2021 renmingshuai - 8.2P1-14 +- Type:bugfix +- CVE:CVE-2021-41617 +- SUG:NA +- DESC:fix CVE-2021-41617 + * Mon Aug 09 2021 chxssg - 8.2P1-13 - Type:bugfix - CVE:NA -- Gitee From f07a9b0a86010e0ae036d27c2f23886c44b63211 Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Wed, 15 Dec 2021 16:27:35 +0800 Subject: [PATCH 09/22] fix CVE-2021-28041 --- backport-CVE-2021-28041.patch | 16 ++++++++++++++++ openssh.spec | 10 +++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2021-28041.patch diff --git a/backport-CVE-2021-28041.patch b/backport-CVE-2021-28041.patch new file mode 100644 index 0000000..7ba8c70 --- /dev/null +++ b/backport-CVE-2021-28041.patch @@ -0,0 +1,16 @@ +Reference:https://src.fedoraproject.org/rpms/openssh/blob/f33/f/openssh-8.4p1-cve-2021-28041.patch +diff --git a/ssh-agent.c b/ssh-agent.c +index 6e536e5..3bac42d 100644 +--- a/ssh-agent.c ++++ b/ssh-agent.c +@@ -496,6 +496,7 @@ process_add_identity(SocketEntry *e) + goto err; + } + free(ext_name); ++ ext_name = NULL; + break; + default: + error("%s: Unknown constraint %d", __func__, ctype); +-- +1.8.3.1 + diff --git a/openssh.spec b/openssh.spec index b16b081..ef1cbdf 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-CVE-2021-28041.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 +* Wed Dec 15 2021 renmingshuai - 8.2P1-15 +- Type:cves +- CVE:CVE-2021-28041 +- SUG:NA +- DESC:fix CVE-2021-28041 + * Sat Oct 09 2021 renmingshuai - 8.2P1-14 - Type:bugfix - CVE:CVE-2021-41617 -- Gitee From d9a8350df0d01b2c3a06221a3eafa6afd59ffe2f Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Tue, 8 Feb 2022 14:37:49 +0800 Subject: [PATCH 10/22] change convtime form returning long to returning int --- ...form-returning-long-to-returning-int.patch | 71 +++++++++++++++++++ ...n-convtime-unit-test-to-int-to-match.patch | 25 +++++++ openssh.spec | 12 +++- 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 backport-change-convtime-form-returning-long-to-returning-int.patch create mode 100644 backport-change-types-in-convtime-unit-test-to-int-to-match.patch diff --git a/backport-change-convtime-form-returning-long-to-returning-int.patch b/backport-change-convtime-form-returning-long-to-returning-int.patch new file mode 100644 index 0000000..4dfa552 --- /dev/null +++ b/backport-change-convtime-form-returning-long-to-returning-int.patch @@ -0,0 +1,71 @@ +Reference:https://github.com/openssh/openssh-portable/commit/6d30673fedec +--- + misc.c | 8 ++++---- + misc.h | 2 +- + ssh-agent.c | 2 +- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/misc.c b/misc.c +index 45d93b6..aa36684 100644 +--- a/misc.c ++++ b/misc.c +@@ -490,7 +490,7 @@ a2tun(const char *s, int *remote) + * + * Return -1 if time string is invalid. + */ +-long ++int + convtime(const char *s) + { + long total, secs, multiplier = 1; +@@ -507,7 +507,7 @@ convtime(const char *s) + while (*p) { + secs = strtol(p, &endp, 10); + if (p == endp || +- (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || ++ (errno == ERANGE && (secs == INT_MIN || secs == INT_MAX)) || + secs < 0) + return -1; + +@@ -537,10 +537,10 @@ convtime(const char *s) + default: + return -1; + } +- if (secs >= LONG_MAX / multiplier) ++ if (secs >= INT_MAX / multiplier) + return -1; + secs *= multiplier; +- if (total >= LONG_MAX - secs) ++ if (total >= INT_MAX - secs) + return -1; + total += secs; + if (total < 0) +diff --git a/misc.h b/misc.h +index 4a05db2..2f82f77 100644 +--- a/misc.h ++++ b/misc.h +@@ -65,7 +65,7 @@ char *colon(char *); + int parse_user_host_path(const char *, char **, char **, char **); + int parse_user_host_port(const char *, char **, char **, int *); + int parse_uri(const char *, const char *, char **, char **, int *, char **); +-long convtime(const char *); ++int convtime(const char *); + char *tilde_expand_filename(const char *, uid_t); + char *percent_expand(const char *, ...) __attribute__((__sentinel__)); + char *tohex(const void *, size_t); +diff --git a/ssh-agent.c b/ssh-agent.c +index 3bac42d..4818e56 100644 +--- a/ssh-agent.c ++++ b/ssh-agent.c +@@ -163,7 +163,7 @@ u_char lock_salt[LOCK_SALT_SIZE]; + extern char *__progname; + + /* Default lifetime in seconds (0 == forever) */ +-static long lifetime = 0; ++static int lifetime = 0; + + static int fingerprint_hash = SSH_FP_HASH_DEFAULT; + +-- +1.8.3.1 + diff --git a/backport-change-types-in-convtime-unit-test-to-int-to-match.patch b/backport-change-types-in-convtime-unit-test-to-int-to-match.patch new file mode 100644 index 0000000..06a4adc --- /dev/null +++ b/backport-change-types-in-convtime-unit-test-to-int-to-match.patch @@ -0,0 +1,25 @@ +Reference:https://github.com/openssh/openssh-portable/commit/02da325f10b +--- + misc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/misc.c b/misc.c +index aa36684..ecd4ca0 100644 +--- a/misc.c ++++ b/misc.c +@@ -537,10 +537,10 @@ convtime(const char *s) + default: + return -1; + } +- if (secs >= INT_MAX / multiplier) ++ if (secs > INT_MAX / multiplier) + return -1; + secs *= multiplier; +- if (total >= INT_MAX - secs) ++ if (total > INT_MAX - secs) + return -1; + total += secs; + if (total < 0) +-- +1.8.3.1 + diff --git a/openssh.spec b/openssh.spec index ef1cbdf..639fbc5 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 15 +%global openssh_release 16 Name: openssh Version: 8.2p1 @@ -95,6 +95,8 @@ 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-CVE-2021-28041.patch +Patch66: backport-change-convtime-form-returning-long-to-returning-int.patch +Patch67: backport-change-types-in-convtime-unit-test-to-int-to-match.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -262,6 +264,8 @@ popd %patch63 -p1 %patch64 -p1 %patch65 -p1 +%patch66 -p1 +%patch67 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -473,6 +477,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Tue Feb 8 2022 renmingshuai - 8.2P1-16 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:change convtime form returning long to returning int + * Wed Dec 15 2021 renmingshuai - 8.2P1-15 - Type:cves - CVE:CVE-2021-28041 -- Gitee From ffcc5237d44165584e05aee51c248074d47307c8 Mon Sep 17 00:00:00 2001 From: mylee Date: Tue, 10 May 2022 13:43:54 +0800 Subject: [PATCH 11/22] fix spec changelog date --- openssh.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssh.spec b/openssh.spec index 639fbc5..3edba71 100644 --- a/openssh.spec +++ b/openssh.spec @@ -507,7 +507,7 @@ getent passwd sshd >/dev/null || \ - SUG:NA - DESC:add strict-scp-check for check command injection -* Tue Jul 12 2021 panchenbo - 8.2P1-11 +* Mon Jul 12 2021 panchenbo - 8.2P1-11 - fix pam_ssh_agent_auth.8.gz conflicts * Tue Jan 12 2021 yuboyun - 8.2P1-10 -- Gitee From e76c6bad3d81b29e8785950301d6bf863298d97a Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Thu, 1 Sep 2022 18:22:10 +0800 Subject: [PATCH 12/22] add SMx support in openssh --- feature-add-SMx-support.patch | 1565 +++++++++++++++++++++++++++++++++ openssh.spec | 10 +- 2 files changed, 1574 insertions(+), 1 deletion(-) create mode 100644 feature-add-SMx-support.patch diff --git a/feature-add-SMx-support.patch b/feature-add-SMx-support.patch new file mode 100644 index 0000000..1bbb2ab --- /dev/null +++ b/feature-add-SMx-support.patch @@ -0,0 +1,1565 @@ +From 93b312c0263cbf40f66448ff7ddbea7a2def1953 Mon Sep 17 00:00:00 2001 +From: kircher +Date: Fri, 29 Jul 2022 10:45:08 +0800 +Subject: [PATCH] add SMx support in openssh +HostKeyAlgorithms sm2 +KexAlgorithms sm2-sm3 +MACs hmac-sm3 +Ciphers sm4-ctr +PubkeyAcceptedKeyTypes sm2 +FingerprintHash sm3 + +--- + Makefile.in | 4 +- + authfd.c | 2 + + authfile.c | 1 + + cipher.c | 1 + + digest-openssl.c | 1 + + digest.h | 3 +- + kex.c | 1 + + kex.h | 3 + + kexecdh.c | 23 +- + kexgen.c | 3 + + kexsm2.c | 406 ++++++++++++++++++++++++++++++++++ + mac.c | 1 + + pathnames.h | 1 + + regress/agent.sh | 9 + + regress/keytype.sh | 2 + + regress/misc/fuzz-harness/sig_fuzz.cc | 4 + + regress/unittests/kex/test_kex.c | 3 + + ssh-ecdsa.c | 6 +- + ssh-keygen.c | 12 +- + ssh-keyscan.c | 12 +- + ssh-sm2.c | 230 +++++++++++++++++++ + ssh_api.c | 2 + + sshconnect2.c | 1 + + sshd.c | 7 + + sshkey.c | 63 +++++- + sshkey.h | 9 + + 26 files changed, 794 insertions(+), 16 deletions(-) + create mode 100644 kexsm2.c + create mode 100644 ssh-sm2.c + +diff --git a/Makefile.in b/Makefile.in +index bc8f77f..72b7a97 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -107,14 +107,14 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + log.o match.o moduli.o nchan.o packet.o \ + readpass.o ttymodes.o xmalloc.o addrmatch.o \ + atomicio.o dispatch.o mac.o misc.o utf8.o \ +- monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \ ++ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-sm2.o ssh-ecdsa-sk.o \ + ssh-ed25519-sk.o ssh-rsa.o dh.o \ + msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ + ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \ + poly1305.o chacha.o cipher-chachapoly.o \ + ssh-ed25519.o digest-openssl.o digest-libc.o \ + hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ +- kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ ++ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o kexsm2.o \ + kexgexc.o kexgexs.o \ + sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \ + kexgssc.o \ +diff --git a/authfd.c b/authfd.c +index 05fd454..6939b01 100644 +--- a/authfd.c ++++ b/authfd.c +@@ -493,6 +493,8 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, + case KEY_DSA_CERT: + case KEY_ECDSA: + case KEY_ECDSA_CERT: ++ case KEY_SM2: ++ case KEY_SM2_CERT: + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: + #endif +diff --git a/authfile.c b/authfile.c +index 8af07d3..0155009 100644 +--- a/authfile.c ++++ b/authfile.c +@@ -346,6 +346,7 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase, + case KEY_RSA: + case KEY_DSA: + case KEY_ECDSA: ++ case KEY_SM2: + #endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_XMSS: +diff --git a/cipher.c b/cipher.c +index f18bdc5..71d46f4 100644 +--- a/cipher.c ++++ b/cipher.c +@@ -90,6 +90,7 @@ static const struct sshcipher ciphers[] = { + #endif + { "chacha20-poly1305@openssh.com", + 8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL }, ++ { "sm4-ctr", 16, 16, 0, 0, 0, EVP_sm4_ctr }, + { "none", 8, 0, 0, 0, CFLAG_NONE, NULL }, + + { NULL, 0, 0, 0, 0, 0, NULL } +diff --git a/digest-openssl.c b/digest-openssl.c +index 993d3f6..5250d18 100644 +--- a/digest-openssl.c ++++ b/digest-openssl.c +@@ -61,6 +61,7 @@ const struct ssh_digest digests[] = { + { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, + { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, + { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, ++ { SSH_DIGEST_SM3, "SM3", 32, EVP_sm3 }, + { -1, NULL, 0, NULL }, + }; + +diff --git a/digest.h b/digest.h +index c7ceeb3..520722c 100644 +--- a/digest.h ++++ b/digest.h +@@ -27,7 +27,8 @@ + #define SSH_DIGEST_SHA256 2 + #define SSH_DIGEST_SHA384 3 + #define SSH_DIGEST_SHA512 4 +-#define SSH_DIGEST_MAX 5 ++#define SSH_DIGEST_SM3 5 ++#define SSH_DIGEST_MAX 6 + + struct sshbuf; + struct ssh_digest_ctx; +diff --git a/kex.c b/kex.c +index 5029433..b1ab7de 100644 +--- a/kex.c ++++ b/kex.c +@@ -122,6 +122,7 @@ static const struct kexalg kexalgs[] = { + { KEX_SNTRUP4591761X25519_SHA512, KEX_KEM_SNTRUP4591761X25519_SHA512, 0, + SSH_DIGEST_SHA512 }, + #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ ++ { "sm2-sm3", KEX_SM2_SM3, NID_sm2, SSH_DIGEST_SM3 }, + { NULL, 0, -1, -1}, + }; + static const struct kexalg gss_kexalgs[] = { +diff --git a/kex.h b/kex.h +index 6ab0682..5b36e43 100644 +--- a/kex.h ++++ b/kex.h +@@ -102,6 +102,7 @@ enum kex_exchange { + KEX_ECDH_SHA2, + KEX_C25519_SHA256, + KEX_KEM_SNTRUP4591761X25519_SHA512, ++ KEX_SM2_SM3, + #ifdef GSSAPI + KEX_GSS_GRP1_SHA1, + KEX_GSS_GRP14_SHA1, +@@ -277,6 +278,8 @@ int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); + ++int SM2KAP_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *eckey, int server); ++ + #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) + void dump_digest(const char *, const u_char *, int); + #endif +diff --git a/kexecdh.c b/kexecdh.c +index efb2e55..69ec13b 100644 +--- a/kexecdh.c ++++ b/kexecdh.c +@@ -44,7 +44,7 @@ + + static int + kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key, +- const EC_GROUP *, struct sshbuf **); ++ const EC_GROUP *, struct sshbuf **, int server); + + int + kex_ecdh_keypair(struct kex *kex) +@@ -124,7 +124,7 @@ kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob, + (r = sshbuf_get_u32(server_blob, NULL)) != 0) + goto out; + if ((r = kex_ecdh_dec_key_group(kex, client_blob, server_key, group, +- shared_secretp)) != 0) ++ shared_secretp, 1)) != 0) + goto out; + *server_blobp = server_blob; + server_blob = NULL; +@@ -136,7 +136,7 @@ kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob, + + static int + kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob, +- EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp) ++ EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp, int server) + { + struct sshbuf *buf = NULL; + BIGNUM *shared_secret = NULL; +@@ -176,11 +176,20 @@ kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob, + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen || ++ if (kex->ec_nid == NID_sm2) { ++ if (SM2KAP_compute_key(kbuf, klen, dh_pub, key, server) != (int)klen || + BN_bin2bn(kbuf, klen, shared_secret) == NULL) { +- r = SSH_ERR_LIBCRYPTO_ERROR; +- goto out; ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ } else { ++ if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen || ++ BN_bin2bn(kbuf, klen, shared_secret) == NULL) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } + } ++ + #ifdef DEBUG_KEXECDH + dump_digest("shared secret", kbuf, klen); + #endif +@@ -203,7 +212,7 @@ kex_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob, + int r; + + r = kex_ecdh_dec_key_group(kex, server_blob, kex->ec_client_key, +- kex->ec_group, shared_secretp); ++ kex->ec_group, shared_secretp, 0); + EC_KEY_free(kex->ec_client_key); + kex->ec_client_key = NULL; + return r; +diff --git a/kexgen.c b/kexgen.c +index c0e8c2f..0b856fb 100644 +--- a/kexgen.c ++++ b/kexgen.c +@@ -111,6 +111,7 @@ kex_gen_client(struct ssh *ssh) + r = kex_dh_keypair(kex); + break; + case KEX_ECDH_SHA2: ++ case KEX_SM2_SM3: + r = kex_ecdh_keypair(kex); + break; + #endif +@@ -179,6 +180,7 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) + r = kex_dh_dec(kex, server_blob, &shared_secret); + break; + case KEX_ECDH_SHA2: ++ case KEX_SM2_SM3: + r = kex_ecdh_dec(kex, server_blob, &shared_secret); + break; + #endif +@@ -274,6 +276,7 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) + &shared_secret); + break; + case KEX_ECDH_SHA2: ++ case KEX_SM2_SM3: + r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey, + &shared_secret); + break; +diff --git a/kexsm2.c b/kexsm2.c +new file mode 100644 +index 0000000..f507557 +--- /dev/null ++++ b/kexsm2.c +@@ -0,0 +1,406 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++int sm2_compute_z_digest(uint8_t *out, ++ const EVP_MD *digest, ++ const uint8_t *id, ++ const size_t id_len, ++ const EC_KEY *key) ++{ ++ int rc = 0; ++ const EC_GROUP *group = EC_KEY_get0_group(key); ++ BN_CTX *ctx = NULL; ++ EVP_MD_CTX *hash = NULL; ++ BIGNUM *p = NULL; ++ BIGNUM *a = NULL; ++ BIGNUM *b = NULL; ++ BIGNUM *xG = NULL; ++ BIGNUM *yG = NULL; ++ BIGNUM *xA = NULL; ++ BIGNUM *yA = NULL; ++ int p_bytes = 0; ++ uint8_t *buf = NULL; ++ uint16_t entl = 0; ++ uint8_t e_byte = 0; ++ ++ hash = EVP_MD_CTX_new(); ++ ctx = BN_CTX_new(); ++ if (hash == NULL || ctx == NULL) { ++ goto done; ++ } ++ ++ p = BN_CTX_get(ctx); ++ a = BN_CTX_get(ctx); ++ b = BN_CTX_get(ctx); ++ xG = BN_CTX_get(ctx); ++ yG = BN_CTX_get(ctx); ++ xA = BN_CTX_get(ctx); ++ yA = BN_CTX_get(ctx); ++ ++ if (yA == NULL) { ++ goto done; ++ } ++ ++ if (!EVP_DigestInit(hash, digest)) { ++ goto done; ++ } ++ ++ /* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */ ++ ++ if (id_len >= (UINT16_MAX / 8)) { ++ /* too large */ ++ goto done; ++ } ++ ++ entl = (uint16_t)(8 * id_len); ++ ++ e_byte = entl >> 8; ++ if (!EVP_DigestUpdate(hash, &e_byte, 1)) { ++ goto done; ++ } ++ e_byte = entl & 0xFF; ++ if (!EVP_DigestUpdate(hash, &e_byte, 1)) { ++ goto done; ++ } ++ ++ if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) { ++ goto done; ++ } ++ ++ if (!EC_GROUP_get_curve(group, p, a, b, ctx)) { ++ goto done; ++ } ++ ++ p_bytes = BN_num_bytes(p); ++ buf = OPENSSL_zalloc(p_bytes); ++ if (buf == NULL) { ++ goto done; ++ } ++ ++ if (BN_bn2binpad(a, buf, p_bytes) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || BN_bn2binpad(b, buf, p_bytes) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || !EC_POINT_get_affine_coordinates(group, ++ EC_GROUP_get0_generator(group), ++ xG, yG, ctx) ++ || BN_bn2binpad(xG, buf, p_bytes) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || BN_bn2binpad(yG, buf, p_bytes) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || !EC_POINT_get_affine_coordinates(group, ++ EC_KEY_get0_public_key(key), ++ xA, yA, ctx) ++ || BN_bn2binpad(xA, buf, p_bytes) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || BN_bn2binpad(yA, buf, p_bytes) < 0 ++ || !EVP_DigestUpdate(hash, buf, p_bytes) ++ || !EVP_DigestFinal(hash, out, NULL)) { ++ goto done; ++ } ++ ++ rc = 1; ++ ++ done: ++ OPENSSL_free(buf); ++ BN_CTX_free(ctx); ++ EVP_MD_CTX_free(hash); ++ return rc; ++} ++ ++ ++/* GM/T003_2012 Defined Key Derive Function */ ++int kdf_gmt003_2012(unsigned char *out, size_t outlen, const unsigned char *Z, size_t Zlen, const unsigned char *SharedInfo, size_t SharedInfolen, const EVP_MD *md) ++{ ++ EVP_MD_CTX *mctx = NULL; ++ unsigned int counter; ++ unsigned char ctr[4]; ++ size_t mdlen; ++ int retval = 0; ++ unsigned char dgst[EVP_MAX_MD_SIZE]; ++ ++ if (!out || !outlen) return retval; ++ if (md == NULL) { ++ md = EVP_sm3(); ++ } ++ mdlen = EVP_MD_size(md); ++ mctx = EVP_MD_CTX_new(); ++ if (mctx == NULL) { ++ goto err; ++ } ++ ++ for (counter = 1;; counter++) { ++ if (!EVP_DigestInit(mctx, md)) { ++ goto err; ++ } ++ ctr[0] = (unsigned char)((counter >> 24) & 0xFF); ++ ctr[1] = (unsigned char)((counter >> 16) & 0xFF); ++ ctr[2] = (unsigned char)((counter >> 8) & 0xFF); ++ ctr[3] = (unsigned char)(counter & 0xFF); ++ ++ if (!EVP_DigestUpdate(mctx, Z, Zlen)) { ++ goto err; ++ } ++ if (!EVP_DigestUpdate(mctx, ctr, sizeof(ctr))) { ++ goto err; ++ } ++ if (!EVP_DigestUpdate(mctx, SharedInfo, SharedInfolen)) { ++ goto err; ++ } ++ if (!EVP_DigestFinal(mctx, dgst, NULL)) { ++ goto err; ++ } ++ ++ if (outlen > mdlen) { ++ memcpy(out, dgst, mdlen); ++ out += mdlen; ++ outlen -= mdlen; ++ } else { ++ memcpy(out, dgst, outlen); ++ memset(dgst, 0, mdlen); ++ break; ++ } ++ } ++ ++ retval = 1; ++ ++err: ++ EVP_MD_CTX_free(mctx); ++ return retval; ++} ++ ++int sm2_kap_compute_key(void *out, size_t outlen, int server,\ ++ const uint8_t *peer_uid, int peer_uid_len, const uint8_t *self_uid, int self_uid_len, \ ++ const EC_KEY *peer_ecdhe_key, const EC_KEY *self_ecdhe_key, const EC_KEY *peer_pub_key, const EC_KEY *self_eckey, \ ++ const EVP_MD *md) ++{ ++ BN_CTX *ctx = NULL; ++ EC_POINT *UorV = NULL; ++ const EC_POINT *Rs, *Rp; ++ BIGNUM *Xs = NULL, *Xp = NULL, *h = NULL, *t = NULL, *two_power_w = NULL, *order = NULL; ++ const BIGNUM *priv_key, *r; ++ const EC_GROUP *group; ++ int w; ++ int ret = -1; ++ size_t buflen, len; ++ unsigned char *buf = NULL; ++ ++ if (outlen > INT_MAX) { ++ goto err; ++ } ++ ++ if (!peer_pub_key || !self_eckey) { ++ goto err; ++ } ++ ++ priv_key = EC_KEY_get0_private_key(self_eckey); ++ if (!priv_key) { ++ goto err; ++ } ++ ++ if (!peer_ecdhe_key || !self_ecdhe_key) { ++ goto err; ++ } ++ ++ Rs = EC_KEY_get0_public_key(self_ecdhe_key); ++ Rp = EC_KEY_get0_public_key(peer_ecdhe_key); ++ r = EC_KEY_get0_private_key(self_ecdhe_key); ++ ++ if (!Rs || !Rp || !r) { ++ goto err; ++ } ++ ++ ctx = BN_CTX_new(); ++ Xs = BN_new(); ++ Xp = BN_new(); ++ h = BN_new(); ++ t = BN_new(); ++ two_power_w = BN_new(); ++ order = BN_new(); ++ if (!Xs || !Xp || !h || !t || !two_power_w || !order) { ++ goto err; ++ } ++ ++ group = EC_KEY_get0_group(self_eckey); ++ ++ /*Second: Caculate -- w*/ ++ if (!EC_GROUP_get_order(group, order, ctx) || !EC_GROUP_get_cofactor(group, h, ctx)) { ++ goto err; ++ } ++ ++ w = (BN_num_bits(order) + 1) / 2 - 1; ++ if (!BN_lshift(two_power_w, BN_value_one(), w)) { ++ goto err; ++ } ++ ++ /*Third: Caculate -- X = 2 ^ w + (x & (2 ^ w - 1)) = 2 ^ w + (x mod 2 ^ w)*/ ++ UorV = EC_POINT_new(group); ++ ++ if (!UorV) { ++ goto err; ++ } ++ ++ /*Test peer public key On curve*/ ++ if (!EC_POINT_is_on_curve(group, Rp, ctx)) { ++ goto err; ++ } ++ ++ /*Get x*/ ++ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { ++ if (!EC_POINT_get_affine_coordinates_GFp(group, Rs, Xs, NULL, ctx)) { ++ goto err; ++ } ++ ++ if (!EC_POINT_get_affine_coordinates_GFp(group, Rp, Xp, NULL, ctx)) { ++ goto err; ++ } ++ } ++ ++ /*x mod 2 ^ w*/ ++ /*Caculate Self x*/ ++ if (!BN_nnmod(Xs, Xs, two_power_w, ctx)) { ++ goto err; ++ } ++ ++ if (!BN_add(Xs, Xs, two_power_w)) { ++ goto err; ++ } ++ ++ /*Caculate Peer x*/ ++ if (!BN_nnmod(Xp, Xp, two_power_w, ctx)) { ++ goto err; ++ } ++ ++ if (!BN_add(Xp, Xp, two_power_w)) { ++ goto err; ++ } ++ ++ /*Forth: Caculate t*/ ++ if (!BN_mod_mul(t, Xs, r, order, ctx)) { ++ goto err; ++ } ++ ++ if (!BN_mod_add(t, t, priv_key, order, ctx)) { ++ goto err; ++ } ++ ++ /*Fifth: Caculate V or U*/ ++ if (!BN_mul(t, t, h, ctx)) { ++ goto err; ++ } ++ ++ /* [x]R */ ++ if (!EC_POINT_mul(group, UorV, NULL, Rp, Xp, ctx)) { ++ goto err; ++ } ++ ++ /* P + [x]R */ ++ if (!EC_POINT_add(group, UorV, UorV, EC_KEY_get0_public_key(peer_pub_key), ctx)) { ++ goto err; ++ } ++ ++ if (!EC_POINT_mul(group, UorV, NULL, UorV, t, ctx)) { ++ goto err; ++ } ++ ++ /* Detect UorV is in */ ++ if (EC_POINT_is_at_infinity(group, UorV)) { ++ goto err; ++ } ++ ++ /*Sixth: Caculate Key -- Need Xuorv, Yuorv, Zc, Zs, klen*/ ++ { ++ /* ++ size_t buflen, len; ++ unsigned char *buf = NULL; ++ */ ++ size_t elemet_len, idx; ++ ++ elemet_len = (size_t)((EC_GROUP_get_degree(group) + 7) / 8); ++ buflen = elemet_len * 2 + 32 * 2 + 1; /*add 1 byte tag*/ ++ buf = (unsigned char *)OPENSSL_malloc(buflen + 10); ++ if (!buf) { ++ goto err; ++ } ++ memset(buf, 0, buflen + 10); ++ /*1 : Get public key for UorV, Notice: the first byte is a tag, not a valid char*/ ++ idx = EC_POINT_point2oct(group, UorV, 4, buf, buflen, ctx); ++ if (!idx) { ++ goto err; ++ } ++ ++ if (!server) { ++ /*SIDE A*/ ++ len = buflen - idx; ++ if (!sm2_compute_z_digest( (unsigned char *)(buf + idx), md, (const uint8_t *)self_uid, self_uid_len, self_eckey)) { ++ goto err; ++ } ++ len = 32; ++ idx += len; ++ } ++ ++ /*Caculate Peer Z*/ ++ len = buflen - idx; ++ if (!sm2_compute_z_digest( (unsigned char *)(buf + idx), md, (const uint8_t *)peer_uid, peer_uid_len, peer_pub_key)) { ++ goto err; ++ } ++ len = 32; ++ idx += len; ++ ++ if (server) { ++ /*SIDE B*/ ++ len = buflen - idx; ++ if (!sm2_compute_z_digest( (unsigned char *)(buf + idx), md, (const uint8_t *)self_uid, self_uid_len, self_eckey)) { ++ goto err; ++ } ++ len = 32; ++ idx += len; ++ } ++ ++ len = outlen; ++ if (!kdf_gmt003_2012(out, len, (const unsigned char *)(buf + 1), idx - 1, NULL, 0, md)) { ++ goto err; ++ } ++ } ++ ++ ret = outlen; ++ ++err: ++ if (Xs) BN_free(Xs); ++ if (Xp) BN_free(Xp); ++ if (h) BN_free(h); ++ if (t) BN_free(t); ++ if (two_power_w) BN_free(two_power_w); ++ if (order) BN_free(order); ++ if (UorV) EC_POINT_free(UorV); ++ if (buf) OPENSSL_free(buf); ++ if (ctx) BN_CTX_free(ctx); ++ ++ return ret; ++} ++ ++int SM2KAP_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *eckey, int server) ++{ ++ int ret = 0; ++ EC_KEY *pubkey = NULL; ++ unsigned char id[16] = {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; ++ ++ if ((pubkey = EC_KEY_new_by_curve_name(NID_sm2)) == NULL) { ++ return ret; ++ } ++ ++ if (EC_KEY_set_public_key(pubkey, pub_key) != 1) { ++ ret = 0; ++ goto out; ++ } ++ ++ ret = sm2_kap_compute_key(out, outlen, server, id, sizeof(id), id, sizeof(id), pubkey, eckey, pubkey, eckey, (EVP_MD*)EVP_sm3()); ++ ++out: ++ EC_KEY_free(pubkey); ++ return ret; ++} +diff --git a/mac.c b/mac.c +index bf051ba..2de17a0 100644 +--- a/mac.c ++++ b/mac.c +@@ -65,6 +65,7 @@ static const struct macalg macs[] = { + { "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 }, + { "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 }, + { "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 }, ++ { "hmac-sm3", SSH_DIGEST, SSH_DIGEST_SM3, 0, 0, 0, 0 }, + + /* Encrypt-then-MAC variants */ + { "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 }, +diff --git a/pathnames.h b/pathnames.h +index f7ca5a7..74b7e82 100644 +--- a/pathnames.h ++++ b/pathnames.h +@@ -79,6 +79,7 @@ + #define _PATH_SSH_CLIENT_ID_XMSS _PATH_SSH_USER_DIR "/id_xmss" + #define _PATH_SSH_CLIENT_ID_ECDSA_SK _PATH_SSH_USER_DIR "/id_ecdsa_sk" + #define _PATH_SSH_CLIENT_ID_ED25519_SK _PATH_SSH_USER_DIR "/id_ed25519_sk" ++#define _PATH_SSH_CLIENT_ID_SM2 _PATH_SSH_USER_DIR "/id_sm2" + + /* + * Configuration file in user's home directory. This file need not be +diff --git a/regress/agent.sh b/regress/agent.sh +index 3940365..9ae8f64 100644 +--- a/regress/agent.sh ++++ b/regress/agent.sh +@@ -84,9 +84,18 @@ fi + for t in ${SSH_KEYTYPES}; do + trace "connect via agent using $t key" + if [ "$t" = "ssh-dss" ]; then ++ sed -i "/PubkeyAcceptedKeyTypes/d" $OBJ/ssh_proxy ++ sed -i "/PubkeyAcceptedKeyTypes/d" $OBJ/sshd_proxy + echo "PubkeyAcceptedKeyTypes +ssh-dss" >> $OBJ/ssh_proxy + echo "PubkeyAcceptedKeyTypes +ssh-dss" >> $OBJ/sshd_proxy + fi ++ if [ "$t" = "sm2" ]; then ++ sed -i "/PubkeyAcceptedKeyTypes/d" $OBJ/ssh_proxy ++ sed -i "/PubkeyAcceptedKeyTypes/d" $OBJ/sshd_proxy ++ echo "PubkeyAcceptedKeyTypes +sm2,sm2-cert" >> $OBJ/ssh_proxy ++ echo "PubkeyAcceptedKeyTypes +sm2,sm2-cert" >> $OBJ/sshd_proxy ++ fi ++ + ${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub -oIdentitiesOnly=yes \ + somehost exit 52 + r=$? +diff --git a/regress/keytype.sh b/regress/keytype.sh +index 20a8cea..fb34941 100644 +--- a/regress/keytype.sh ++++ b/regress/keytype.sh +@@ -18,6 +18,7 @@ for i in ${SSH_KEYTYPES}; do + ecdsa-sha2-nistp521) ktypes="$ktypes ecdsa-521" ;; + sk-ssh-ed25519*) ktypes="$ktypes ed25519-sk" ;; + sk-ecdsa-sha2-nistp256*) ktypes="$ktypes ecdsa-sk" ;; ++ sm2) ktypes="$ktypes sm2-256" ;; + esac + done + +@@ -44,6 +45,7 @@ kname_to_ktype() { + rsa-*) echo rsa-sha2-512,rsa-sha2-256,ssh-rsa;; + ed25519-sk) echo sk-ssh-ed25519@openssh.com;; + ecdsa-sk) echo sk-ecdsa-sha2-nistp256@openssh.com;; ++ sm2-256) echo sm2;; + esac + } + +diff --git a/regress/misc/fuzz-harness/sig_fuzz.cc b/regress/misc/fuzz-harness/sig_fuzz.cc +index b32502b..8faad6e 100644 +--- a/regress/misc/fuzz-harness/sig_fuzz.cc ++++ b/regress/misc/fuzz-harness/sig_fuzz.cc +@@ -33,6 +33,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* sig, size_t slen) + #endif + struct sshkey_sig_details *details = NULL; + static struct sshkey *ed25519 = generate_or_die(KEY_ED25519, 0); ++ static struct sshkey *sm2 = generate_or_die(KEY_SM2, 256); + static const char *data = "If everyone started announcing his nose had " + "run away, I don’t know how it would all end"; + static const size_t dlen = strlen(data); +@@ -56,6 +57,9 @@ int LLVMFuzzerTestOneInput(const uint8_t* sig, size_t slen) + #endif + sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); + sshkey_sig_details_free(details); ++ details = NULL; ++ sshkey_verify(sm2, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); ++ sshkey_sig_details_free(details); + return 0; + } + +diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c +index 0e7cd9e..f19cda8 100644 +--- a/regress/unittests/kex/test_kex.c ++++ b/regress/unittests/kex/test_kex.c +@@ -152,6 +152,7 @@ do_kex_with_key(char *kex, int keytype, int bits) + #endif /* OPENSSL_HAS_ECC */ + #endif /* WITH_OPENSSL */ + server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server; ++ server2->kex->kex[KEX_SM2_SM3] = kex_gen_server; + server2->kex->load_host_public_key = server->kex->load_host_public_key; + server2->kex->load_host_private_key = server->kex->load_host_private_key; + server2->kex->sign = server->kex->sign; +@@ -185,6 +186,7 @@ do_kex(char *kex) + #endif /* OPENSSL_HAS_ECC */ + #endif /* WITH_OPENSSL */ + do_kex_with_key(kex, KEY_ED25519, 256); ++ do_kex_with_key(kex, KEY_SM2, 256); + } + + void +@@ -201,5 +203,6 @@ kex_tests(void) + do_kex("diffie-hellman-group-exchange-sha1"); + do_kex("diffie-hellman-group14-sha1"); + do_kex("diffie-hellman-group1-sha1"); ++ do_kex("sm2-sm3"); + #endif /* WITH_OPENSSL */ + } +diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c +index b036796..6697be6 100644 +--- a/ssh-ecdsa.c ++++ b/ssh-ecdsa.c +@@ -66,7 +66,8 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + *sigp = NULL; + + if (key == NULL || key->ecdsa == NULL || +- sshkey_type_plain(key->type) != KEY_ECDSA) ++ (sshkey_type_plain(key->type) != KEY_ECDSA && ++ sshkey_type_plain(key->type) != KEY_SM2)) + return SSH_ERR_INVALID_ARGUMENT; + + if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) +@@ -133,7 +134,8 @@ ssh_ecdsa_verify(const struct sshkey *key, + unsigned char *sigb = NULL, *psig = NULL; + + if (key == NULL || key->ecdsa == NULL || +- sshkey_type_plain(key->type) != KEY_ECDSA || ++ (sshkey_type_plain(key->type) != KEY_ECDSA && ++ sshkey_type_plain(key->type) != KEY_SM2) || + signature == NULL || signaturelen == 0) + return SSH_ERR_INVALID_ARGUMENT; + +diff --git a/ssh-keygen.c b/ssh-keygen.c +index 2056ff9..d2b4781 100644 +--- a/ssh-keygen.c ++++ b/ssh-keygen.c +@@ -191,6 +191,7 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) + *bitsp = DEFAULT_BITS_DSA; + break; + case KEY_ECDSA: ++ case KEY_SM2: + if (name != NULL && + (nid = sshkey_ecdsa_nid_from_name(name)) > 0) + *bitsp = sshkey_curve_nid_to_bits(nid); +@@ -223,6 +224,10 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) + fatal("Invalid RSA key length: maximum is %d bits", + OPENSSL_RSA_MAX_MODULUS_BITS); + break; ++ case KEY_SM2: ++ if (*bitsp != 256) ++ fatal("Invalid SM2 key length: must be 256 bits"); ++ break; + case KEY_ECDSA: + if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1) + fatal("Invalid ECDSA key length: valid lengths are " +@@ -278,6 +283,9 @@ ask_filename(struct passwd *pw, const char *prompt) + case KEY_ECDSA: + name = _PATH_SSH_CLIENT_ID_ECDSA; + break; ++ case KEY_SM2: ++ name = _PATH_SSH_CLIENT_ID_SM2; ++ break; + case KEY_ECDSA_SK_CERT: + case KEY_ECDSA_SK: + name = _PATH_SSH_CLIENT_ID_ECDSA_SK; +@@ -390,6 +398,7 @@ do_convert_to_pkcs8(struct sshkey *k) + break; + #ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: ++ case KEY_SM2: + if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) + fatal("PEM_write_EC_PUBKEY failed"); + break; +@@ -414,6 +423,7 @@ do_convert_to_pem(struct sshkey *k) + break; + #ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: ++ case KEY_SM2: + if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) + fatal("PEM_write_EC_PUBKEY failed"); + break; +@@ -3070,7 +3080,7 @@ usage(void) + { + fprintf(stderr, + "usage: ssh-keygen [-q] [-b bits] [-C comment] [-f output_keyfile] [-m format]\n" +- " [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n" ++ " [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa | sm2]\n" + " [-N new_passphrase] [-O option] [-w provider]\n" + " ssh-keygen -p [-f keyfile] [-m format] [-N new_passphrase]\n" + " [-P old_passphrase]\n" +diff --git a/ssh-keyscan.c b/ssh-keyscan.c +index fa2d21b..4faafb7 100644 +--- a/ssh-keyscan.c ++++ b/ssh-keyscan.c +@@ -63,9 +63,10 @@ int ssh_port = SSH_DEFAULT_PORT; + #define KT_XMSS (1<<4) + #define KT_ECDSA_SK (1<<5) + #define KT_ED25519_SK (1<<6) ++#define KT_SM2 (1<<7) + + #define KT_MIN KT_DSA +-#define KT_MAX KT_ED25519_SK ++#define KT_MAX KT_SM2 + + int get_cert = 0; + int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519|KT_ECDSA_SK|KT_ED25519_SK; +@@ -261,6 +262,11 @@ keygrab_ssh2(con *c) + "ecdsa-sha2-nistp384," + "ecdsa-sha2-nistp521"; + break; ++ case KT_SM2: ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? ++ "sm2-cert" : ++ "sm2"; ++ break; + case KT_ECDSA_SK: + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? + "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" : +@@ -290,6 +296,7 @@ keygrab_ssh2(con *c) + c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; + # ifdef OPENSSL_HAS_ECC + c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; ++ c->c_ssh->kex->kex[KEX_SM2_SM3] = kex_gen_client; + # endif + #endif + c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; +@@ -738,6 +745,9 @@ main(int argc, char **argv) + case KEY_ECDSA: + get_keytypes |= KT_ECDSA; + break; ++ case KEY_SM2: ++ get_keytypes |= KT_SM2; ++ break; + case KEY_RSA: + get_keytypes |= KT_RSA; + break; +diff --git a/ssh-sm2.c b/ssh-sm2.c +new file mode 100644 +index 0000000..c242139 +--- /dev/null ++++ b/ssh-sm2.c +@@ -0,0 +1,230 @@ ++#include "includes.h" ++#include ++#include ++#include ++#include ++ ++#include ++#include "sshbuf.h" ++#include "ssherr.h" ++#include "digest.h" ++#include "sshkey.h" ++ ++#include "openbsd-compat/openssl-compat.h" ++ ++const unsigned char *sm2_id = (const unsigned char *)"1234567812345678"; ++ ++int ++ssh_sm2_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, ++ const u_char *data, size_t datalen, u_int compat) ++{ ++ u_char *sig = NULL; ++ size_t slen = 0; ++ int pkey_len = 0; ++ int r = 0; ++ int len = 0; ++ EVP_PKEY *key_sm2 = NULL; ++ struct sshbuf *b = NULL; ++ EVP_PKEY_CTX *pctx = NULL; ++ EVP_MD_CTX *mctx = NULL; ++ int ret = SSH_ERR_INTERNAL_ERROR; ++ ++ if (lenp != NULL) ++ *lenp = 0; ++ if (sigp != NULL) ++ *sigp = NULL; ++ ++ if (key == NULL || key->ecdsa == NULL || ++ sshkey_type_plain(key->type) != KEY_SM2) ++ return SSH_ERR_INVALID_ARGUMENT; ++ ++ if ((key_sm2 = EVP_PKEY_new()) == NULL) { ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ ++ if ((EVP_PKEY_set1_EC_KEY(key_sm2, key->ecdsa)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((pkey_len = EVP_PKEY_size(key_sm2)) == 0) { ++ ret = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } ++ ++ slen = pkey_len; ++ ++ if ((EVP_PKEY_set_alias_type(key_sm2, EVP_PKEY_SM2)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((sig = OPENSSL_malloc(pkey_len)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if ((pctx = EVP_PKEY_CTX_new(key_sm2, NULL)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if (EVP_PKEY_CTX_set1_id(pctx, sm2_id, 16) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((mctx = EVP_MD_CTX_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ EVP_MD_CTX_set_pkey_ctx(mctx, pctx); ++ ++ if ((EVP_DigestSignInit(mctx, NULL, EVP_sm3(), NULL, key_sm2)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((EVP_DigestSignUpdate(mctx, data, datalen)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((EVP_DigestSignFinal(mctx, sig, &slen)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((b = sshbuf_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if ((r = sshbuf_put_cstring(b, "sm2")) != 0 || ++ (r = sshbuf_put_string(b, sig, slen)) != 0) ++ goto out; ++ len = sshbuf_len(b); ++ if (sigp != NULL) { ++ if ((*sigp = malloc(len)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ memcpy(*sigp, sshbuf_ptr(b), len); ++ } ++ if (lenp != NULL) ++ *lenp = len; ++ ret = 0; ++ ++out: ++ EVP_PKEY_free(key_sm2); ++ if (sig != NULL) { ++ explicit_bzero(sig, slen); ++ OPENSSL_free(sig); ++ } ++ EVP_PKEY_CTX_free(pctx); ++ EVP_MD_CTX_free(mctx); ++ sshbuf_free(b); ++ return ret; ++} ++ ++int ++ssh_sm2_verify(const struct sshkey *key, ++ const u_char *signature, size_t signaturelen, ++ const u_char *data, size_t datalen, u_int compat) ++{ ++ const u_char *sig = NULL; ++ char *ktype = NULL; ++ size_t slen = 0; ++ int pkey_len = 0; ++ int r = 0; ++ int len = 0; ++ EVP_PKEY *key_sm2 = NULL; ++ struct sshbuf *b = NULL; ++ EVP_PKEY_CTX *pctx = NULL; ++ EVP_MD_CTX *mctx = NULL; ++ int ret = SSH_ERR_INTERNAL_ERROR; ++ ++ if (key == NULL || ++ sshkey_type_plain(key->type) != KEY_SM2 || ++ signature == NULL || signaturelen == 0) ++ return SSH_ERR_INVALID_ARGUMENT; ++ ++ if ((b = sshbuf_from(signature, signaturelen)) == NULL) ++ return SSH_ERR_ALLOC_FAIL; ++ ++ if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 || ++ (r = sshbuf_get_string_direct(b, &sig, &slen)) != 0) ++ goto out; ++ ++ if (strcmp("sm2", ktype) != 0) { ++ ret = SSH_ERR_KEY_TYPE_MISMATCH; ++ goto out; ++ } ++ ++ if (sshbuf_len(b) != 0) { ++ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; ++ goto out; ++ } ++ ++ if ((key_sm2 = EVP_PKEY_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if ((EVP_PKEY_set1_EC_KEY(key_sm2, key->ecdsa)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((pkey_len = EVP_PKEY_size(key_sm2)) == 0) { ++ ret = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } ++ ++ if ((EVP_PKEY_set_alias_type(key_sm2, EVP_PKEY_SM2)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((pctx = EVP_PKEY_CTX_new(key_sm2, NULL)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if (EVP_PKEY_CTX_set1_id(pctx, sm2_id, 16) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((mctx = EVP_MD_CTX_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ EVP_MD_CTX_set_pkey_ctx(mctx, pctx); ++ ++ if ((EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, key_sm2)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((EVP_DigestVerifyUpdate(mctx, data, datalen)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((EVP_DigestVerifyFinal(mctx, sig, slen)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ ret = 0; ++out: ++ EVP_PKEY_free(key_sm2); ++ EVP_PKEY_CTX_free(pctx); ++ EVP_MD_CTX_free(mctx); ++ sshbuf_free(b); ++ free(ktype); ++ return ret; ++} +diff --git a/ssh_api.c b/ssh_api.c +index e0b1955..c4a875e 100644 +--- a/ssh_api.c ++++ b/ssh_api.c +@@ -119,6 +119,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) + ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; + # ifdef OPENSSL_HAS_ECC + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_server; ++ ssh->kex->kex[KEX_SM2_SM3] = kex_gen_server; + # endif + #endif /* WITH_OPENSSL */ + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server; +@@ -137,6 +138,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) + ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; + # ifdef OPENSSL_HAS_ECC + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; ++ ssh->kex->kex[KEX_SM2_SM3] = kex_gen_client; + # endif + #endif /* WITH_OPENSSL */ + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; +diff --git a/sshconnect2.c b/sshconnect2.c +index b87cbf2..b1e251c 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -297,6 +297,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; + # ifdef OPENSSL_HAS_ECC + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; ++ ssh->kex->kex[KEX_SM2_SM3] = kex_gen_client; + # endif + # ifdef GSSAPI + if (options.gss_keyex) { +diff --git a/sshd.c b/sshd.c +index c291a5e..b0cc313 100644 +--- a/sshd.c ++++ b/sshd.c +@@ -715,6 +715,7 @@ list_hostkey_types(void) + /* FALLTHROUGH */ + case KEY_DSA: + case KEY_ECDSA: ++ case KEY_SM2: + case KEY_ED25519: + case KEY_ECDSA_SK: + case KEY_ED25519_SK: +@@ -736,6 +737,7 @@ list_hostkey_types(void) + /* FALLTHROUGH */ + case KEY_DSA_CERT: + case KEY_ECDSA_CERT: ++ case KEY_SM2_CERT: + case KEY_ED25519_CERT: + case KEY_ECDSA_SK_CERT: + case KEY_ED25519_SK_CERT: +@@ -762,6 +764,7 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) + case KEY_RSA_CERT: + case KEY_DSA_CERT: + case KEY_ECDSA_CERT: ++ case KEY_SM2_CERT: + case KEY_ED25519_CERT: + case KEY_ECDSA_SK_CERT: + case KEY_ED25519_SK_CERT: +@@ -778,8 +781,10 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) + continue; + switch (type) { + case KEY_ECDSA: ++ case KEY_SM2: + case KEY_ECDSA_SK: + case KEY_ECDSA_CERT: ++ case KEY_SM2_CERT: + case KEY_ECDSA_SK_CERT: + if (key->ecdsa_nid != nid) + continue; +@@ -1949,6 +1954,7 @@ main(int ac, char **av) + case KEY_RSA: + case KEY_DSA: + case KEY_ECDSA: ++ case KEY_SM2: + case KEY_ED25519: + case KEY_ECDSA_SK: + case KEY_ED25519_SK: +@@ -2538,6 +2544,7 @@ do_ssh2_kex(struct ssh *ssh) + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; + # ifdef OPENSSL_HAS_ECC + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; ++ kex->kex[KEX_SM2_SM3] = kex_gen_server; + # endif + # ifdef GSSAPI + if (options.gss_keyex) { +diff --git a/sshkey.c b/sshkey.c +index 3a9e0f3..afb1e85 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -157,6 +157,8 @@ static const struct keytype keytypes[] = { + # endif /* OPENSSL_HAS_ECC */ + #endif /* WITH_OPENSSL */ + { "null", "null", NULL, KEY_NULL, 0, 0, 0 }, ++ { "sm2", "SM2", NULL, KEY_SM2, NID_sm2, 0, 0 }, ++ { "sm2-cert", "SM2-CERT", NULL, KEY_SM2_CERT, NID_sm2, 1, 0 }, + { NULL, NULL, NULL, -1, -1, 0, 0 } + }; + +@@ -231,6 +233,8 @@ key_type_is_ecdsa_variant(int type) + case KEY_ECDSA_CERT: + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: ++ case KEY_SM2: ++ case KEY_SM2_CERT: + return 1; + } + return 0; +@@ -340,6 +344,8 @@ sshkey_size(const struct sshkey *k) + case KEY_ECDSA_CERT: + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: ++ case KEY_SM2: ++ case KEY_SM2_CERT: + return sshkey_curve_nid_to_bits(k->ecdsa_nid); + #endif /* WITH_OPENSSL */ + case KEY_ED25519: +@@ -364,6 +370,8 @@ sshkey_type_is_valid_ca(int type) + case KEY_ED25519: + case KEY_ED25519_SK: + case KEY_XMSS: ++ case KEY_SM2: ++ case KEY_SM2_CERT: + return 1; + default: + return 0; +@@ -443,6 +451,8 @@ sshkey_type_plain(int type) + return KEY_ED25519_SK; + case KEY_XMSS_CERT: + return KEY_XMSS; ++ case KEY_SM2_CERT: ++ return KEY_SM2; + default: + return type; + } +@@ -538,6 +548,8 @@ sshkey_curve_name_to_nid(const char *name) + else if (strcmp(name, "nistp521") == 0) + return NID_secp521r1; + # endif /* OPENSSL_HAS_NISTP521 */ ++ else if (strcmp(name, "sm2") == 0) ++ return NID_sm2; + else + return -1; + } +@@ -554,6 +566,8 @@ sshkey_curve_nid_to_bits(int nid) + case NID_secp521r1: + return 521; + # endif /* OPENSSL_HAS_NISTP521 */ ++ case NID_sm2: ++ return 256; + default: + return 0; + } +@@ -588,6 +602,8 @@ sshkey_curve_nid_to_name(int nid) + case NID_secp521r1: + return "nistp521"; + # endif /* OPENSSL_HAS_NISTP521 */ ++ case NID_sm2: ++ return "sm2"; + default: + return NULL; + } +@@ -693,6 +709,8 @@ sshkey_new(int type) + case KEY_ECDSA_CERT: + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: ++ case KEY_SM2: ++ case KEY_SM2_CERT: + /* Cannot do anything until we know the group */ + break; + #endif /* WITH_OPENSSL */ +@@ -747,6 +765,8 @@ sshkey_free(struct sshkey *k) + /* FALLTHROUGH */ + case KEY_ECDSA: + case KEY_ECDSA_CERT: ++ case KEY_SM2: ++ case KEY_SM2_CERT: + EC_KEY_free(k->ecdsa); + k->ecdsa = NULL; + break; +@@ -856,6 +876,8 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) + /* FALLTHROUGH */ + case KEY_ECDSA_CERT: + case KEY_ECDSA: ++ case KEY_SM2: ++ case KEY_SM2_CERT: + if (a->ecdsa == NULL || b->ecdsa == NULL || + EC_KEY_get0_public_key(a->ecdsa) == NULL || + EC_KEY_get0_public_key(b->ecdsa) == NULL) +@@ -931,6 +953,7 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, + #ifdef WITH_OPENSSL + case KEY_DSA_CERT: + case KEY_ECDSA_CERT: ++ case KEY_SM2_CERT: + case KEY_ECDSA_SK_CERT: + case KEY_RSA_CERT: + #endif /* WITH_OPENSSL */ +@@ -960,6 +983,7 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + case KEY_ECDSA_SK: ++ case KEY_SM2: + if (key->ecdsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if ((ret = sshbuf_put_cstring(b, typename)) != 0 || +@@ -1438,6 +1462,8 @@ sshkey_read(struct sshkey *ret, char **cpp) + case KEY_DSA: + case KEY_ECDSA: + case KEY_ECDSA_SK: ++ case KEY_SM2: ++ case KEY_SM2_CERT: + case KEY_ED25519: + case KEY_ED25519_SK: + case KEY_DSA_CERT: +@@ -1537,6 +1563,7 @@ sshkey_read(struct sshkey *ret, char **cpp) + break; + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: ++ case KEY_SM2: + EC_KEY_free(ret->ecdsa); + ret->ecdsa = k->ecdsa; + ret->ecdsa_nid = k->ecdsa_nid; +@@ -1797,7 +1824,7 @@ sshkey_ecdsa_key_to_nid(EC_KEY *k) + } + + static int +-ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) ++ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap, int sm2) + { + EC_KEY *private; + int ret = SSH_ERR_INTERNAL_ERROR; +@@ -1806,6 +1833,9 @@ ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) + return SSH_ERR_INVALID_ARGUMENT; + if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) + return SSH_ERR_KEY_LENGTH; ++ if (sm2 && bits == 256) { ++ *nid = NID_sm2; ++ } + *ecdsap = NULL; + if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; +@@ -1859,7 +1889,11 @@ sshkey_generate(int type, u_int bits, struct sshkey **keyp) + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid, +- &k->ecdsa); ++ &k->ecdsa, 0); ++ break; ++ case KEY_SM2: ++ ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid, ++ &k->ecdsa, 1); + break; + # endif /* OPENSSL_HAS_ECC */ + case KEY_RSA: +@@ -1995,6 +2029,8 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) + case KEY_ECDSA_CERT: + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: ++ case KEY_SM2: ++ case KEY_SM2_CERT: + n->ecdsa_nid = k->ecdsa_nid; + n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); + if (n->ecdsa == NULL) { +@@ -2550,6 +2586,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, + break; + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA_CERT: ++ case KEY_SM2_CERT: + case KEY_ECDSA_SK_CERT: + /* Skip nonce */ + if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { +@@ -2559,6 +2596,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, + /* FALLTHROUGH */ + case KEY_ECDSA: + case KEY_ECDSA_SK: ++ case KEY_SM2: + if ((key = sshkey_new(type)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; +@@ -2867,6 +2905,10 @@ sshkey_sign(struct sshkey *key, + case KEY_ECDSA: + r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat); + break; ++ case KEY_SM2: ++ case KEY_SM2_CERT: ++ r = ssh_sm2_sign(key, sigp, lenp, data, datalen, compat); ++ break; + # endif /* OPENSSL_HAS_ECC */ + case KEY_RSA_CERT: + case KEY_RSA: +@@ -2922,6 +2964,9 @@ sshkey_verify(const struct sshkey *key, + case KEY_ECDSA_CERT: + case KEY_ECDSA: + return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat); ++ case KEY_SM2: ++ case KEY_SM2_CERT: ++ return ssh_sm2_verify(key, sig, siglen, data, dlen, compat); + case KEY_ECDSA_SK_CERT: + case KEY_ECDSA_SK: + return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen, +@@ -2965,6 +3010,9 @@ sshkey_to_certified(struct sshkey *k) + case KEY_ECDSA: + newtype = KEY_ECDSA_CERT; + break; ++ case KEY_SM2: ++ newtype = KEY_SM2_CERT; ++ break; + case KEY_ECDSA_SK: + newtype = KEY_ECDSA_SK_CERT; + break; +@@ -3068,6 +3116,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, + break; + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA_CERT: ++ case KEY_SM2_CERT: + case KEY_ECDSA_SK_CERT: + if ((ret = sshbuf_put_cstring(cert, + sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 || +@@ -3351,6 +3400,7 @@ sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, + break; + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: ++ case KEY_SM2: + if ((r = sshbuf_put_cstring(b, + sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || + (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 || +@@ -3359,6 +3409,7 @@ sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, + goto out; + break; + case KEY_ECDSA_CERT: ++ case KEY_SM2_CERT: + if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; +@@ -3552,6 +3603,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + break; + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: ++ case KEY_SM2: + if ((k = sshkey_new(type)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; +@@ -3584,6 +3636,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + goto out; + break; + case KEY_ECDSA_CERT: ++ case KEY_SM2_CERT: + if ((r = sshkey_froms(buf, &k)) != 0 || + (r = sshbuf_get_bignum2(buf, &exponent)) != 0) + goto out; +@@ -4446,6 +4499,7 @@ sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf, + break; + #ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: ++ case KEY_SM2: + if (format == SSHKEY_PRIVATE_PEM) { + success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, + cipher, passphrase, len, NULL, NULL); +@@ -4507,6 +4561,7 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, + #ifdef WITH_OPENSSL + case KEY_DSA: + case KEY_ECDSA: ++ case KEY_SM2: + case KEY_RSA: + break; /* see below */ + #endif /* WITH_OPENSSL */ +@@ -4687,6 +4742,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, + prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk); + prv->type = KEY_ECDSA; + prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa); ++ if (prv->ecdsa_nid == NID_sm2) { ++ prv->type = KEY_SM2; ++ } + if (prv->ecdsa_nid == -1 || + sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL || + sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), +@@ -4732,6 +4790,7 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, + #ifdef WITH_OPENSSL + case KEY_DSA: + case KEY_ECDSA: ++ case KEY_SM2: + case KEY_RSA: + return sshkey_parse_private_pem_fileblob(blob, type, + passphrase, keyp); +diff --git a/sshkey.h b/sshkey.h +index b8803b7..2f91d97 100644 +--- a/sshkey.h ++++ b/sshkey.h +@@ -31,6 +31,7 @@ + #ifdef WITH_OPENSSL + #include + #include ++#include + # ifdef OPENSSL_HAS_ECC + # include + # include +@@ -63,6 +64,8 @@ enum sshkey_types { + KEY_DSA_CERT, + KEY_ECDSA_CERT, + KEY_ED25519_CERT, ++ KEY_SM2, ++ KEY_SM2_CERT, + KEY_XMSS, + KEY_XMSS_CERT, + KEY_ECDSA_SK, +@@ -319,6 +322,12 @@ int ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + int ssh_xmss_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat); ++int ssh_sm2_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, ++ const u_char *data, size_t datalen, u_int compat); ++int ssh_sm2_verify(const struct sshkey *key, ++ const u_char *signature, size_t signaturelen, ++ const u_char *data, size_t datalen, u_int compat); ++ + #endif + + #if !defined(WITH_OPENSSL) +-- +1.8.3.1 + diff --git a/openssh.spec b/openssh.spec index 3edba71..b7b9111 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 16 +%global openssh_release 17 Name: openssh Version: 8.2p1 @@ -97,6 +97,7 @@ Patch64: backport-CVE-2021-41617-2.patch Patch65: backport-CVE-2021-28041.patch Patch66: backport-change-convtime-form-returning-long-to-returning-int.patch Patch67: backport-change-types-in-convtime-unit-test-to-int-to-match.patch +Patch68: feature-add-SMx-support.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -266,6 +267,7 @@ popd %patch65 -p1 %patch66 -p1 %patch67 -p1 +%patch68 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -477,6 +479,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Thu Sep 1 2022 renmingshuai - 8.2P1-17 +- Type:requirement +- CVE: +- SUG:NA +- DESC:add SMx support in openssh + * Tue Feb 8 2022 renmingshuai - 8.2P1-16 - Type:bugfix - CVE: -- Gitee From 868f7b811e1f6b715860b0aff720cfbf74d29885 Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Sat, 3 Sep 2022 17:56:01 +0800 Subject: [PATCH 13/22] modifyAfter=network.targetinsshd.service --- openssh.spec | 8 +++++++- sshd.service | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index b7b9111..3016cfd 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 17 +%global openssh_release 18 Name: openssh Version: 8.2p1 @@ -479,6 +479,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Sat Sep 3 2022 renmingshuai - 8.2P1-18 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:modify After=network.target in sshd.service + * Thu Sep 1 2022 renmingshuai - 8.2P1-17 - Type:requirement - CVE: diff --git a/sshd.service b/sshd.service index 8f3dbd6..8c3ecd8 100644 --- a/sshd.service +++ b/sshd.service @@ -1,7 +1,8 @@ +# /usr/lib/systemd/system/sshd.service [Unit] Description=OpenSSH server daemon Documentation=man:sshd(8) man:sshd_config(5) -After=network.target sshd-keygen.target +After=network-online.target sshd-keygen.target Wants=sshd-keygen.target [Service] -- Gitee From fef00598905b1bf4fe1c2a7542ac76399c9d07d4 Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Mon, 5 Sep 2022 10:05:01 +0800 Subject: [PATCH 14/22] add ssh-keygen bash completion --- openssh.spec | 12 ++++++- ssh-keygen-bash-completion.sh | 63 +++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 ssh-keygen-bash-completion.sh diff --git a/openssh.spec b/openssh.spec index 3016cfd..098f7dd 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 18 +%global openssh_release 19 Name: openssh Version: 8.2p1 @@ -29,6 +29,7 @@ Source12: sshd-keygen@.service Source13: sshd-keygen Source14: sshd.tmpfiles Source15: sshd-keygen.target +Source16: ssh-keygen-bash-completion.sh Patch0: openssh-6.7p1-coverity.patch Patch1: openssh-7.6p1-audit.patch Patch2: openssh-7.1p2-audit-race-condition.patch @@ -351,6 +352,7 @@ mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ssh_config.d mkdir -p -m755 $RPM_BUILD_ROOT%{_libexecdir}/openssh mkdir -p -m755 $RPM_BUILD_ROOT%{_var}/empty/sshd +mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d %make_install @@ -375,6 +377,7 @@ install -m755 contrib/ssh-copy-id $RPM_BUILD_ROOT%{_bindir}/ install contrib/ssh-copy-id.1 $RPM_BUILD_ROOT%{_mandir}/man1/ install -m644 -D %{SOURCE14} $RPM_BUILD_ROOT%{_tmpfilesdir}/%{name}.conf install contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass +install -m644 %{SOURCE16} $RPM_BUILD_ROOT/etc/bash_completion.d/ssh-keygen-bash-completion.sh ln -s gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/ssh-askpass install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/ @@ -413,6 +416,7 @@ getent passwd sshd >/dev/null || \ %attr(0755,root,root) %{_bindir}/ssh-keygen %attr(0755,root,root) %dir %{_libexecdir}/openssh %attr(2555,root,ssh_keys) %{_libexecdir}/openssh/ssh-keysign +%attr(0644,root,root) %{_sysconfdir}/bash_completion.d/ssh-keygen-bash-completion.sh %files clients %attr(0755,root,root) %{_bindir}/ssh @@ -479,6 +483,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Mon Sep 5 2022 renmingshuai - 8.2P1-19 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:add ssh-keygen bash completion + * Sat Sep 3 2022 renmingshuai - 8.2P1-18 - Type:bugfix - CVE: diff --git a/ssh-keygen-bash-completion.sh b/ssh-keygen-bash-completion.sh new file mode 100644 index 0000000..f601174 --- /dev/null +++ b/ssh-keygen-bash-completion.sh @@ -0,0 +1,63 @@ +# ssh-keygen(1) completion -*- shell-script -*- + +_ssh_keygen() +{ + local cur prev words cword + _init_completion -n = || return + + case $prev in + -*[abCIJjMNnrPSVWz]) + return + ;; + -*E) + COMPREPLY=( $(compgen -W 'md5 sha256' -- "$cur") ) + return + ;; + -*[FR]) + # TODO: trim this down to actual entries in known hosts files + _known_hosts_real -- "$cur" + return + ;; + -*D) + _filedir so + return + ;; + -*[fGKsT]) + _filedir + return + ;; + -*m) + COMPREPLY=( $(compgen -W 'PEM PKCS8 RFC4716' -- "$cur") ) + return + ;; + -*O) + if [[ $cur != *=* ]]; then + COMPREPLY=( $(compgen -W 'clear force-command= + no-agent-forwarding no-port-forwarding no-pty no-user-rc + no-x11-forwarding permit-agent-forwarding + permit-port-forwarding permit-pty permit-user-rc + permit-x11-forwarding source-address=' -- "$cur") ) + [[ $COMPREPLY == *= ]] && compopt -o nospace + fi + return + ;; + -*t) + local protocols=$(_xfunc ssh _ssh_query "$1" protocol-version) + local types='dsa ecdsa ed25519 rsa sm2' + if [[ $protocols == *1* ]]; then + types+=' rsa1' + fi + COMPREPLY=( $(compgen -W "$types" -- "$cur") ) + return + ;; + esac + + if [[ $cur == -* ]]; then + local opts=$(_parse_usage "$1" "-?") + [[ -z "$opts" ]] && opts=$(_parse_help "$1" "-?") # OpenSSH < 7 + COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) + fi +} && +complete -F _ssh_keygen ssh-keygen + +# ex: filetype=sh -- Gitee From 3e16963f4ecabf5170589d6e85da68b8c9a4e0dc Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Mon, 5 Sep 2022 10:48:24 +0800 Subject: [PATCH 15/22] set ssh config --- openssh.spec | 10 +++++++--- set-ssh-config.patch | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 set-ssh-config.patch diff --git a/openssh.spec b/openssh.spec index 098f7dd..07070fd 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 19 +%global openssh_release 20 Name: openssh Version: 8.2p1 @@ -365,7 +365,6 @@ install -d $RPM_BUILD_ROOT%{_libdir}/fipscheck install -m644 %{SOURCE2} $RPM_BUILD_ROOT/etc/pam.d/sshd install -m644 %{SOURCE6} $RPM_BUILD_ROOT/etc/pam.d/ssh-keycat install -m644 %{SOURCE7} $RPM_BUILD_ROOT/etc/sysconfig/sshd -install -m644 ssh_config_redhat $RPM_BUILD_ROOT/etc/ssh/ssh_config.d/05-redhat.conf install -d -m755 $RPM_BUILD_ROOT/%{_unitdir} install -m644 %{SOURCE9} $RPM_BUILD_ROOT/%{_unitdir}/sshd@.service install -m644 %{SOURCE10} $RPM_BUILD_ROOT/%{_unitdir}/sshd.socket @@ -423,7 +422,6 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_libdir}/fipscheck/ssh.hmac %attr(0755,root,root) %{_bindir}/scp %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config -%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config.d/05-redhat.conf %attr(0755,root,root) %{_bindir}/ssh-agent %attr(0755,root,root) %{_bindir}/ssh-add %attr(0755,root,root) %{_bindir}/ssh-keyscan @@ -483,6 +481,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Wed Jun 17 2022 renmingshuai - 8.2P1-20 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:set ssh_config + * Mon Sep 5 2022 renmingshuai - 8.2P1-19 - Type:bugfix - CVE: diff --git a/set-ssh-config.patch b/set-ssh-config.patch new file mode 100644 index 0000000..8da9e7e --- /dev/null +++ b/set-ssh-config.patch @@ -0,0 +1,30 @@ +From 8b8319aac379d9d6f75577507e87a97a8aa8aadc Mon Sep 17 00:00:00 2001 +From: renmingshuai +Date: Mon, 5 Sep 2022 10:33:02 +0800 +Subject: [PATCH] set-ssh-config + +--- + ssh_config | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/ssh_config b/ssh_config +index df22e2f..46b0987 100644 +--- a/ssh_config ++++ b/ssh_config +@@ -48,4 +48,13 @@ + # + # To modify the system-wide ssh configuration, create a *.conf file under + # /etc/ssh/ssh_config.d/ which will be automatically included below ++Match final all ++ Include /etc/crypto-policies/back-ends/openssh.config ++ GSSAPIAuthentication yes ++ ForwardX11Trusted yes ++ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES ++ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT ++ SendEnv LC_IDENTIFIACTION LC_ALL_LANGUAGE ++ SendEnv XMODIFIERS ++ + Include /etc/ssh/ssh_config.d/*.conf +-- +1.8.3.1 + -- Gitee From 825991c7603a4e488e4ee19f0bffef039f079d85 Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Mon, 5 Sep 2022 16:25:33 +0800 Subject: [PATCH 16/22] add require openssl version --- openssh.spec | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 07070fd..5dfa3fc 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 20 +%global openssh_release 21 Name: openssh Version: 8.2p1 @@ -103,6 +103,7 @@ Patch68: feature-add-SMx-support.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 Requires: openssh-server = %{version}-%{release} %{name}-help +Requires: openssl-libs >= 1:1.1.1f-1 BuildRequires: gtk2-devel libX11-devel openldap-devel autoconf automake perl-interpreter perl-generators BuildRequires: zlib-devel audit-libs-devel >= 2.0.5 util-linux groff pam-devel fipscheck-devel >= 1.3.0 @@ -481,7 +482,13 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog -* Wed Jun 17 2022 renmingshuai - 8.2P1-20 +* Wed Sep 5 2022 renmingshuai - 8.2P1-21 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:add require openssl version + +* Mon Sep 5 2022 renmingshuai - 8.2P1-20 - Type:bugfix - CVE: - SUG:NA -- Gitee From 622e460ef658b06de364bcb283bbfbe00d09ad4d Mon Sep 17 00:00:00 2001 From: licihua Date: Thu, 8 Sep 2022 17:27:50 +0800 Subject: [PATCH 17/22] =?UTF-8?q?=E6=98=8E=E7=A1=AEopenssh=E5=AF=B9help?= =?UTF-8?q?=E5=8C=85=E7=9A=84=E7=89=88=E6=9C=AC=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openssh.spec | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 5dfa3fc..c232356 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 21 +%global openssh_release 22 Name: openssh Version: 8.2p1 @@ -102,7 +102,7 @@ Patch68: feature-add-SMx-support.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 -Requires: openssh-server = %{version}-%{release} %{name}-help +Requires: openssh-server = %{version}-%{release} %{name}-help = %{version}-%{release} Requires: openssl-libs >= 1:1.1.1f-1 BuildRequires: gtk2-devel libX11-devel openldap-devel autoconf automake perl-interpreter perl-generators @@ -482,6 +482,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Thu Sep 8 2022 licihua - 8.2P1-22 +- Type:bugfix +- CVE: +- SUG:NA +- DESC: define openssh-develp version + * Wed Sep 5 2022 renmingshuai - 8.2P1-21 - Type:bugfix - CVE: -- Gitee From ae64edfb138804e20813716adb7f5fae9b30a1bc Mon Sep 17 00:00:00 2001 From: lvfei Date: Thu, 8 Sep 2022 23:06:53 -0400 Subject: [PATCH 18/22] remove require openssh-help --- openssh.spec | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index c232356..f532dc8 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 22 +%global openssh_release 23 Name: openssh Version: 8.2p1 @@ -102,7 +102,7 @@ Patch68: feature-add-SMx-support.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 -Requires: openssh-server = %{version}-%{release} %{name}-help = %{version}-%{release} +Requires: openssh-server = %{version}-%{release} Requires: openssl-libs >= 1:1.1.1f-1 BuildRequires: gtk2-devel libX11-devel openldap-devel autoconf automake perl-interpreter perl-generators @@ -482,6 +482,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Fri Sep 9 2022 lvfei - 8.2P1-23 +- Type:bugfix +- CVE: +- SUG:NA +- DESC: remove require openssh-help version + * Thu Sep 8 2022 licihua - 8.2P1-22 - Type:bugfix - CVE: -- Gitee From ee4c9e35f6b84b5dd8d8df1ab2771a87ff829e65 Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Mon, 28 Nov 2022 16:28:08 +0800 Subject: [PATCH 19/22] ssh-keygen -Y check-novalidate Signed-off-by: renmingshuai --- ...gen-Y-check-novalidate-requires-name.patch | 41 +++++++++++++++++++ openssh.spec | 10 ++++- 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 backport-upstream-ssh-keygen-Y-check-novalidate-requires-name.patch diff --git a/backport-upstream-ssh-keygen-Y-check-novalidate-requires-name.patch b/backport-upstream-ssh-keygen-Y-check-novalidate-requires-name.patch new file mode 100644 index 0000000..2e26b9a --- /dev/null +++ b/backport-upstream-ssh-keygen-Y-check-novalidate-requires-name.patch @@ -0,0 +1,41 @@ +From a0b5816f8f1f645acdf74f7bc11b34455ec30bac Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Fri, 18 Mar 2022 02:31:25 +0000 +Subject: [PATCH] upstream: ssh-keygen -Y check-novalidate requires namespace + or SEGV + +will ensue. Patch from Mateusz Adamowski via GHPR#307 + +OpenBSD-Commit-ID: 99e8ec38f9feb38bce6de240335be34aedeba5fd +Reference:https://github.com/openssh/openssh-portable/commit/a0b5816f8f1f645acdf74f7bc11b34455ec30bac +Conflict:NA +--- + ssh-keygen.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/ssh-keygen.c b/ssh-keygen.c +index d2b4781..9559f70 100644 +--- a/ssh-keygen.c ++++ b/ssh-keygen.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: ssh-keygen.c,v 1.398 2020/02/07 03:27:54 djm Exp $ */ ++/* $OpenBSD: ssh-keygen.c,v 1.449 2022/03/18 02:31:25 djm Exp $ */ + /* + * Author: Tatu Ylonen + * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland +@@ -3405,6 +3405,12 @@ main(int argc, char **argv) + return sig_sign(identity_file, cert_principals, + argc, argv); + } else if (strncmp(sign_op, "check-novalidate", 16) == 0) { ++ if (cert_principals == NULL || ++ *cert_principals == '\0') { ++ error("Too few arguments for check-novalidate: " ++ "missing namespace"); ++ exit(1); ++ } + if (ca_key_path == NULL) { + error("Too few arguments for check-novalidate: " + "missing signature file"); +-- +2.23.0 + diff --git a/openssh.spec b/openssh.spec index f532dc8..47de2e7 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 23 +%global openssh_release 24 Name: openssh Version: 8.2p1 @@ -99,6 +99,7 @@ Patch65: backport-CVE-2021-28041.patch Patch66: backport-change-convtime-form-returning-long-to-returning-int.patch Patch67: backport-change-types-in-convtime-unit-test-to-int-to-match.patch Patch68: feature-add-SMx-support.patch +Patch69: backport-upstream-ssh-keygen-Y-check-novalidate-requires-name.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -270,6 +271,7 @@ popd %patch66 -p1 %patch67 -p1 %patch68 -p1 +%patch69 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -482,6 +484,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Mon Nov 28 2022 renmingshuai - 8.2P1-24 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:ssh-keygen -Y check-novalidate requires namespace or SEGV + * Fri Sep 9 2022 lvfei - 8.2P1-23 - Type:bugfix - CVE: -- Gitee From 8dd27bce0cd6d08a9db08ae11fedfbe6397e9b88 Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Tue, 3 Jan 2023 19:24:10 +0800 Subject: [PATCH 20/22] always make tests --- openssh.spec | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openssh.spec b/openssh.spec index 47de2e7..48c80ed 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 24 +%global openssh_release 25 Name: openssh Version: 8.2p1 @@ -345,10 +345,7 @@ popd %{nil} %check -#to run tests use "--with check" -%if %{?_with_check:1}%{!?_with_check:0} make tests -%endif %install mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh @@ -484,6 +481,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Tue Jan 03 2023 renmingshuai - 8.2p1-25 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:always make tests + * Mon Nov 28 2022 renmingshuai - 8.2P1-24 - Type:bugfix - CVE: -- Gitee From 8384875e7d73d36b058d081012780d7d8148e1a4 Mon Sep 17 00:00:00 2001 From: "renmingshuai@huawei.com" Date: Mon, 9 Jan 2023 19:40:00 +0800 Subject: [PATCH 21/22] fix possible NULL deref when built without FIDO --- ...e-NULL-deref-when-built-without-FIDO.patch | 33 +++++++++++++++++++ openssh.spec | 10 +++++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 backport-fix-possible-NULL-deref-when-built-without-FIDO.patch diff --git a/backport-fix-possible-NULL-deref-when-built-without-FIDO.patch b/backport-fix-possible-NULL-deref-when-built-without-FIDO.patch new file mode 100644 index 0000000..8421498 --- /dev/null +++ b/backport-fix-possible-NULL-deref-when-built-without-FIDO.patch @@ -0,0 +1,33 @@ +From 7d25b37fb2a5ff4dadabcbdac6087a97479434f5 Mon Sep 17 00:00:00 2001 +From: Damien Miller +Date: Fri, 24 Jun 2022 13:46:39 +1000 +Subject: [PATCH] fix possible NULL deref when built without FIDO + +Analysis/fix from kircher in bz3443; ok dtucker@ + +Reference:https://github.com/openssh/openssh-portable/commit/7d25b37fb2a5ff +Conflict:NA +--- + ssh-sk.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ssh-sk.c b/ssh-sk.c +index a1ff5cc4..ba514607 100644 +--- a/ssh-sk.c ++++ b/ssh-sk.c +@@ -127,10 +127,11 @@ sshsk_open(const char *path) + ret->sk_enroll = ssh_sk_enroll; + ret->sk_sign = ssh_sk_sign; + ret->sk_load_resident_keys = ssh_sk_load_resident_keys; ++ return ret; + #else + error("internal security key support not enabled"); ++ goto fail; + #endif +- return ret; + } + if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) { + error("Provider \"%s\" dlopen failed: %s", path, dlerror()); +-- +2.23.0 + diff --git a/openssh.spec b/openssh.spec index 48c80ed..57d97aa 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 25 +%global openssh_release 26 Name: openssh Version: 8.2p1 @@ -100,6 +100,7 @@ Patch66: backport-change-convtime-form-returning-long-to-returning-int.pa Patch67: backport-change-types-in-convtime-unit-test-to-int-to-match.patch Patch68: feature-add-SMx-support.patch Patch69: backport-upstream-ssh-keygen-Y-check-novalidate-requires-name.patch +Patch70: backport-fix-possible-NULL-deref-when-built-without-FIDO.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -272,6 +273,7 @@ popd %patch67 -p1 %patch68 -p1 %patch69 -p1 +%patch70 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -481,6 +483,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Mon Jan 09 2023 renmingshuai - 8.2p1-26 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:fix possible NULL deref when built without FIDO + * Tue Jan 03 2023 renmingshuai - 8.2p1-25 - Type:bugfix - CVE: -- Gitee From 41fb943f9302c401689822201c240e885a0f9519 Mon Sep 17 00:00:00 2001 From: renmingshuai Date: Mon, 6 Feb 2023 14:44:47 +0800 Subject: [PATCH 22/22] fix CVE-2023-25136 --- ...5136-Always-return-allocated-strings.patch | 85 +++++++++++++++++++ openssh.spec | 10 ++- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 backport-upstream-CVE-2023-25136-Always-return-allocated-strings.patch diff --git a/backport-upstream-CVE-2023-25136-Always-return-allocated-strings.patch b/backport-upstream-CVE-2023-25136-Always-return-allocated-strings.patch new file mode 100644 index 0000000..4e84d0c --- /dev/null +++ b/backport-upstream-CVE-2023-25136-Always-return-allocated-strings.patch @@ -0,0 +1,85 @@ +From 486c4dc3b83b4b67d663fb0fa62bc24138ec3946 Mon Sep 17 00:00:00 2001 +From: "dtucker@openbsd.org" +Date: Fri, 1 Jul 2022 03:35:45 +0000 +Subject: [PATCH] upstream: Always return allocated strings from the kex + filtering so + +that we can free them later. Fix one leak in compat_kex_proposal. Based on +github PR#324 from ZoltanFridrich with some simplications by me. ok djm@ + +OpenBSD-Commit-ID: 9171616da3307612d0ede086fd511142f91246e4 + +Reference: +https://anongit.mindrot.org/openssh.git/patch/?id=486c4dc3b83b4b67d663fb0fa62bc24138ec3946 +Conflict: Contxt modification which remove global varibale used to stash +compat flags and use ssh->compat instead that is not related to fix the CVE +--- +diff --git a/compat.c b/compat.c +index 0624dc6..e5be5b4 100644 +--- a/compat.c ++++ b/compat.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: compat.c,v 1.113 2018/08/13 02:41:05 djm Exp $ */ ++/* $OpenBSD: compat.c,v 1.120 2022/07/01 03:35:45 dtucker Exp $ */ + /* + * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. + * +@@ -183,11 +183,12 @@ proto_spec(const char *spec) + return ret; + } + ++/* Always returns pointer to allocated memory, caller must free. */ + char * + compat_cipher_proposal(char *cipher_prop) + { + if (!(datafellows & SSH_BUG_BIGENDIANAES)) +- return cipher_prop; ++ return xstrdup(cipher_prop); + debug2("%s: original cipher proposal: %s", __func__, cipher_prop); + if ((cipher_prop = match_filter_blacklist(cipher_prop, "aes*")) == NULL) + fatal("match_filter_blacklist failed"); +@@ -197,11 +198,12 @@ compat_cipher_proposal(char *cipher_prop) + return cipher_prop; + } + ++/* Always returns pointer to allocated memory, caller must free. */ + char * + compat_pkalg_proposal(char *pkalg_prop) + { + if (!(datafellows & SSH_BUG_RSASIGMD5)) +- return pkalg_prop; ++ return xstrdup(pkalg_prop); + debug2("%s: original public key proposal: %s", __func__, pkalg_prop); + if ((pkalg_prop = match_filter_blacklist(pkalg_prop, "ssh-rsa")) == NULL) + fatal("match_filter_blacklist failed"); +@@ -211,21 +213,25 @@ compat_pkalg_proposal(char *pkalg_prop) + return pkalg_prop; + } + ++/* Always returns pointer to allocated memory, caller must free. */ + char * + compat_kex_proposal(char *p) + { +- if ((datafellows & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) +- return p; ++ char *cp = NULL; ++ if ((datafellows & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) ++ return xstrdup(p); + debug2("%s: original KEX proposal: %s", __func__, p); + if ((datafellows & SSH_BUG_CURVE25519PAD) != 0) + if ((p = match_filter_blacklist(p, + "curve25519-sha256@libssh.org")) == NULL) + fatal("match_filter_blacklist failed"); + if ((datafellows & SSH_OLD_DHGEX) != 0) { ++ cp = p; + if ((p = match_filter_blacklist(p, + "diffie-hellman-group-exchange-sha256," + "diffie-hellman-group-exchange-sha1")) == NULL) + fatal("match_filter_blacklist failed"); ++ free(cp); + } + debug2("%s: compat KEX proposal: %s", __func__, p); + if (*p == '\0') +-- +2.23.0 + diff --git a/openssh.spec b/openssh.spec index 57d97aa..1000553 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,7 +6,7 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 26 +%global openssh_release 27 Name: openssh Version: 8.2p1 @@ -101,6 +101,7 @@ Patch67: backport-change-types-in-convtime-unit-test-to-int-to-match.patc Patch68: feature-add-SMx-support.patch Patch69: backport-upstream-ssh-keygen-Y-check-novalidate-requires-name.patch Patch70: backport-fix-possible-NULL-deref-when-built-without-FIDO.patch +Patch71: backport-upstream-CVE-2023-25136-Always-return-allocated-strings.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -274,6 +275,7 @@ popd %patch68 -p1 %patch69 -p1 %patch70 -p1 +%patch71 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -483,6 +485,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Mon Feb 06 2023 renmingshuai - 8.2p1-27 +- Type:CVE +- CVE:CVE-2023-25136 +- SUG:NA +- DESC:fix CVE-2023-25136 + * Mon Jan 09 2023 renmingshuai - 8.2p1-26 - Type:bugfix - CVE: -- Gitee