diff options
Diffstat (limited to 'usr.bin/ssh/cipher.c')
-rw-r--r-- | usr.bin/ssh/cipher.c | 123 |
1 files changed, 121 insertions, 2 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)); } |