-
-/* 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));
-}
-
-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
-cipher_encrypt(CipherContext *context, unsigned char *dest,
- const unsigned char *src, unsigned 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));
- }
-}
-
-/* Decrypts data using the cipher. */
-
-void
-cipher_decrypt(CipherContext *context, unsigned char *dest,
- const unsigned char *src, unsigned int len)
-{
- if ((len & 7) != 0)
- fatal("cipher_decrypt: bad ciphertext length %d", len);
-
- 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));
- }
-}