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 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 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 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 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 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 * 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 * 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 * 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 * 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