diff options
author | CoprDistGit <infra@openeuler.org> | 2024-07-03 02:42:38 +0000 |
---|---|---|
committer | CoprDistGit <infra@openeuler.org> | 2024-07-03 02:42:38 +0000 |
commit | 3c362eae690284f325824e38431881825e32ffdd (patch) | |
tree | d2d0e11b92bf88d35c270559d268845d391a4703 /feature-add-SMx-support.patch | |
parent | 62f0a34c39a6846b6a86f2bbc7fb8c319bd46d94 (diff) |
automatic import of openssh
Diffstat (limited to 'feature-add-SMx-support.patch')
-rw-r--r-- | feature-add-SMx-support.patch | 820 |
1 files changed, 442 insertions, 378 deletions
diff --git a/feature-add-SMx-support.patch b/feature-add-SMx-support.patch index e8b0f3c..d7fe61c 100644 --- a/feature-add-SMx-support.patch +++ b/feature-add-SMx-support.patch @@ -1,7 +1,13 @@ -From d2e28809c673f914b49147ca3fa31e08b9e885d7 Mon Sep 17 00:00:00 2001 -From: renmingshuai <renmingshuai@huawei.com> -Date: Sat, 29 Jul 2023 10:50:29 +0800 -Subject: [PATCH] feature add sm2 +From 93b312c0263cbf40f66448ff7ddbea7a2def1953 Mon Sep 17 00:00:00 2001 +From: kircher <majun65@huawei.com> +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 +PubkeyAcceptedAlgorithms sm2 +FingerprintHash sm3 --- Makefile.in | 4 +- @@ -25,21 +31,21 @@ Subject: [PATCH] feature add sm2 ssh-ecdsa.c | 6 +- ssh-keygen.c | 12 +- ssh-keyscan.c | 12 +- - ssh-sm2.c | 381 ++++++++++++++++++++++++ + ssh-sm2.c | 230 +++++++++++++++ ssh_api.c | 2 + sshconnect2.c | 1 + sshd.c | 7 + - sshkey.c | 21 ++ - sshkey.h | 2 + - 27 files changed, 899 insertions(+), 14 deletions(-) + sshkey.c | 62 +++- + sshkey.h | 9 + + 27 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 5fec5b3..7dcda3e 100644 +index 07bf440..1393190 100644 --- a/Makefile.in +++ b/Makefile.in -@@ -102,14 +102,14 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ +@@ -100,14 +100,14 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ log.o match.o moduli.o nchan.o packet.o \ readpass.o ttymodes.o xmalloc.o addr.o addrmatch.o \ atomicio.o dispatch.o mac.o misc.o utf8.o \ @@ -50,17 +56,17 @@ index 5fec5b3..7dcda3e 100644 ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \ poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ ssh-ed25519.o digest-openssl.o digest-libc.o \ - hmac.o ed25519.o hash.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 \ kexsntrup761x25519.o sntrup761.o kexgen.o \ kexgssc.o \ diff --git a/authfd.c b/authfd.c -index 25a3636..bcc25a7 100644 +index 9f092f7..163b4b5 100644 --- a/authfd.c +++ b/authfd.c -@@ -583,6 +583,8 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, +@@ -512,6 +512,8 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, case KEY_DSA_CERT: case KEY_ECDSA: case KEY_ECDSA_CERT: @@ -70,10 +76,10 @@ index 25a3636..bcc25a7 100644 case KEY_ECDSA_SK_CERT: #endif diff --git a/authfile.c b/authfile.c -index 445f2dd..3884031 100644 +index 666730b..dce1e84 100644 --- a/authfile.c +++ b/authfile.c -@@ -332,6 +332,7 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase, +@@ -343,6 +343,7 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase, case KEY_RSA: case KEY_DSA: case KEY_ECDSA: @@ -82,10 +88,10 @@ index 445f2dd..3884031 100644 case KEY_ED25519: case KEY_XMSS: diff --git a/cipher.c b/cipher.c -index 609450d..7f98413 100644 +index b54b994..039e414 100644 --- a/cipher.c +++ b/cipher.c -@@ -86,6 +86,7 @@ static const struct sshcipher ciphers[] = { +@@ -88,6 +88,7 @@ static const struct sshcipher ciphers[] = { #endif { "chacha20-poly1305@openssh.com", 8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL }, @@ -120,10 +126,10 @@ index c7ceeb3..520722c 100644 struct sshbuf; struct ssh_digest_ctx; diff --git a/kex.c b/kex.c -index 0fbd0ca..e9dfcc2 100644 +index d0a9dee..6284f90 100644 --- a/kex.c +++ b/kex.c -@@ -125,6 +125,7 @@ static const struct kexalg kexalgs[] = { +@@ -124,6 +124,7 @@ static const struct kexalg kexalgs[] = { SSH_DIGEST_SHA512 }, #endif #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ @@ -132,7 +138,7 @@ index 0fbd0ca..e9dfcc2 100644 }; static const struct kexalg gss_kexalgs[] = { diff --git a/kex.h b/kex.h -index 0fac9d3..044ec18 100644 +index d26ba26..8b95227 100644 --- a/kex.h +++ b/kex.h @@ -102,6 +102,7 @@ enum kex_exchange { @@ -143,7 +149,7 @@ index 0fac9d3..044ec18 100644 #ifdef GSSAPI KEX_GSS_GRP1_SHA1, KEX_GSS_GRP14_SHA1, -@@ -287,6 +288,8 @@ int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], +@@ -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))); @@ -217,7 +223,7 @@ index efb2e55..69ec13b 100644 kex->ec_client_key = NULL; return r; diff --git a/kexgen.c b/kexgen.c -index ca70484..4855d5c 100644 +index 31f90f5..f3eff47 100644 --- a/kexgen.c +++ b/kexgen.c @@ -111,6 +111,7 @@ kex_gen_client(struct ssh *ssh) @@ -236,7 +242,7 @@ index ca70484..4855d5c 100644 r = kex_ecdh_dec(kex, server_blob, &shared_secret); break; #endif -@@ -298,6 +300,7 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) +@@ -280,6 +282,7 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) &shared_secret); break; case KEX_ECDH_SHA2: @@ -681,7 +687,7 @@ index a094888..0a805ad 100644 /* * Configuration file in user's home directory. This file need not be diff --git a/regress/agent.sh b/regress/agent.sh -index 5f10606..3ab40b4 100644 +index f187b67..42a5124 100644 --- a/regress/agent.sh +++ b/regress/agent.sh @@ -87,9 +87,18 @@ fi @@ -758,10 +764,10 @@ index b32502b..f260692 100644 sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); sshkey_sig_details_free(details); diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c -index c26761e..d335b29 100644 +index 3bd71a9..312e8f2 100644 --- a/regress/unittests/kex/test_kex.c +++ b/regress/unittests/kex/test_kex.c -@@ -151,6 +151,7 @@ do_kex_with_key(char *kex, int keytype, int bits) +@@ -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; @@ -769,7 +775,7 @@ index c26761e..d335b29 100644 server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = 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; -@@ -185,6 +186,7 @@ do_kex(char *kex) +@@ -186,6 +187,7 @@ do_kex(char *kex) #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ do_kex_with_key(kex, KEY_ED25519, 256); @@ -777,7 +783,7 @@ index c26761e..d335b29 100644 } void -@@ -201,6 +203,7 @@ kex_tests(void) +@@ -202,6 +204,7 @@ kex_tests(void) do_kex("diffie-hellman-group-exchange-sha1"); do_kex("diffie-hellman-group14-sha1"); do_kex("diffie-hellman-group1-sha1"); @@ -786,10 +792,10 @@ index c26761e..d335b29 100644 do_kex("sntrup761x25519-sha512@openssh.com"); # endif /* USE_SNTRUP761X25519 */ diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c -index b705157..5445ab5 100644 +index b036796..6697be6 100644 --- a/ssh-ecdsa.c +++ b/ssh-ecdsa.c -@@ -256,7 +256,8 @@ ssh_ecdsa_sign(struct sshkey *key, +@@ -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 || @@ -799,21 +805,21 @@ index b705157..5445ab5 100644 return SSH_ERR_INVALID_ARGUMENT; if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) -@@ -332,7 +333,8 @@ ssh_ecdsa_verify(const struct sshkey *key, +@@ -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) || - sig == NULL || siglen == 0) ++ (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 0bff209..46f4998 100644 +index b9c4dce..bd6ea16 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c -@@ -193,6 +193,7 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) +@@ -192,6 +192,7 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) *bitsp = DEFAULT_BITS_DSA; break; case KEY_ECDSA: @@ -821,7 +827,7 @@ index 0bff209..46f4998 100644 if (name != NULL && (nid = sshkey_ecdsa_nid_from_name(name)) > 0) *bitsp = sshkey_curve_nid_to_bits(nid); -@@ -219,6 +220,10 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) +@@ -224,6 +225,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; @@ -832,7 +838,7 @@ index 0bff209..46f4998 100644 case KEY_ECDSA: if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1) #ifdef OPENSSL_HAS_NISTP521 -@@ -275,6 +280,9 @@ ask_filename(struct passwd *pw, const char *prompt) +@@ -280,6 +285,9 @@ ask_filename(struct passwd *pw, const char *prompt) case KEY_ECDSA: name = _PATH_SSH_CLIENT_ID_ECDSA; break; @@ -842,7 +848,7 @@ index 0bff209..46f4998 100644 case KEY_ECDSA_SK_CERT: case KEY_ECDSA_SK: name = _PATH_SSH_CLIENT_ID_ECDSA_SK; -@@ -386,6 +394,7 @@ do_convert_to_pkcs8(struct sshkey *k) +@@ -391,6 +399,7 @@ do_convert_to_pkcs8(struct sshkey *k) break; #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: @@ -850,7 +856,7 @@ index 0bff209..46f4998 100644 if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) fatal("PEM_write_EC_PUBKEY failed"); break; -@@ -410,6 +419,7 @@ do_convert_to_pem(struct sshkey *k) +@@ -415,6 +424,7 @@ do_convert_to_pem(struct sshkey *k) break; #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: @@ -858,7 +864,7 @@ index 0bff209..46f4998 100644 if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) fatal("PEM_write_EC_PUBKEY failed"); break; -@@ -3280,7 +3290,7 @@ usage(void) +@@ -3148,7 +3158,7 @@ usage(void) fprintf(stderr, "usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n" " [-m format] [-N new_passphrase] [-O option]\n" @@ -868,10 +874,10 @@ index 0bff209..46f4998 100644 " ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n" " [-P old_passphrase] [-Z cipher]\n" diff --git a/ssh-keyscan.c b/ssh-keyscan.c -index 245c73d..b402a21 100644 +index 9ec4d9a..be2af0a 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c -@@ -68,9 +68,10 @@ int ssh_port = SSH_DEFAULT_PORT; +@@ -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) @@ -883,7 +889,7 @@ index 245c73d..b402a21 100644 int get_cert = 0; int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519|KT_ECDSA_SK|KT_ED25519_SK; -@@ -267,6 +268,11 @@ keygrab_ssh2(con *c) +@@ -261,6 +262,11 @@ keygrab_ssh2(con *c) "ecdsa-sha2-nistp384," "ecdsa-sha2-nistp521"; break; @@ -895,7 +901,7 @@ index 245c73d..b402a21 100644 case KT_ECDSA_SK: myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" : -@@ -296,6 +302,7 @@ keygrab_ssh2(con *c) +@@ -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; @@ -903,7 +909,7 @@ index 245c73d..b402a21 100644 # endif #endif c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; -@@ -789,6 +796,9 @@ main(int argc, char **argv) +@@ -730,6 +737,9 @@ main(int argc, char **argv) case KEY_ECDSA: get_keytypes |= KT_ECDSA; break; @@ -915,10 +921,10 @@ index 245c73d..b402a21 100644 break; diff --git a/ssh-sm2.c b/ssh-sm2.c new file mode 100644 -index 0000000..75e9731 +index 0000000..c242139 --- /dev/null +++ b/ssh-sm2.c -@@ -0,0 +1,381 @@ +@@ -0,0 +1,230 @@ +#include "includes.h" +#include <sys/types.h> +#include <openssl/bn.h> @@ -933,167 +939,30 @@ index 0000000..75e9731 + +#include "openbsd-compat/openssl-compat.h" + -+/* Reuse some ECDSA internals */ -+extern struct sshkey_impl_funcs sshkey_ecdsa_funcs; -+ +const unsigned char *sm2_id = (const unsigned char *)"1234567812345678"; + -+static void -+ssh_sm2_cleanup(struct sshkey *k) -+{ -+ EC_KEY_free(k->ecdsa); -+ k->ecdsa = NULL; -+} -+ -+static int -+ssh_sm2_equal(const struct sshkey *a, const struct sshkey *b) -+{ -+ if (!sshkey_ecdsa_funcs.equal(a, b)) -+ return 0; -+ return 1; -+} -+ -+static int -+ssh_sm2_serialize_public(const struct sshkey *key, struct sshbuf *b, -+ enum sshkey_serialize_rep opts) -+{ -+ int r; -+ -+ if ((r = sshkey_ecdsa_funcs.serialize_public(key, b, opts)) != 0) -+ return r; -+ -+ return 0; -+} -+ -+static int -+ssh_sm2_deserialize_public(const char *ktype, struct sshbuf *b, -+ struct sshkey *key) -+{ -+ int r; -+ -+ if ((r = sshkey_ecdsa_funcs.deserialize_public(ktype, b, key)) != 0) -+ return r; -+ return 0; -+} -+ -+static int -+ssh_sm2_serialize_private(const struct sshkey *key, struct sshbuf *b, -+ enum sshkey_serialize_rep opts) -+{ -+ int r; -+ -+ if ((r = sshkey_ecdsa_funcs.serialize_private(key, b, opts)) != 0) -+ return r; -+ -+ return 0; -+} -+ -+static int -+ssh_sm2_deserialize_private(const char *ktype, struct sshbuf *b, -+ struct sshkey *key) -+{ -+ int r; -+ -+ if ((r = sshkey_ecdsa_funcs.deserialize_private(ktype, b, key)) != 0) -+ return r; -+ -+ return 0; -+} -+ -+static int -+ssh_sm2_generate(struct sshkey *k, int bits) -+{ -+ EC_KEY *private; -+ -+ k->ecdsa_nid = NID_sm2; -+ if ((private = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL) -+ return SSH_ERR_ALLOC_FAIL; -+ if (EC_KEY_generate_key(private) != 1) { -+ EC_KEY_free(private); -+ return SSH_ERR_LIBCRYPTO_ERROR; -+ } -+ EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); -+ k->ecdsa = private; -+ return 0; -+} -+ -+static int -+ssh_sm2_copy_public(const struct sshkey *from, struct sshkey *to) -+{ -+ int r; -+ -+ if ((r = sshkey_ecdsa_funcs.copy_public(from, to)) != 0) -+ return r; -+ return 0; -+} -+ -+static int -+sm2_get_sig(EVP_PKEY *pkey, const u_char *data, -+ size_t datalen, u_char *sig, size_t *slen) -+{ -+ EVP_PKEY_CTX *pctx = NULL; -+ EVP_MD_CTX *mctx = NULL; -+ int ret = SSH_ERR_INTERNAL_ERROR; -+ -+ if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ if ((mctx = EVP_MD_CTX_new()) == 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; -+ } -+ -+ EVP_MD_CTX_set_pkey_ctx(mctx, pctx); -+ -+ if ((EVP_DigestSignInit(mctx, NULL, EVP_sm3(), NULL, pkey)) != 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; -+ } -+ ret = 0; -+ -+out: -+ EVP_PKEY_CTX_free(pctx); -+ EVP_MD_CTX_free(mctx); -+ return ret; -+} -+ -+static int -+ssh_sm2_sign(struct sshkey *key, -+ u_char **sigp, size_t *lenp, -+ const u_char *data, size_t datalen, -+ const char *alg, const char *sk_provider, const char *sk_pin, 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) +{ + u_char *sig = NULL; -+ size_t slen = 0; ++ size_t slen = 0; + int pkey_len = 0; + int r = 0; + int len = 0; + EVP_PKEY *key_sm2 = NULL; -+ struct sshbuf *b = NULL; -+ int ret = SSH_ERR_INTERNAL_ERROR; ++ 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 (lenp != NULL) ++ *lenp = 0; ++ if (sigp != NULL) ++ *sigp = NULL; + + if (key == NULL || key->ecdsa == NULL || -+ sshkey_type_plain(key->type) != KEY_SM2) ++ sshkey_type_plain(key->type) != KEY_SM2) + return SSH_ERR_INVALID_ARGUMENT; + + if ((key_sm2 = EVP_PKEY_new()) == NULL) { @@ -1105,201 +974,187 @@ index 0000000..75e9731 + goto out; + } + -+ if ((pkey_len = EVP_PKEY_size(key_sm2)) == 0) { -+ ret = SSH_ERR_INVALID_ARGUMENT; ++ if ((pkey_len = EVP_PKEY_size(key_sm2)) == 0) { ++ ret = SSH_ERR_INVALID_ARGUMENT; + goto out; -+ } ++ } + + slen = pkey_len; -+ -+ if ((sig = OPENSSL_malloc(pkey_len)) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ if (ret = sm2_get_sig(key_sm2, data, datalen, sig, &slen)) { ++ ++ if ((EVP_PKEY_set_alias_type(key_sm2, EVP_PKEY_SM2)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; + goto out; + } + -+ if ((b = sshbuf_new()) == NULL) { ++ if ((sig = OPENSSL_malloc(pkey_len)) == 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); -+ } -+ sshbuf_free(b); -+ return ret; -+} -+ -+static int -+sm2_verify_sig(EVP_PKEY *pkey, const u_char *data, -+ size_t datalen, const u_char *sig, size_t slen) -+{ -+ EVP_PKEY_CTX *pctx = NULL; -+ EVP_MD_CTX *mctx = NULL; -+ int ret = SSH_ERR_INTERNAL_ERROR; ++ } + -+ if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { ++ if ((pctx = EVP_PKEY_CTX_new(key_sm2, NULL)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ if ((mctx = EVP_MD_CTX_new()) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; ++ goto out; + } + + if (EVP_PKEY_CTX_set1_id(pctx, sm2_id, 16) != 1) { + ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; ++ 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, pkey)) != 1) { ++ if ((EVP_DigestSignInit(mctx, NULL, EVP_sm3(), NULL, key_sm2)) != 1) { + ret = SSH_ERR_INTERNAL_ERROR; + goto out; + } + -+ if ((EVP_DigestVerifyUpdate(mctx, data, datalen)) != 1) { ++ if ((EVP_DigestSignUpdate(mctx, data, datalen)) != 1) { + ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; ++ goto out; + } -+ -+ if ((EVP_DigestVerifyFinal(mctx, sig, slen)) != 1) { ++ ++ if ((EVP_DigestSignFinal(mctx, sig, &slen)) != 1) { + ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; ++ 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; +} + -+static int ++int +ssh_sm2_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, -+ const u_char *data, size_t datalen, const char *alg, u_int compat, -+ struct sshkey_sig_details **detailsp) ++ 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; ++ int pkey_len = 0; ++ int r = 0; ++ int len = 0; + EVP_PKEY *key_sm2 = NULL; -+ struct sshbuf *b = NULL; -+ int ret = SSH_ERR_INTERNAL_ERROR; ++ 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 (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 ((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 ((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; ++ ret = SSH_ERR_KEY_TYPE_MISMATCH; ++ goto out; + } + -+ if (sshbuf_len(b) != 0) { -+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; -+ 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 ((key_sm2 = EVP_PKEY_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + -+ if ((EVP_PKEY_set1_EC_KEY(key_sm2, key->ecdsa)) != 1) { ++ 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; ++ goto out; + } -+ -+ if ((pkey_len = EVP_PKEY_size(key_sm2)) == 0) { -+ ret = SSH_ERR_INVALID_ARGUMENT; -+ goto out; ++ ++ if ((EVP_DigestVerifyUpdate(mctx, data, datalen)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; + } -+ -+ if (ret = sm2_verify_sig(key_sm2, data, datalen, sig, slen)) { -+ goto out; ++ ++ if ((EVP_DigestVerifyFinal(mctx, sig, slen)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; + } + + ret = 0; +out: + EVP_PKEY_free(key_sm2); -+ sshbuf_free(b); ++ EVP_PKEY_CTX_free(pctx); ++ EVP_MD_CTX_free(mctx); ++ sshbuf_free(b); + free(ktype); + return ret; +} -+ -+static const struct sshkey_impl_funcs sshkey_sm2_funcs = { -+ /* .size = */ NULL, -+ /* .alloc = */ NULL, -+ /* .cleanup = */ ssh_sm2_cleanup, -+ /* .equal = */ ssh_sm2_equal, -+ /* .ssh_serialize_public = */ ssh_sm2_serialize_public, -+ /* .ssh_deserialize_public = */ ssh_sm2_deserialize_public, -+ /* .ssh_serialize_private = */ ssh_sm2_serialize_private, -+ /* .ssh_deserialize_private = */ssh_sm2_deserialize_private, -+ /* .generate = */ ssh_sm2_generate, -+ /* .copy_public = */ ssh_sm2_copy_public, -+ /* .sign = */ ssh_sm2_sign, -+ /* .verify = */ ssh_sm2_verify, -+}; -+ -+const struct sshkey_impl sshkey_sm2_impl = { -+ /* .name = */ "sm2", -+ /* .shortname = */ "SM2", -+ /* .sigalg = */ NULL, -+ /* .type = */ KEY_SM2, -+ /* .nid = */ NID_sm2, -+ /* .cert = */ 0, -+ /* .sigonly = */ 0, -+ /* .keybits = */ 256, -+ /* .funcs = */ &sshkey_sm2_funcs, -+}; -+ -+const struct sshkey_impl sshkey_sm2_cert_impl = { -+ /* .name = */ "sm2-cert", -+ /* .shortname = */ "SM2-CERT", -+ /* .sigalg = */ NULL, -+ /* .type = */ KEY_SM2_CERT, -+ /* .nid = */ NID_sm2, -+ /* .cert = */ 1, -+ /* .sigonly = */ 0, -+ /* .keybits = */ 256, -+ /* .funcs = */ &sshkey_sm2_funcs, -+}; diff --git a/ssh_api.c b/ssh_api.c index d3c6617..adc2598 100644 --- a/ssh_api.c @@ -1321,10 +1176,10 @@ index d3c6617..adc2598 100644 #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; diff --git a/sshconnect2.c b/sshconnect2.c -index 3acfdb6..3fbff57 100644 +index fafc0a2..9a01f1a 100644 --- a/sshconnect2.c +++ b/sshconnect2.c -@@ -326,6 +326,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, +@@ -327,6 +327,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; @@ -1333,10 +1188,10 @@ index 3acfdb6..3fbff57 100644 # ifdef GSSAPI if (options.gss_keyex) { diff --git a/sshd.c b/sshd.c -index f366457..52c66ed 100644 +index 8424e33..57d70fe 100644 --- a/sshd.c +++ b/sshd.c -@@ -695,6 +695,7 @@ list_hostkey_types(void) +@@ -706,6 +706,7 @@ list_hostkey_types(void) /* FALLTHROUGH */ case KEY_DSA: case KEY_ECDSA: @@ -1344,7 +1199,7 @@ index f366457..52c66ed 100644 case KEY_ED25519: case KEY_ECDSA_SK: case KEY_ED25519_SK: -@@ -716,6 +717,7 @@ list_hostkey_types(void) +@@ -727,6 +728,7 @@ list_hostkey_types(void) /* FALLTHROUGH */ case KEY_DSA_CERT: case KEY_ECDSA_CERT: @@ -1352,7 +1207,7 @@ index f366457..52c66ed 100644 case KEY_ED25519_CERT: case KEY_ECDSA_SK_CERT: case KEY_ED25519_SK_CERT: -@@ -742,6 +744,7 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) +@@ -753,6 +755,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: @@ -1360,7 +1215,7 @@ index f366457..52c66ed 100644 case KEY_ED25519_CERT: case KEY_ECDSA_SK_CERT: case KEY_ED25519_SK_CERT: -@@ -758,8 +761,10 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) +@@ -769,8 +772,10 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) continue; switch (type) { case KEY_ECDSA: @@ -1371,7 +1226,7 @@ index f366457..52c66ed 100644 case KEY_ECDSA_SK_CERT: if (key->ecdsa_nid != nid) continue; -@@ -2012,6 +2017,7 @@ main(int ac, char **av) +@@ -1983,6 +1988,7 @@ main(int ac, char **av) case KEY_RSA: case KEY_DSA: case KEY_ECDSA: @@ -1379,7 +1234,7 @@ index f366457..52c66ed 100644 case KEY_ED25519: case KEY_ECDSA_SK: case KEY_ED25519_SK: -@@ -2573,6 +2579,7 @@ do_ssh2_kex(struct ssh *ssh) +@@ -2572,6 +2578,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; @@ -1388,28 +1243,19 @@ index f366457..52c66ed 100644 # ifdef GSSAPI if (options.gss_keyex) { diff --git a/sshkey.c b/sshkey.c -index 1735159..1aee244 100644 +index b0c2189..51f8e51 100644 --- a/sshkey.c +++ b/sshkey.c -@@ -130,6 +130,8 @@ extern const struct sshkey_impl sshkey_dsa_cert_impl; - extern const struct sshkey_impl sshkey_xmss_impl; - extern const struct sshkey_impl sshkey_xmss_cert_impl; - #endif -+extern const struct sshkey_impl sshkey_sm2_impl; -+extern const struct sshkey_impl sshkey_sm2_cert_impl; - - static int ssh_gss_equal(const struct sshkey *, const struct sshkey *) - { -@@ -237,6 +239,8 @@ const struct sshkey_impl * const keyimpls[] = { - &sshkey_xmss_cert_impl, - #endif - &sshkey_gss_kex_impl, -+ &sshkey_sm2_impl, -+ &sshkey_sm2_cert_impl, - NULL +@@ -159,6 +159,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 } }; -@@ -340,6 +344,8 @@ key_type_is_ecdsa_variant(int type) +@@ -233,6 +235,8 @@ key_type_is_ecdsa_variant(int type) case KEY_ECDSA_CERT: case KEY_ECDSA_SK: case KEY_ECDSA_SK_CERT: @@ -1418,7 +1264,25 @@ index 1735159..1aee244 100644 return 1; } return 0; -@@ -548,6 +554,8 @@ sshkey_type_plain(int type) +@@ -342,6 +346,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: +@@ -366,6 +372,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; +@@ -445,6 +453,8 @@ sshkey_type_plain(int type) return KEY_ED25519_SK; case KEY_XMSS_CERT: return KEY_XMSS; @@ -1427,16 +1291,7 @@ index 1735159..1aee244 100644 default: return type; } -@@ -564,6 +572,8 @@ sshkey_type_certified(int type) - return KEY_DSA_CERT; - case KEY_ECDSA: - return KEY_ECDSA_CERT; -+ case KEY_SM2: -+ return KEY_SM2_CERT; - case KEY_ECDSA_SK: - return KEY_ECDSA_SK_CERT; - case KEY_ED25519: -@@ -670,6 +680,8 @@ sshkey_curve_name_to_nid(const char *name) +@@ -540,6 +550,8 @@ sshkey_curve_name_to_nid(const char *name) else if (strcmp(name, "nistp521") == 0) return NID_secp521r1; # endif /* OPENSSL_HAS_NISTP521 */ @@ -1445,7 +1300,7 @@ index 1735159..1aee244 100644 else return -1; } -@@ -686,6 +698,8 @@ sshkey_curve_nid_to_bits(int nid) +@@ -556,6 +568,8 @@ sshkey_curve_nid_to_bits(int nid) case NID_secp521r1: return 521; # endif /* OPENSSL_HAS_NISTP521 */ @@ -1454,7 +1309,7 @@ index 1735159..1aee244 100644 default: return 0; } -@@ -720,6 +734,8 @@ sshkey_curve_nid_to_name(int nid) +@@ -590,6 +604,8 @@ sshkey_curve_nid_to_name(int nid) case NID_secp521r1: return "nistp521"; # endif /* OPENSSL_HAS_NISTP521 */ @@ -1463,7 +1318,195 @@ index 1735159..1aee244 100644 default: return NULL; } -@@ -3424,6 +3440,7 @@ sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf, +@@ -695,6 +711,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 */ +@@ -749,6 +767,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; +@@ -858,6 +878,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) +@@ -933,6 +955,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 */ +@@ -962,6 +985,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 || +@@ -1436,6 +1460,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: +@@ -1535,6 +1561,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; +@@ -1795,7 +1822,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; +@@ -1804,6 +1831,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; +@@ -1857,7 +1887,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: +@@ -1993,6 +2027,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) { +@@ -2548,6 +2584,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) { +@@ -2557,6 +2594,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; +@@ -2865,6 +2903,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: +@@ -2920,6 +2962,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, +@@ -2963,6 +3008,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; +@@ -3067,6 +3115,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 || +@@ -3380,6 +3429,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 || +@@ -3388,6 +3438,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; +@@ -3605,6 +3656,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + break; + # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: ++ case KEY_SM2: + if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; +@@ -3624,6 +3676,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) + goto out; + /* FALLTHROUGH */ + case KEY_ECDSA_CERT: ++ case KEY_SM2_CERT: + if ((r = sshbuf_get_bignum2(buf, &exponent)) != 0) + goto out; + if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { +@@ -4519,6 +4572,7 @@ sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf, break; #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: @@ -1471,7 +1514,7 @@ index 1735159..1aee244 100644 if (format == SSHKEY_PRIVATE_PEM) { success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, cipher, passphrase, len, NULL, NULL); -@@ -3485,6 +3502,7 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, +@@ -4580,6 +4634,7 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, #ifdef WITH_OPENSSL case KEY_DSA: case KEY_ECDSA: @@ -1479,7 +1522,7 @@ index 1735159..1aee244 100644 case KEY_RSA: break; /* see below */ #endif /* WITH_OPENSSL */ -@@ -3665,6 +3683,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, +@@ -4760,6 +4815,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); @@ -1490,10 +1533,18 @@ index 1735159..1aee244 100644 sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL || sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), diff --git a/sshkey.h b/sshkey.h -index 8d662d1..c8d2662 100644 +index 43eef5e..3b84096 100644 --- a/sshkey.h +++ b/sshkey.h -@@ -68,6 +68,8 @@ enum sshkey_types { +@@ -31,6 +31,7 @@ + #ifdef WITH_OPENSSL + #include <openssl/rsa.h> + #include <openssl/dsa.h> ++#include <openssl/evp.h> + # ifdef OPENSSL_HAS_ECC + # include <openssl/ec.h> + # include <openssl/ecdsa.h> +@@ -65,6 +66,8 @@ enum sshkey_types { KEY_DSA_CERT, KEY_ECDSA_CERT, KEY_ED25519_CERT, @@ -1502,6 +1553,19 @@ index 8d662d1..c8d2662 100644 KEY_XMSS, KEY_XMSS_CERT, KEY_ECDSA_SK, +@@ -323,6 +326,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) -- 2.23.0 |