+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));
+ }
+}
+