1 /* $OpenBSD: cipher-ctr.c,v 1.11 2010/10/01 23:05:32 djm Exp $ */ 2 /* 3 * Copyright (c) 2003 Markus Friedl <markus (at) 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 36 const EVP_CIPHER *evp_aes_128_ctr(void); 37 void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t); 38 39 struct 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 */ 50 static void 51 ssh_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 60 static int 61 ssh_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 84 static int 85 ssh_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 102 static int 103 ssh_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 115 void 116 ssh_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 128 const EVP_CIPHER * 129 evp_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