Home | History | Annotate | Line # | Download | only in dist
      1  1.10  pgoyette /*	$NetBSD: cipher-ctr-mt.c,v 1.10 2019/01/27 02:08:33 pgoyette 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.10 2019/01/27 02:08:33 pgoyette 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