Home | History | Annotate | Download | only in openssh
      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 #if defined(WITH_OPENSSL) && !defined(OPENSSL_HAVE_EVPCTR)
     20 #include <sys/types.h>
     21 
     22 #include <stdarg.h>
     23 #include <string.h>
     24 
     25 #include <openssl/evp.h>
     26 
     27 #include "xmalloc.h"
     28 #include "log.h"
     29 
     30 /* compatibility with old or broken OpenSSL versions */
     31 #include "openbsd-compat/openssl-compat.h"
     32 
     33 #ifndef USE_BUILTIN_RIJNDAEL
     34 #include <openssl/aes.h>
     35 #endif
     36 
     37 struct ssh_aes_ctr_ctx
     38 {
     39 	AES_KEY		aes_ctx;
     40 	u_char		aes_counter[AES_BLOCK_SIZE];
     41 };
     42 
     43 /*
     44  * increment counter 'ctr',
     45  * the counter is of size 'len' bytes and stored in network-byte-order.
     46  * (LSB at ctr[len-1], MSB at ctr[0])
     47  */
     48 static void
     49 ssh_ctr_inc(u_char *ctr, size_t len)
     50 {
     51 	int i;
     52 
     53 	for (i = len - 1; i >= 0; i--)
     54 		if (++ctr[i])	/* continue on overflow */
     55 			return;
     56 }
     57 
     58 static int
     59 ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
     60     LIBCRYPTO_EVP_INL_TYPE len)
     61 {
     62 	struct ssh_aes_ctr_ctx *c;
     63 	size_t n = 0;
     64 	u_char buf[AES_BLOCK_SIZE];
     65 
     66 	if (len == 0)
     67 		return (1);
     68 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
     69 		return (0);
     70 
     71 	while ((len--) > 0) {
     72 		if (n == 0) {
     73 			AES_encrypt(c->aes_counter, buf, &c->aes_ctx);
     74 			ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
     75 		}
     76 		*(dest++) = *(src++) ^ buf[n];
     77 		n = (n + 1) % AES_BLOCK_SIZE;
     78 	}
     79 	return (1);
     80 }
     81 
     82 static int
     83 ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
     84     int enc)
     85 {
     86 	struct ssh_aes_ctr_ctx *c;
     87 
     88 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
     89 		c = xmalloc(sizeof(*c));
     90 		EVP_CIPHER_CTX_set_app_data(ctx, c);
     91 	}
     92 	if (key != NULL)
     93 		AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
     94 		    &c->aes_ctx);
     95 	if (iv != NULL)
     96 		memcpy(c->aes_counter, iv, AES_BLOCK_SIZE);
     97 	return (1);
     98 }
     99 
    100 static int
    101 ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
    102 {
    103 	struct ssh_aes_ctr_ctx *c;
    104 
    105 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
    106 		memset(c, 0, sizeof(*c));
    107 		free(c);
    108 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
    109 	}
    110 	return (1);
    111 }
    112 
    113 void
    114 ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, size_t len)
    115 {
    116 	struct ssh_aes_ctr_ctx *c;
    117 
    118 	if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
    119 		fatal("ssh_aes_ctr_iv: no context");
    120 	if (doset)
    121 		memcpy(c->aes_counter, iv, len);
    122 	else
    123 		memcpy(iv, c->aes_counter, len);
    124 }
    125 
    126 const EVP_CIPHER *
    127 evp_aes_128_ctr(void)
    128 {
    129 	static EVP_CIPHER aes_ctr;
    130 
    131 	memset(&aes_ctr, 0, sizeof(EVP_CIPHER));
    132 	aes_ctr.nid = NID_undef;
    133 	aes_ctr.block_size = AES_BLOCK_SIZE;
    134 	aes_ctr.iv_len = AES_BLOCK_SIZE;
    135 	aes_ctr.key_len = 16;
    136 	aes_ctr.init = ssh_aes_ctr_init;
    137 	aes_ctr.cleanup = ssh_aes_ctr_cleanup;
    138 	aes_ctr.do_cipher = ssh_aes_ctr;
    139 #ifndef SSH_OLD_EVP
    140 	aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
    141 	    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
    142 #endif
    143 	return (&aes_ctr);
    144 }
    145 
    146 #endif /* defined(WITH_OPENSSL) && !defined(OPENSSL_HAVE_EVPCTR) */
    147