summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2003-05-15 13:37:19 +1000
committerDamien Miller <djm@mindrot.org>2003-05-15 13:37:19 +1000
commit3a3261ff99f660b8191f3e5366054566fb0a05de (patch)
tree9ab551d0385a2011027cc63cfc433ec5502ba395
parentb0622653baa8e4136e116945fdd1c393ab0eaba3 (diff)
downloadopenssh-git-3a3261ff99f660b8191f3e5366054566fb0a05de.tar.gz
- markus@cvs.openbsd.org 2003/05/15 03:08:29
[cipher.c cipher-bf1.c cipher-aes.c cipher-3des1.c] split out custom EVP ciphers
-rw-r--r--ChangeLog5
-rw-r--r--Makefile.in5
-rw-r--r--cipher-3des1.c171
-rw-r--r--cipher-aes.c156
-rw-r--r--cipher-bf1.c97
-rw-r--r--cipher.c338
6 files changed, 437 insertions, 335 deletions
diff --git a/ChangeLog b/ChangeLog
index 5243876e..2e7aeb13 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,6 +22,9 @@
- jakob@cvs.openbsd.org 2003/05/15 02:27:15
[dns.c]
add missing freerrset
+ - markus@cvs.openbsd.org 2003/05/15 03:08:29
+ [cipher.c cipher-bf1.c cipher-aes.c cipher-3des1.c]
+ split out custom EVP ciphers
- (djm) Always parse UsePAM
- (djm) Configure glue for DNS support (code doesn't work in portable yet)
- (djm) Import getrrsetbyname() function from OpenBSD libc (for DNS support)
@@ -1502,4 +1505,4 @@
save auth method before monitor_reset_key_state(); bugzilla bug #284;
ok provos@
-$Id: ChangeLog,v 1.2710 2003/05/15 03:27:28 djm Exp $
+$Id: ChangeLog,v 1.2711 2003/05/15 03:37:19 djm Exp $
diff --git a/Makefile.in b/Makefile.in
index 5758d0db..8bdef203 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.234 2003/05/15 03:23:07 djm Exp $
+# $Id: Makefile.in,v 1.235 2003/05/15 03:37:20 djm Exp $
# uncomment if you run a non bourne compatable shell. Ie. csh
#SHELL = @SH@
@@ -61,7 +61,8 @@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT)
LIBSSH_OBJS=authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o \
- cipher.o compat.o compress.o crc32.o deattack.o fatal.o \
+ cipher.o cipher-aes.o cipher-bf1.o cipher-3des1.o \
+ compat.o compress.o crc32.o deattack.o fatal.o \
hostfile.o log.o match.o mpaux.o nchan.o packet.o radix.o \
readpass.o rsa.o tildexpand.o ttymodes.o xmalloc.o atomicio.o \
key.o dispatch.o kex.o mac.o uuencode.o misc.o \
diff --git a/cipher-3des1.c b/cipher-3des1.c
new file mode 100644
index 00000000..f9a35239
--- /dev/null
+++ b/cipher-3des1.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2003 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: cipher-3des1.c,v 1.1 2003/05/15 03:08:29 markus Exp $");
+
+#include <openssl/evp.h>
+#include "xmalloc.h"
+#include "log.h"
+
+/*
+ * This is used by SSH1:
+ *
+ * What kind of triple DES are these 2 routines?
+ *
+ * Why is there a redundant initialization vector?
+ *
+ * If only iv3 was used, then, this would till effect have been
+ * outer-cbc. However, there is also a private iv1 == iv2 which
+ * perhaps makes differential analysis easier. On the other hand, the
+ * private iv1 probably makes the CRC-32 attack ineffective. This is a
+ * result of that there is no longer any known iv1 to use when
+ * choosing the X block.
+ */
+struct ssh1_3des_ctx
+{
+ EVP_CIPHER_CTX k1, k2, k3;
+};
+
+const EVP_CIPHER * evp_ssh1_3des(void);
+void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
+
+static int
+ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
+ int enc)
+{
+ struct ssh1_3des_ctx *c;
+ u_char *k1, *k2, *k3;
+
+ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+ c = xmalloc(sizeof(*c));
+ EVP_CIPHER_CTX_set_app_data(ctx, c);
+ }
+ if (key == NULL)
+ return (1);
+ if (enc == -1)
+ enc = ctx->encrypt;
+ k1 = k2 = k3 = (u_char *) key;
+ k2 += 8;
+ if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
+ if (enc)
+ k3 += 16;
+ else
+ k1 += 16;
+ }
+ EVP_CIPHER_CTX_init(&c->k1);
+ EVP_CIPHER_CTX_init(&c->k2);
+ EVP_CIPHER_CTX_init(&c->k3);
+#ifdef SSH_OLD_EVP
+ EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
+ EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
+ EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
+#else
+ if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
+ EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
+ EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
+ memset(c, 0, sizeof(*c));
+ xfree(c);
+ EVP_CIPHER_CTX_set_app_data(ctx, NULL);
+ return (0);
+ }
+#endif
+ return (1);
+}
+
+static int
+ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
+{
+ struct ssh1_3des_ctx *c;
+
+ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+ error("ssh1_3des_cbc: no context");
+ return (0);
+ }
+#ifdef SSH_OLD_EVP
+ EVP_Cipher(&c->k1, dest, (u_char *)src, len);
+ EVP_Cipher(&c->k2, dest, dest, len);
+ EVP_Cipher(&c->k3, dest, dest, len);
+#else
+ if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
+ EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
+ EVP_Cipher(&c->k3, dest, dest, len) == 0)
+ return (0);
+#endif
+ return (1);
+}
+
+static int
+ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
+{
+ struct ssh1_3des_ctx *c;
+
+ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+ memset(c, 0, sizeof(*c));
+ xfree(c);
+ EVP_CIPHER_CTX_set_app_data(ctx, NULL);
+ }
+ return (1);
+}
+
+void
+ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
+{
+ struct ssh1_3des_ctx *c;
+
+ if (len != 24)
+ fatal("%s: bad 3des iv length: %d", __func__, len);
+ if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
+ fatal("%s: no 3des context", __func__);
+ if (doset) {
+ debug3("%s: Installed 3DES IV", __func__);
+ memcpy(c->k1.iv, iv, 8);
+ memcpy(c->k2.iv, iv + 8, 8);
+ memcpy(c->k3.iv, iv + 16, 8);
+ } else {
+ debug3("%s: Copying 3DES IV", __func__);
+ memcpy(iv, c->k1.iv, 8);
+ memcpy(iv + 8, c->k2.iv, 8);
+ memcpy(iv + 16, c->k3.iv, 8);
+ }
+}
+
+const EVP_CIPHER *
+evp_ssh1_3des(void)
+{
+ static EVP_CIPHER ssh1_3des;
+
+ memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
+ ssh1_3des.nid = NID_undef;
+ ssh1_3des.block_size = 8;
+ ssh1_3des.iv_len = 0;
+ ssh1_3des.key_len = 16;
+ ssh1_3des.init = ssh1_3des_init;
+ ssh1_3des.cleanup = ssh1_3des_cleanup;
+ ssh1_3des.do_cipher = ssh1_3des_cbc;
+#ifndef SSH_OLD_EVP
+ ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
+#endif
+ return (&ssh1_3des);
+}
diff --git a/cipher-aes.c b/cipher-aes.c
new file mode 100644
index 00000000..bbfbe721
--- /dev/null
+++ b/cipher-aes.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2003 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+#include "includes.h"
+RCSID("$OpenBSD: cipher-aes.c,v 1.1 2003/05/15 03:08:29 markus Exp $");
+
+#include <openssl/evp.h>
+#include "rijndael.h"
+#include "xmalloc.h"
+#include "log.h"
+
+#define RIJNDAEL_BLOCKSIZE 16
+struct ssh_rijndael_ctx
+{
+ rijndael_ctx r_ctx;
+ u_char r_iv[RIJNDAEL_BLOCKSIZE];
+};
+
+const EVP_CIPHER * evp_rijndael(void);
+void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
+
+static int
+ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
+ int enc)
+{
+ struct ssh_rijndael_ctx *c;
+
+ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+ c = xmalloc(sizeof(*c));
+ EVP_CIPHER_CTX_set_app_data(ctx, c);
+ }
+ if (key != NULL) {
+ if (enc == -1)
+ enc = ctx->encrypt;
+ rijndael_set_key(&c->r_ctx, (u_char *)key,
+ 8*EVP_CIPHER_CTX_key_length(ctx), enc);
+ }
+ if (iv != NULL)
+ memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
+ return (1);
+}
+
+static int
+ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
+ u_int len)
+{
+ struct ssh_rijndael_ctx *c;
+ u_char buf[RIJNDAEL_BLOCKSIZE];
+ u_char *cprev, *cnow, *plain, *ivp;
+ int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
+
+ if (len == 0)
+ return (1);
+ if (len % RIJNDAEL_BLOCKSIZE)
+ fatal("ssh_rijndael_cbc: bad len %d", len);
+ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
+ error("ssh_rijndael_cbc: no context");
+ return (0);
+ }
+ if (ctx->encrypt) {
+ cnow = dest;
+ plain = (u_char *)src;
+ cprev = c->r_iv;
+ for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
+ cnow+=RIJNDAEL_BLOCKSIZE) {
+ for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
+ buf[j] = plain[j] ^ cprev[j];
+ rijndael_encrypt(&c->r_ctx, buf, cnow);
+ cprev = cnow;
+ }
+ memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
+ } else {
+ cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
+ plain = dest+len-RIJNDAEL_BLOCKSIZE;
+
+ memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
+ for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
+ plain-=RIJNDAEL_BLOCKSIZE) {
+ rijndael_decrypt(&c->r_ctx, cnow, plain);
+ ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
+ for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
+ plain[j] ^= ivp[j];
+ }
+ memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
+ }
+ return (1);
+}
+
+static int
+ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
+{
+ struct ssh_rijndael_ctx *c;
+
+ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+ memset(c, 0, sizeof(*c));
+ xfree(c);
+ EVP_CIPHER_CTX_set_app_data(ctx, NULL);
+ }
+ return (1);
+}
+
+void
+ssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
+{
+ struct ssh_rijndael_ctx *c;
+
+ if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
+ fatal("ssh_rijndael_iv: no context");
+ if (doset)
+ memcpy(c->r_iv, iv, len);
+ else
+ memcpy(iv, c->r_iv, len);
+}
+
+const EVP_CIPHER *
+evp_rijndael(void)
+{
+ static EVP_CIPHER rijndal_cbc;
+
+ memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
+ rijndal_cbc.nid = NID_undef;
+ rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
+ rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
+ rijndal_cbc.key_len = 16;
+ rijndal_cbc.init = ssh_rijndael_init;
+ rijndal_cbc.cleanup = ssh_rijndael_cleanup;
+ rijndal_cbc.do_cipher = ssh_rijndael_cbc;
+#ifndef SSH_OLD_EVP
+ rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
+#endif
+ return (&rijndal_cbc);
+}
+#endif
diff --git a/cipher-bf1.c b/cipher-bf1.c
new file mode 100644
index 00000000..64578bae
--- /dev/null
+++ b/cipher-bf1.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2003 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: cipher-bf1.c,v 1.1 2003/05/15 03:08:29 markus Exp $");
+
+#include <openssl/evp.h>
+#include "xmalloc.h"
+#include "log.h"
+/*
+ * SSH1 uses a variation on Blowfish, all bytes must be swapped before
+ * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
+ */
+
+const EVP_CIPHER * evp_ssh1_bf(void);
+
+static void
+swap_bytes(const u_char *src, u_char *dst, int n)
+{
+ u_char c[4];
+
+ /* Process 4 bytes every lap. */
+ for (n = n / 4; n > 0; n--) {
+ c[3] = *src++;
+ c[2] = *src++;
+ c[1] = *src++;
+ c[0] = *src++;
+
+ *dst++ = c[0];
+ *dst++ = c[1];
+ *dst++ = c[2];
+ *dst++ = c[3];
+ }
+}
+
+#ifdef SSH_OLD_EVP
+static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ if (iv != NULL)
+ memcpy (&(ctx->oiv[0]), iv, 8);
+ memcpy (&(ctx->iv[0]), &(ctx->oiv[0]), 8);
+ if (key != NULL)
+ BF_set_key (&(ctx->c.bf_ks), EVP_CIPHER_CTX_key_length (ctx),
+ key);
+}
+#endif
+
+static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
+
+static int
+bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
+{
+ int ret;
+
+ swap_bytes(in, out, len);
+ ret = (*orig_bf)(ctx, out, out, len);
+ swap_bytes(out, out, len);
+ return (ret);
+}
+
+const EVP_CIPHER *
+evp_ssh1_bf(void)
+{
+ static EVP_CIPHER ssh1_bf;
+
+ memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
+ orig_bf = ssh1_bf.do_cipher;
+ ssh1_bf.nid = NID_undef;
+#ifdef SSH_OLD_EVP
+ ssh1_bf.init = bf_ssh1_init;
+#endif
+ ssh1_bf.do_cipher = bf_ssh1_cipher;
+ ssh1_bf.key_len = 32;
+ return (&ssh1_bf);
+}
diff --git a/cipher.c b/cipher.c
index b6637b64..acb436c8 100644
--- a/cipher.c
+++ b/cipher.c
@@ -35,7 +35,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: cipher.c,v 1.63 2003/04/12 10:13:57 markus Exp $");
+RCSID("$OpenBSD: cipher.c,v 1.64 2003/05/15 03:08:29 markus Exp $");
#include "xmalloc.h"
#include "log.h"
@@ -49,11 +49,12 @@ RCSID("$OpenBSD: cipher.c,v 1.63 2003/04/12 10:13:57 markus Exp $");
#endif
#if OPENSSL_VERSION_NUMBER < 0x00907000L
-#include "rijndael.h"
-static const EVP_CIPHER *evp_rijndael(void);
+extern const EVP_CIPHER *evp_rijndael(void);
+extern void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
#endif
-static const EVP_CIPHER *evp_ssh1_3des(void);
-static const EVP_CIPHER *evp_ssh1_bf(void);
+extern const EVP_CIPHER *evp_ssh1_bf(void);
+extern const EVP_CIPHER *evp_ssh1_3des(void);
+extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
struct Cipher {
char *name;
@@ -296,333 +297,6 @@ cipher_set_key_string(CipherContext *cc, Cipher *cipher,
memset(&md, 0, sizeof(md));
}
-/* Implementations for other non-EVP ciphers */
-
-/*
- * This is used by SSH1:
- *
- * What kind of triple DES are these 2 routines?
- *
- * Why is there a redundant initialization vector?
- *
- * If only iv3 was used, then, this would till effect have been
- * outer-cbc. However, there is also a private iv1 == iv2 which
- * perhaps makes differential analysis easier. On the other hand, the
- * private iv1 probably makes the CRC-32 attack ineffective. This is a
- * result of that there is no longer any known iv1 to use when
- * choosing the X block.
- */
-struct ssh1_3des_ctx
-{
- EVP_CIPHER_CTX k1, k2, k3;
-};
-
-static int
-ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
- int enc)
-{
- struct ssh1_3des_ctx *c;
- u_char *k1, *k2, *k3;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
- c = xmalloc(sizeof(*c));
- EVP_CIPHER_CTX_set_app_data(ctx, c);
- }
- if (key == NULL)
- return (1);
- if (enc == -1)
- enc = ctx->encrypt;
- k1 = k2 = k3 = (u_char *) key;
- k2 += 8;
- if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
- if (enc)
- k3 += 16;
- else
- k1 += 16;
- }
- EVP_CIPHER_CTX_init(&c->k1);
- EVP_CIPHER_CTX_init(&c->k2);
- EVP_CIPHER_CTX_init(&c->k3);
-#ifdef SSH_OLD_EVP
- EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
- EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
- EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
-#else
- if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
- EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
- EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
- memset(c, 0, sizeof(*c));
- xfree(c);
- EVP_CIPHER_CTX_set_app_data(ctx, NULL);
- return (0);
- }
-#endif
- return (1);
-}
-
-static int
-ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
-{
- struct ssh1_3des_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
- error("ssh1_3des_cbc: no context");
- return (0);
- }
-#ifdef SSH_OLD_EVP
- EVP_Cipher(&c->k1, dest, (u_char *)src, len);
- EVP_Cipher(&c->k2, dest, dest, len);
- EVP_Cipher(&c->k3, dest, dest, len);
-#else
- if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
- EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
- EVP_Cipher(&c->k3, dest, dest, len) == 0)
- return (0);
-#endif
- return (1);
-}
-
-static int
-ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
-{
- struct ssh1_3des_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
- memset(c, 0, sizeof(*c));
- xfree(c);
- EVP_CIPHER_CTX_set_app_data(ctx, NULL);
- }
- return (1);
-}
-
-static void
-ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
-{
- struct ssh1_3des_ctx *c;
-
- if (len != 24)
- fatal("%s: bad 3des iv length: %d", __func__, len);
- if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
- fatal("%s: no 3des context", __func__);
- if (doset) {
- debug3("%s: Installed 3DES IV", __func__);
- memcpy(c->k1.iv, iv, 8);
- memcpy(c->k2.iv, iv + 8, 8);
- memcpy(c->k3.iv, iv + 16, 8);
- } else {
- debug3("%s: Copying 3DES IV", __func__);
- memcpy(iv, c->k1.iv, 8);
- memcpy(iv + 8, c->k2.iv, 8);
- memcpy(iv + 16, c->k3.iv, 8);
- }
-}
-
-static const EVP_CIPHER *
-evp_ssh1_3des(void)
-{
- static EVP_CIPHER ssh1_3des;
-
- memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
- ssh1_3des.nid = NID_undef;
- ssh1_3des.block_size = 8;
- ssh1_3des.iv_len = 0;
- ssh1_3des.key_len = 16;
- ssh1_3des.init = ssh1_3des_init;
- ssh1_3des.cleanup = ssh1_3des_cleanup;
- ssh1_3des.do_cipher = ssh1_3des_cbc;
-#ifndef SSH_OLD_EVP
- ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
-#endif
- return (&ssh1_3des);
-}
-
-/*
- * SSH1 uses a variation on Blowfish, all bytes must be swapped before
- * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
- */
-static void
-swap_bytes(const u_char *src, u_char *dst, int n)
-{
- u_char c[4];
-
- /* Process 4 bytes every lap. */
- for (n = n / 4; n > 0; n--) {
- c[3] = *src++;
- c[2] = *src++;
- c[1] = *src++;
- c[0] = *src++;
-
- *dst++ = c[0];
- *dst++ = c[1];
- *dst++ = c[2];
- *dst++ = c[3];
- }
-}
-
-#ifdef SSH_OLD_EVP
-static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key,
- const unsigned char *iv, int enc)
-{
- if (iv != NULL)
- memcpy (&(ctx->oiv[0]), iv, 8);
- memcpy (&(ctx->iv[0]), &(ctx->oiv[0]), 8);
- if (key != NULL)
- BF_set_key (&(ctx->c.bf_ks), EVP_CIPHER_CTX_key_length (ctx),
- key);
-}
-#endif
-static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
-
-static int
-bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
-{
- int ret;
-
- swap_bytes(in, out, len);
- ret = (*orig_bf)(ctx, out, out, len);
- swap_bytes(out, out, len);
- return (ret);
-}
-
-static const EVP_CIPHER *
-evp_ssh1_bf(void)
-{
- static EVP_CIPHER ssh1_bf;
-
- memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
- orig_bf = ssh1_bf.do_cipher;
- ssh1_bf.nid = NID_undef;
-#ifdef SSH_OLD_EVP
- ssh1_bf.init = bf_ssh1_init;
-#endif
- ssh1_bf.do_cipher = bf_ssh1_cipher;
- ssh1_bf.key_len = 32;
- return (&ssh1_bf);
-}
-
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
-/* RIJNDAEL */
-#define RIJNDAEL_BLOCKSIZE 16
-struct ssh_rijndael_ctx
-{
- rijndael_ctx r_ctx;
- u_char r_iv[RIJNDAEL_BLOCKSIZE];
-};
-
-static int
-ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
- int enc)
-{
- struct ssh_rijndael_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
- c = xmalloc(sizeof(*c));
- EVP_CIPHER_CTX_set_app_data(ctx, c);
- }
- if (key != NULL) {
- if (enc == -1)
- enc = ctx->encrypt;
- rijndael_set_key(&c->r_ctx, (u_char *)key,
- 8*EVP_CIPHER_CTX_key_length(ctx), enc);
- }
- if (iv != NULL)
- memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
- return (1);
-}
-
-static int
-ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
- u_int len)
-{
- struct ssh_rijndael_ctx *c;
- u_char buf[RIJNDAEL_BLOCKSIZE];
- u_char *cprev, *cnow, *plain, *ivp;
- int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
-
- if (len == 0)
- return (1);
- if (len % RIJNDAEL_BLOCKSIZE)
- fatal("ssh_rijndael_cbc: bad len %d", len);
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
- error("ssh_rijndael_cbc: no context");
- return (0);
- }
- if (ctx->encrypt) {
- cnow = dest;
- plain = (u_char *)src;
- cprev = c->r_iv;
- for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
- cnow+=RIJNDAEL_BLOCKSIZE) {
- for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
- buf[j] = plain[j] ^ cprev[j];
- rijndael_encrypt(&c->r_ctx, buf, cnow);
- cprev = cnow;
- }
- memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
- } else {
- cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
- plain = dest+len-RIJNDAEL_BLOCKSIZE;
-
- memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
- for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
- plain-=RIJNDAEL_BLOCKSIZE) {
- rijndael_decrypt(&c->r_ctx, cnow, plain);
- ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
- for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
- plain[j] ^= ivp[j];
- }
- memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
- }
- return (1);
-}
-
-static int
-ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
-{
- struct ssh_rijndael_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
- memset(c, 0, sizeof(*c));
- xfree(c);
- EVP_CIPHER_CTX_set_app_data(ctx, NULL);
- }
- return (1);
-}
-
-static void
-ssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
-{
- struct ssh_rijndael_ctx *c;
-
- if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
- fatal("ssh_rijndael_iv: no context");
- if (doset)
- memcpy(c->r_iv, iv, len);
- else
- memcpy(iv, c->r_iv, len);
-}
-
-static const EVP_CIPHER *
-evp_rijndael(void)
-{
- static EVP_CIPHER rijndal_cbc;
-
- memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
- rijndal_cbc.nid = NID_undef;
- rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
- rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
- rijndal_cbc.key_len = 16;
- rijndal_cbc.init = ssh_rijndael_init;
- rijndal_cbc.cleanup = ssh_rijndael_cleanup;
- rijndal_cbc.do_cipher = ssh_rijndael_cbc;
-#ifndef SSH_OLD_EVP
- rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
-#endif
- return (&rijndal_cbc);
-}
-#endif
-
/*
* Exports an IV from the CipherContext required to export the key
* state back from the unprivileged child to the privileged parent