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