cipher.c revision 92559
157429Smarkm/*
257429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi>
357429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
457429Smarkm *                    All rights reserved
560576Skris *
665674Skris * As far as I am concerned, the code I have written for this software
765674Skris * can be used freely for any purpose.  Any derived versions of this
865674Skris * software must be clearly marked as such, and if the derived work is
965674Skris * incompatible with the protocol description in the RFC file, it must be
1065674Skris * called by a name other than "ssh" or "Secure Shell".
1160576Skris *
1265674Skris *
1365674Skris * Copyright (c) 1999 Niels Provos.  All rights reserved.
1492559Sdes * Copyright (c) 1999, 2000 Markus Friedl.  All rights reserved.
1565674Skris *
1665674Skris * Redistribution and use in source and binary forms, with or without
1765674Skris * modification, are permitted provided that the following conditions
1865674Skris * are met:
1965674Skris * 1. Redistributions of source code must retain the above copyright
2065674Skris *    notice, this list of conditions and the following disclaimer.
2165674Skris * 2. Redistributions in binary form must reproduce the above copyright
2265674Skris *    notice, this list of conditions and the following disclaimer in the
2365674Skris *    documentation and/or other materials provided with the distribution.
2465674Skris *
2565674Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2665674Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2765674Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2865674Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2965674Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3065674Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3165674Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3265674Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3365674Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3465674Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3557429Smarkm */
3657429Smarkm
3757429Smarkm#include "includes.h"
3892559SdesRCSID("$OpenBSD: cipher.c,v 1.52 2002/02/18 13:05:32 markus Exp $");
3965674SkrisRCSID("$FreeBSD: head/crypto/openssh/cipher.c 92559 2002-03-18 10:09:43Z des $");
4057429Smarkm
4160576Skris#include "xmalloc.h"
4276262Sgreen#include "log.h"
4376262Sgreen#include "cipher.h"
4457429Smarkm
4557464Sgreen#include <openssl/md5.h>
4692559Sdes#include "rijndael.h"
4757429Smarkm
4892559Sdesstatic EVP_CIPHER *evp_ssh1_3des(void);
4992559Sdesstatic EVP_CIPHER *evp_ssh1_bf(void);
5092559Sdesstatic EVP_CIPHER *evp_rijndael(void);
5169591Sgreen
5292559Sdesstruct Cipher {
5392559Sdes	char	*name;
5492559Sdes	int	number;		/* for ssh1 only */
5592559Sdes	u_int	block_size;
5692559Sdes	u_int	key_len;
5792559Sdes	EVP_CIPHER	*(*evptype)(void);
5892559Sdes} ciphers[] = {
5992559Sdes	{ "none", 		SSH_CIPHER_NONE, 8, 0, EVP_enc_null },
6092559Sdes	{ "des", 		SSH_CIPHER_DES, 8, 8, EVP_des_cbc },
6192559Sdes	{ "3des", 		SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des },
6292559Sdes	{ "blowfish", 		SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf },
6369591Sgreen
6492559Sdes	{ "3des-cbc", 		SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc },
6592559Sdes	{ "blowfish-cbc", 	SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc },
6692559Sdes	{ "cast128-cbc", 	SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc },
6792559Sdes	{ "arcfour", 		SSH_CIPHER_SSH2, 8, 16, EVP_rc4 },
6892559Sdes	{ "aes128-cbc", 	SSH_CIPHER_SSH2, 16, 16, evp_rijndael },
6992559Sdes	{ "aes192-cbc", 	SSH_CIPHER_SSH2, 16, 24, evp_rijndael },
7092559Sdes	{ "aes256-cbc", 	SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
7169591Sgreen
7292559Sdes	{ NULL,			SSH_CIPHER_ILLEGAL, 0, 0, NULL }
7392559Sdes};
7469591Sgreen
7592559Sdes/*--*/
7657429Smarkm
7792559Sdesu_int
7892559Sdescipher_blocksize(Cipher *c)
7957429Smarkm{
8092559Sdes	return (c->block_size);
8157429Smarkm}
8292559Sdesu_int
8392559Sdescipher_keylen(Cipher *c)
8469591Sgreen{
8592559Sdes	return (c->key_len);
8669591Sgreen}
8769591Sgreen
8876262Sgreenu_int
8969591Sgreencipher_mask_ssh1(int client)
9057429Smarkm{
9176262Sgreen	u_int mask = 0;
9292559Sdes	mask |= 1 << SSH_CIPHER_3DES;		/* Mandatory */
9357429Smarkm	mask |= 1 << SSH_CIPHER_BLOWFISH;
9469591Sgreen	if (client) {
9569591Sgreen		mask |= 1 << SSH_CIPHER_DES;
9669591Sgreen	}
9757429Smarkm	return mask;
9857429Smarkm}
9969591Sgreen
10069591SgreenCipher *
10169591Sgreencipher_by_name(const char *name)
10260576Skris{
10369591Sgreen	Cipher *c;
10469591Sgreen	for (c = ciphers; c->name != NULL; c++)
10569591Sgreen		if (strcasecmp(c->name, name) == 0)
10669591Sgreen			return c;
10769591Sgreen	return NULL;
10860576Skris}
10957429Smarkm
11069591SgreenCipher *
11169591Sgreencipher_by_number(int id)
11257429Smarkm{
11369591Sgreen	Cipher *c;
11469591Sgreen	for (c = ciphers; c->name != NULL; c++)
11569591Sgreen		if (c->number == id)
11669591Sgreen			return c;
11769591Sgreen	return NULL;
11857429Smarkm}
11957429Smarkm
12060576Skris#define	CIPHER_SEP	","
12160576Skrisint
12260576Skrisciphers_valid(const char *names)
12360576Skris{
12469591Sgreen	Cipher *c;
12565674Skris	char *ciphers, *cp;
12660576Skris	char *p;
12760576Skris
12861212Skris	if (names == NULL || strcmp(names, "") == 0)
12960576Skris		return 0;
13065674Skris	ciphers = cp = xstrdup(names);
13169591Sgreen	for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
13292559Sdes	    (p = strsep(&cp, CIPHER_SEP))) {
13369591Sgreen		c = cipher_by_name(p);
13469591Sgreen		if (c == NULL || c->number != SSH_CIPHER_SSH2) {
13569591Sgreen			debug("bad cipher %s [%s]", p, names);
13660576Skris			xfree(ciphers);
13760576Skris			return 0;
13869591Sgreen		} else {
13969591Sgreen			debug3("cipher ok: %s [%s]", p, names);
14060576Skris		}
14160576Skris	}
14269591Sgreen	debug3("ciphers ok: [%s]", names);
14360576Skris	xfree(ciphers);
14460576Skris	return 1;
14560576Skris}
14660576Skris
14757429Smarkm/*
14857429Smarkm * Parses the name of the cipher.  Returns the number of the corresponding
14957429Smarkm * cipher, or -1 on error.
15057429Smarkm */
15157429Smarkm
15257429Smarkmint
15357429Smarkmcipher_number(const char *name)
15457429Smarkm{
15569591Sgreen	Cipher *c;
15661212Skris	if (name == NULL)
15761212Skris		return -1;
15869591Sgreen	c = cipher_by_name(name);
15969591Sgreen	return (c==NULL) ? -1 : c->number;
16057429Smarkm}
16157429Smarkm
16269591Sgreenchar *
16369591Sgreencipher_name(int id)
16457429Smarkm{
16569591Sgreen	Cipher *c = cipher_by_number(id);
16669591Sgreen	return (c==NULL) ? "<unknown>" : c->name;
16757429Smarkm}
16857429Smarkm
16960576Skrisvoid
17069591Sgreencipher_init(CipherContext *cc, Cipher *cipher,
17192559Sdes    const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
17292559Sdes    int encrypt)
17357429Smarkm{
17492559Sdes	static int dowarn = 1;
17592559Sdes	const EVP_CIPHER *type;
17692559Sdes	int klen;
17792559Sdes
17892559Sdes	if (cipher->number == SSH_CIPHER_DES) {
17992559Sdes		if (dowarn) {
18092559Sdes			error("Warning: use of DES is strongly discouraged "
18192559Sdes			    "due to cryptographic weaknesses");
18292559Sdes			dowarn = 0;
18392559Sdes		}
18492559Sdes		if (keylen > 8)
18592559Sdes			keylen = 8;
18692559Sdes	}
18792559Sdes	cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
18892559Sdes
18969591Sgreen	if (keylen < cipher->key_len)
19069591Sgreen		fatal("cipher_init: key length %d is insufficient for %s.",
19169591Sgreen		    keylen, cipher->name);
19269591Sgreen	if (iv != NULL && ivlen < cipher->block_size)
19369591Sgreen		fatal("cipher_init: iv length %d is insufficient for %s.",
19469591Sgreen		    ivlen, cipher->name);
19569591Sgreen	cc->cipher = cipher;
19692559Sdes
19792559Sdes	type = (*cipher->evptype)();
19892559Sdes
19992559Sdes	EVP_CIPHER_CTX_init(&cc->evp);
20092559Sdes	if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
20192559Sdes	    (encrypt == CIPHER_ENCRYPT)) == 0)
20292559Sdes		fatal("cipher_init: EVP_CipherInit failed for %s",
20392559Sdes		    cipher->name);
20492559Sdes	klen = EVP_CIPHER_CTX_key_length(&cc->evp);
20592559Sdes	if (klen > 0 && keylen != klen) {
20692559Sdes		debug("cipher_init: set keylen (%d -> %d)", klen, keylen);
20792559Sdes		if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
20892559Sdes			fatal("cipher_init: set keylen failed (%d -> %d)",
20992559Sdes			    klen, keylen);
21092559Sdes	}
21192559Sdes	if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
21292559Sdes		fatal("cipher_init: EVP_CipherInit: set key failed for %s",
21392559Sdes		    cipher->name);
21457429Smarkm}
21557429Smarkm
21660576Skrisvoid
21792559Sdescipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
21860576Skris{
21969591Sgreen	if (len % cc->cipher->block_size)
22069591Sgreen		fatal("cipher_encrypt: bad plaintext length %d", len);
22192559Sdes	if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
22292559Sdes		fatal("evp_crypt: EVP_Cipher failed");
22360576Skris}
22460576Skris
22560576Skrisvoid
22692559Sdescipher_cleanup(CipherContext *cc)
22757429Smarkm{
22892559Sdes	if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
22992559Sdes		error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
23057429Smarkm}
23157429Smarkm
23269591Sgreen/*
23369591Sgreen * Selects the cipher, and keys if by computing the MD5 checksum of the
23469591Sgreen * passphrase and using the resulting 16 bytes as the key.
23569591Sgreen */
23657429Smarkm
23760576Skrisvoid
23869591Sgreencipher_set_key_string(CipherContext *cc, Cipher *cipher,
23992559Sdes    const char *passphrase, int encrypt)
24057429Smarkm{
24169591Sgreen	MD5_CTX md;
24276262Sgreen	u_char digest[16];
24357429Smarkm
24469591Sgreen	MD5_Init(&md);
24569591Sgreen	MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
24669591Sgreen	MD5_Final(digest, &md);
24757429Smarkm
24892559Sdes	cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt);
24957429Smarkm
25069591Sgreen	memset(digest, 0, sizeof(digest));
25169591Sgreen	memset(&md, 0, sizeof(md));
25257429Smarkm}
25392559Sdes
25492559Sdes/* Implementations for other non-EVP ciphers */
25592559Sdes
25692559Sdes/*
25792559Sdes * This is used by SSH1:
25892559Sdes *
25992559Sdes * What kind of triple DES are these 2 routines?
26092559Sdes *
26192559Sdes * Why is there a redundant initialization vector?
26292559Sdes *
26392559Sdes * If only iv3 was used, then, this would till effect have been
26492559Sdes * outer-cbc. However, there is also a private iv1 == iv2 which
26592559Sdes * perhaps makes differential analysis easier. On the other hand, the
26692559Sdes * private iv1 probably makes the CRC-32 attack ineffective. This is a
26792559Sdes * result of that there is no longer any known iv1 to use when
26892559Sdes * choosing the X block.
26992559Sdes */
27092559Sdesstruct ssh1_3des_ctx
27192559Sdes{
27292559Sdes	EVP_CIPHER_CTX	k1, k2, k3;
27392559Sdes};
27492559Sdesstatic int
27592559Sdesssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
27692559Sdes    int enc)
27792559Sdes{
27892559Sdes	struct ssh1_3des_ctx *c;
27992559Sdes	u_char *k1, *k2, *k3;
28092559Sdes
28192559Sdes	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
28292559Sdes		c = xmalloc(sizeof(*c));
28392559Sdes		EVP_CIPHER_CTX_set_app_data(ctx, c);
28492559Sdes	}
28592559Sdes	if (key == NULL)
28692559Sdes		return (1);
28792559Sdes	if (enc == -1)
28892559Sdes		enc = ctx->encrypt;
28992559Sdes	k1 = k2 = k3 = (u_char *) key;
29092559Sdes	k2 += 8;
29192559Sdes	if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
29292559Sdes		if (enc)
29392559Sdes			k3 += 16;
29492559Sdes		else
29592559Sdes			k1 += 16;
29692559Sdes	}
29792559Sdes	EVP_CIPHER_CTX_init(&c->k1);
29892559Sdes	EVP_CIPHER_CTX_init(&c->k2);
29992559Sdes	EVP_CIPHER_CTX_init(&c->k3);
30092559Sdes	if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
30192559Sdes	    EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
30292559Sdes	    EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
30392559Sdes		memset(c, 0, sizeof(*c));
30492559Sdes		xfree(c);
30592559Sdes		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
30692559Sdes		return (0);
30792559Sdes	}
30892559Sdes	return (1);
30992559Sdes}
31092559Sdesstatic int
31192559Sdesssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
31292559Sdes{
31392559Sdes	struct ssh1_3des_ctx *c;
31492559Sdes
31592559Sdes	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
31692559Sdes		error("ssh1_3des_cbc: no context");
31792559Sdes		return (0);
31892559Sdes	}
31992559Sdes	if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
32092559Sdes	    EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
32192559Sdes	    EVP_Cipher(&c->k3, dest, dest, len) == 0)
32292559Sdes		return (0);
32392559Sdes	return (1);
32492559Sdes}
32592559Sdesstatic int
32692559Sdesssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
32792559Sdes{
32892559Sdes	struct ssh1_3des_ctx *c;
32992559Sdes
33092559Sdes	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
33192559Sdes		memset(c, 0, sizeof(*c));
33292559Sdes		xfree(c);
33392559Sdes		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
33492559Sdes	}
33592559Sdes	return (1);
33692559Sdes}
33792559Sdesstatic EVP_CIPHER *
33892559Sdesevp_ssh1_3des(void)
33992559Sdes{
34092559Sdes	static EVP_CIPHER ssh1_3des;
34192559Sdes
34292559Sdes	memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
34392559Sdes	ssh1_3des.nid = NID_undef;
34492559Sdes	ssh1_3des.block_size = 8;
34592559Sdes	ssh1_3des.iv_len = 0;
34692559Sdes	ssh1_3des.key_len = 16;
34792559Sdes	ssh1_3des.init = ssh1_3des_init;
34892559Sdes	ssh1_3des.cleanup = ssh1_3des_cleanup;
34992559Sdes	ssh1_3des.do_cipher = ssh1_3des_cbc;
35092559Sdes	ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
35192559Sdes	return (&ssh1_3des);
35292559Sdes}
35392559Sdes
35492559Sdes/*
35592559Sdes * SSH1 uses a variation on Blowfish, all bytes must be swapped before
35692559Sdes * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
35792559Sdes */
35892559Sdesstatic void
35992559Sdesswap_bytes(const u_char *src, u_char *dst, int n)
36092559Sdes{
36192559Sdes	u_char c[4];
36292559Sdes
36392559Sdes	/* Process 4 bytes every lap. */
36492559Sdes	for (n = n / 4; n > 0; n--) {
36592559Sdes		c[3] = *src++;
36692559Sdes		c[2] = *src++;
36792559Sdes		c[1] = *src++;
36892559Sdes		c[0] = *src++;
36992559Sdes
37092559Sdes		*dst++ = c[0];
37192559Sdes		*dst++ = c[1];
37292559Sdes		*dst++ = c[2];
37392559Sdes		*dst++ = c[3];
37492559Sdes	}
37592559Sdes}
37692559Sdesstatic int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
37792559Sdesstatic int
37892559Sdesbf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
37992559Sdes{
38092559Sdes	int ret;
38192559Sdes
38292559Sdes	swap_bytes(in, out, len);
38392559Sdes	ret = (*orig_bf)(ctx, out, out, len);
38492559Sdes	swap_bytes(out, out, len);
38592559Sdes	return (ret);
38692559Sdes}
38792559Sdesstatic EVP_CIPHER *
38892559Sdesevp_ssh1_bf(void)
38992559Sdes{
39092559Sdes	static EVP_CIPHER ssh1_bf;
39192559Sdes
39292559Sdes	memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
39392559Sdes	orig_bf = ssh1_bf.do_cipher;
39492559Sdes	ssh1_bf.nid = NID_undef;
39592559Sdes	ssh1_bf.do_cipher = bf_ssh1_cipher;
39692559Sdes	ssh1_bf.key_len = 32;
39792559Sdes	return (&ssh1_bf);
39892559Sdes}
39992559Sdes
40092559Sdes/* RIJNDAEL */
40192559Sdes#define RIJNDAEL_BLOCKSIZE 16
40292559Sdesstruct ssh_rijndael_ctx
40392559Sdes{
40492559Sdes	rijndael_ctx	r_ctx;
40592559Sdes	u_char		r_iv[RIJNDAEL_BLOCKSIZE];
40692559Sdes};
40792559Sdes
40892559Sdesstatic int
40992559Sdesssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
41092559Sdes    int enc)
41192559Sdes{
41292559Sdes	struct ssh_rijndael_ctx *c;
41392559Sdes
41492559Sdes	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
41592559Sdes		c = xmalloc(sizeof(*c));
41692559Sdes		EVP_CIPHER_CTX_set_app_data(ctx, c);
41792559Sdes	}
41892559Sdes	if (key != NULL) {
41992559Sdes		if (enc == -1)
42092559Sdes			enc = ctx->encrypt;
42192559Sdes		rijndael_set_key(&c->r_ctx, (u_char *)key,
42292559Sdes		    8*EVP_CIPHER_CTX_key_length(ctx), enc);
42392559Sdes	}
42492559Sdes	if (iv != NULL)
42592559Sdes		memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
42692559Sdes	return (1);
42792559Sdes}
42892559Sdesstatic int
42992559Sdesssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
43092559Sdes    u_int len)
43192559Sdes{
43292559Sdes	struct ssh_rijndael_ctx *c;
43392559Sdes	u_char buf[RIJNDAEL_BLOCKSIZE];
43492559Sdes	u_char *cprev, *cnow, *plain, *ivp;
43592559Sdes	int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
43692559Sdes
43792559Sdes	if (len == 0)
43892559Sdes		return (1);
43992559Sdes	if (len % RIJNDAEL_BLOCKSIZE)
44092559Sdes		fatal("ssh_rijndael_cbc: bad len %d", len);
44192559Sdes	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
44292559Sdes		error("ssh_rijndael_cbc: no context");
44392559Sdes		return (0);
44492559Sdes	}
44592559Sdes	if (ctx->encrypt) {
44692559Sdes		cnow  = dest;
44792559Sdes		plain = (u_char *)src;
44892559Sdes		cprev = c->r_iv;
44992559Sdes		for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
45092559Sdes		    cnow+=RIJNDAEL_BLOCKSIZE) {
45192559Sdes			for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
45292559Sdes				buf[j] = plain[j] ^ cprev[j];
45392559Sdes			rijndael_encrypt(&c->r_ctx, buf, cnow);
45492559Sdes			cprev = cnow;
45592559Sdes		}
45692559Sdes		memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
45792559Sdes	} else {
45892559Sdes		cnow  = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
45992559Sdes		plain = dest+len-RIJNDAEL_BLOCKSIZE;
46092559Sdes
46192559Sdes		memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
46292559Sdes		for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
46392559Sdes		    plain-=RIJNDAEL_BLOCKSIZE) {
46492559Sdes			rijndael_decrypt(&c->r_ctx, cnow, plain);
46592559Sdes			ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
46692559Sdes			for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
46792559Sdes				plain[j] ^= ivp[j];
46892559Sdes		}
46992559Sdes		memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
47092559Sdes	}
47192559Sdes	return (1);
47292559Sdes}
47392559Sdesstatic int
47492559Sdesssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
47592559Sdes{
47692559Sdes	struct ssh_rijndael_ctx *c;
47792559Sdes
47892559Sdes	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
47992559Sdes		memset(c, 0, sizeof(*c));
48092559Sdes		xfree(c);
48192559Sdes		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
48292559Sdes	}
48392559Sdes	return (1);
48492559Sdes}
48592559Sdesstatic EVP_CIPHER *
48692559Sdesevp_rijndael(void)
48792559Sdes{
48892559Sdes	static EVP_CIPHER rijndal_cbc;
48992559Sdes
49092559Sdes	memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
49192559Sdes	rijndal_cbc.nid = NID_undef;
49292559Sdes	rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
49392559Sdes	rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
49492559Sdes	rijndal_cbc.key_len = 16;
49592559Sdes	rijndal_cbc.init = ssh_rijndael_init;
49692559Sdes	rijndal_cbc.cleanup = ssh_rijndael_cleanup;
49792559Sdes	rijndal_cbc.do_cipher = ssh_rijndael_cbc;
49892559Sdes	rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
49992559Sdes	    EVP_CIPH_ALWAYS_CALL_INIT;
50092559Sdes	return (&rijndal_cbc);
50192559Sdes}
502