mirror of
https://abf.rosa.ru/djam/openssh.git
synced 2025-02-24 02:02:57 +00:00
support GOST (from ALT Linux)
This commit is contained in:
parent
3faae1666e
commit
acc6d5b84f
2 changed files with 646 additions and 1 deletions
636
ALT-openssh-openssl-gost-engine.patch
Normal file
636
ALT-openssh-openssl-gost-engine.patch
Normal file
|
@ -0,0 +1,636 @@
|
|||
From ac75e02d00b0779ad3d48fc1b2bf8af978ae6890 Mon Sep 17 00:00:00 2001
|
||||
From: Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
|
||||
Date: Fri, 10 Aug 2018 15:39:21 +0300
|
||||
Subject: [PATCH] Add support of gost cipher and digests
|
||||
|
||||
[ mikhailnov@ROSA:
|
||||
copied algo names xxx@altlinux.org to xxx,
|
||||
e.g. "magma-ctr@altlinux.org" and "magma-ctr" are the same
|
||||
]
|
||||
|
||||
---
|
||||
Makefile.in | 2 +
|
||||
cipher.c | 24 ++++++++++++-
|
||||
digest-openssl.c | 35 ++++++++++++++++++
|
||||
digest.h | 7 +++-
|
||||
ext-mac.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
ext-mac.h | 38 ++++++++++++++++++++
|
||||
gost-engine.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
gost-engine.h | 24 ++++++++++++
|
||||
mac.c | 49 +++++++++++++++++++++++++-
|
||||
mac.h | 1 +
|
||||
sshd.c | 1 +
|
||||
11 files changed, 378 insertions(+), 3 deletions(-)
|
||||
create mode 100644 ext-mac.c
|
||||
create mode 100644 ext-mac.h
|
||||
create mode 100644 gost-engine.c
|
||||
create mode 100644 gost-engine.h
|
||||
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index 126b2c7..8b6193b 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -102,6 +102,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
|
||||
kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
|
||||
platform-pledge.o platform-tracing.o platform-misc.o
|
||||
|
||||
+LIBSSH_OBJS += ext-mac.o gost-engine.o
|
||||
+
|
||||
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
||||
sshconnect.o sshconnect2.o mux.o
|
||||
|
||||
diff --git a/cipher.c b/cipher.c
|
||||
index 12c5988..6eabcc4 100644
|
||||
--- a/cipher.c
|
||||
+++ b/cipher.c
|
||||
@@ -51,6 +51,8 @@
|
||||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
|
||||
+#include "gost-engine.h"
|
||||
+
|
||||
|
||||
struct sshcipher_ctx {
|
||||
int plaintext;
|
||||
@@ -106,6 +108,22 @@ static const struct sshcipher ciphers[] = {
|
||||
#endif
|
||||
{ "chacha20-poly1305@openssh.com",
|
||||
8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL },
|
||||
+ { "grasshopper-cbc@altlinux.org",
|
||||
+ 16, 32, 0, 0, CFLAG_CBC, EVP_grasshopper_cbc },
|
||||
+ { "grasshopper-cbc",
|
||||
+ 16, 32, 0, 0, CFLAG_CBC, EVP_grasshopper_cbc },
|
||||
+ { "grasshopper-ctr@altlinux.org",
|
||||
+ 16, 32, 0, 0, 0, EVP_grasshopper_ctr },
|
||||
+ { "grasshopper-ctr",
|
||||
+ 16, 32, 0, 0, 0, EVP_grasshopper_ctr },
|
||||
+ { "magma-cbc@altlinux.org",
|
||||
+ 8, 32, 0, 0, CFLAG_CBC, EVP_magma_cbc },
|
||||
+ { "magma-cbc",
|
||||
+ 8, 32, 0, 0, CFLAG_CBC, EVP_magma_cbc },
|
||||
+ { "magma-ctr@altlinux.org",
|
||||
+ 8, 32, 0, 0, 0, EVP_magma_ctr },
|
||||
+ { "magma-ctr",
|
||||
+ 8, 32, 0, 0, 0, EVP_magma_ctr },
|
||||
{ "none", 8, 0, 0, 0, CFLAG_NONE, NULL },
|
||||
|
||||
{ NULL, 0, 0, 0, 0, 0, NULL }
|
||||
@@ -113,6 +123,15 @@ static const struct sshcipher ciphers[] = {
|
||||
|
||||
/*--*/
|
||||
|
||||
+static int
|
||||
+cipher_avaliable(const struct sshcipher * c)
|
||||
+{
|
||||
+ if (c->evptype && c->evptype() == NULL)
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* Returns a comma-separated list of supported ciphers. */
|
||||
char *
|
||||
cipher_alg_list(char sep, int auth_only)
|
||||
@@ -122,6 +141,8 @@ cipher_alg_list(char sep, int auth_only)
|
||||
const struct sshcipher *c;
|
||||
|
||||
for (c = ciphers; c->name != NULL; c++) {
|
||||
+ if (cipher_avaliable(c) < 0)
|
||||
+ continue;
|
||||
if ((c->flags & CFLAG_INTERNAL) != 0)
|
||||
continue;
|
||||
if (auth_only && c->auth_len == 0)
|
||||
@@ -214,7 +235,8 @@ ciphers_valid(const char *names)
|
||||
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
|
||||
(p = strsep(&cp, CIPHER_SEP))) {
|
||||
c = cipher_by_name(p);
|
||||
- if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0) {
|
||||
+ if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0 ||
|
||||
+ cipher_avaliable(c) < 0) {
|
||||
free(cipher_list);
|
||||
return 0;
|
||||
}
|
||||
diff --git a/digest-openssl.c b/digest-openssl.c
|
||||
index da7ed72..536c34f 100644
|
||||
--- a/digest-openssl.c
|
||||
+++ b/digest-openssl.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "sshbuf.h"
|
||||
#include "digest.h"
|
||||
#include "ssherr.h"
|
||||
+#include "gost-engine.h"
|
||||
|
||||
#ifndef HAVE_EVP_RIPEMD160
|
||||
# define EVP_ripemd160 NULL
|
||||
@@ -60,6 +61,9 @@ 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_STREEBOG_256, "STREEBOG_256", 32, EVP_streebog_256 },
|
||||
+ { SSH_DIGEST_STREEBOG_512, "STREEBOG_512", 64, EVP_streebog_512 },
|
||||
+ { SSH_DIGEST_GRASSHOPPER, "GRASSHOPPER-MAC", 16, EVP_grasshopper_omac },
|
||||
{ -1, NULL, 0, NULL },
|
||||
};
|
||||
|
||||
@@ -109,6 +113,16 @@ ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
|
||||
return EVP_MD_CTX_block_size(ctx->mdctx);
|
||||
}
|
||||
|
||||
+int
|
||||
+ssh_digest_avaliable(int alg) {
|
||||
+ const struct ssh_digest *digest = ssh_digest_by_alg(alg);
|
||||
+ if (digest == NULL)
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ if (digest->mdfunc() == NULL)
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
struct ssh_digest_ctx *
|
||||
ssh_digest_start(int alg)
|
||||
{
|
||||
@@ -130,6 +144,27 @@ ssh_digest_start(int alg)
|
||||
}
|
||||
|
||||
int
|
||||
+ssh_digest_set_key(struct ssh_digest_ctx *ctx, const void *key, size_t klen)
|
||||
+{
|
||||
+ const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
|
||||
+ const EVP_MD *md = digest->mdfunc();
|
||||
+
|
||||
+#ifndef EVP_MD_CTRL_SET_KEY
|
||||
+#define EVP_MD_CTRL_SET_KEY (EVP_MD_CTRL_ALG_CTRL+4)
|
||||
+#endif
|
||||
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
+ if (md->md_ctrl &&
|
||||
+ md->md_ctrl(&ctx->mdctx, EVP_MD_CTRL_SET_KEY, klen, (void *)key) != 1)
|
||||
+#else
|
||||
+ int (*md_ctrl)(EVP_MD_CTX *, int, int, void *) = EVP_MD_meth_get_ctrl(md);
|
||||
+ if (md_ctrl &&
|
||||
+ md_ctrl(ctx->mdctx, EVP_MD_CTRL_SET_KEY, klen, (void *)key) != 1)
|
||||
+#endif
|
||||
+ return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
|
||||
{
|
||||
if (from->alg != to->alg)
|
||||
diff --git a/digest.h b/digest.h
|
||||
index 274574d..2fc3df2 100644
|
||||
--- a/digest.h
|
||||
+++ b/digest.h
|
||||
@@ -27,7 +27,10 @@
|
||||
#define SSH_DIGEST_SHA256 2
|
||||
#define SSH_DIGEST_SHA384 3
|
||||
#define SSH_DIGEST_SHA512 4
|
||||
-#define SSH_DIGEST_MAX 5
|
||||
+#define SSH_DIGEST_STREEBOG_256 5
|
||||
+#define SSH_DIGEST_STREEBOG_512 6
|
||||
+#define SSH_DIGEST_GRASSHOPPER 7
|
||||
+#define SSH_DIGEST_MAX 8
|
||||
|
||||
struct sshbuf;
|
||||
struct ssh_digest_ctx;
|
||||
@@ -55,9 +58,11 @@ int ssh_digest_memory(int alg, const void *m, size_t mlen,
|
||||
__attribute__((__bounded__(__buffer__, 4, 5)));
|
||||
int ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
|
||||
__attribute__((__bounded__(__buffer__, 3, 4)));
|
||||
+int ssh_digest_avaliable(int alg);
|
||||
|
||||
/* Update API */
|
||||
struct ssh_digest_ctx *ssh_digest_start(int alg);
|
||||
+int ssh_digest_set_key(struct ssh_digest_ctx *ctx, const void *key, size_t klen);
|
||||
int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
|
||||
__attribute__((__bounded__(__buffer__, 2, 3)));
|
||||
int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx,
|
||||
diff --git a/ext-mac.c b/ext-mac.c
|
||||
new file mode 100644
|
||||
index 0000000..b505394
|
||||
--- /dev/null
|
||||
+++ b/ext-mac.c
|
||||
@@ -0,0 +1,103 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2014 Markus Friedl. All rights reserved.
|
||||
+ * Copyright (c) 2018 Gleb Fotengauer-Malinovskiy. All rights reserved.
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include "includes.h"
|
||||
+
|
||||
+#include <sys/types.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include "sshbuf.h"
|
||||
+#include "digest.h"
|
||||
+#include "ext-mac.h"
|
||||
+
|
||||
+struct ssh_ext_mac_ctx {
|
||||
+ int alg;
|
||||
+ struct ssh_digest_ctx *digest;
|
||||
+ struct ssh_digest_ctx *octx;
|
||||
+};
|
||||
+
|
||||
+size_t
|
||||
+ssh_ext_mac_bytes(int alg)
|
||||
+{
|
||||
+ return ssh_digest_bytes(alg);
|
||||
+}
|
||||
+
|
||||
+struct ssh_ext_mac_ctx *
|
||||
+ssh_ext_mac_start(int alg)
|
||||
+{
|
||||
+ struct ssh_ext_mac_ctx *ret;
|
||||
+
|
||||
+ if ((ret = calloc(1, sizeof(*ret))) == NULL)
|
||||
+ return NULL;
|
||||
+ ret->alg = alg;
|
||||
+ if ((ret->digest = ssh_digest_start(alg)) == NULL ||
|
||||
+ (ret->octx = ssh_digest_start(alg)) == NULL)
|
||||
+ goto fail;
|
||||
+ return ret;
|
||||
+fail:
|
||||
+ ssh_ext_mac_free(ret);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+ssh_ext_mac_init(struct ssh_ext_mac_ctx *ctx, const void *key, size_t klen)
|
||||
+{
|
||||
+ if (key != NULL && ssh_digest_set_key(ctx->octx, key, klen) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ /* (re)start with octx */
|
||||
+ if (ssh_digest_copy_state(ctx->octx, ctx->digest) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+ssh_ext_mac_update(struct ssh_ext_mac_ctx *ctx, const void *m, size_t mlen)
|
||||
+{
|
||||
+ return ssh_digest_update(ctx->digest, m, mlen);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+ssh_ext_mac_update_buffer(struct ssh_ext_mac_ctx *ctx, const struct sshbuf *b)
|
||||
+{
|
||||
+ return ssh_digest_update_buffer(ctx->digest, b);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+ssh_ext_mac_final(struct ssh_ext_mac_ctx *ctx, u_char *d, size_t dlen)
|
||||
+{
|
||||
+ size_t len;
|
||||
+
|
||||
+ len = ssh_digest_bytes(ctx->alg);
|
||||
+ if (dlen < len ||
|
||||
+ ssh_digest_final(ctx->digest, d, dlen))
|
||||
+ return -1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+ssh_ext_mac_free(struct ssh_ext_mac_ctx *ctx)
|
||||
+{
|
||||
+ if (ctx != NULL) {
|
||||
+ ssh_digest_free(ctx->digest);
|
||||
+ ssh_digest_free(ctx->octx);
|
||||
+ explicit_bzero(ctx, sizeof(*ctx));
|
||||
+ free(ctx);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/ext-mac.h b/ext-mac.h
|
||||
new file mode 100644
|
||||
index 0000000..a55209c
|
||||
--- /dev/null
|
||||
+++ b/ext-mac.h
|
||||
@@ -0,0 +1,38 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2014 Markus Friedl. All rights reserved.
|
||||
+ * Copyright (c) 2018 Gleb Fotengauer-Malinovskiy. All rights reserved.
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _EXT_MAC_H
|
||||
+#define _EXT_MAC_H
|
||||
+
|
||||
+/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
|
||||
+size_t ssh_ext_mac_bytes(int alg);
|
||||
+
|
||||
+struct sshbuf;
|
||||
+struct ssh_ext_mac_ctx;
|
||||
+struct ssh_ext_mac_ctx *ssh_ext_mac_start(int alg);
|
||||
+
|
||||
+/* Sets the state of the EXT_MAC or resets the state if key == NULL */
|
||||
+int ssh_ext_mac_init(struct ssh_ext_mac_ctx *ctx, const void *key, size_t klen)
|
||||
+ __attribute__((__bounded__(__buffer__, 2, 3)));
|
||||
+int ssh_ext_mac_update(struct ssh_ext_mac_ctx *ctx, const void *m, size_t mlen)
|
||||
+ __attribute__((__bounded__(__buffer__, 2, 3)));
|
||||
+int ssh_ext_mac_update_buffer(struct ssh_ext_mac_ctx *ctx, const struct sshbuf *b);
|
||||
+int ssh_ext_mac_final(struct ssh_ext_mac_ctx *ctx, u_char *d, size_t dlen)
|
||||
+ __attribute__((__bounded__(__buffer__, 2, 3)));
|
||||
+void ssh_ext_mac_free(struct ssh_ext_mac_ctx *ctx);
|
||||
+
|
||||
+#endif /* _EXT_MAC_H */
|
||||
diff --git a/gost-engine.c b/gost-engine.c
|
||||
new file mode 100644
|
||||
index 0000000..c0aac3f
|
||||
--- /dev/null
|
||||
+++ b/gost-engine.c
|
||||
@@ -0,0 +1,97 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2018 Gleb Fotengauer-Malinovskiy. All rights reserved.
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include <openssl/engine.h>
|
||||
+#include <openssl/conf.h>
|
||||
+
|
||||
+#include "openbsd-compat/openssl-compat.h"
|
||||
+
|
||||
+static void
|
||||
+init_algorithms() {
|
||||
+ static int algorithms_init = -1;
|
||||
+
|
||||
+ if (algorithms_init < 0) {
|
||||
+ OpenSSL_add_all_algorithms();
|
||||
+ ERR_load_crypto_strings();
|
||||
+ algorithms_init = 1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static const EVP_MD*
|
||||
+get_gost_md_by_nid(int nid)
|
||||
+{
|
||||
+ init_algorithms();
|
||||
+
|
||||
+ const EVP_MD* digest;
|
||||
+ if (!(digest = EVP_get_digestbynid(nid)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return digest;
|
||||
+}
|
||||
+
|
||||
+static const EVP_CIPHER*
|
||||
+get_gost_cipher_by_nid(int nid)
|
||||
+{
|
||||
+ init_algorithms();
|
||||
+
|
||||
+ const EVP_CIPHER *cipher;
|
||||
+ if (!(cipher = EVP_get_cipherbynid(nid)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return cipher;
|
||||
+}
|
||||
+
|
||||
+const EVP_MD*
|
||||
+EVP_streebog_256()
|
||||
+{
|
||||
+ return get_gost_md_by_nid(NID_id_GostR3411_2012_256);
|
||||
+}
|
||||
+
|
||||
+const EVP_MD*
|
||||
+EVP_streebog_512()
|
||||
+{
|
||||
+ return get_gost_md_by_nid(NID_id_GostR3411_2012_512);
|
||||
+}
|
||||
+
|
||||
+const EVP_MD*
|
||||
+EVP_grasshopper_omac()
|
||||
+{
|
||||
+ return get_gost_md_by_nid(NID_grasshopper_mac);
|
||||
+}
|
||||
+
|
||||
+const EVP_CIPHER*
|
||||
+EVP_magma_cbc()
|
||||
+{
|
||||
+ return get_gost_cipher_by_nid(NID_magma_cbc);
|
||||
+}
|
||||
+
|
||||
+const EVP_CIPHER*
|
||||
+EVP_magma_ctr()
|
||||
+{
|
||||
+ return get_gost_cipher_by_nid(NID_magma_ctr);
|
||||
+}
|
||||
+
|
||||
+const EVP_CIPHER*
|
||||
+EVP_grasshopper_cbc()
|
||||
+{
|
||||
+ return get_gost_cipher_by_nid(NID_grasshopper_cbc);
|
||||
+}
|
||||
+
|
||||
+const EVP_CIPHER*
|
||||
+EVP_grasshopper_ctr()
|
||||
+{
|
||||
+ return get_gost_cipher_by_nid(NID_grasshopper_ctr);
|
||||
+}
|
||||
diff --git a/gost-engine.h b/gost-engine.h
|
||||
new file mode 100644
|
||||
index 0000000..54e4b11
|
||||
--- /dev/null
|
||||
+++ b/gost-engine.h
|
||||
@@ -0,0 +1,24 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2018 Gleb Fotengauer-Malinovskiy. All rights reserved.
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+const EVP_MD* EVP_streebog_256();
|
||||
+const EVP_MD* EVP_streebog_512();
|
||||
+const EVP_MD* EVP_grasshopper_omac();
|
||||
+
|
||||
+const EVP_CIPHER* EVP_magma_cbc();
|
||||
+const EVP_CIPHER* EVP_magma_ctr();
|
||||
+const EVP_CIPHER* EVP_grasshopper_cbc();
|
||||
+const EVP_CIPHER* EVP_grasshopper_ctr();
|
||||
diff --git a/mac.c b/mac.c
|
||||
index 51dc11d..be27109 100644
|
||||
--- a/mac.c
|
||||
+++ b/mac.c
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "digest.h"
|
||||
#include "hmac.h"
|
||||
+#include "ext-mac.h"
|
||||
#include "umac.h"
|
||||
#include "mac.h"
|
||||
#include "misc.h"
|
||||
@@ -43,6 +44,7 @@
|
||||
#define SSH_DIGEST 1 /* SSH_DIGEST_XXX */
|
||||
#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */
|
||||
#define SSH_UMAC128 3
|
||||
+#define SSH_EXTMAC 4
|
||||
|
||||
struct macalg {
|
||||
char *name;
|
||||
@@ -79,6 +81,17 @@ static const struct macalg macs[] = {
|
||||
{ "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 },
|
||||
{ "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 },
|
||||
|
||||
+ { "grasshopper-mac@altlinux.org", SSH_EXTMAC, SSH_DIGEST_GRASSHOPPER, 0, 256, 64, 0 },
|
||||
+
|
||||
+ { "hmac-gostr3411-2012-256@altlinux.org", SSH_DIGEST, SSH_DIGEST_STREEBOG_256, 0, 0, 0, 0 },
|
||||
+ { "hmac-streebog-256@altlinux.org", SSH_DIGEST, SSH_DIGEST_STREEBOG_256, 0, 0, 0, 0 },
|
||||
+ { "hmac-gostr3411-2012-512@altlinux.org", SSH_DIGEST, SSH_DIGEST_STREEBOG_512, 0, 0, 0, 0 },
|
||||
+ { "hmac-streebog-512@altlinux.org", SSH_DIGEST, SSH_DIGEST_STREEBOG_512, 0, 0, 0, 0 },
|
||||
+
|
||||
+ { "hmac-gostr3411-2012-256-etm@altlinux.org", SSH_DIGEST, SSH_DIGEST_STREEBOG_256, 0, 0, 0, 1 },
|
||||
+ { "hmac-streebog-256-etm@altlinux.org", SSH_DIGEST, SSH_DIGEST_STREEBOG_256, 0, 0, 0, 1 },
|
||||
+ { "hmac-gostr3411-2012-512-etm@altlinux.org", SSH_DIGEST, SSH_DIGEST_STREEBOG_512, 0, 0, 0, 1 },
|
||||
+ { "hmac-streebog-512-etm@altlinux.org", SSH_DIGEST, SSH_DIGEST_STREEBOG_512, 0, 0, 0, 1 },
|
||||
{ NULL, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -91,6 +104,8 @@ mac_alg_list(char sep)
|
||||
const struct macalg *m;
|
||||
|
||||
for (m = macs; m->name != NULL; m++) {
|
||||
+ if (ssh_digest_avaliable(m->alg) < 0)
|
||||
+ continue;
|
||||
if (ret != NULL)
|
||||
ret[rlen++] = sep;
|
||||
nlen = strlen(m->name);
|
||||
@@ -113,6 +128,11 @@ mac_setup_by_alg(struct sshmac *mac, const struct macalg *macalg)
|
||||
if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg);
|
||||
+ } else if (mac->type == SSH_EXTMAC) {
|
||||
+ if ((mac->ext_mac_ctx = ssh_ext_mac_start(macalg->alg)) == NULL)
|
||||
+ return SSH_ERR_ALLOC_FAIL;
|
||||
+ mac->mac_len = macalg->len / 8;
|
||||
+ mac->key_len = macalg->key_len / 8;
|
||||
} else {
|
||||
mac->mac_len = macalg->len / 8;
|
||||
mac->key_len = macalg->key_len / 8;
|
||||
@@ -150,6 +170,11 @@ mac_init(struct sshmac *mac)
|
||||
ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
return 0;
|
||||
+ case SSH_EXTMAC:
|
||||
+ if (mac->ext_mac_ctx == NULL ||
|
||||
+ ssh_ext_mac_init(mac->ext_mac_ctx, mac->key, mac->key_len) < 0)
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ return 0;
|
||||
case SSH_UMAC:
|
||||
if ((mac->umac_ctx = umac_new(mac->key)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
@@ -188,6 +213,15 @@ mac_compute(struct sshmac *mac, u_int32_t seqno,
|
||||
ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
break;
|
||||
+ case SSH_EXTMAC:
|
||||
+ put_u32(b, seqno);
|
||||
+ /* reset HMAC context */
|
||||
+ if (ssh_ext_mac_init(mac->ext_mac_ctx, NULL, 0) < 0 ||
|
||||
+ ssh_ext_mac_update(mac->ext_mac_ctx, b, sizeof(b)) < 0 ||
|
||||
+ ssh_ext_mac_update(mac->ext_mac_ctx, data, datalen) < 0 ||
|
||||
+ ssh_ext_mac_final(mac->ext_mac_ctx, u.m, sizeof(u.m)) < 0)
|
||||
+ return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ break;
|
||||
case SSH_UMAC:
|
||||
POKE_U64(nonce, seqno);
|
||||
umac_update(mac->umac_ctx, data, datalen);
|
||||
@@ -242,6 +276,19 @@ mac_clear(struct sshmac *mac)
|
||||
mac->umac_ctx = NULL;
|
||||
}
|
||||
|
||||
+static int
|
||||
+mac_avaliable(char *name)
|
||||
+{
|
||||
+ const struct macalg *m;
|
||||
+
|
||||
+ for (m = macs; m->name != NULL; m++) {
|
||||
+ if (strcmp(name, m->name) != 0)
|
||||
+ continue;
|
||||
+ return ssh_digest_avaliable(m->alg);
|
||||
+ }
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+}
|
||||
+
|
||||
/* XXX copied from ciphers_valid */
|
||||
#define MAC_SEP ","
|
||||
int
|
||||
@@ -255,7 +302,7 @@ mac_valid(const char *names)
|
||||
return 0;
|
||||
for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0';
|
||||
(p = strsep(&cp, MAC_SEP))) {
|
||||
- if (mac_setup(NULL, p) < 0) {
|
||||
+ if (mac_avaliable(p) < 0 || mac_setup(NULL, p) < 0) {
|
||||
free(maclist);
|
||||
return 0;
|
||||
}
|
||||
diff --git a/mac.h b/mac.h
|
||||
index 0b119d7..7612f93 100644
|
||||
--- a/mac.h
|
||||
+++ b/mac.h
|
||||
@@ -37,6 +37,7 @@ struct sshmac {
|
||||
int type;
|
||||
int etm; /* Encrypt-then-MAC */
|
||||
struct ssh_hmac_ctx *hmac_ctx;
|
||||
+ struct ssh_ext_mac_ctx *ext_mac_ctx;
|
||||
struct umac_ctx *umac_ctx;
|
||||
};
|
||||
|
||||
diff --git a/sshd.c b/sshd.c
|
||||
index 7a3384c..b7c092e 100644
|
||||
--- a/sshd.c
|
||||
+++ b/sshd.c
|
||||
@@ -78,6 +78,7 @@
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rand.h>
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
+#include "gost-engine.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SECUREWARE
|
||||
--
|
||||
1.7.3.3
|
||||
|
11
openssh.spec
11
openssh.spec
|
@ -14,7 +14,7 @@
|
|||
Summary: OpenSSH free Secure Shell (SSH) implementation
|
||||
Name: openssh
|
||||
Version: 8.2p1
|
||||
Release: 1
|
||||
Release: 2
|
||||
License: BSD
|
||||
Group: Networking/Remote access
|
||||
Url: http://www.openssh.com/
|
||||
|
@ -56,6 +56,15 @@ Patch31: openssh-6.6p1-keycat.patch
|
|||
# Pass inetd flags for SELinux down to openbsd compat level
|
||||
Patch32: openssh-7.6p1-cleanup-selinux.patch
|
||||
|
||||
# Support of GOST R 34.12-2015 and other GOSTs
|
||||
# From http://git.altlinux.org/gears/o/openssh-gostcrypto.git
|
||||
# Adjusted a bit for compatibility with both
|
||||
# "xxx@altlinux.org" and "xxx" as algo names.
|
||||
# TODO: get rid of dlopen()-ing gost-engine and use LibreSSL,
|
||||
# delete checks of availability of algos (not needed in case of
|
||||
# LibreSSL where they are known at compile time).
|
||||
Patch40: ALT-openssh-openssl-gost-engine.patch
|
||||
|
||||
BuildRequires: groff-base
|
||||
BuildRequires: systemd-units
|
||||
%if %{with ldap}
|
||||
|
|
Loading…
Add table
Reference in a new issue