Home | History | Annotate | Line # | Download | only in dist
cipher-ctr-mt.c revision 1.9
      1  1.4  christos /*	$NetBSD: cipher-ctr-mt.c,v 1.9 2018/04/06 18:59:00 christos Exp $	*/
      2  1.1  christos /*
      3  1.1  christos  * OpenSSH Multi-threaded AES-CTR Cipher
      4  1.1  christos  *
      5  1.1  christos  * Author: Benjamin Bennett <ben (at) psc.edu>
      6  1.1  christos  * Copyright (c) 2008 Pittsburgh Supercomputing Center. All rights reserved.
      7  1.1  christos  *
      8  1.1  christos  * Based on original OpenSSH AES-CTR cipher. Small portions remain unchanged,
      9  1.1  christos  * Copyright (c) 2003 Markus Friedl <markus (at) openbsd.org>
     10  1.1  christos  *
     11  1.1  christos  * Permission to use, copy, modify, and distribute this software for any
     12  1.1  christos  * purpose with or without fee is hereby granted, provided that the above
     13  1.1  christos  * copyright notice and this permission notice appear in all copies.
     14  1.1  christos  *
     15  1.1  christos  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     16  1.1  christos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     17  1.1  christos  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     18  1.1  christos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19  1.1  christos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     20  1.1  christos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     21  1.1  christos  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22  1.1  christos  */
     23  1.1  christos #include "includes.h"
     24  1.9  christos __RCSID("$NetBSD: cipher-ctr-mt.c,v 1.9 2018/04/06 18:59:00 christos Exp $");
     25  1.1  christos 
     26  1.1  christos #include <sys/types.h>
     27  1.1  christos 
     28  1.1  christos #include <stdarg.h>
     29  1.1  christos #include <string.h>
     30  1.1  christos 
     31  1.1  christos #include <openssl/evp.h>
     32  1.1  christos 
     33  1.1  christos #include "xmalloc.h"
     34  1.1  christos #include "log.h"
     35  1.1  christos 
     36  1.1  christos #ifndef USE_BUILTIN_RIJNDAEL
     37  1.1  christos #include <openssl/aes.h>
     38  1.1  christos #endif
     39  1.1  christos 
     40  1.1  christos #include <pthread.h>
     41  1.1  christos 
     42  1.1  christos /*-------------------- TUNABLES --------------------*/
     43  1.1  christos /* Number of pregen threads to use */
     44  1.1  christos #define CIPHER_THREADS	2
     45  1.1  christos 
     46  1.1  christos /* Number of keystream queues */
     47  1.1  christos #define NUMKQ		(CIPHER_THREADS + 2)
     48  1.1  christos 
     49  1.1  christos /* Length of a keystream queue */
     50  1.1  christos #define KQLEN		4096
     51  1.1  christos 
     52  1.1  christos /* Processor cacheline length */
     53  1.1  christos #define CACHELINE_LEN	64
     54  1.1  christos 
     55  1.1  christos /* Collect thread stats and print at cancellation when in debug mode */
     56  1.1  christos /* #define CIPHER_THREAD_STATS */
     57  1.1  christos 
     58  1.1  christos /* Use single-byte XOR instead of 8-byte XOR */
     59  1.1  christos /* #define CIPHER_BYTE_XOR */
     60  1.1  christos /*-------------------- END TUNABLES --------------------*/
     61  1.1  christos 
     62  1.1  christos #ifdef AES_CTR_MT
     63  1.1  christos 
     64  1.1  christos 
     65  1.1  christos const EVP_CIPHER *evp_aes_ctr_mt(void);
     66  1.1  christos 
     67  1.1  christos #ifdef CIPHER_THREAD_STATS
     68  1.1  christos /*
     69  1.1  christos  * Struct to collect thread stats
     70  1.1  christos  */
     71  1.1  christos struct thread_stats {
     72  1.1  christos 	u_int	fills;
     73  1.1  christos 	u_int	skips;
     74  1.1  christos 	u_int	waits;
     75  1.1  christos 	u_int	drains;
     76  1.1  christos };
     77  1.1  christos 
     78  1.1  christos /*
     79  1.1  christos  * Debug print the thread stats
     80  1.1  christos  * Use with pthread_cleanup_push for displaying at thread cancellation
     81  1.1  christos  */
     82  1.1  christos static void
     83  1.1  christos thread_loop_stats(void *x)
     84  1.1  christos {
     85  1.1  christos 	struct thread_stats *s = x;
     86  1.1  christos 
     87  1.1  christos 	debug("tid %lu - %u fills, %u skips, %u waits", pthread_self(),
     88  1.1  christos 			s->fills, s->skips, s->waits);
     89  1.1  christos }
     90  1.1  christos 
     91  1.2      adam  #define STATS_STRUCT(s)	struct thread_stats s
     92  1.2      adam  #define STATS_INIT(s)		{ memset(&s, 0, sizeof(s)); }
     93  1.2      adam  #define STATS_FILL(s)		{ s.fills++; }
     94  1.2      adam  #define STATS_SKIP(s)		{ s.skips++; }
     95  1.2      adam  #define STATS_WAIT(s)		{ s.waits++; }
     96  1.2      adam  #define STATS_DRAIN(s)		{ s.drains++; }
     97  1.1  christos #else
     98  1.1  christos  #define STATS_STRUCT(s)
     99  1.1  christos  #define STATS_INIT(s)
    100  1.1  christos  #define STATS_FILL(s)
    101  1.1  christos  #define STATS_SKIP(s)
    102  1.1  christos  #define STATS_WAIT(s)
    103  1.1  christos  #define STATS_DRAIN(s)
    104  1.1  christos #endif
    105  1.1  christos 
    106  1.1  christos /* Keystream Queue state */
    107  1.1  christos enum {
    108  1.1  christos 	KQINIT,
    109  1.1  christos 	KQEMPTY,
    110  1.1  christos 	KQFILLING,
    111  1.1  christos 	KQFULL,
    112  1.1  christos 	KQDRAINING
    113  1.1  christos };
    114  1.1  christos 
    115  1.1  christos /* Keystream Queue struct */
    116  1.1  christos struct kq {
    117  1.1  christos 	u_char		keys[KQLEN][AES_BLOCK_SIZE];
    118  1.1  christos 	u_char		ctr[AES_BLOCK_SIZE];
    119  1.1  christos 	u_char		pad0[CACHELINE_LEN];
    120  1.1  christos 	volatile int	qstate;
    121  1.1  christos 	pthread_mutex_t	lock;
    122  1.1  christos 	pthread_cond_t	cond;
    123  1.1  christos 	u_char		pad1[CACHELINE_LEN];
    124  1.1  christos };
    125  1.1  christos 
    126  1.1  christos /* Context struct */
    127  1.1  christos struct ssh_aes_ctr_ctx
    128  1.1  christos {
    129  1.1  christos 	struct kq	q[NUMKQ];
    130  1.1  christos 	AES_KEY		aes_ctx;
    131  1.2      adam 	STATS_STRUCT(stats);
    132  1.1  christos 	u_char		aes_counter[AES_BLOCK_SIZE];
    133  1.1  christos 	pthread_t	tid[CIPHER_THREADS];
    134  1.1  christos 	int		state;
    135  1.1  christos 	int		qidx;
    136  1.1  christos 	int		ridx;
    137  1.1  christos };
    138  1.1  christos 
    139  1.1  christos /* <friedl>
    140  1.1  christos  * increment counter 'ctr',
    141  1.1  christos  * the counter is of size 'len' bytes and stored in network-byte-order.
    142  1.1  christos  * (LSB at ctr[len-1], MSB at ctr[0])
    143  1.1  christos  */
    144  1.1  christos static void
    145  1.1  christos ssh_ctr_inc(u_char *ctr, u_int len)
    146  1.1  christos {
    147  1.1  christos 	int i;
    148  1.1  christos 
    149  1.1  christos 	for (i = len - 1; i >= 0; i--)
    150  1.1  christos 		if (++ctr[i])	/* continue on overflow */
    151  1.1  christos 			return;
    152  1.1  christos }
    153  1.1  christos 
    154  1.1  christos /*
    155  1.1  christos  * Add num to counter 'ctr'
    156  1.1  christos  */
    157  1.1  christos static void
    158  1.1  christos ssh_ctr_add(u_char *ctr, uint32_t num, u_int len)
    159  1.1  christos {
    160  1.1  christos 	int i;
    161  1.1  christos 	uint16_t n;
    162  1.1  christos 
    163  1.1  christos 	for (n = 0, i = len - 1; i >= 0 && (num || n); i--) {
    164  1.1  christos 		n = ctr[i] + (num & 0xff) + n;
    165  1.1  christos 		num >>= 8;
    166  1.1  christos 		ctr[i] = n & 0xff;
    167  1.1  christos 		n >>= 8;
    168  1.1  christos 	}
    169  1.1  christos }
    170  1.1  christos 
    171  1.1  christos /*
    172  1.1  christos  * Threads may be cancelled in a pthread_cond_wait, we must free the mutex
    173  1.1  christos  */
    174  1.1  christos static void
    175  1.1  christos thread_loop_cleanup(void *x)
    176  1.1  christos {
    177  1.1  christos 	pthread_mutex_unlock((pthread_mutex_t *)x);
    178  1.1  christos }
    179  1.1  christos 
    180  1.1  christos /*
    181  1.1  christos  * The life of a pregen thread:
    182  1.1  christos  *    Find empty keystream queues and fill them using their counter.
    183  1.1  christos  *    When done, update counter for the next fill.
    184  1.1  christos  */
    185  1.1  christos static void *
    186  1.1  christos thread_loop(void *x)
    187  1.1  christos {
    188  1.1  christos 	AES_KEY key;
    189  1.2      adam 	STATS_STRUCT(stats);
    190  1.1  christos 	struct ssh_aes_ctr_ctx *c = x;
    191  1.1  christos 	struct kq *q;
    192  1.1  christos 	int i;
    193  1.1  christos 	int qidx;
    194  1.1  christos 
    195  1.1  christos 	/* Threads stats on cancellation */
    196  1.1  christos 	STATS_INIT(stats);
    197  1.1  christos #ifdef CIPHER_THREAD_STATS
    198  1.1  christos 	pthread_cleanup_push(thread_loop_stats, &stats);
    199  1.1  christos #endif
    200  1.1  christos 
    201  1.1  christos 	/* Thread local copy of AES key */
    202  1.1  christos 	memcpy(&key, &c->aes_ctx, sizeof(key));
    203  1.1  christos 
    204  1.1  christos 	/*
    205  1.1  christos 	 * Handle the special case of startup, one thread must fill
    206  1.1  christos  	 * the first KQ then mark it as draining. Lock held throughout.
    207  1.1  christos  	 */
    208  1.1  christos 	if (pthread_equal(pthread_self(), c->tid[0])) {
    209  1.1  christos 		q = &c->q[0];
    210  1.1  christos 		pthread_mutex_lock(&q->lock);
    211  1.1  christos 		if (q->qstate == KQINIT) {
    212  1.1  christos 			for (i = 0; i < KQLEN; i++) {
    213  1.1  christos 				AES_encrypt(q->ctr, q->keys[i], &key);
    214  1.1  christos 				ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE);
    215  1.1  christos 			}
    216  1.1  christos 			ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE);
    217  1.1  christos 			q->qstate = KQDRAINING;
    218  1.1  christos 			STATS_FILL(stats);
    219  1.1  christos 			pthread_cond_broadcast(&q->cond);
    220  1.1  christos 		}
    221  1.1  christos 		pthread_mutex_unlock(&q->lock);
    222  1.1  christos 	}
    223  1.1  christos 	else
    224  1.1  christos 		STATS_SKIP(stats);
    225  1.1  christos 
    226  1.1  christos 	/*
    227  1.1  christos  	 * Normal case is to find empty queues and fill them, skipping over
    228  1.1  christos  	 * queues already filled by other threads and stopping to wait for
    229  1.1  christos  	 * a draining queue to become empty.
    230  1.1  christos  	 *
    231  1.1  christos  	 * Multiple threads may be waiting on a draining queue and awoken
    232  1.1  christos  	 * when empty.  The first thread to wake will mark it as filling,
    233  1.1  christos  	 * others will move on to fill, skip, or wait on the next queue.
    234  1.1  christos  	 */
    235  1.1  christos 	for (qidx = 1;; qidx = (qidx + 1) % NUMKQ) {
    236  1.1  christos 		/* Check if I was cancelled, also checked in cond_wait */
    237  1.1  christos 		pthread_testcancel();
    238  1.1  christos 
    239  1.1  christos 		/* Lock queue and block if its draining */
    240  1.1  christos 		q = &c->q[qidx];
    241  1.1  christos 		pthread_mutex_lock(&q->lock);
    242  1.1  christos 		pthread_cleanup_push(thread_loop_cleanup, &q->lock);
    243  1.1  christos 		while (q->qstate == KQDRAINING || q->qstate == KQINIT) {
    244  1.1  christos 			STATS_WAIT(stats);
    245  1.1  christos 			pthread_cond_wait(&q->cond, &q->lock);
    246  1.1  christos 		}
    247  1.1  christos 		pthread_cleanup_pop(0);
    248  1.1  christos 
    249  1.1  christos 		/* If filling or full, somebody else got it, skip */
    250  1.1  christos 		if (q->qstate != KQEMPTY) {
    251  1.1  christos 			pthread_mutex_unlock(&q->lock);
    252  1.1  christos 			STATS_SKIP(stats);
    253  1.1  christos 			continue;
    254  1.1  christos 		}
    255  1.1  christos 
    256  1.1  christos 		/*
    257  1.1  christos  		 * Empty, let's fill it.
    258  1.1  christos  		 * Queue lock is relinquished while we do this so others
    259  1.1  christos  		 * can see that it's being filled.
    260  1.1  christos  		 */
    261  1.1  christos 		q->qstate = KQFILLING;
    262  1.1  christos 		pthread_mutex_unlock(&q->lock);
    263  1.1  christos 		for (i = 0; i < KQLEN; i++) {
    264  1.1  christos 			AES_encrypt(q->ctr, q->keys[i], &key);
    265  1.1  christos 			ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE);
    266  1.1  christos 		}
    267  1.1  christos 
    268  1.1  christos 		/* Re-lock, mark full and signal consumer */
    269  1.1  christos 		pthread_mutex_lock(&q->lock);
    270  1.1  christos 		ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE);
    271  1.1  christos 		q->qstate = KQFULL;
    272  1.1  christos 		STATS_FILL(stats);
    273  1.1  christos 		pthread_cond_signal(&q->cond);
    274  1.1  christos 		pthread_mutex_unlock(&q->lock);
    275  1.1  christos 	}
    276  1.1  christos 
    277  1.1  christos #ifdef CIPHER_THREAD_STATS
    278  1.1  christos 	/* Stats */
    279  1.1  christos 	pthread_cleanup_pop(1);
    280  1.1  christos #endif
    281  1.1  christos 
    282  1.1  christos 	return NULL;
    283  1.1  christos }
    284  1.1  christos 
    285  1.1  christos static int
    286  1.1  christos ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
    287  1.1  christos     u_int len)
    288  1.1  christos {
    289  1.1  christos 	struct ssh_aes_ctr_ctx *c;
    290  1.1  christos 	struct kq *q, *oldq;
    291  1.1  christos 	int ridx;
    292  1.1  christos 	u_char *buf;
    293  1.1  christos 
    294  1.1  christos 	if (len == 0)
    295  1.1  christos 		return (1);
    296  1.1  christos 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
    297  1.1  christos 		return (0);
    298  1.1  christos 
    299  1.1  christos 	q = &c->q[c->qidx];
    300  1.1  christos 	ridx = c->ridx;
    301  1.1  christos 
    302  1.1  christos 	/* src already padded to block multiple */
    303  1.1  christos 	while (len > 0) {
    304  1.1  christos 		buf = q->keys[ridx];
    305  1.1  christos 
    306  1.1  christos #ifdef CIPHER_BYTE_XOR
    307  1.1  christos 		dest[0] = src[0] ^ buf[0];
    308  1.1  christos 		dest[1] = src[1] ^ buf[1];
    309  1.1  christos 		dest[2] = src[2] ^ buf[2];
    310  1.1  christos 		dest[3] = src[3] ^ buf[3];
    311  1.1  christos 		dest[4] = src[4] ^ buf[4];
    312  1.1  christos 		dest[5] = src[5] ^ buf[5];
    313  1.1  christos 		dest[6] = src[6] ^ buf[6];
    314  1.1  christos 		dest[7] = src[7] ^ buf[7];
    315  1.1  christos 		dest[8] = src[8] ^ buf[8];
    316  1.1  christos 		dest[9] = src[9] ^ buf[9];
    317  1.1  christos 		dest[10] = src[10] ^ buf[10];
    318  1.1  christos 		dest[11] = src[11] ^ buf[11];
    319  1.1  christos 		dest[12] = src[12] ^ buf[12];
    320  1.1  christos 		dest[13] = src[13] ^ buf[13];
    321  1.1  christos 		dest[14] = src[14] ^ buf[14];
    322  1.1  christos 		dest[15] = src[15] ^ buf[15];
    323  1.1  christos #else
    324  1.1  christos 		*(uint64_t *)dest = *(uint64_t *)src ^ *(uint64_t *)buf;
    325  1.1  christos 		*(uint64_t *)(dest + 8) = *(uint64_t *)(src + 8) ^
    326  1.1  christos 						*(uint64_t *)(buf + 8);
    327  1.1  christos #endif
    328  1.1  christos 
    329  1.1  christos 		dest += 16;
    330  1.1  christos 		src += 16;
    331  1.1  christos 		len -= 16;
    332  1.1  christos 		ssh_ctr_inc(ctx->iv, AES_BLOCK_SIZE);
    333  1.1  christos 
    334  1.1  christos 		/* Increment read index, switch queues on rollover */
    335  1.1  christos 		if ((ridx = (ridx + 1) % KQLEN) == 0) {
    336  1.1  christos 			oldq = q;
    337  1.1  christos 
    338  1.1  christos 			/* Mark next queue draining, may need to wait */
    339  1.1  christos 			c->qidx = (c->qidx + 1) % NUMKQ;
    340  1.1  christos 			q = &c->q[c->qidx];
    341  1.1  christos 			pthread_mutex_lock(&q->lock);
    342  1.1  christos 			while (q->qstate != KQFULL) {
    343  1.1  christos 				STATS_WAIT(c->stats);
    344  1.1  christos 				pthread_cond_wait(&q->cond, &q->lock);
    345  1.1  christos 			}
    346  1.1  christos 			q->qstate = KQDRAINING;
    347  1.1  christos 			pthread_mutex_unlock(&q->lock);
    348  1.1  christos 
    349  1.1  christos 			/* Mark consumed queue empty and signal producers */
    350  1.1  christos 			pthread_mutex_lock(&oldq->lock);
    351  1.1  christos 			oldq->qstate = KQEMPTY;
    352  1.1  christos 			STATS_DRAIN(c->stats);
    353  1.1  christos 			pthread_cond_broadcast(&oldq->cond);
    354  1.1  christos 			pthread_mutex_unlock(&oldq->lock);
    355  1.1  christos 		}
    356  1.1  christos 	}
    357  1.1  christos 	c->ridx = ridx;
    358  1.1  christos 	return (1);
    359  1.1  christos }
    360  1.1  christos 
    361  1.1  christos #define HAVE_NONE       0
    362  1.1  christos #define HAVE_KEY        1
    363  1.1  christos #define HAVE_IV         2
    364  1.1  christos static int
    365  1.1  christos ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
    366  1.1  christos     int enc)
    367  1.1  christos {
    368  1.1  christos 	struct ssh_aes_ctr_ctx *c;
    369  1.1  christos 	int i;
    370  1.1  christos 
    371  1.1  christos 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
    372  1.1  christos 		c = xmalloc(sizeof(*c));
    373  1.1  christos 
    374  1.1  christos 		c->state = HAVE_NONE;
    375  1.1  christos 		for (i = 0; i < NUMKQ; i++) {
    376  1.1  christos 			pthread_mutex_init(&c->q[i].lock, NULL);
    377  1.1  christos 			pthread_cond_init(&c->q[i].cond, NULL);
    378  1.1  christos 		}
    379  1.1  christos 
    380  1.1  christos 		STATS_INIT(c->stats);
    381  1.1  christos 
    382  1.1  christos 		EVP_CIPHER_CTX_set_app_data(ctx, c);
    383  1.1  christos 	}
    384  1.1  christos 
    385  1.1  christos 	if (c->state == (HAVE_KEY | HAVE_IV)) {
    386  1.1  christos 		/* Cancel pregen threads */
    387  1.1  christos 		for (i = 0; i < CIPHER_THREADS; i++)
    388  1.1  christos 			pthread_cancel(c->tid[i]);
    389  1.1  christos 		for (i = 0; i < CIPHER_THREADS; i++)
    390  1.1  christos 			pthread_join(c->tid[i], NULL);
    391  1.1  christos 		/* Start over getting key & iv */
    392  1.1  christos 		c->state = HAVE_NONE;
    393  1.1  christos 	}
    394  1.1  christos 
    395  1.1  christos 	if (key != NULL) {
    396  1.1  christos 		AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
    397  1.1  christos 		    &c->aes_ctx);
    398  1.1  christos 		c->state |= HAVE_KEY;
    399  1.1  christos 	}
    400  1.1  christos 
    401  1.1  christos 	if (iv != NULL) {
    402  1.1  christos 		memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
    403  1.1  christos 		c->state |= HAVE_IV;
    404  1.1  christos 	}
    405  1.1  christos 
    406  1.1  christos 	if (c->state == (HAVE_KEY | HAVE_IV)) {
    407  1.1  christos 		/* Clear queues */
    408  1.1  christos 		memcpy(c->q[0].ctr, ctx->iv, AES_BLOCK_SIZE);
    409  1.1  christos 		c->q[0].qstate = KQINIT;
    410  1.1  christos 		for (i = 1; i < NUMKQ; i++) {
    411  1.1  christos 			memcpy(c->q[i].ctr, ctx->iv, AES_BLOCK_SIZE);
    412  1.1  christos 			ssh_ctr_add(c->q[i].ctr, i * KQLEN, AES_BLOCK_SIZE);
    413  1.1  christos 			c->q[i].qstate = KQEMPTY;
    414  1.1  christos 		}
    415  1.1  christos 		c->qidx = 0;
    416  1.1  christos 		c->ridx = 0;
    417  1.1  christos 
    418  1.1  christos 		/* Start threads */
    419  1.1  christos 		for (i = 0; i < CIPHER_THREADS; i++) {
    420  1.1  christos 			pthread_create(&c->tid[i], NULL, thread_loop, c);
    421  1.1  christos 		}
    422  1.1  christos 		pthread_mutex_lock(&c->q[0].lock);
    423  1.1  christos 		while (c->q[0].qstate != KQDRAINING)
    424  1.1  christos 			pthread_cond_wait(&c->q[0].cond, &c->q[0].lock);
    425  1.1  christos 		pthread_mutex_unlock(&c->q[0].lock);
    426  1.1  christos 
    427  1.1  christos 	}
    428  1.1  christos 	return (1);
    429  1.1  christos }
    430  1.1  christos 
    431  1.1  christos static int
    432  1.1  christos ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
    433  1.1  christos {
    434  1.1  christos 	struct ssh_aes_ctr_ctx *c;
    435  1.1  christos 	int i;
    436  1.1  christos 
    437  1.1  christos 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
    438  1.1  christos #ifdef CIPHER_THREAD_STATS
    439  1.1  christos 		debug("main thread: %u drains, %u waits", c->stats.drains,
    440  1.1  christos 				c->stats.waits);
    441  1.1  christos #endif
    442  1.1  christos 		/* Cancel pregen threads */
    443  1.1  christos 		for (i = 0; i < CIPHER_THREADS; i++)
    444  1.1  christos 			pthread_cancel(c->tid[i]);
    445  1.1  christos 		for (i = 0; i < CIPHER_THREADS; i++)
    446  1.1  christos 			pthread_join(c->tid[i], NULL);
    447  1.1  christos 
    448  1.1  christos 		memset(c, 0, sizeof(*c));
    449  1.4  christos 		free(c);
    450  1.1  christos 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
    451  1.1  christos 	}
    452  1.1  christos 	return (1);
    453  1.1  christos }
    454  1.1  christos 
    455  1.1  christos /* <friedl> */
    456  1.1  christos const EVP_CIPHER *
    457  1.1  christos evp_aes_ctr_mt(void)
    458  1.1  christos {
    459  1.1  christos 	static EVP_CIPHER aes_ctr;
    460  1.1  christos 
    461  1.1  christos 	memset(&aes_ctr, 0, sizeof(EVP_CIPHER));
    462  1.1  christos 	aes_ctr.nid = NID_undef;
    463  1.1  christos 	aes_ctr.block_size = AES_BLOCK_SIZE;
    464  1.1  christos 	aes_ctr.iv_len = AES_BLOCK_SIZE;
    465  1.1  christos 	aes_ctr.key_len = 16;
    466  1.1  christos 	aes_ctr.init = ssh_aes_ctr_init;
    467  1.1  christos 	aes_ctr.cleanup = ssh_aes_ctr_cleanup;
    468  1.1  christos 	aes_ctr.do_cipher = ssh_aes_ctr;
    469  1.1  christos #ifndef SSH_OLD_EVP
    470  1.1  christos 	aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
    471  1.1  christos 	    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
    472  1.1  christos #endif
    473  1.1  christos 	return (&aes_ctr);
    474  1.1  christos }
    475  1.2      adam #endif /* AES_CTR_MT */
    476