17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any
57c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above
67c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
97c478bd9Sstevel@tonic-gate * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
107c478bd9Sstevel@tonic-gate * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
117c478bd9Sstevel@tonic-gate * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
127c478bd9Sstevel@tonic-gate * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
137c478bd9Sstevel@tonic-gate * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
147c478bd9Sstevel@tonic-gate * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
157c478bd9Sstevel@tonic-gate */
167c478bd9Sstevel@tonic-gate /*
17*cd7d5fafSJan Pechanec * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
187c478bd9Sstevel@tonic-gate * Use is subject to license terms.
197c478bd9Sstevel@tonic-gate */
20*cd7d5fafSJan Pechanec
217c478bd9Sstevel@tonic-gate #include "includes.h"
227c478bd9Sstevel@tonic-gate RCSID("$OpenBSD: cipher-ctr.c,v 1.4 2004/02/06 23:41:13 dtucker Exp $");
237c478bd9Sstevel@tonic-gate
247c478bd9Sstevel@tonic-gate #include <openssl/evp.h>
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include "log.h"
277c478bd9Sstevel@tonic-gate #include "xmalloc.h"
287c478bd9Sstevel@tonic-gate #include <openssl/aes.h>
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate const EVP_CIPHER *evp_aes_128_ctr(void);
317c478bd9Sstevel@tonic-gate void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate struct ssh_aes_ctr_ctx
347c478bd9Sstevel@tonic-gate {
357c478bd9Sstevel@tonic-gate AES_KEY aes_ctx;
367c478bd9Sstevel@tonic-gate u_char aes_counter[AES_BLOCK_SIZE];
377c478bd9Sstevel@tonic-gate };
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate * increment counter 'ctr',
417c478bd9Sstevel@tonic-gate * the counter is of size 'len' bytes and stored in network-byte-order.
427c478bd9Sstevel@tonic-gate * (LSB at ctr[len-1], MSB at ctr[0])
437c478bd9Sstevel@tonic-gate */
447c478bd9Sstevel@tonic-gate static void
ssh_ctr_inc(u_char * ctr,u_int len)457c478bd9Sstevel@tonic-gate ssh_ctr_inc(u_char *ctr, u_int len)
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate int i;
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate for (i = len - 1; i >= 0; i--)
507c478bd9Sstevel@tonic-gate if (++ctr[i]) /* continue on overflow */
517c478bd9Sstevel@tonic-gate return;
527c478bd9Sstevel@tonic-gate }
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate static int
ssh_aes_ctr(EVP_CIPHER_CTX * ctx,u_char * dest,const u_char * src,u_int len)557c478bd9Sstevel@tonic-gate ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
567c478bd9Sstevel@tonic-gate u_int len)
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate struct ssh_aes_ctr_ctx *c;
597c478bd9Sstevel@tonic-gate u_int n = 0;
607c478bd9Sstevel@tonic-gate u_char buf[AES_BLOCK_SIZE];
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate if (len == 0)
637c478bd9Sstevel@tonic-gate return (1);
647c478bd9Sstevel@tonic-gate if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
657c478bd9Sstevel@tonic-gate return (0);
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate while ((len--) > 0) {
687c478bd9Sstevel@tonic-gate if (n == 0) {
697c478bd9Sstevel@tonic-gate AES_encrypt(c->aes_counter, buf, &c->aes_ctx);
707c478bd9Sstevel@tonic-gate ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate *(dest++) = *(src++) ^ buf[n];
737c478bd9Sstevel@tonic-gate n = (n + 1) % AES_BLOCK_SIZE;
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate return (1);
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate static int
ssh_aes_ctr_init(EVP_CIPHER_CTX * ctx,const u_char * key,const u_char * iv,int enc)797c478bd9Sstevel@tonic-gate ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
807c478bd9Sstevel@tonic-gate int enc)
817c478bd9Sstevel@tonic-gate {
827c478bd9Sstevel@tonic-gate struct ssh_aes_ctr_ctx *c;
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
857c478bd9Sstevel@tonic-gate c = xmalloc(sizeof(*c));
867c478bd9Sstevel@tonic-gate EVP_CIPHER_CTX_set_app_data(ctx, c);
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate if (key != NULL)
897c478bd9Sstevel@tonic-gate AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
907c478bd9Sstevel@tonic-gate &c->aes_ctx);
917c478bd9Sstevel@tonic-gate if (iv != NULL)
927c478bd9Sstevel@tonic-gate memcpy(c->aes_counter, iv, AES_BLOCK_SIZE);
937c478bd9Sstevel@tonic-gate return (1);
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate static int
ssh_aes_ctr_cleanup(EVP_CIPHER_CTX * ctx)977c478bd9Sstevel@tonic-gate ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
987c478bd9Sstevel@tonic-gate {
997c478bd9Sstevel@tonic-gate struct ssh_aes_ctr_ctx *c;
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
1027c478bd9Sstevel@tonic-gate memset(c, 0, sizeof(*c));
1037c478bd9Sstevel@tonic-gate xfree(c);
1047c478bd9Sstevel@tonic-gate EVP_CIPHER_CTX_set_app_data(ctx, NULL);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate return (1);
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate void
ssh_aes_ctr_iv(EVP_CIPHER_CTX * evp,int doset,u_char * iv,u_int len)1107c478bd9Sstevel@tonic-gate ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate struct ssh_aes_ctr_ctx *c;
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
1157c478bd9Sstevel@tonic-gate fatal("ssh_aes_ctr_iv: no context");
1167c478bd9Sstevel@tonic-gate if (doset)
1177c478bd9Sstevel@tonic-gate memcpy(c->aes_counter, iv, len);
1187c478bd9Sstevel@tonic-gate else
1197c478bd9Sstevel@tonic-gate memcpy(iv, c->aes_counter, len);
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate
122*cd7d5fafSJan Pechanec /*
123*cd7d5fafSJan Pechanec * Function fills an EVP_CIPHER structure for AES CTR functions based on the NID
124*cd7d5fafSJan Pechanec * and the key length.
125*cd7d5fafSJan Pechanec */
126*cd7d5fafSJan Pechanec static const EVP_CIPHER *
evp_aes_ctr(const char * nid,int key_len,EVP_CIPHER * aes_ctr)127*cd7d5fafSJan Pechanec evp_aes_ctr(const char *nid, int key_len, EVP_CIPHER *aes_ctr)
128*cd7d5fafSJan Pechanec {
129*cd7d5fafSJan Pechanec memset(aes_ctr, 0, sizeof(EVP_CIPHER));
130*cd7d5fafSJan Pechanec /*
131*cd7d5fafSJan Pechanec * If the PKCS#11 engine is used the AES CTR NIDs were dynamically
132*cd7d5fafSJan Pechanec * created during the engine initialization. If the engine is not used
133*cd7d5fafSJan Pechanec * we work with NID_undef's which is OK since in that case OpenSSL
134*cd7d5fafSJan Pechanec * doesn't use NIDs at all.
135*cd7d5fafSJan Pechanec */
136*cd7d5fafSJan Pechanec if ((aes_ctr->nid = OBJ_ln2nid(nid)) != NID_undef)
137*cd7d5fafSJan Pechanec debug3("%s NID found", nid);
138*cd7d5fafSJan Pechanec
139*cd7d5fafSJan Pechanec aes_ctr->block_size = AES_BLOCK_SIZE;
140*cd7d5fafSJan Pechanec aes_ctr->iv_len = AES_BLOCK_SIZE;
141*cd7d5fafSJan Pechanec aes_ctr->key_len = key_len;
142*cd7d5fafSJan Pechanec aes_ctr->init = ssh_aes_ctr_init;
143*cd7d5fafSJan Pechanec aes_ctr->cleanup = ssh_aes_ctr_cleanup;
144*cd7d5fafSJan Pechanec aes_ctr->do_cipher = ssh_aes_ctr;
145*cd7d5fafSJan Pechanec aes_ctr->flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
146*cd7d5fafSJan Pechanec EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
147*cd7d5fafSJan Pechanec return (aes_ctr);
148*cd7d5fafSJan Pechanec }
149*cd7d5fafSJan Pechanec
1507c478bd9Sstevel@tonic-gate const EVP_CIPHER *
evp_aes_128_ctr(void)1517c478bd9Sstevel@tonic-gate evp_aes_128_ctr(void)
1527c478bd9Sstevel@tonic-gate {
1537c478bd9Sstevel@tonic-gate static EVP_CIPHER aes_ctr;
1547c478bd9Sstevel@tonic-gate
155*cd7d5fafSJan Pechanec return (evp_aes_ctr("aes-128-ctr", 16, &aes_ctr));
156*cd7d5fafSJan Pechanec }
157*cd7d5fafSJan Pechanec
158*cd7d5fafSJan Pechanec const EVP_CIPHER *
evp_aes_192_ctr(void)159*cd7d5fafSJan Pechanec evp_aes_192_ctr(void)
160*cd7d5fafSJan Pechanec {
161*cd7d5fafSJan Pechanec static EVP_CIPHER aes_ctr;
162*cd7d5fafSJan Pechanec
163*cd7d5fafSJan Pechanec return (evp_aes_ctr("aes-192-ctr", 24, &aes_ctr));
164*cd7d5fafSJan Pechanec }
165*cd7d5fafSJan Pechanec
166*cd7d5fafSJan Pechanec const EVP_CIPHER *
evp_aes_256_ctr(void)167*cd7d5fafSJan Pechanec evp_aes_256_ctr(void)
168*cd7d5fafSJan Pechanec {
169*cd7d5fafSJan Pechanec static EVP_CIPHER aes_ctr;
170*cd7d5fafSJan Pechanec
171*cd7d5fafSJan Pechanec return (evp_aes_ctr("aes-256-ctr", 32, &aes_ctr));
1727c478bd9Sstevel@tonic-gate }
173