11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2003 Markus Friedl. All rights reserved. 31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without 51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions 61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met: 71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright 81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * notice, this list of conditions and the following disclaimer. 91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright 101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * notice, this list of conditions and the following disclaimer in the 111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * documentation and/or other materials provided with the distribution. 121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h" 261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* compatibility with old or broken OpenSSL versions */ 281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/openssl-compat.h" 291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_BUILTIN_RIJNDAEL 311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h> 321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/evp.h> 341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h> 361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h> 371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "rijndael.h" 391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h" 401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h" 411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define RIJNDAEL_BLOCKSIZE 16 431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct ssh_rijndael_ctx 441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndael_ctx r_ctx; 461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char r_iv[RIJNDAEL_BLOCKSIZE]; 471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}; 481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst EVP_CIPHER * evp_rijndael(void); 501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); 511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, 541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int enc) 551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct ssh_rijndael_ctx *c; 571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { 591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c = xmalloc(sizeof(*c)); 601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_CIPHER_CTX_set_app_data(ctx, c); 611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key != NULL) { 631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (enc == -1) 641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood enc = ctx->encrypt; 651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndael_set_key(&c->r_ctx, (u_char *)key, 661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8*EVP_CIPHER_CTX_key_length(ctx), enc); 671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (iv != NULL) 691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE); 701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (1); 711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, 751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood LIBCRYPTO_EVP_INL_TYPE len) 761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct ssh_rijndael_ctx *c; 781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char buf[RIJNDAEL_BLOCKSIZE]; 791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char *cprev, *cnow, *plain, *ivp; 801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int i, j, blocks = len / RIJNDAEL_BLOCKSIZE; 811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len == 0) 831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (1); 841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len % RIJNDAEL_BLOCKSIZE) 851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("ssh_rijndael_cbc: bad len %d", len); 861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { 871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("ssh_rijndael_cbc: no context"); 881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (0); 891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (ctx->encrypt) { 911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cnow = dest; 921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood plain = (u_char *)src; 931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cprev = c->r_iv; 941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE, 951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cnow+=RIJNDAEL_BLOCKSIZE) { 961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) 971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buf[j] = plain[j] ^ cprev[j]; 981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndael_encrypt(&c->r_ctx, buf, cnow); 991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cprev = cnow; 1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE); 1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE); 1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood plain = dest+len-RIJNDAEL_BLOCKSIZE; 1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE); 1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE, 1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood plain-=RIJNDAEL_BLOCKSIZE) { 1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndael_decrypt(&c->r_ctx, cnow, plain); 1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE; 1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++) 1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood plain[j] ^= ivp[j]; 1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE); 1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (1); 1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx) 1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct ssh_rijndael_ctx *c; 1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { 1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(c, 0, sizeof(*c)); 1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(c); 1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_CIPHER_CTX_set_app_data(ctx, NULL); 1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (1); 1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len) 1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct ssh_rijndael_ctx *c; 1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) 1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("ssh_rijndael_iv: no context"); 1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (doset) 1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(c->r_iv, iv, len); 1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(iv, c->r_iv, len); 1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconst EVP_CIPHER * 1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodevp_rijndael(void) 1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood static EVP_CIPHER rijndal_cbc; 1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER)); 1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndal_cbc.nid = NID_undef; 1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE; 1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE; 1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndal_cbc.key_len = 16; 1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndal_cbc.init = ssh_rijndael_init; 1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndal_cbc.cleanup = ssh_rijndael_cleanup; 1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndal_cbc.do_cipher = ssh_rijndael_cbc; 1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef SSH_OLD_EVP 1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | 1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; 1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (&rijndal_cbc); 1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_BUILTIN_RIJNDAEL */ 165