1/* $OpenBSD: cipher-ctr.c,v 1.11 2010/10/01 23:05:32 djm Exp $ */ 2/* 3 * Copyright (c) 2003 Markus Friedl <markus@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17#include "includes.h" 18 19#include <sys/types.h> 20 21#include <stdarg.h> 22#include <string.h> 23 24#include <openssl/evp.h> 25 26#include "xmalloc.h" 27#include "log.h" 28 29/* compatibility with old or broken OpenSSL versions */ 30#include "openbsd-compat/openssl-compat.h" 31 32#ifndef USE_BUILTIN_RIJNDAEL 33#include <openssl/aes.h> 34#endif 35 36const EVP_CIPHER *evp_aes_128_ctr(void); 37void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t); 38 39struct ssh_aes_ctr_ctx 40{ 41 AES_KEY aes_ctx; 42 u_char aes_counter[AES_BLOCK_SIZE]; 43}; 44 45/* 46 * increment counter 'ctr', 47 * the counter is of size 'len' bytes and stored in network-byte-order. 48 * (LSB at ctr[len-1], MSB at ctr[0]) 49 */ 50static void 51ssh_ctr_inc(u_char *ctr, size_t len) 52{ 53 int i; 54 55 for (i = len - 1; i >= 0; i--) 56 if (++ctr[i]) /* continue on overflow */ 57 return; 58} 59 60static int 61ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, 62 LIBCRYPTO_EVP_INL_TYPE len) 63{ 64 struct ssh_aes_ctr_ctx *c; 65 size_t n = 0; 66 u_char buf[AES_BLOCK_SIZE]; 67 68 if (len == 0) 69 return (1); 70 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) 71 return (0); 72 73 while ((len--) > 0) { 74 if (n == 0) { 75 AES_encrypt(c->aes_counter, buf, &c->aes_ctx); 76 ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); 77 } 78 *(dest++) = *(src++) ^ buf[n]; 79 n = (n + 1) % AES_BLOCK_SIZE; 80 } 81 return (1); 82} 83 84static int 85ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, 86 int enc) 87{ 88 struct ssh_aes_ctr_ctx *c; 89 90 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { 91 c = xmalloc(sizeof(*c)); 92 EVP_CIPHER_CTX_set_app_data(ctx, c); 93 } 94 if (key != NULL) 95 AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, 96 &c->aes_ctx); 97 if (iv != NULL) 98 memcpy(c->aes_counter, iv, AES_BLOCK_SIZE); 99 return (1); 100} 101 102static int 103ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) 104{ 105 struct ssh_aes_ctr_ctx *c; 106 107 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { 108 memset(c, 0, sizeof(*c)); 109 xfree(c); 110 EVP_CIPHER_CTX_set_app_data(ctx, NULL); 111 } 112 return (1); 113} 114 115void 116ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, size_t len) 117{ 118 struct ssh_aes_ctr_ctx *c; 119 120 if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) 121 fatal("ssh_aes_ctr_iv: no context"); 122 if (doset) 123 memcpy(c->aes_counter, iv, len); 124 else 125 memcpy(iv, c->aes_counter, len); 126} 127 128const EVP_CIPHER * 129evp_aes_128_ctr(void) 130{ 131 static EVP_CIPHER aes_ctr; 132 133 memset(&aes_ctr, 0, sizeof(EVP_CIPHER)); 134 aes_ctr.nid = NID_undef; 135 aes_ctr.block_size = AES_BLOCK_SIZE; 136 aes_ctr.iv_len = AES_BLOCK_SIZE; 137 aes_ctr.key_len = 16; 138 aes_ctr.init = ssh_aes_ctr_init; 139 aes_ctr.cleanup = ssh_aes_ctr_cleanup; 140 aes_ctr.do_cipher = ssh_aes_ctr; 141#ifndef SSH_OLD_EVP 142 aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | 143 EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; 144#endif 145 return (&aes_ctr); 146} 147