diff options
-rw-r--r-- | usr.bin/ssh/cipher.c | 123 | ||||
-rw-r--r-- | usr.bin/ssh/cipher.h | 20 |
2 files changed, 140 insertions, 3 deletions
diff --git a/usr.bin/ssh/cipher.c b/usr.bin/ssh/cipher.c index 682a980175c..cbdec264375 100644 --- a/usr.bin/ssh/cipher.c +++ b/usr.bin/ssh/cipher.c @@ -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)); } diff --git a/usr.bin/ssh/cipher.h b/usr.bin/ssh/cipher.h index a6f458a54de..b8e647ca67e 100644 --- a/usr.bin/ssh/cipher.h +++ b/usr.bin/ssh/cipher.h @@ -11,13 +11,15 @@ * */ -/* 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. */ @@ -29,6 +31,13 @@ #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, |