1221420Sdes/* $OpenBSD: cipher-ctr.c,v 1.11 2010/10/01 23:05:32 djm Exp $ */
2124208Sdes/*
3124208Sdes * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
4124208Sdes *
5124208Sdes * Permission to use, copy, modify, and distribute this software for any
6124208Sdes * purpose with or without fee is hereby granted, provided that the above
7124208Sdes * copyright notice and this permission notice appear in all copies.
8124208Sdes *
9124208Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10124208Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11124208Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12124208Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13124208Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14124208Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15124208Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16124208Sdes */
17124208Sdes#include "includes.h"
18124208Sdes
19295367Sdes#if defined(WITH_OPENSSL) && !defined(OPENSSL_HAVE_EVPCTR)
20162852Sdes#include <sys/types.h>
21162852Sdes
22162852Sdes#include <stdarg.h>
23162852Sdes#include <string.h>
24162852Sdes
25124208Sdes#include <openssl/evp.h>
26124208Sdes
27162852Sdes#include "xmalloc.h"
28124208Sdes#include "log.h"
29124208Sdes
30157016Sdes/* compatibility with old or broken OpenSSL versions */
31157016Sdes#include "openbsd-compat/openssl-compat.h"
32124208Sdes
33181111Sdes#ifndef USE_BUILTIN_RIJNDAEL
34124208Sdes#include <openssl/aes.h>
35124208Sdes#endif
36124208Sdes
37124208Sdesstruct ssh_aes_ctr_ctx
38124208Sdes{
39124208Sdes	AES_KEY		aes_ctx;
40124208Sdes	u_char		aes_counter[AES_BLOCK_SIZE];
41124208Sdes};
42124208Sdes
43124208Sdes/*
44124208Sdes * increment counter 'ctr',
45124208Sdes * the counter is of size 'len' bytes and stored in network-byte-order.
46124208Sdes * (LSB at ctr[len-1], MSB at ctr[0])
47124208Sdes */
48124208Sdesstatic void
49221420Sdesssh_ctr_inc(u_char *ctr, size_t len)
50124208Sdes{
51124208Sdes	int i;
52124208Sdes
53124208Sdes	for (i = len - 1; i >= 0; i--)
54124208Sdes		if (++ctr[i])	/* continue on overflow */
55124208Sdes			return;
56124208Sdes}
57124208Sdes
58124208Sdesstatic int
59124208Sdesssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
60221420Sdes    LIBCRYPTO_EVP_INL_TYPE len)
61124208Sdes{
62124208Sdes	struct ssh_aes_ctr_ctx *c;
63221420Sdes	size_t n = 0;
64124208Sdes	u_char buf[AES_BLOCK_SIZE];
65124208Sdes
66124208Sdes	if (len == 0)
67124208Sdes		return (1);
68124208Sdes	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
69124208Sdes		return (0);
70124208Sdes
71124208Sdes	while ((len--) > 0) {
72124208Sdes		if (n == 0) {
73124208Sdes			AES_encrypt(c->aes_counter, buf, &c->aes_ctx);
74124208Sdes			ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
75124208Sdes		}
76124208Sdes		*(dest++) = *(src++) ^ buf[n];
77124208Sdes		n = (n + 1) % AES_BLOCK_SIZE;
78124208Sdes	}
79124208Sdes	return (1);
80124208Sdes}
81124208Sdes
82124208Sdesstatic int
83124208Sdesssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
84124208Sdes    int enc)
85124208Sdes{
86124208Sdes	struct ssh_aes_ctr_ctx *c;
87124208Sdes
88124208Sdes	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
89124208Sdes		c = xmalloc(sizeof(*c));
90124208Sdes		EVP_CIPHER_CTX_set_app_data(ctx, c);
91124208Sdes	}
92124208Sdes	if (key != NULL)
93126274Sdes		AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
94149749Sdes		    &c->aes_ctx);
95124208Sdes	if (iv != NULL)
96124208Sdes		memcpy(c->aes_counter, iv, AES_BLOCK_SIZE);
97124208Sdes	return (1);
98124208Sdes}
99124208Sdes
100124208Sdesstatic int
101124208Sdesssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
102124208Sdes{
103124208Sdes	struct ssh_aes_ctr_ctx *c;
104124208Sdes
105124208Sdes	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
106124208Sdes		memset(c, 0, sizeof(*c));
107255767Sdes		free(c);
108124208Sdes		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
109124208Sdes	}
110124208Sdes	return (1);
111124208Sdes}
112124208Sdes
113124208Sdesvoid
114221420Sdesssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, size_t len)
115124208Sdes{
116124208Sdes	struct ssh_aes_ctr_ctx *c;
117124208Sdes
118124208Sdes	if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
119124208Sdes		fatal("ssh_aes_ctr_iv: no context");
120124208Sdes	if (doset)
121124208Sdes		memcpy(c->aes_counter, iv, len);
122124208Sdes	else
123124208Sdes		memcpy(iv, c->aes_counter, len);
124124208Sdes}
125124208Sdes
126124208Sdesconst EVP_CIPHER *
127124208Sdesevp_aes_128_ctr(void)
128124208Sdes{
129124208Sdes	static EVP_CIPHER aes_ctr;
130124208Sdes
131124208Sdes	memset(&aes_ctr, 0, sizeof(EVP_CIPHER));
132124208Sdes	aes_ctr.nid = NID_undef;
133124208Sdes	aes_ctr.block_size = AES_BLOCK_SIZE;
134124208Sdes	aes_ctr.iv_len = AES_BLOCK_SIZE;
135124208Sdes	aes_ctr.key_len = 16;
136124208Sdes	aes_ctr.init = ssh_aes_ctr_init;
137124208Sdes	aes_ctr.cleanup = ssh_aes_ctr_cleanup;
138124208Sdes	aes_ctr.do_cipher = ssh_aes_ctr;
139124208Sdes#ifndef SSH_OLD_EVP
140124208Sdes	aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
141124208Sdes	    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
142124208Sdes#endif
143124208Sdes	return (&aes_ctr);
144124208Sdes}
145248619Sdes
146295367Sdes#endif /* defined(WITH_OPENSSL) && !defined(OPENSSL_HAVE_EVPCTR) */
147