support ssh2 ciphers
authormarkus <markus@openbsd.org>
Tue, 28 Mar 2000 20:24:49 +0000 (20:24 +0000)
committermarkus <markus@openbsd.org>
Tue, 28 Mar 2000 20:24:49 +0000 (20:24 +0000)
usr.bin/ssh/cipher.c
usr.bin/ssh/cipher.h

index 682a980..cbdec26 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: cipher.c,v 1.20 2000/03/22 09:55:10 markus Exp $");
+RCSID("$Id: cipher.c,v 1.21 2000/03/28 20:24:49 markus Exp $");
 
 #include "ssh.h"
 #include "cipher.h"
@@ -116,7 +116,12 @@ static char *cipher_names[] =
        "3des",
        "tss",
        "rc4",
-       "blowfish"
+       "blowfish",
+       "reserved",
+       "blowfish-cbc",
+       "3des-cbc",
+       "arcfour",
+       "cast128-cbc"
 };
 
 /*
@@ -131,6 +136,10 @@ cipher_mask()
        unsigned int mask = 0;
        mask |= 1 << SSH_CIPHER_3DES;           /* Mandatory */
        mask |= 1 << SSH_CIPHER_BLOWFISH;
+       mask |= 1 << SSH_CIPHER_BLOWFISH_CBC;
+       mask |= 1 << SSH_CIPHER_3DES_CBC;
+       mask |= 1 << SSH_CIPHER_ARCFOUR;
+       mask |= 1 << SSH_CIPHER_CAST128_CBC;
        return mask;
 }
 
@@ -227,16 +236,84 @@ cipher_set_key(CipherContext *context, int cipher,
                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));
 }
 
+
+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));
+       }
+}
+
 /* Encrypts data using the cipher. */
 
 void 
@@ -266,6 +343,27 @@ cipher_encrypt(CipherContext *context, unsigned char *dest,
                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));
        }
@@ -300,6 +398,27 @@ cipher_decrypt(CipherContext *context, unsigned char *dest,
                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));
        }
index a6f458a..b8e647c 100644 (file)
  * 
  */
 
-/* RCSID("$Id: cipher.h,v 1.11 2000/03/22 09:55:10 markus Exp $"); */
+/* RCSID("$Id: cipher.h,v 1.12 2000/03/28 20:24:50 markus Exp $"); */
 
 #ifndef CIPHER_H
 #define CIPHER_H
 
 #include <ssl/des.h>
 #include <ssl/blowfish.h>
+#include <ssl/rc4.h>
+#include <ssl/cast.h>
 
 /* Cipher types.  New types can be added, but old types should not be removed
    for compatibility.  The maximum allowed value is 31. */
 #define SSH_CIPHER_BROKEN_TSS  4       /* TRI's Simple Stream encryption CBC */
 #define SSH_CIPHER_BROKEN_RC4  5       /* Alleged RC4 */
 #define SSH_CIPHER_BLOWFISH    6
+#define SSH_CIPHER_RESERVED    7
+
+/* 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 {
        unsigned int type;
@@ -44,6 +53,11 @@ typedef struct {
                        struct bf_key_st key;
                        unsigned char iv[8];
                }       bf;
+               struct {
+                       CAST_KEY key;
+                       unsigned char iv[8];
+               } cast;
+               RC4_KEY rc4;
        }       u;
 }       CipherContext;
 /*
@@ -69,6 +83,10 @@ int     cipher_number(const char *name);
 void 
 cipher_set_key(CipherContext * context, int cipher,
     const unsigned char *key, int keylen, int for_encryption);
+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,