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 #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