char  *out, *iv;
char  *out; void  *iv;
padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,		   const unsigned char *in_arg, size_t nbytes){	struct padlock_cipher_data *cdata;	const  void *inp;	char  *out, *iv;	int    inp_misaligned, out_misaligned, realign_in_loop;	size_t chunk, allocated=0;	if (nbytes == 0)		return 1;	if (nbytes % AES_BLOCK_SIZE)		return 0; /* are we expected to do tail processing? */	/* VIA promises CPUs that won't require alignment in the future.	   For now padlock_aes_align_required is initialized to 1 and	   the condition is never met... */	if (!padlock_aes_align_required)		return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes);	inp_misaligned = (((size_t)in_arg) & 0x0F);	out_misaligned = (((size_t)out_arg) & 0x0F);	/* Note that even if output is aligned and input not,	 * I still prefer to loop instead of copy the whole	 * input and then encrypt in one stroke. This is done	 * in order to improve L1 cache utilization... */	realign_in_loop = out_misaligned|inp_misaligned;	if (!realign_in_loop)		return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes);	/* this takes one "if" out of the loops */	chunk  = nbytes;	chunk %= PADLOCK_CHUNK;	if (chunk==0) chunk = PADLOCK_CHUNK;	if (out_misaligned) {		/* optmize for small input */		allocated = (chunk<nbytes?PADLOCK_CHUNK:nbytes);		out = alloca(0x10 + allocated);		out = NEAREST_ALIGNED(out);	}	else		out = out_arg;	cdata = ALIGNED_CIPHER_DATA(ctx);	padlock_verify_context(cdata);	switch (EVP_CIPHER_CTX_mode(ctx)) {	case EVP_CIPH_ECB_MODE:		do	{			if (inp_misaligned)				inp = memcpy(out, in_arg, chunk);			else				inp = in_arg;			in_arg += chunk;			padlock_xcrypt_ecb(chunk/AES_BLOCK_SIZE, cdata, out, inp);			if (out_misaligned)				out_arg = (char *)memcpy(out_arg, out, chunk) + chunk;			else				out     = out_arg+=chunk;			nbytes -= chunk;			chunk   = PADLOCK_CHUNK;		} while (nbytes);		break;	case EVP_CIPH_CBC_MODE:		memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);		goto cbc_shortcut;		do	{			if (iv != cdata->iv)				memcpy(cdata->iv, iv, AES_BLOCK_SIZE);			chunk = PADLOCK_CHUNK;		cbc_shortcut: /* optimize for small input */			if (inp_misaligned)				inp = memcpy(out, in_arg, chunk);			else				inp = in_arg;			in_arg += chunk;			iv = padlock_xcrypt_cbc(chunk/AES_BLOCK_SIZE, cdata, out, inp);			if (out_misaligned)				out_arg = (char *)memcpy(out_arg, out, chunk) + chunk;			else				out     = out_arg+=chunk;		} while (nbytes -= chunk);		memcpy(ctx->iv, iv, AES_BLOCK_SIZE);		break;	case EVP_CIPH_CFB_MODE:		memcpy (cdata->iv, ctx->iv, AES_BLOCK_SIZE);		goto cfb_shortcut;		do	{			if (iv != cdata->iv)				memcpy(cdata->iv, iv, AES_BLOCK_SIZE);			chunk = PADLOCK_CHUNK;		cfb_shortcut: /* optimize for small input */			if (inp_misaligned)				inp = memcpy(out, in_arg, chunk);			else				inp = in_arg;			in_arg += chunk;			iv = padlock_xcrypt_cfb(chunk/AES_BLOCK_SIZE, cdata, out, inp);			if (out_misaligned)				out_arg = (char *)memcpy(out_arg, out, chunk) + chunk;			else				out     = out_arg+=chunk;		} while (nbytes -= chunk);		memcpy(ctx->iv, iv, AES_BLOCK_SIZE);		break;	case EVP_CIPH_OFB_MODE:		memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);		do	{			if (inp_misaligned)				inp = memcpy(out, in_arg, chunk);			else				inp = in_arg;			in_arg += chunk;			padlock_xcrypt_ofb(chunk/AES_BLOCK_SIZE, cdata, out, inp);			if (out_misaligned)				out_arg = (char *)memcpy(out_arg, out, chunk) + chunk;			else				out     = out_arg+=chunk;			nbytes -= chunk;			chunk   = PADLOCK_CHUNK;		} while (nbytes);		memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);		break;	default:		return 0;	}	/* Clean the realign buffer if it was used */	if (out_misaligned) {		volatile unsigned long *p=(void *)out;		size_t   n = allocated/sizeof(*p);		while (n--) *p++=0;	}	memset(cdata->iv, 0, AES_BLOCK_SIZE);	return 1;}