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