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