cipher-aes.c revision 124208
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" 26124208Sdes#if OPENSSL_VERSION_NUMBER < 0x00907000L 27124208SdesRCSID("$OpenBSD: cipher-aes.c,v 1.1 2003/05/15 03:08:29 markus Exp $"); 28124208Sdes 29124208Sdes#include <openssl/evp.h> 30124208Sdes#include "rijndael.h" 31124208Sdes#include "xmalloc.h" 32124208Sdes#include "log.h" 33124208Sdes 34124208Sdes#if OPENSSL_VERSION_NUMBER < 0x00906000L 35124208Sdes#define SSH_OLD_EVP 36124208Sdes#endif 37124208Sdes 38124208Sdes#define RIJNDAEL_BLOCKSIZE 16 39124208Sdesstruct ssh_rijndael_ctx 40124208Sdes{ 41124208Sdes rijndael_ctx r_ctx; 42124208Sdes u_char r_iv[RIJNDAEL_BLOCKSIZE]; 43124208Sdes}; 44124208Sdes 45124208Sdesconst EVP_CIPHER * evp_rijndael(void); 46124208Sdesvoid ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); 47124208Sdes 48124208Sdesstatic int 49124208Sdesssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, 50124208Sdes int enc) 51124208Sdes{ 52124208Sdes struct ssh_rijndael_ctx *c; 53124208Sdes 54124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { 55124208Sdes c = xmalloc(sizeof(*c)); 56124208Sdes EVP_CIPHER_CTX_set_app_data(ctx, c); 57124208Sdes } 58124208Sdes if (key != NULL) { 59124208Sdes if (enc == -1) 60124208Sdes enc = ctx->encrypt; 61124208Sdes rijndael_set_key(&c->r_ctx, (u_char *)key, 62124208Sdes 8*EVP_CIPHER_CTX_key_length(ctx), enc); 63124208Sdes } 64124208Sdes if (iv != NULL) 65124208Sdes memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE); 66124208Sdes return (1); 67124208Sdes} 68124208Sdes 69124208Sdesstatic int 70124208Sdesssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, 71124208Sdes u_int len) 72124208Sdes{ 73124208Sdes struct ssh_rijndael_ctx *c; 74124208Sdes u_char buf[RIJNDAEL_BLOCKSIZE]; 75124208Sdes u_char *cprev, *cnow, *plain, *ivp; 76124208Sdes int i, j, blocks = len / RIJNDAEL_BLOCKSIZE; 77124208Sdes 78124208Sdes if (len == 0) 79124208Sdes return (1); 80124208Sdes if (len % RIJNDAEL_BLOCKSIZE) 81124208Sdes fatal("ssh_rijndael_cbc: bad len %d", len); 82124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { 83124208Sdes error("ssh_rijndael_cbc: no context"); 84124208Sdes return (0); 85124208Sdes } 86124208Sdes if (ctx->encrypt) { 87124208Sdes cnow = dest; 88124208Sdes plain = (u_char *)src; 89124208Sdes cprev = c->r_iv; 90124208Sdes for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE, 91124208Sdes cnow+=RIJNDAEL_BLOCKSIZE) { 92124208Sdes for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) 93124208Sdes buf[j] = plain[j] ^ cprev[j]; 94124208Sdes rijndael_encrypt(&c->r_ctx, buf, cnow); 95124208Sdes cprev = cnow; 96124208Sdes } 97124208Sdes memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE); 98124208Sdes } else { 99124208Sdes cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE); 100124208Sdes plain = dest+len-RIJNDAEL_BLOCKSIZE; 101124208Sdes 102124208Sdes memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE); 103124208Sdes for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE, 104124208Sdes plain-=RIJNDAEL_BLOCKSIZE) { 105124208Sdes rijndael_decrypt(&c->r_ctx, cnow, plain); 106124208Sdes ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE; 107124208Sdes for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) 108124208Sdes plain[j] ^= ivp[j]; 109124208Sdes } 110124208Sdes memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE); 111124208Sdes } 112124208Sdes return (1); 113124208Sdes} 114124208Sdes 115124208Sdesstatic int 116124208Sdesssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx) 117124208Sdes{ 118124208Sdes struct ssh_rijndael_ctx *c; 119124208Sdes 120124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { 121124208Sdes memset(c, 0, sizeof(*c)); 122124208Sdes xfree(c); 123124208Sdes EVP_CIPHER_CTX_set_app_data(ctx, NULL); 124124208Sdes } 125124208Sdes return (1); 126124208Sdes} 127124208Sdes 128124208Sdesvoid 129124208Sdesssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len) 130124208Sdes{ 131124208Sdes struct ssh_rijndael_ctx *c; 132124208Sdes 133124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) 134124208Sdes fatal("ssh_rijndael_iv: no context"); 135124208Sdes if (doset) 136124208Sdes memcpy(c->r_iv, iv, len); 137124208Sdes else 138124208Sdes memcpy(iv, c->r_iv, len); 139124208Sdes} 140124208Sdes 141124208Sdesconst EVP_CIPHER * 142124208Sdesevp_rijndael(void) 143124208Sdes{ 144124208Sdes static EVP_CIPHER rijndal_cbc; 145124208Sdes 146124208Sdes memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER)); 147124208Sdes rijndal_cbc.nid = NID_undef; 148124208Sdes rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE; 149124208Sdes rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE; 150124208Sdes rijndal_cbc.key_len = 16; 151124208Sdes rijndal_cbc.init = ssh_rijndael_init; 152124208Sdes rijndal_cbc.cleanup = ssh_rijndael_cleanup; 153124208Sdes rijndal_cbc.do_cipher = ssh_rijndael_cbc; 154124208Sdes#ifndef SSH_OLD_EVP 155124208Sdes rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | 156124208Sdes EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; 157124208Sdes#endif 158124208Sdes return (&rijndal_cbc); 159124208Sdes} 160124208Sdes#endif /* OPENSSL_VERSION_NUMBER */ 161