xref: /onnv-gate/usr/src/cmd/ssh/libssh/common/cipher-ctr.c (revision 7574:e19e13b485fa)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software for any
50Sstevel@tonic-gate  * purpose with or without fee is hereby granted, provided that the above
60Sstevel@tonic-gate  * copyright notice and this permission notice appear in all copies.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
90Sstevel@tonic-gate  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
100Sstevel@tonic-gate  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
110Sstevel@tonic-gate  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
120Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
130Sstevel@tonic-gate  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
140Sstevel@tonic-gate  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
150Sstevel@tonic-gate  */
160Sstevel@tonic-gate /*
17*7574SJan.Pechanec@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
180Sstevel@tonic-gate  * Use is subject to license terms.
190Sstevel@tonic-gate  */
20*7574SJan.Pechanec@Sun.COM 
210Sstevel@tonic-gate #include "includes.h"
220Sstevel@tonic-gate RCSID("$OpenBSD: cipher-ctr.c,v 1.4 2004/02/06 23:41:13 dtucker Exp $");
230Sstevel@tonic-gate 
240Sstevel@tonic-gate #include <openssl/evp.h>
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include "log.h"
270Sstevel@tonic-gate #include "xmalloc.h"
280Sstevel@tonic-gate #include <openssl/aes.h>
290Sstevel@tonic-gate 
300Sstevel@tonic-gate const EVP_CIPHER *evp_aes_128_ctr(void);
310Sstevel@tonic-gate void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
320Sstevel@tonic-gate 
330Sstevel@tonic-gate struct ssh_aes_ctr_ctx
340Sstevel@tonic-gate {
350Sstevel@tonic-gate 	AES_KEY		aes_ctx;
360Sstevel@tonic-gate 	u_char		aes_counter[AES_BLOCK_SIZE];
370Sstevel@tonic-gate };
380Sstevel@tonic-gate 
390Sstevel@tonic-gate /*
400Sstevel@tonic-gate  * increment counter 'ctr',
410Sstevel@tonic-gate  * the counter is of size 'len' bytes and stored in network-byte-order.
420Sstevel@tonic-gate  * (LSB at ctr[len-1], MSB at ctr[0])
430Sstevel@tonic-gate  */
440Sstevel@tonic-gate static void
ssh_ctr_inc(u_char * ctr,u_int len)450Sstevel@tonic-gate ssh_ctr_inc(u_char *ctr, u_int len)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate 	int i;
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	for (i = len - 1; i >= 0; i--)
500Sstevel@tonic-gate 		if (++ctr[i])	/* continue on overflow */
510Sstevel@tonic-gate 			return;
520Sstevel@tonic-gate }
530Sstevel@tonic-gate 
540Sstevel@tonic-gate static int
ssh_aes_ctr(EVP_CIPHER_CTX * ctx,u_char * dest,const u_char * src,u_int len)550Sstevel@tonic-gate ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
560Sstevel@tonic-gate     u_int len)
570Sstevel@tonic-gate {
580Sstevel@tonic-gate 	struct ssh_aes_ctr_ctx *c;
590Sstevel@tonic-gate 	u_int n = 0;
600Sstevel@tonic-gate 	u_char buf[AES_BLOCK_SIZE];
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	if (len == 0)
630Sstevel@tonic-gate 		return (1);
640Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
650Sstevel@tonic-gate 		return (0);
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 	while ((len--) > 0) {
680Sstevel@tonic-gate 		if (n == 0) {
690Sstevel@tonic-gate 			AES_encrypt(c->aes_counter, buf, &c->aes_ctx);
700Sstevel@tonic-gate 			ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
710Sstevel@tonic-gate 		}
720Sstevel@tonic-gate 		*(dest++) = *(src++) ^ buf[n];
730Sstevel@tonic-gate 		n = (n + 1) % AES_BLOCK_SIZE;
740Sstevel@tonic-gate 	}
750Sstevel@tonic-gate 	return (1);
760Sstevel@tonic-gate }
770Sstevel@tonic-gate 
780Sstevel@tonic-gate static int
ssh_aes_ctr_init(EVP_CIPHER_CTX * ctx,const u_char * key,const u_char * iv,int enc)790Sstevel@tonic-gate ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
800Sstevel@tonic-gate     int enc)
810Sstevel@tonic-gate {
820Sstevel@tonic-gate 	struct ssh_aes_ctr_ctx *c;
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
850Sstevel@tonic-gate 		c = xmalloc(sizeof(*c));
860Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, c);
870Sstevel@tonic-gate 	}
880Sstevel@tonic-gate 	if (key != NULL)
890Sstevel@tonic-gate 		AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
900Sstevel@tonic-gate 		     &c->aes_ctx);
910Sstevel@tonic-gate 	if (iv != NULL)
920Sstevel@tonic-gate 		memcpy(c->aes_counter, iv, AES_BLOCK_SIZE);
930Sstevel@tonic-gate 	return (1);
940Sstevel@tonic-gate }
950Sstevel@tonic-gate 
960Sstevel@tonic-gate static int
ssh_aes_ctr_cleanup(EVP_CIPHER_CTX * ctx)970Sstevel@tonic-gate ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
980Sstevel@tonic-gate {
990Sstevel@tonic-gate 	struct ssh_aes_ctr_ctx *c;
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
1020Sstevel@tonic-gate 		memset(c, 0, sizeof(*c));
1030Sstevel@tonic-gate 		xfree(c);
1040Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
1050Sstevel@tonic-gate 	}
1060Sstevel@tonic-gate 	return (1);
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate void
ssh_aes_ctr_iv(EVP_CIPHER_CTX * evp,int doset,u_char * iv,u_int len)1100Sstevel@tonic-gate ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
1110Sstevel@tonic-gate {
1120Sstevel@tonic-gate 	struct ssh_aes_ctr_ctx *c;
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
1150Sstevel@tonic-gate 		fatal("ssh_aes_ctr_iv: no context");
1160Sstevel@tonic-gate 	if (doset)
1170Sstevel@tonic-gate 		memcpy(c->aes_counter, iv, len);
1180Sstevel@tonic-gate 	else
1190Sstevel@tonic-gate 		memcpy(iv, c->aes_counter, len);
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate 
122*7574SJan.Pechanec@Sun.COM /*
123*7574SJan.Pechanec@Sun.COM  * Function fills an EVP_CIPHER structure for AES CTR functions based on the NID
124*7574SJan.Pechanec@Sun.COM  * and the key length.
125*7574SJan.Pechanec@Sun.COM  */
126*7574SJan.Pechanec@Sun.COM static const EVP_CIPHER *
evp_aes_ctr(const char * nid,int key_len,EVP_CIPHER * aes_ctr)127*7574SJan.Pechanec@Sun.COM evp_aes_ctr(const char *nid, int key_len, EVP_CIPHER *aes_ctr)
128*7574SJan.Pechanec@Sun.COM {
129*7574SJan.Pechanec@Sun.COM 	memset(aes_ctr, 0, sizeof(EVP_CIPHER));
130*7574SJan.Pechanec@Sun.COM 	/*
131*7574SJan.Pechanec@Sun.COM 	 * If the PKCS#11 engine is used the AES CTR NIDs were dynamically
132*7574SJan.Pechanec@Sun.COM 	 * created during the engine initialization. If the engine is not used
133*7574SJan.Pechanec@Sun.COM 	 * we work with NID_undef's which is OK since in that case OpenSSL
134*7574SJan.Pechanec@Sun.COM 	 * doesn't use NIDs at all.
135*7574SJan.Pechanec@Sun.COM 	 */
136*7574SJan.Pechanec@Sun.COM 	if ((aes_ctr->nid = OBJ_ln2nid(nid)) != NID_undef)
137*7574SJan.Pechanec@Sun.COM 		debug3("%s NID found", nid);
138*7574SJan.Pechanec@Sun.COM 
139*7574SJan.Pechanec@Sun.COM 	aes_ctr->block_size = AES_BLOCK_SIZE;
140*7574SJan.Pechanec@Sun.COM 	aes_ctr->iv_len = AES_BLOCK_SIZE;
141*7574SJan.Pechanec@Sun.COM 	aes_ctr->key_len = key_len;
142*7574SJan.Pechanec@Sun.COM 	aes_ctr->init = ssh_aes_ctr_init;
143*7574SJan.Pechanec@Sun.COM 	aes_ctr->cleanup = ssh_aes_ctr_cleanup;
144*7574SJan.Pechanec@Sun.COM 	aes_ctr->do_cipher = ssh_aes_ctr;
145*7574SJan.Pechanec@Sun.COM 	aes_ctr->flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
146*7574SJan.Pechanec@Sun.COM 	    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
147*7574SJan.Pechanec@Sun.COM 	return (aes_ctr);
148*7574SJan.Pechanec@Sun.COM }
149*7574SJan.Pechanec@Sun.COM 
1500Sstevel@tonic-gate const EVP_CIPHER *
evp_aes_128_ctr(void)1510Sstevel@tonic-gate evp_aes_128_ctr(void)
1520Sstevel@tonic-gate {
1530Sstevel@tonic-gate 	static EVP_CIPHER aes_ctr;
1540Sstevel@tonic-gate 
155*7574SJan.Pechanec@Sun.COM 	return (evp_aes_ctr("aes-128-ctr", 16, &aes_ctr));
1560Sstevel@tonic-gate }
157*7574SJan.Pechanec@Sun.COM 
158*7574SJan.Pechanec@Sun.COM const EVP_CIPHER *
evp_aes_192_ctr(void)159*7574SJan.Pechanec@Sun.COM evp_aes_192_ctr(void)
160*7574SJan.Pechanec@Sun.COM {
161*7574SJan.Pechanec@Sun.COM 	static EVP_CIPHER aes_ctr;
162*7574SJan.Pechanec@Sun.COM 
163*7574SJan.Pechanec@Sun.COM 	return (evp_aes_ctr("aes-192-ctr", 24, &aes_ctr));
164*7574SJan.Pechanec@Sun.COM }
165*7574SJan.Pechanec@Sun.COM 
166*7574SJan.Pechanec@Sun.COM const EVP_CIPHER *
evp_aes_256_ctr(void)167*7574SJan.Pechanec@Sun.COM evp_aes_256_ctr(void)
168*7574SJan.Pechanec@Sun.COM {
169*7574SJan.Pechanec@Sun.COM 	static EVP_CIPHER aes_ctr;
170*7574SJan.Pechanec@Sun.COM 
171*7574SJan.Pechanec@Sun.COM 	return (evp_aes_ctr("aes-256-ctr", 32, &aes_ctr));
172*7574SJan.Pechanec@Sun.COM }
173