1124208Sdes/* 2124208Sdes * Copyright (c) 2003 Markus Friedl. All rights reserved. 3124208Sdes * 4124208Sdes * Redistribution and use in source and binary forms, with or without 5124208Sdes * modification, are permitted provided that the following conditions 6124208Sdes * are met: 7124208Sdes * 1. Redistributions of source code must retain the above copyright 8124208Sdes * notice, this list of conditions and the following disclaimer. 9124208Sdes * 2. Redistributions in binary form must reproduce the above copyright 10124208Sdes * notice, this list of conditions and the following disclaimer in the 11124208Sdes * documentation and/or other materials provided with the distribution. 12124208Sdes * 13124208Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14124208Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15124208Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16124208Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17124208Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18124208Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19124208Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20124208Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21124208Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22124208Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23124208Sdes */ 24124208Sdes 25124208Sdes#include "includes.h" 26157016Sdes 27157016Sdes/* compatibility with old or broken OpenSSL versions */ 28157016Sdes#include "openbsd-compat/openssl-compat.h" 29157016Sdes 30157016Sdes#ifdef USE_BUILTIN_RIJNDAEL 31162852Sdes#include <sys/types.h> 32124208Sdes 33124208Sdes#include <openssl/evp.h> 34162852Sdes 35162852Sdes#include <stdarg.h> 36162852Sdes#include <string.h> 37162852Sdes 38124208Sdes#include "rijndael.h" 39124208Sdes#include "xmalloc.h" 40124208Sdes#include "log.h" 41124208Sdes 42124208Sdes#define RIJNDAEL_BLOCKSIZE 16 43124208Sdesstruct ssh_rijndael_ctx 44124208Sdes{ 45124208Sdes rijndael_ctx r_ctx; 46124208Sdes u_char r_iv[RIJNDAEL_BLOCKSIZE]; 47124208Sdes}; 48124208Sdes 49124208Sdesstatic int 50124208Sdesssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, 51124208Sdes int enc) 52124208Sdes{ 53124208Sdes struct ssh_rijndael_ctx *c; 54124208Sdes 55124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { 56124208Sdes c = xmalloc(sizeof(*c)); 57124208Sdes EVP_CIPHER_CTX_set_app_data(ctx, c); 58124208Sdes } 59124208Sdes if (key != NULL) { 60124208Sdes if (enc == -1) 61124208Sdes enc = ctx->encrypt; 62124208Sdes rijndael_set_key(&c->r_ctx, (u_char *)key, 63124208Sdes 8*EVP_CIPHER_CTX_key_length(ctx), enc); 64124208Sdes } 65124208Sdes if (iv != NULL) 66124208Sdes memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE); 67124208Sdes return (1); 68124208Sdes} 69124208Sdes 70124208Sdesstatic int 71124208Sdesssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, 72221420Sdes LIBCRYPTO_EVP_INL_TYPE len) 73124208Sdes{ 74124208Sdes struct ssh_rijndael_ctx *c; 75124208Sdes u_char buf[RIJNDAEL_BLOCKSIZE]; 76124208Sdes u_char *cprev, *cnow, *plain, *ivp; 77124208Sdes int i, j, blocks = len / RIJNDAEL_BLOCKSIZE; 78124208Sdes 79124208Sdes if (len == 0) 80124208Sdes return (1); 81124208Sdes if (len % RIJNDAEL_BLOCKSIZE) 82124208Sdes fatal("ssh_rijndael_cbc: bad len %d", len); 83124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { 84124208Sdes error("ssh_rijndael_cbc: no context"); 85124208Sdes return (0); 86124208Sdes } 87124208Sdes if (ctx->encrypt) { 88124208Sdes cnow = dest; 89124208Sdes plain = (u_char *)src; 90124208Sdes cprev = c->r_iv; 91124208Sdes for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE, 92124208Sdes cnow+=RIJNDAEL_BLOCKSIZE) { 93124208Sdes for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) 94124208Sdes buf[j] = plain[j] ^ cprev[j]; 95124208Sdes rijndael_encrypt(&c->r_ctx, buf, cnow); 96124208Sdes cprev = cnow; 97124208Sdes } 98124208Sdes memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE); 99124208Sdes } else { 100124208Sdes cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE); 101124208Sdes plain = dest+len-RIJNDAEL_BLOCKSIZE; 102124208Sdes 103124208Sdes memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE); 104124208Sdes for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE, 105124208Sdes plain-=RIJNDAEL_BLOCKSIZE) { 106124208Sdes rijndael_decrypt(&c->r_ctx, cnow, plain); 107124208Sdes ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE; 108124208Sdes for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) 109124208Sdes plain[j] ^= ivp[j]; 110124208Sdes } 111124208Sdes memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE); 112124208Sdes } 113124208Sdes return (1); 114124208Sdes} 115124208Sdes 116124208Sdesstatic int 117124208Sdesssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx) 118124208Sdes{ 119124208Sdes struct ssh_rijndael_ctx *c; 120124208Sdes 121124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { 122124208Sdes memset(c, 0, sizeof(*c)); 123255767Sdes free(c); 124124208Sdes EVP_CIPHER_CTX_set_app_data(ctx, NULL); 125124208Sdes } 126124208Sdes return (1); 127124208Sdes} 128124208Sdes 129124208Sdesvoid 130124208Sdesssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len) 131124208Sdes{ 132124208Sdes struct ssh_rijndael_ctx *c; 133124208Sdes 134124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) 135124208Sdes fatal("ssh_rijndael_iv: no context"); 136124208Sdes if (doset) 137124208Sdes memcpy(c->r_iv, iv, len); 138124208Sdes else 139124208Sdes memcpy(iv, c->r_iv, len); 140124208Sdes} 141124208Sdes 142124208Sdesconst EVP_CIPHER * 143124208Sdesevp_rijndael(void) 144124208Sdes{ 145124208Sdes static EVP_CIPHER rijndal_cbc; 146124208Sdes 147124208Sdes memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER)); 148124208Sdes rijndal_cbc.nid = NID_undef; 149124208Sdes rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE; 150124208Sdes rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE; 151124208Sdes rijndal_cbc.key_len = 16; 152124208Sdes rijndal_cbc.init = ssh_rijndael_init; 153124208Sdes rijndal_cbc.cleanup = ssh_rijndael_cleanup; 154124208Sdes rijndal_cbc.do_cipher = ssh_rijndael_cbc; 155124208Sdes#ifndef SSH_OLD_EVP 156124208Sdes rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | 157124208Sdes EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; 158124208Sdes#endif 159124208Sdes return (&rijndal_cbc); 160124208Sdes} 161157016Sdes#endif /* USE_BUILTIN_RIJNDAEL */ 162