Home | History | Annotate | Download | only in aes
      1 /* crypto/aes/aes_ige.c -*- mode:C; c-file-style: "eay" -*- */
      2 /* ====================================================================
      3  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  *
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in
     14  *    the documentation and/or other materials provided with the
     15  *    distribution.
     16  *
     17  * 3. All advertising materials mentioning features or use of this
     18  *    software must display the following acknowledgment:
     19  *    "This product includes software developed by the OpenSSL Project
     20  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
     21  *
     22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     23  *    endorse or promote products derived from this software without
     24  *    prior written permission. For written permission, please contact
     25  *    openssl-core (at) openssl.org.
     26  *
     27  * 5. Products derived from this software may not be called "OpenSSL"
     28  *    nor may "OpenSSL" appear in their names without prior written
     29  *    permission of the OpenSSL Project.
     30  *
     31  * 6. Redistributions of any form whatsoever must retain the following
     32  *    acknowledgment:
     33  *    "This product includes software developed by the OpenSSL Project
     34  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
     35  *
     36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     47  * OF THE POSSIBILITY OF SUCH DAMAGE.
     48  * ====================================================================
     49  *
     50  */
     51 
     52 #include "cryptlib.h"
     53 
     54 #include <openssl/aes.h>
     55 #include "aes_locl.h"
     56 
     57 #define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long))
     58 typedef struct {
     59         unsigned long data[N_WORDS];
     60 } aes_block_t;
     61 
     62 /* XXX: probably some better way to do this */
     63 #if defined(__i386__) || defined(__x86_64__)
     64 #define UNALIGNED_MEMOPS_ARE_FAST 1
     65 #else
     66 #define UNALIGNED_MEMOPS_ARE_FAST 0
     67 #endif
     68 
     69 #if UNALIGNED_MEMOPS_ARE_FAST
     70 #define load_block(d, s)        (d) = *(const aes_block_t *)(s)
     71 #define store_block(d, s)       *(aes_block_t *)(d) = (s)
     72 #else
     73 #define load_block(d, s)        memcpy((d).data, (s), AES_BLOCK_SIZE)
     74 #define store_block(d, s)       memcpy((d), (s).data, AES_BLOCK_SIZE)
     75 #endif
     76 
     77 /* N.B. The IV for this mode is _twice_ the block size */
     78 
     79 void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
     80 					 size_t length, const AES_KEY *key,
     81 					 unsigned char *ivec, const int enc)
     82 	{
     83 	size_t n;
     84 	size_t len = length;
     85 
     86 	OPENSSL_assert(in && out && key && ivec);
     87 	OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
     88 	OPENSSL_assert((length%AES_BLOCK_SIZE) == 0);
     89 
     90 	len = length / AES_BLOCK_SIZE;
     91 
     92 	if (AES_ENCRYPT == enc)
     93 		{
     94 		if (in != out &&
     95 		    (UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(long)==0))
     96 			{
     97 			aes_block_t *ivp = (aes_block_t *)ivec;
     98 			aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE);
     99 
    100 			while (len)
    101 				{
    102 				aes_block_t *inp = (aes_block_t *)in;
    103 				aes_block_t *outp = (aes_block_t *)out;
    104 
    105 				for(n=0 ; n < N_WORDS; ++n)
    106 					outp->data[n] = inp->data[n] ^ ivp->data[n];
    107 				AES_encrypt((unsigned char *)outp->data, (unsigned char *)outp->data, key);
    108 				for(n=0 ; n < N_WORDS; ++n)
    109 					outp->data[n] ^= iv2p->data[n];
    110 				ivp = outp;
    111 				iv2p = inp;
    112 				--len;
    113 				in += AES_BLOCK_SIZE;
    114 				out += AES_BLOCK_SIZE;
    115 				}
    116 			memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
    117 			memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
    118 			}
    119 		else
    120 			{
    121 			aes_block_t tmp, tmp2;
    122 			aes_block_t iv;
    123 			aes_block_t iv2;
    124 
    125 			load_block(iv, ivec);
    126 			load_block(iv2, ivec + AES_BLOCK_SIZE);
    127 
    128 			while (len)
    129 				{
    130 				load_block(tmp, in);
    131 				for(n=0 ; n < N_WORDS; ++n)
    132 					tmp2.data[n] = tmp.data[n] ^ iv.data[n];
    133 				AES_encrypt((unsigned char *)tmp2.data, (unsigned char *)tmp2.data, key);
    134 				for(n=0 ; n < N_WORDS; ++n)
    135 					tmp2.data[n] ^= iv2.data[n];
    136 				store_block(out, tmp2);
    137 				iv = tmp2;
    138 				iv2 = tmp;
    139 				--len;
    140 				in += AES_BLOCK_SIZE;
    141 				out += AES_BLOCK_SIZE;
    142 				}
    143 			memcpy(ivec, iv.data, AES_BLOCK_SIZE);
    144 			memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
    145 			}
    146 		}
    147 	else
    148 		{
    149 		if (in != out &&
    150 		    (UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(long)==0))
    151 			{
    152 			aes_block_t *ivp = (aes_block_t *)ivec;
    153 			aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE);
    154 
    155 			while (len)
    156 				{
    157 				aes_block_t tmp;
    158 				aes_block_t *inp = (aes_block_t *)in;
    159 				aes_block_t *outp = (aes_block_t *)out;
    160 
    161 				for(n=0 ; n < N_WORDS; ++n)
    162 					tmp.data[n] = inp->data[n] ^ iv2p->data[n];
    163 				AES_decrypt((unsigned char *)tmp.data, (unsigned char *)outp->data, key);
    164 				for(n=0 ; n < N_WORDS; ++n)
    165 					outp->data[n] ^= ivp->data[n];
    166 				ivp = inp;
    167 				iv2p = outp;
    168 				--len;
    169 				in += AES_BLOCK_SIZE;
    170 				out += AES_BLOCK_SIZE;
    171 				}
    172 			memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
    173 			memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
    174 			}
    175 		else
    176 			{
    177 			aes_block_t tmp, tmp2;
    178 			aes_block_t iv;
    179 			aes_block_t iv2;
    180 
    181 			load_block(iv, ivec);
    182 			load_block(iv2, ivec + AES_BLOCK_SIZE);
    183 
    184 			while (len)
    185 				{
    186 				load_block(tmp, in);
    187 				tmp2 = tmp;
    188 				for(n=0 ; n < N_WORDS; ++n)
    189 					tmp.data[n] ^= iv2.data[n];
    190 				AES_decrypt((unsigned char *)tmp.data, (unsigned char *)tmp.data, key);
    191 				for(n=0 ; n < N_WORDS; ++n)
    192 					tmp.data[n] ^= iv.data[n];
    193 				store_block(out, tmp);
    194 				iv = tmp2;
    195 				iv2 = tmp;
    196 				--len;
    197 				in += AES_BLOCK_SIZE;
    198 				out += AES_BLOCK_SIZE;
    199 				}
    200 			memcpy(ivec, iv.data, AES_BLOCK_SIZE);
    201 			memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
    202 			}
    203 		}
    204 	}
    205 
    206 /*
    207  * Note that its effectively impossible to do biIGE in anything other
    208  * than a single pass, so no provision is made for chaining.
    209  */
    210 
    211 /* N.B. The IV for this mode is _four times_ the block size */
    212 
    213 void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
    214 						size_t length, const AES_KEY *key,
    215 						const AES_KEY *key2, const unsigned char *ivec,
    216 						const int enc)
    217 	{
    218 	size_t n;
    219 	size_t len = length;
    220 	unsigned char tmp[AES_BLOCK_SIZE];
    221 	unsigned char tmp2[AES_BLOCK_SIZE];
    222 	unsigned char tmp3[AES_BLOCK_SIZE];
    223 	unsigned char prev[AES_BLOCK_SIZE];
    224 	const unsigned char *iv;
    225 	const unsigned char *iv2;
    226 
    227 	OPENSSL_assert(in && out && key && ivec);
    228 	OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
    229 	OPENSSL_assert((length%AES_BLOCK_SIZE) == 0);
    230 
    231 	if (AES_ENCRYPT == enc)
    232 		{
    233 		/* XXX: Do a separate case for when in != out (strictly should
    234 		   check for overlap, too) */
    235 
    236 		/* First the forward pass */
    237 		iv = ivec;
    238 		iv2 = ivec + AES_BLOCK_SIZE;
    239 		while (len >= AES_BLOCK_SIZE)
    240 			{
    241 			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
    242 				out[n] = in[n] ^ iv[n];
    243 			AES_encrypt(out, out, key);
    244 			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
    245 				out[n] ^= iv2[n];
    246 			iv = out;
    247 			memcpy(prev, in, AES_BLOCK_SIZE);
    248 			iv2 = prev;
    249 			len -= AES_BLOCK_SIZE;
    250 			in += AES_BLOCK_SIZE;
    251 			out += AES_BLOCK_SIZE;
    252 			}
    253 
    254 		/* And now backwards */
    255 		iv = ivec + AES_BLOCK_SIZE*2;
    256 		iv2 = ivec + AES_BLOCK_SIZE*3;
    257 		len = length;
    258 		while(len >= AES_BLOCK_SIZE)
    259 			{
    260 			out -= AES_BLOCK_SIZE;
    261 			/* XXX: reduce copies by alternating between buffers */
    262 			memcpy(tmp, out, AES_BLOCK_SIZE);
    263 			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
    264 				out[n] ^= iv[n];
    265 			/*			hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE); */
    266 			AES_encrypt(out, out, key);
    267 			/*			hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */
    268 			/*			hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */
    269 			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
    270 				out[n] ^= iv2[n];
    271 			/*			hexdump(stdout,"out", out, AES_BLOCK_SIZE); */
    272 			iv = out;
    273 			memcpy(prev, tmp, AES_BLOCK_SIZE);
    274 			iv2 = prev;
    275 			len -= AES_BLOCK_SIZE;
    276 			}
    277 		}
    278 	else
    279 		{
    280 		/* First backwards */
    281 		iv = ivec + AES_BLOCK_SIZE*2;
    282 		iv2 = ivec + AES_BLOCK_SIZE*3;
    283 		in += length;
    284 		out += length;
    285 		while (len >= AES_BLOCK_SIZE)
    286 			{
    287 			in -= AES_BLOCK_SIZE;
    288 			out -= AES_BLOCK_SIZE;
    289 			memcpy(tmp, in, AES_BLOCK_SIZE);
    290 			memcpy(tmp2, in, AES_BLOCK_SIZE);
    291 			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
    292 				tmp[n] ^= iv2[n];
    293 			AES_decrypt(tmp, out, key);
    294 			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
    295 				out[n] ^= iv[n];
    296 			memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
    297 			iv = tmp3;
    298 			iv2 = out;
    299 			len -= AES_BLOCK_SIZE;
    300 			}
    301 
    302 		/* And now forwards */
    303 		iv = ivec;
    304 		iv2 = ivec + AES_BLOCK_SIZE;
    305 		len = length;
    306 		while (len >= AES_BLOCK_SIZE)
    307 			{
    308 			memcpy(tmp, out, AES_BLOCK_SIZE);
    309 			memcpy(tmp2, out, AES_BLOCK_SIZE);
    310 			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
    311 				tmp[n] ^= iv2[n];
    312 			AES_decrypt(tmp, out, key);
    313 			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
    314 				out[n] ^= iv[n];
    315 			memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
    316 			iv = tmp3;
    317 			iv2 = out;
    318 			len -= AES_BLOCK_SIZE;
    319 			in += AES_BLOCK_SIZE;
    320 			out += AES_BLOCK_SIZE;
    321 			}
    322 		}
    323 	}
    324