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