summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/ssh/auth.c3
-rw-r--r--usr.bin/ssh/auth1.c3
-rw-r--r--usr.bin/ssh/auth2.c3
-rw-r--r--usr.bin/ssh/authfile.c44
-rw-r--r--usr.bin/ssh/cipher.c606
-rw-r--r--usr.bin/ssh/cipher.h123
-rw-r--r--usr.bin/ssh/kex.c36
-rw-r--r--usr.bin/ssh/kex.h10
-rw-r--r--usr.bin/ssh/myproposal.h2
-rw-r--r--usr.bin/ssh/packet.c64
-rw-r--r--usr.bin/ssh/readconf.c3
-rw-r--r--usr.bin/ssh/session.c3
-rw-r--r--usr.bin/ssh/ssh.c7
-rw-r--r--usr.bin/ssh/ssh.h10
-rw-r--r--usr.bin/ssh/sshconnect1.c13
-rw-r--r--usr.bin/ssh/sshconnect2.c20
-rw-r--r--usr.bin/ssh/sshd.c11
17 files changed, 450 insertions, 511 deletions
diff --git a/usr.bin/ssh/auth.c b/usr.bin/ssh/auth.c
index 2d4f6d04177..182d6464922 100644
--- a/usr.bin/ssh/auth.c
+++ b/usr.bin/ssh/auth.c
@@ -33,7 +33,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth.c,v 1.10 2000/09/07 21:13:36 markus Exp $");
+RCSID("$OpenBSD: auth.c,v 1.11 2000/10/11 20:27:23 markus Exp $");
#include "xmalloc.h"
#include "rsa.h"
@@ -41,7 +41,6 @@ RCSID("$OpenBSD: auth.c,v 1.10 2000/09/07 21:13:36 markus Exp $");
#include "pty.h"
#include "packet.h"
#include "buffer.h"
-#include "cipher.h"
#include "mpaux.h"
#include "servconf.h"
#include "compat.h"
diff --git a/usr.bin/ssh/auth1.c b/usr.bin/ssh/auth1.c
index b642a4fb7bd..8d50d288796 100644
--- a/usr.bin/ssh/auth1.c
+++ b/usr.bin/ssh/auth1.c
@@ -10,14 +10,13 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth1.c,v 1.5 2000/10/03 18:03:03 markus Exp $");
+RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $");
#include "xmalloc.h"
#include "rsa.h"
#include "ssh.h"
#include "packet.h"
#include "buffer.h"
-#include "cipher.h"
#include "mpaux.h"
#include "servconf.h"
#include "compat.h"
diff --git a/usr.bin/ssh/auth2.c b/usr.bin/ssh/auth2.c
index 2d05a2f2e93..4d53e1670b0 100644
--- a/usr.bin/ssh/auth2.c
+++ b/usr.bin/ssh/auth2.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth2.c,v 1.18 2000/10/11 20:14:38 markus Exp $");
+RCSID("$OpenBSD: auth2.c,v 1.19 2000/10/11 20:27:23 markus Exp $");
#include <openssl/dsa.h>
#include <openssl/rsa.h>
@@ -35,7 +35,6 @@ RCSID("$OpenBSD: auth2.c,v 1.18 2000/10/11 20:14:38 markus Exp $");
#include "pty.h"
#include "packet.h"
#include "buffer.h"
-#include "cipher.h"
#include "servconf.h"
#include "compat.h"
#include "channels.h"
diff --git a/usr.bin/ssh/authfile.c b/usr.bin/ssh/authfile.c
index bd6fee05f52..fdeab801729 100644
--- a/usr.bin/ssh/authfile.c
+++ b/usr.bin/ssh/authfile.c
@@ -36,7 +36,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: authfile.c,v 1.19 2000/09/07 20:27:49 deraadt Exp $");
+RCSID("$OpenBSD: authfile.c,v 1.20 2000/10/11 20:27:23 markus Exp $");
#include <openssl/bn.h>
#include <openssl/dsa.h>
@@ -47,7 +47,6 @@ RCSID("$OpenBSD: authfile.c,v 1.19 2000/09/07 20:27:49 deraadt Exp $");
#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
-#include "cipher.h"
#include "ssh.h"
#include "key.h"
@@ -68,8 +67,8 @@ save_private_key_rsa(const char *filename, const char *passphrase,
Buffer buffer, encrypted;
char buf[100], *cp;
int fd, i;
- CipherContext cipher;
- int cipher_type;
+ CipherContext ciphercontext;
+ Cipher *cipher;
u_int32_t rand;
/*
@@ -77,9 +76,11 @@ save_private_key_rsa(const char *filename, const char *passphrase,
* to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
*/
if (strcmp(passphrase, "") == 0)
- cipher_type = SSH_CIPHER_NONE;
+ cipher = cipher_by_number(SSH_CIPHER_NONE);
else
- cipher_type = SSH_AUTHFILE_CIPHER;
+ cipher = cipher_by_number(SSH_AUTHFILE_CIPHER);
+ if (cipher == NULL)
+ fatal("save_private_key_rsa: bad cipher");
/* This buffer is used to built the secret part of the private key. */
buffer_init(&buffer);
@@ -116,7 +117,7 @@ save_private_key_rsa(const char *filename, const char *passphrase,
buffer_put_char(&encrypted, 0);
/* Store cipher type. */
- buffer_put_char(&encrypted, cipher_type);
+ buffer_put_char(&encrypted, cipher->number);
buffer_put_int(&encrypted, 0); /* For future extension */
/* Store public key. This will be in plain text. */
@@ -128,11 +129,10 @@ save_private_key_rsa(const char *filename, const char *passphrase,
/* Allocate space for the private part of the key in the buffer. */
buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
- cipher_set_key_string(&cipher, cipher_type, passphrase);
- cipher_encrypt(&cipher, (unsigned char *) cp,
- (unsigned char *) buffer_ptr(&buffer),
- buffer_len(&buffer));
- memset(&cipher, 0, sizeof(cipher));
+ cipher_set_key_string(&ciphercontext, cipher, passphrase);
+ cipher_encrypt(&ciphercontext, (unsigned char *) cp,
+ (unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer));
+ memset(&ciphercontext, 0, sizeof(ciphercontext));
/* Destroy temporary data. */
memset(buf, 0, sizeof(buf));
@@ -313,7 +313,8 @@ load_private_key_rsa(int fd, const char *filename,
off_t len;
Buffer buffer, decrypted;
char *cp;
- CipherContext cipher;
+ CipherContext ciphercontext;
+ Cipher *cipher;
BN_CTX *ctx;
BIGNUM *aux;
@@ -364,10 +365,10 @@ load_private_key_rsa(int fd, const char *filename,
xfree(buffer_get_string(&buffer, NULL));
/* Check that it is a supported cipher. */
- if (((cipher_mask1() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &
- (1 << cipher_type)) == 0) {
- debug("Unsupported cipher %.100s used in key file %.200s.",
- cipher_name(cipher_type), filename);
+ cipher = cipher_by_number(cipher_type);
+ if (cipher == NULL) {
+ debug("Unsupported cipher %d used in key file %.200s.",
+ cipher_type, filename);
buffer_free(&buffer);
goto fail;
}
@@ -376,11 +377,10 @@ load_private_key_rsa(int fd, const char *filename,
buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
- cipher_set_key_string(&cipher, cipher_type, passphrase);
- cipher_decrypt(&cipher, (unsigned char *) cp,
- (unsigned char *) buffer_ptr(&buffer),
- buffer_len(&buffer));
-
+ cipher_set_key_string(&ciphercontext, cipher, passphrase);
+ cipher_decrypt(&ciphercontext, (unsigned char *) cp,
+ (unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer));
+ memset(&ciphercontext, 0, sizeof(ciphercontext));
buffer_free(&buffer);
check1 = buffer_get_char(&decrypted);
diff --git a/usr.bin/ssh/cipher.c b/usr.bin/ssh/cipher.c
index c7985a79c0c..8edb4fd42ad 100644
--- a/usr.bin/ssh/cipher.c
+++ b/usr.bin/ssh/cipher.c
@@ -35,14 +35,85 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: cipher.c,v 1.31 2000/09/12 00:38:32 deraadt Exp $");
+RCSID("$OpenBSD: cipher.c,v 1.32 2000/10/11 20:27:23 markus Exp $");
#include "ssh.h"
-#include "cipher.h"
#include "xmalloc.h"
#include <openssl/md5.h>
+
+/* no encryption */
+void
+none_setkey(CipherContext *cc, const u_char *key, u_int keylen)
+{
+}
+void
+none_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
+{
+}
+void
+none_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+{
+ memcpy(dest, src, len);
+}
+
+/* DES */
+void
+des_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)
+{
+ des_set_key((void *)key, cc->u.des.key);
+}
+void
+des_ssh1_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
+{
+ memset(cc->u.des.iv, 0, sizeof(cc->u.des.iv));
+}
+void
+des_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+{
+ des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,
+ DES_ENCRYPT);
+}
+void
+des_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+{
+ des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,
+ DES_DECRYPT);
+}
+
+/* 3DES */
+void
+des3_setkey(CipherContext *cc, const u_char *key, u_int keylen)
+{
+ des_set_key((void *) key, cc->u.des3.key1);
+ des_set_key((void *) (key+8), cc->u.des3.key2);
+ des_set_key((void *) (key+16), cc->u.des3.key3);
+}
+void
+des3_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
+{
+ memset(cc->u.des3.iv2, 0, sizeof(cc->u.des3.iv2));
+ memset(cc->u.des3.iv3, 0, sizeof(cc->u.des3.iv3));
+ if (iv == NULL)
+ return;
+ memcpy(cc->u.des3.iv3, (char *)iv, 8);
+}
+void
+des3_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+{
+ des_ede3_cbc_encrypt(src, dest, len,
+ cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3,
+ &cc->u.des3.iv3, DES_ENCRYPT);
+}
+void
+des3_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+{
+ des_ede3_cbc_encrypt(src, dest, len,
+ cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3,
+ &cc->u.des3.iv3, DES_DECRYPT);
+}
+
/*
* This is used by SSH1:
*
@@ -58,48 +129,84 @@ RCSID("$OpenBSD: cipher.c,v 1.31 2000/09/12 00:38:32 deraadt Exp $");
* choosing the X block.
*/
void
-SSH_3CBC_ENCRYPT(des_key_schedule ks1,
- des_key_schedule ks2, des_cblock * iv2,
- des_key_schedule ks3, des_cblock * iv3,
- unsigned char *dest, unsigned char *src,
- unsigned int len)
+des3_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)
+{
+ des_set_key((void *) key, cc->u.des3.key1);
+ des_set_key((void *) (key+8), cc->u.des3.key2);
+ if (keylen <= 16)
+ des_set_key((void *) key, cc->u.des3.key3);
+ else
+ des_set_key((void *) (key+16), cc->u.des3.key3);
+}
+void
+des3_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
+ u_int len)
{
des_cblock iv1;
+ des_cblock *iv2 = &cc->u.des3.iv2;
+ des_cblock *iv3 = &cc->u.des3.iv3;
memcpy(&iv1, iv2, 8);
- des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT);
+ des_cbc_encrypt(src, dest, len, cc->u.des3.key1, &iv1, DES_ENCRYPT);
memcpy(&iv1, dest + len - 8, 8);
- des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT);
+ des_cbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_DECRYPT);
memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */
- des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT);
+ des_cbc_encrypt(dest, dest, len, cc->u.des3.key3, iv3, DES_ENCRYPT);
memcpy(iv3, dest + len - 8, 8);
}
-
void
-SSH_3CBC_DECRYPT(des_key_schedule ks1,
- des_key_schedule ks2, des_cblock * iv2,
- des_key_schedule ks3, des_cblock * iv3,
- unsigned char *dest, unsigned char *src,
- unsigned int len)
+des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
+ u_int len)
{
des_cblock iv1;
+ des_cblock *iv2 = &cc->u.des3.iv2;
+ des_cblock *iv3 = &cc->u.des3.iv3;
memcpy(&iv1, iv2, 8);
- des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT);
+ des_cbc_encrypt(src, dest, len, cc->u.des3.key3, iv3, DES_DECRYPT);
memcpy(iv3, src + len - 8, 8);
- des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT);
+ des_cbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_ENCRYPT);
memcpy(iv2, dest + len - 8, 8);
- des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT);
+ des_cbc_encrypt(dest, dest, len, cc->u.des3.key1, &iv1, DES_DECRYPT);
/* memcpy(&iv1, iv2, 8); */
/* Note how iv1 == iv2 on entry and exit. */
}
+/* Blowfish */
+void
+blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen)
+{
+ BF_set_key(&cc->u.bf.key, keylen, (unsigned char *)key);
+}
+void
+blowfish_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
+{
+ if (iv == NULL)
+ memset(cc->u.bf.iv, 0, 8);
+ else
+ memcpy(cc->u.bf.iv, (char *)iv, 8);
+}
+void
+blowfish_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
+ u_int len)
+{
+ BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv,
+ BF_ENCRYPT);
+}
+void
+blowfish_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
+ u_int len)
+{
+ BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv,
+ BF_DECRYPT);
+}
+
/*
* SSH1 uses a variation on Blowfish, all bytes must be swapped before
* and after encryption/decryption. Thus the swap_bytes stuff (yuk).
@@ -130,88 +237,162 @@ swap_bytes(const unsigned char *src, unsigned char *dst_, int n)
}
}
-/*
- * Names of all encryption algorithms.
- * These must match the numbers defined in cipher.h.
- */
-static char *cipher_names[] =
-{
- "none",
- "idea",
- "des",
- "3des",
- "tss",
- "rc4", /* Alleged RC4 */
- "blowfish",
- "reserved",
- "blowfish-cbc",
- "3des-cbc",
- "arcfour",
- "cast128-cbc"
-};
+void
+blowfish_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
+ u_int len)
+{
+ swap_bytes(src, dest, len);
+ BF_cbc_encrypt((void *)dest, dest, len, &cc->u.bf.key, cc->u.bf.iv,
+ BF_ENCRYPT);
+ swap_bytes(dest, dest, len);
+}
+void
+blowfish_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
+ u_int len)
+{
+ swap_bytes(src, dest, len);
+ BF_cbc_encrypt((void *)dest, dest, len, &cc->u.bf.key, cc->u.bf.iv,
+ BF_DECRYPT);
+ swap_bytes(dest, dest, len);
+}
-/*
- * Returns a bit mask indicating which ciphers are supported by this
- * implementation. The bit mask has the corresponding bit set of each
- * supported cipher.
- */
+/* alleged rc4 */
+void
+arcfour_setkey(CipherContext *cc, const u_char *key, u_int keylen)
+{
+ RC4_set_key(&cc->u.rc4, keylen, (u_char *)key);
+}
+void
+arcfour_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+{
+ RC4(&cc->u.rc4, len, (u_char *)src, dest);
+}
-unsigned int
-cipher_mask1()
+/* CAST */
+void
+cast_setkey(CipherContext *cc, const u_char *key, u_int keylen)
{
- unsigned int mask = 0;
- mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
- mask |= 1 << SSH_CIPHER_BLOWFISH;
- return mask;
+ CAST_set_key(&cc->u.cast.key, keylen, (unsigned char *) key);
+}
+void
+cast_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
+{
+ if (iv == NULL)
+ fatal("no IV for %s.", cc->cipher->name);
+ memcpy(cc->u.cast.iv, (char *)iv, 8);
+}
+void
+cast_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+{
+ CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,
+ CAST_ENCRYPT);
+}
+void
+cast_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+{
+ CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,
+ CAST_DECRYPT);
}
+
+/*--*/
+
+Cipher ciphers[] = {
+ { "none",
+ SSH_CIPHER_NONE, 8, 0,
+ none_setkey, none_setiv,
+ none_crypt, none_crypt },
+ { "des",
+ SSH_CIPHER_DES, 8, 8,
+ des_ssh1_setkey, des_ssh1_setiv,
+ des_ssh1_encrypt, des_ssh1_decrypt },
+ { "3des",
+ SSH_CIPHER_3DES, 8, 16,
+ des3_ssh1_setkey, des3_setiv,
+ des3_ssh1_encrypt, des3_ssh1_decrypt },
+ { "blowfish",
+ SSH_CIPHER_BLOWFISH, 8, 16,
+ blowfish_setkey, blowfish_setiv,
+ blowfish_ssh1_encrypt, blowfish_ssh1_decrypt },
+
+ { "3des-cbc",
+ SSH_CIPHER_SSH2, 8, 24,
+ des3_setkey, des3_setiv,
+ des3_cbc_encrypt, des3_cbc_decrypt },
+ { "blowfish-cbc",
+ SSH_CIPHER_SSH2, 8, 16,
+ blowfish_setkey, blowfish_setiv,
+ blowfish_cbc_encrypt, blowfish_cbc_decrypt },
+ { "cast128-cbc",
+ SSH_CIPHER_SSH2, 8, 16,
+ cast_setkey, cast_setiv,
+ cast_cbc_encrypt, cast_cbc_decrypt },
+ { "arcfour",
+ SSH_CIPHER_SSH2, 8, 16,
+ arcfour_setkey, none_setiv,
+ arcfour_crypt, arcfour_crypt },
+ { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
+/*--*/
+
unsigned int
-cipher_mask2()
+cipher_mask1()
{
unsigned int mask = 0;
- mask |= 1 << SSH_CIPHER_BLOWFISH_CBC;
- mask |= 1 << SSH_CIPHER_3DES_CBC;
- mask |= 1 << SSH_CIPHER_ARCFOUR;
- mask |= 1 << SSH_CIPHER_CAST128_CBC;
+ Cipher *c;
+ for (c = ciphers; c->name != NULL; c++) {
+ if (c->number > SSH_CIPHER_NONE)
+ mask |= 1 << c->number;
+ }
return mask;
}
-unsigned int
-cipher_mask()
+
+Cipher *
+cipher_by_name(const char *name)
{
- return cipher_mask1() | cipher_mask2();
+ Cipher *c;
+ if (strcmp(name, "des") == 0)
+ error("Warning: use of DES is strongly discouraged "
+ "due to cryptographic weaknesses");
+ for (c = ciphers; c->name != NULL; c++)
+ if (strcasecmp(c->name, name) == 0)
+ return c;
+ return NULL;
}
-/* Returns the name of the cipher. */
-
-const char *
-cipher_name(int cipher)
+Cipher *
+cipher_by_number(int id)
{
- if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) ||
- cipher_names[cipher] == NULL)
- fatal("cipher_name: bad cipher name: %d", cipher);
- return cipher_names[cipher];
+ Cipher *c;
+ for (c = ciphers; c->name != NULL; c++)
+ if (c->number == id)
+ return c;
+ return NULL;
}
-/* Returns 1 if the name of the ciphers are valid. */
-
#define CIPHER_SEP ","
int
ciphers_valid(const char *names)
{
+ Cipher *c;
char *ciphers, *cp;
char *p;
- int i;
if (names == NULL || strcmp(names, "") == 0)
return 0;
ciphers = cp = xstrdup(names);
- for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
+ for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
(p = strsep(&cp, CIPHER_SEP))) {
- i = cipher_number(p);
- if (i == -1 || !(cipher_mask2() & (1 << i))) {
+ c = cipher_by_name(p);
+ if (c == NULL || c->number != SSH_CIPHER_SSH2) {
+ debug("bad cipher %s [%s]", p, names);
xfree(ciphers);
return 0;
+ } else {
+ debug("cipher ok: %s [%s]", p, names);
}
}
+ debug("ciphers ok: [%s]", names);
xfree(ciphers);
return 1;
}
@@ -224,264 +405,69 @@ ciphers_valid(const char *names)
int
cipher_number(const char *name)
{
- int i;
+ Cipher *c;
if (name == NULL)
return -1;
- for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++)
- if (strcmp(cipher_names[i], name) == 0 &&
- (cipher_mask() & (1 << i)))
- return i;
- return -1;
+ c = cipher_by_name(name);
+ return (c==NULL) ? -1 : c->number;
}
-/*
- * Selects the cipher, and keys if by computing the MD5 checksum of the
- * passphrase and using the resulting 16 bytes as the key.
- */
-
-void
-cipher_set_key_string(CipherContext *context, int cipher, const char *passphrase)
+char *
+cipher_name(int id)
{
- MD5_CTX md;
- unsigned char digest[16];
-
- MD5_Init(&md);
- MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase));
- MD5_Final(digest, &md);
-
- cipher_set_key(context, cipher, digest, 16);
-
- memset(digest, 0, sizeof(digest));
- memset(&md, 0, sizeof(md));
+ Cipher *c = cipher_by_number(id);
+ return (c==NULL) ? "<unknown>" : c->name;
}
-/* Selects the cipher to use and sets the key. */
-
void
-cipher_set_key(CipherContext *context, int cipher, const unsigned char *key,
- int keylen)
-{
- unsigned char padded[32];
-
- /* Set cipher type. */
- context->type = cipher;
-
- /* Get 32 bytes of key data. Pad if necessary. (So that code
- below does not need to worry about key size). */
- memset(padded, 0, sizeof(padded));
- memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded));
-
- /* Initialize the initialization vector. */
- switch (cipher) {
- case SSH_CIPHER_NONE:
- /*
- * Has to stay for authfile saving of private key with no
- * passphrase
- */
- break;
-
- case SSH_CIPHER_3DES:
- /*
- * Note: the least significant bit of each byte of key is
- * parity, and must be ignored by the implementation. 16
- * bytes of key are used (first and last keys are the same).
- */
- if (keylen < 16)
- error("Key length %d is insufficient for 3DES.", keylen);
- des_set_key((void *) padded, context->u.des3.key1);
- des_set_key((void *) (padded + 8), context->u.des3.key2);
- if (keylen <= 16)
- des_set_key((void *) padded, context->u.des3.key3);
- else
- des_set_key((void *) (padded + 16), context->u.des3.key3);
- memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2));
- memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3));
- break;
-
- case SSH_CIPHER_BLOWFISH:
- if (keylen < 16)
- error("Key length %d is insufficient for blowfish.", keylen);
- BF_set_key(&context->u.bf.key, keylen, padded);
- memset(context->u.bf.iv, 0, 8);
- break;
-
- case SSH_CIPHER_3DES_CBC:
- case SSH_CIPHER_BLOWFISH_CBC:
- case SSH_CIPHER_ARCFOUR:
- case SSH_CIPHER_CAST128_CBC:
- fatal("cipher_set_key: illegal cipher: %s", cipher_name(cipher));
- break;
-
- default:
- fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
- }
- memset(padded, 0, sizeof(padded));
+cipher_init(CipherContext *cc, Cipher *cipher,
+ const u_char *key, u_int keylen, const u_char *iv, u_int ivlen)
+{
+ if (keylen < cipher->key_len)
+ fatal("cipher_init: key length %d is insufficient for %s.",
+ keylen, cipher->name);
+ if (iv != NULL && ivlen < cipher->block_size)
+ fatal("cipher_init: iv length %d is insufficient for %s.",
+ ivlen, cipher->name);
+ cc->cipher = cipher;
+ cipher->setkey(cc, key, keylen);
+ cipher->setiv(cc, iv, ivlen);
}
void
-cipher_set_key_iv(CipherContext * context, int cipher,
- const unsigned char *key, int keylen,
- const unsigned char *iv, int ivlen)
-{
- /* Set cipher type. */
- context->type = cipher;
-
- /* Initialize the initialization vector. */
- switch (cipher) {
- case SSH_CIPHER_NONE:
- break;
-
- case SSH_CIPHER_3DES:
- case SSH_CIPHER_BLOWFISH:
- fatal("cipher_set_key_iv: illegal cipher: %s", cipher_name(cipher));
- break;
-
- case SSH_CIPHER_3DES_CBC:
- if (keylen < 24)
- error("Key length %d is insufficient for 3des-cbc.", keylen);
- des_set_key((void *) key, context->u.des3.key1);
- des_set_key((void *) (key+8), context->u.des3.key2);
- des_set_key((void *) (key+16), context->u.des3.key3);
- if (ivlen < 8)
- error("IV length %d is insufficient for 3des-cbc.", ivlen);
- memcpy(context->u.des3.iv3, (char *)iv, 8);
- break;
-
- case SSH_CIPHER_BLOWFISH_CBC:
- if (keylen < 16)
- error("Key length %d is insufficient for blowfish.", keylen);
- if (ivlen < 8)
- error("IV length %d is insufficient for blowfish.", ivlen);
- BF_set_key(&context->u.bf.key, keylen, (unsigned char *)key);
- memcpy(context->u.bf.iv, (char *)iv, 8);
- break;
-
- case SSH_CIPHER_ARCFOUR:
- if (keylen < 16)
- error("Key length %d is insufficient for arcfour.", keylen);
- RC4_set_key(&context->u.rc4, keylen, (unsigned char *)key);
- break;
-
- case SSH_CIPHER_CAST128_CBC:
- if (keylen < 16)
- error("Key length %d is insufficient for cast128.", keylen);
- if (ivlen < 8)
- error("IV length %d is insufficient for cast128.", ivlen);
- CAST_set_key(&context->u.cast.key, keylen, (unsigned char *) key);
- memcpy(context->u.cast.iv, (char *)iv, 8);
- break;
-
- default:
- fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
- }
+cipher_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+{
+ if (len % cc->cipher->block_size)
+ fatal("cipher_encrypt: bad plaintext length %d", len);
+ cc->cipher->encrypt(cc, dest, src, len);
}
-/* Encrypts data using the cipher. */
-
void
-cipher_encrypt(CipherContext *context, unsigned char *dest,
- const unsigned char *src, unsigned int len)
+cipher_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
{
- if ((len & 7) != 0)
- fatal("cipher_encrypt: bad plaintext length %d", len);
-
- switch (context->type) {
- case SSH_CIPHER_NONE:
- memcpy(dest, src, len);
- break;
-
- case SSH_CIPHER_3DES:
- SSH_3CBC_ENCRYPT(context->u.des3.key1,
- context->u.des3.key2, &context->u.des3.iv2,
- context->u.des3.key3, &context->u.des3.iv3,
- dest, (unsigned char *) src, len);
- break;
-
- case SSH_CIPHER_BLOWFISH:
- swap_bytes(src, dest, len);
- BF_cbc_encrypt(dest, dest, len,
- &context->u.bf.key, context->u.bf.iv,
- BF_ENCRYPT);
- swap_bytes(dest, dest, len);
- break;
-
- case SSH_CIPHER_BLOWFISH_CBC:
- BF_cbc_encrypt((void *)src, dest, len,
- &context->u.bf.key, context->u.bf.iv,
- BF_ENCRYPT);
- break;
-
- case SSH_CIPHER_3DES_CBC:
- des_ede3_cbc_encrypt(src, dest, len,
- context->u.des3.key1, context->u.des3.key2,
- context->u.des3.key3, &context->u.des3.iv3, DES_ENCRYPT);
- break;
-
- case SSH_CIPHER_ARCFOUR:
- RC4(&context->u.rc4, len, (unsigned char *)src, dest);
- break;
-
- case SSH_CIPHER_CAST128_CBC:
- CAST_cbc_encrypt(src, dest, len,
- &context->u.cast.key, context->u.cast.iv, CAST_ENCRYPT);
- break;
-
- default:
- fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type));
- }
+ if (len % cc->cipher->block_size)
+ fatal("cipher_decrypt: bad ciphertext length %d", len);
+ cc->cipher->decrypt(cc, dest, src, len);
}
-/* Decrypts data using the cipher. */
+/*
+ * Selects the cipher, and keys if by computing the MD5 checksum of the
+ * passphrase and using the resulting 16 bytes as the key.
+ */
void
-cipher_decrypt(CipherContext *context, unsigned char *dest,
- const unsigned char *src, unsigned int len)
+cipher_set_key_string(CipherContext *cc, Cipher *cipher,
+ const char *passphrase)
{
- if ((len & 7) != 0)
- fatal("cipher_decrypt: bad ciphertext length %d", len);
+ MD5_CTX md;
+ unsigned char digest[16];
- switch (context->type) {
- case SSH_CIPHER_NONE:
- memcpy(dest, src, len);
- break;
-
- case SSH_CIPHER_3DES:
- SSH_3CBC_DECRYPT(context->u.des3.key1,
- context->u.des3.key2, &context->u.des3.iv2,
- context->u.des3.key3, &context->u.des3.iv3,
- dest, (unsigned char *) src, len);
- break;
-
- case SSH_CIPHER_BLOWFISH:
- swap_bytes(src, dest, len);
- BF_cbc_encrypt((void *) dest, dest, len,
- &context->u.bf.key, context->u.bf.iv,
- BF_DECRYPT);
- swap_bytes(dest, dest, len);
- break;
-
- case SSH_CIPHER_BLOWFISH_CBC:
- BF_cbc_encrypt((void *) src, dest, len,
- &context->u.bf.key, context->u.bf.iv,
- BF_DECRYPT);
- break;
-
- case SSH_CIPHER_3DES_CBC:
- des_ede3_cbc_encrypt(src, dest, len,
- context->u.des3.key1, context->u.des3.key2,
- context->u.des3.key3, &context->u.des3.iv3, DES_DECRYPT);
- break;
-
- case SSH_CIPHER_ARCFOUR:
- RC4(&context->u.rc4, len, (unsigned char *)src, dest);
- break;
-
- case SSH_CIPHER_CAST128_CBC:
- CAST_cbc_encrypt(src, dest, len,
- &context->u.cast.key, context->u.cast.iv, CAST_DECRYPT);
- break;
-
- default:
- fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type));
- }
+ MD5_Init(&md);
+ MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
+ MD5_Final(digest, &md);
+
+ cipher_init(cc, cipher, digest, 16, NULL, 0);
+
+ memset(digest, 0, sizeof(digest));
+ memset(&md, 0, sizeof(md));
}
diff --git a/usr.bin/ssh/cipher.h b/usr.bin/ssh/cipher.h
index bc7a5e22431..1140285856a 100644
--- a/usr.bin/ssh/cipher.h
+++ b/usr.bin/ssh/cipher.h
@@ -8,9 +8,31 @@
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
+ *
+ * Copyright (c) 2000 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.
*/
-/* RCSID("$OpenBSD: cipher.h,v 1.19 2000/09/07 20:27:50 deraadt Exp $"); */
+/* RCSID("$OpenBSD: cipher.h,v 1.20 2000/10/11 20:27:23 markus Exp $"); */
#ifndef CIPHER_H
#define CIPHER_H
@@ -19,9 +41,11 @@
#include <openssl/blowfish.h>
#include <openssl/rc4.h>
#include <openssl/cast.h>
-
-/* Cipher types. New types can be added, but old types should not be removed
- for compatibility. The maximum allowed value is 31. */
+/*
+ * Cipher types for SSH-1. New types can be added, but old types should not
+ * be removed for compatibility. The maximum allowed value is 31.
+ */
+#define SSH_CIPHER_SSH2 -3
#define SSH_CIPHER_ILLEGAL -2 /* No valid cipher selected. */
#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
#define SSH_CIPHER_NONE 0 /* no encryption */
@@ -32,17 +56,18 @@
#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
#define SSH_CIPHER_BLOWFISH 6
#define SSH_CIPHER_RESERVED 7
+#define SSH_CIPHER_MAX 31
-/* these ciphers are used in SSH2: */
-#define SSH_CIPHER_BLOWFISH_CBC 8
-#define SSH_CIPHER_3DES_CBC 9
-#define SSH_CIPHER_ARCFOUR 10 /* Alleged RC4 */
-#define SSH_CIPHER_CAST128_CBC 11
+typedef struct Cipher Cipher;
+typedef struct CipherContext CipherContext;
-typedef struct {
- unsigned int type;
+struct CipherContext {
union {
struct {
+ des_key_schedule key;
+ des_cblock iv;
+ } des;
+ struct {
des_key_schedule key1;
des_key_schedule key2;
des_cblock iv2;
@@ -51,64 +76,36 @@ typedef struct {
} des3;
struct {
struct bf_key_st key;
- unsigned char iv[8];
+ u_char iv[8];
} bf;
struct {
CAST_KEY key;
- unsigned char iv[8];
+ u_char iv[8];
} cast;
RC4_KEY rc4;
} u;
-} CipherContext;
-/*
- * Returns a bit mask indicating which ciphers are supported by this
- * implementation. The bit mask has the corresponding bit set of each
- * supported cipher.
- */
-unsigned int cipher_mask();
-unsigned int cipher_mask1();
-unsigned int cipher_mask2();
-
-/* Returns the name of the cipher. */
-const char *cipher_name(int cipher);
+ Cipher *cipher;
+};
+struct Cipher {
+ char *name;
+ int number; /* for ssh1 only */
+ u_int block_size;
+ u_int key_len;
+ void (*setkey)(CipherContext *, const u_char *, u_int);
+ void (*setiv)(CipherContext *, const u_char *, u_int);
+ void (*encrypt)(CipherContext *, u_char *, const u_char *, u_int);
+ void (*decrypt)(CipherContext *, u_char *, const u_char *, u_int);
+};
-/*
- * Parses the name of the cipher. Returns the number of the corresponding
- * cipher, or -1 on error.
- */
-int cipher_number(const char *name);
-
-/* returns 1 if all ciphers are supported (ssh2 only) */
-int ciphers_valid(const char *names);
-
-/*
- * Selects the cipher to use and sets the key. If for_encryption is true,
- * the key is setup for encryption; otherwise it is setup for decryption.
- */
-void
-cipher_set_key(CipherContext * context, int cipher,
- const unsigned char *key, int keylen);
-void
-cipher_set_key_iv(CipherContext * context, int cipher,
- const unsigned char *key, int keylen,
- const unsigned char *iv, int ivlen);
-
-/*
- * Sets key for the cipher by computing the MD5 checksum of the passphrase,
- * and using the resulting 16 bytes as the key.
- */
-void
-cipher_set_key_string(CipherContext * context, int cipher,
- const char *passphrase);
-
-/* Encrypts data using the cipher. */
-void
-cipher_encrypt(CipherContext * context, unsigned char *dest,
- const unsigned char *src, unsigned int len);
-
-/* Decrypts data using the cipher. */
-void
-cipher_decrypt(CipherContext * context, unsigned char *dest,
- const unsigned char *src, unsigned int len);
+unsigned int cipher_mask1();
+Cipher *cipher_by_name(const char *name);
+Cipher *cipher_by_number(int id);
+int cipher_number(const char *name);
+char *cipher_name(int id);
+int ciphers_valid(const char *names);
+void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, const u_char *, u_int);
+void cipher_encrypt(CipherContext *context, u_char *dest, const u_char *src, u_int len);
+void cipher_decrypt(CipherContext *context, u_char *dest, const u_char *src, u_int len);
+void cipher_set_key_string(CipherContext *context, Cipher *cipher, const char *passphrase);
#endif /* CIPHER_H */
diff --git a/usr.bin/ssh/kex.c b/usr.bin/ssh/kex.c
index 151dc1cffa4..68b9e522e73 100644
--- a/usr.bin/ssh/kex.c
+++ b/usr.bin/ssh/kex.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: kex.c,v 1.11 2000/10/11 04:02:17 provos Exp $");
+RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $");
#include "ssh.h"
#include "ssh2.h"
@@ -31,7 +31,6 @@ RCSID("$OpenBSD: kex.c,v 1.11 2000/10/11 04:02:17 provos Exp $");
#include "buffer.h"
#include "bufaux.h"
#include "packet.h"
-#include "cipher.h"
#include "compat.h"
#include <openssl/bn.h>
@@ -395,28 +394,9 @@ choose_enc(Enc *enc, char *client, char *server)
char *name = get_match(client, server);
if (name == NULL)
fatal("no matching cipher found: client %s server %s", client, server);
- enc->type = cipher_number(name);
-
- switch (enc->type) {
- case SSH_CIPHER_3DES_CBC:
- enc->key_len = 24;
- enc->iv_len = 8;
- enc->block_size = 8;
- break;
- case SSH_CIPHER_BLOWFISH_CBC:
- case SSH_CIPHER_CAST128_CBC:
- enc->key_len = 16;
- enc->iv_len = 8;
- enc->block_size = 8;
- break;
- case SSH_CIPHER_ARCFOUR:
- enc->key_len = 16;
- enc->iv_len = 0;
- enc->block_size = 8;
- break;
- default:
- fatal("unsupported cipher %s", name);
- }
+ enc->cipher = cipher_by_name(name);
+ if (enc->cipher == NULL)
+ fatal("matching cipher is not supported: %s", name);
enc->name = name;
enc->enabled = 0;
enc->iv = NULL;
@@ -513,10 +493,10 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server
sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
need = 0;
for (mode = 0; mode < MODE_MAX; mode++) {
- if (need < k->enc[mode].key_len)
- need = k->enc[mode].key_len;
- if (need < k->enc[mode].iv_len)
- need = k->enc[mode].iv_len;
+ if (need < k->enc[mode].cipher->key_len)
+ need = k->enc[mode].cipher->key_len;
+ if (need < k->enc[mode].cipher->block_size)
+ need = k->enc[mode].cipher->block_size;
if (need < k->mac[mode].key_len)
need = k->mac[mode].key_len;
}
diff --git a/usr.bin/ssh/kex.h b/usr.bin/ssh/kex.h
index 36af701e495..93c77cac062 100644
--- a/usr.bin/ssh/kex.h
+++ b/usr.bin/ssh/kex.h
@@ -59,22 +59,20 @@ typedef struct Comp Comp;
typedef struct Enc Enc;
struct Enc {
+ char *name;
int type;
+ Cipher *cipher;
int enabled;
- int block_size;
unsigned char *key;
unsigned char *iv;
- int key_len;
- int iv_len;
- char *name;
};
struct Mac {
- EVP_MD *md;
+ char *name;
int enabled;
+ EVP_MD *md;
int mac_len;
unsigned char *key;
int key_len;
- char *name;
};
struct Comp {
int type;
diff --git a/usr.bin/ssh/myproposal.h b/usr.bin/ssh/myproposal.h
index 1d368239604..06ef1f70274 100644
--- a/usr.bin/ssh/myproposal.h
+++ b/usr.bin/ssh/myproposal.h
@@ -23,7 +23,7 @@
*/
#define KEX_DEFAULT_KEX "diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1"
#define KEX_DEFAULT_PK_ALG "ssh-dss"
-#define KEX_DEFAULT_ENCRYPT "3des-cbc,blowfish-cbc,arcfour,cast128-cbc"
+#define KEX_DEFAULT_ENCRYPT "3des-cbc,blowfish-cbc,cast128-cbc,arcfour"
#define KEX_DEFAULT_MAC "hmac-sha1,hmac-md5,hmac-ripemd160@openssh.com"
#define KEX_DEFAULT_COMP "zlib,none"
#define KEX_DEFAULT_LANG ""
diff --git a/usr.bin/ssh/packet.c b/usr.bin/ssh/packet.c
index f7d3c12c15d..b5d692cf842 100644
--- a/usr.bin/ssh/packet.c
+++ b/usr.bin/ssh/packet.c
@@ -37,7 +37,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: packet.c,v 1.36 2000/10/03 17:59:57 markus Exp $");
+RCSID("$OpenBSD: packet.c,v 1.37 2000/10/11 20:27:23 markus Exp $");
#include "xmalloc.h"
#include "buffer.h"
@@ -45,7 +45,6 @@ RCSID("$OpenBSD: packet.c,v 1.36 2000/10/03 17:59:57 markus Exp $");
#include "bufaux.h"
#include "ssh.h"
#include "crc32.h"
-#include "cipher.h"
#include "getput.h"
#include "compress.h"
@@ -59,6 +58,7 @@ RCSID("$OpenBSD: packet.c,v 1.36 2000/10/03 17:59:57 markus Exp $");
#include <openssl/dh.h>
#include <openssl/hmac.h>
#include "buffer.h"
+#include "cipher.h"
#include "kex.h"
#include "hmac.h"
@@ -161,11 +161,14 @@ packet_set_ssh2_format(void)
void
packet_set_connection(int fd_in, int fd_out)
{
+ Cipher *none = cipher_by_name("none");
+ if (none == NULL)
+ fatal("packet_set_connection: cannot load cipher 'none'");
connection_in = fd_in;
connection_out = fd_out;
cipher_type = SSH_CIPHER_NONE;
- cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *) "", 0);
- cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *) "", 0);
+ cipher_init(&send_context, none, (unsigned char *) "", 0, NULL, 0);
+ cipher_init(&receive_context, none, (unsigned char *) "", 0, NULL, 0);
if (!initialized) {
initialized = 1;
buffer_init(&input);
@@ -326,28 +329,18 @@ packet_encrypt(CipherContext * cc, void *dest, void *src,
*/
void
-packet_decrypt(CipherContext * cc, void *dest, void *src,
- unsigned int bytes)
+packet_decrypt(CipherContext *context, void *dest, void *src, unsigned int bytes)
{
- int i;
-
- if ((bytes % 8) != 0)
- fatal("packet_decrypt: bad ciphertext length %d", bytes);
-
/*
* Cryptographic attack detector for ssh - Modifications for packet.c
* (C)1998 CORE-SDI, Buenos Aires Argentina Ariel Futoransky(futo@core-sdi.com)
*/
-
- if (cc->type == SSH_CIPHER_NONE || compat20) {
- i = DEATTACK_OK;
- } else {
- i = detect_attack(src, bytes, NULL);
- }
- if (i == DEATTACK_DETECTED)
+ if (!compat20 &&
+ context->cipher->number != SSH_CIPHER_NONE &&
+ detect_attack(src, bytes, NULL) == DEATTACK_DETECTED)
packet_disconnect("crc32 compensation attack: network attack detected");
- cipher_decrypt(cc, dest, src, bytes);
+ cipher_decrypt(context, dest, src, bytes);
}
/*
@@ -358,14 +351,15 @@ packet_decrypt(CipherContext * cc, void *dest, void *src,
void
packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
- int cipher)
+ int number)
{
+ Cipher *cipher = cipher_by_number(number);
+ if (cipher == NULL)
+ fatal("packet_set_encryption_key: unknown cipher number %d", number);
if (keylen < 20)
- fatal("keylen too small: %d", keylen);
-
- /* All other ciphers use the same key in both directions for now. */
- cipher_set_key(&receive_context, cipher, key, keylen);
- cipher_set_key(&send_context, cipher, key, keylen);
+ fatal("packet_set_encryption_key: keylen too small: %d", keylen);
+ cipher_init(&receive_context, cipher, key, keylen, NULL, 0);
+ cipher_init(&send_context, cipher, key, keylen, NULL, 0);
}
/* Starts constructing a packet to send. */
@@ -553,7 +547,7 @@ packet_send2()
mac = &kex->mac[MODE_OUT];
comp = &kex->comp[MODE_OUT];
}
- block_size = enc ? enc->block_size : 8;
+ block_size = enc ? enc->cipher->block_size : 8;
cp = buffer_ptr(&outgoing_packet);
type = cp[5] & 0xff;
@@ -637,10 +631,10 @@ packet_send2()
fatal("packet_send2: no KEX");
if (mac->md != NULL)
mac->enabled = 1;
- DBG(debug("cipher_set_key_iv send_context"));
- cipher_set_key_iv(&send_context, enc->type,
- enc->key, enc->key_len,
- enc->iv, enc->iv_len);
+ DBG(debug("cipher_init send_context"));
+ cipher_init(&send_context, enc->cipher,
+ enc->key, enc->cipher->key_len,
+ enc->iv, enc->cipher->block_size);
clear_enc_keys(enc, kex->we_need);
if (comp->type != 0 && comp->enabled == 0) {
comp->enabled = 1;
@@ -841,7 +835,7 @@ packet_read_poll2(int *payload_len_ptr)
comp = &kex->comp[MODE_IN];
}
maclen = mac && mac->enabled ? mac->mac_len : 0;
- block_size = enc ? enc->block_size : 8;
+ block_size = enc ? enc->cipher->block_size : 8;
if (packet_length == 0) {
/*
@@ -939,10 +933,10 @@ packet_read_poll2(int *payload_len_ptr)
fatal("packet_read_poll2: no KEX");
if (mac->md != NULL)
mac->enabled = 1;
- DBG(debug("cipher_set_key_iv receive_context"));
- cipher_set_key_iv(&receive_context, enc->type,
- enc->key, enc->key_len,
- enc->iv, enc->iv_len);
+ DBG(debug("cipher_init receive_context"));
+ cipher_init(&receive_context, enc->cipher,
+ enc->key, enc->cipher->key_len,
+ enc->iv, enc->cipher->block_size);
clear_enc_keys(enc, kex->we_need);
if (comp->type != 0 && comp->enabled == 0) {
comp->enabled = 1;
diff --git a/usr.bin/ssh/readconf.c b/usr.bin/ssh/readconf.c
index 717d25584a8..bcdbc4c292c 100644
--- a/usr.bin/ssh/readconf.c
+++ b/usr.bin/ssh/readconf.c
@@ -12,10 +12,9 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.48 2000/10/11 20:14:39 markus Exp $");
+RCSID("$OpenBSD: readconf.c,v 1.49 2000/10/11 20:27:23 markus Exp $");
#include "ssh.h"
-#include "cipher.h"
#include "readconf.h"
#include "match.h"
#include "xmalloc.h"
diff --git a/usr.bin/ssh/session.c b/usr.bin/ssh/session.c
index 43215358daf..4e83f2bcf1c 100644
--- a/usr.bin/ssh/session.c
+++ b/usr.bin/ssh/session.c
@@ -33,14 +33,13 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.37 2000/09/07 20:27:53 deraadt Exp $");
+RCSID("$OpenBSD: session.c,v 1.38 2000/10/11 20:27:23 markus Exp $");
#include "xmalloc.h"
#include "ssh.h"
#include "pty.h"
#include "packet.h"
#include "buffer.h"
-#include "cipher.h"
#include "mpaux.h"
#include "servconf.h"
#include "uidswap.h"
diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c
index e2a399945aa..a915b57cd2a 100644
--- a/usr.bin/ssh/ssh.c
+++ b/usr.bin/ssh/ssh.c
@@ -39,7 +39,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.67 2000/10/03 18:16:47 markus Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.68 2000/10/11 20:27:24 markus Exp $");
#include <openssl/evp.h>
#include <openssl/dsa.h>
@@ -404,11 +404,12 @@ main(int ac, char **av)
options.cipher = SSH_CIPHER_ILLEGAL;
} else {
/* SSH1 only */
- options.cipher = cipher_number(optarg);
- if (options.cipher == -1) {
+ Cipher *c = cipher_by_name(optarg);
+ if (c == NULL || c->number < 0) {
fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
exit(1);
}
+ options.cipher = c->number;
}
break;
case 'p':
diff --git a/usr.bin/ssh/ssh.h b/usr.bin/ssh/ssh.h
index 06810e77ef2..f8c58e6051c 100644
--- a/usr.bin/ssh/ssh.h
+++ b/usr.bin/ssh/ssh.h
@@ -12,7 +12,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
-/* RCSID("$OpenBSD: ssh.h,v 1.53 2000/10/11 20:14:39 markus Exp $"); */
+/* RCSID("$OpenBSD: ssh.h,v 1.54 2000/10/11 20:27:24 markus Exp $"); */
#ifndef SSH_H
#define SSH_H
@@ -20,14 +20,6 @@
#include "rsa.h"
#include "cipher.h"
-/*
- * XXX
- * The default cipher used if IDEA is not supported by the remote host. It is
- * recommended that this be one of the mandatory ciphers (DES, 3DES), though
- * that is not required.
- */
-#define SSH_FALLBACK_CIPHER SSH_CIPHER_3DES
-
/* Cipher used for encrypting authentication files. */
#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES
diff --git a/usr.bin/ssh/sshconnect1.c b/usr.bin/ssh/sshconnect1.c
index 2bb4d5387d1..83994f51813 100644
--- a/usr.bin/ssh/sshconnect1.c
+++ b/usr.bin/ssh/sshconnect1.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect1.c,v 1.6 2000/09/07 20:27:54 deraadt Exp $");
+RCSID("$OpenBSD: sshconnect1.c,v 1.7 2000/10/11 20:27:24 markus Exp $");
#include <openssl/bn.h>
#include <openssl/dsa.h>
@@ -25,7 +25,6 @@ RCSID("$OpenBSD: sshconnect1.c,v 1.6 2000/09/07 20:27:54 deraadt Exp $");
#include "ssh.h"
#include "buffer.h"
#include "packet.h"
-#include "cipher.h"
#include "mpaux.h"
#include "uidswap.h"
#include "readconf.h"
@@ -836,17 +835,11 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
if (options.cipher == SSH_CIPHER_ILLEGAL) {
log("No valid SSH1 cipher, using %.100s instead.",
- cipher_name(SSH_FALLBACK_CIPHER));
- options.cipher = SSH_FALLBACK_CIPHER;
+ cipher_name(ssh_cipher_default));
+ options.cipher = ssh_cipher_default;
} else if (options.cipher == SSH_CIPHER_NOT_SET) {
if (cipher_mask1() & supported_ciphers & (1 << ssh_cipher_default))
options.cipher = ssh_cipher_default;
- else {
- debug("Cipher %s not supported, using %.100s instead.",
- cipher_name(ssh_cipher_default),
- cipher_name(SSH_FALLBACK_CIPHER));
- options.cipher = SSH_FALLBACK_CIPHER;
- }
}
/* Check that the selected cipher is supported. */
if (!(supported_ciphers & (1 << options.cipher)))
diff --git a/usr.bin/ssh/sshconnect2.c b/usr.bin/ssh/sshconnect2.c
index f8bbc600322..0785548a486 100644
--- a/usr.bin/ssh/sshconnect2.c
+++ b/usr.bin/ssh/sshconnect2.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect2.c,v 1.23 2000/10/11 20:14:39 markus Exp $");
+RCSID("$OpenBSD: sshconnect2.c,v 1.24 2000/10/11 20:27:24 markus Exp $");
#include <openssl/bn.h>
#include <openssl/rsa.h>
@@ -37,7 +37,6 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.23 2000/10/11 20:14:39 markus Exp $");
#include "rsa.h"
#include "buffer.h"
#include "packet.h"
-#include "cipher.h"
#include "uidswap.h"
#include "compat.h"
#include "readconf.h"
@@ -76,17 +75,16 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
Buffer *client_kexinit, *server_kexinit;
char *sprop[PROPOSAL_MAX];
+ if (options.ciphers == NULL) {
+ if (options.cipher == SSH_CIPHER_3DES) {
+ options.ciphers = "3des-cbc";
+ } else if (options.cipher == SSH_CIPHER_BLOWFISH) {
+ options.ciphers = "blowfish-cbc";
+ }
+ }
if (options.ciphers != NULL) {
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
- } else if (options.cipher == SSH_CIPHER_3DES) {
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- myproposal[PROPOSAL_ENC_ALGS_STOC] =
- (char *) cipher_name(SSH_CIPHER_3DES_CBC);
- } else if (options.cipher == SSH_CIPHER_BLOWFISH) {
- myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- myproposal[PROPOSAL_ENC_ALGS_STOC] =
- (char *) cipher_name(SSH_CIPHER_BLOWFISH_CBC);
}
if (options.compression) {
myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib";
@@ -313,7 +311,7 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
unsigned char *kbuf;
unsigned char *hash;
- nbits = dh_estimate(kex->enc[MODE_OUT].key_len * 8);
+ nbits = dh_estimate(kex->enc[MODE_OUT].cipher->key_len * 8);
debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST.");
packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c
index 3426b68ced7..664d00223f0 100644
--- a/usr.bin/ssh/sshd.c
+++ b/usr.bin/ssh/sshd.c
@@ -40,14 +40,13 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.129 2000/10/11 04:02:17 provos Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.130 2000/10/11 20:27:24 markus Exp $");
#include "xmalloc.h"
#include "rsa.h"
#include "ssh.h"
#include "pty.h"
#include "packet.h"
-#include "cipher.h"
#include "mpaux.h"
#include "servconf.h"
#include "uidswap.h"
@@ -1177,7 +1176,7 @@ do_ssh1_kex()
/* Get cipher type and check whether we accept this. */
cipher_type = packet_get_char();
- if (!(cipher_mask() & (1 << cipher_type)))
+ if (!(cipher_mask1() & (1 << cipher_type)))
packet_disconnect("Warning: client selects unsupported cipher.");
/* Get check bytes from the packet. These must match those we
@@ -1343,6 +1342,9 @@ do_ssh2_kex()
void
ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
{
+#ifdef DEBUG_KEXDH
+ int i;
+#endif
int payload_len, dlen;
int slen;
unsigned char *signature = NULL;
@@ -1464,6 +1466,9 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
void
ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
{
+#ifdef DEBUG_KEXDH
+ int i;
+#endif
int payload_len, dlen;
int slen, nbits;
unsigned char *signature = NULL;