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@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/* 58static void hexdump(FILE *f,const char *title,const unsigned char *s,int l) 59 { 60 int n=0; 61 62 fprintf(f,"%s",title); 63 for( ; n < l ; ++n) 64 { 65 if((n%16) == 0) 66 fprintf(f,"\n%04x",n); 67 fprintf(f," %02x",s[n]); 68 } 69 fprintf(f,"\n"); 70 } 71*/ 72 73/* N.B. The IV for this mode is _twice_ the block size */ 74 75void AES_ige_encrypt(const unsigned char *in, unsigned char *out, 76 const unsigned long length, const AES_KEY *key, 77 unsigned char *ivec, const int enc) 78 { 79 unsigned long n; 80 unsigned long len = length; 81 unsigned char tmp[AES_BLOCK_SIZE]; 82 unsigned char tmp2[AES_BLOCK_SIZE]; 83 unsigned char prev[AES_BLOCK_SIZE]; 84 const unsigned char *iv = ivec; 85 const unsigned char *iv2 = ivec + AES_BLOCK_SIZE; 86 87 OPENSSL_assert(in && out && key && ivec); 88 OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); 89 OPENSSL_assert((length%AES_BLOCK_SIZE) == 0); 90 91 if (AES_ENCRYPT == enc) 92 { 93 /* XXX: Do a separate case for when in != out (strictly should 94 check for overlap, too) */ 95 while (len >= AES_BLOCK_SIZE) 96 { 97 /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ 98 /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ 99 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 100 out[n] = in[n] ^ iv[n]; 101 /* hexdump(stdout, "in ^ iv", out, AES_BLOCK_SIZE); */ 102 AES_encrypt(out, out, key); 103 /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ 104 /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ 105 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 106 out[n] ^= iv2[n]; 107 /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ 108 iv = out; 109 memcpy(prev, in, AES_BLOCK_SIZE); 110 iv2 = prev; 111 len -= AES_BLOCK_SIZE; 112 in += AES_BLOCK_SIZE; 113 out += AES_BLOCK_SIZE; 114 } 115 memcpy(ivec, iv, AES_BLOCK_SIZE); 116 memcpy(ivec + AES_BLOCK_SIZE, iv2, AES_BLOCK_SIZE); 117 } 118 else 119 { 120 while (len >= AES_BLOCK_SIZE) 121 { 122 memcpy(tmp, in, AES_BLOCK_SIZE); 123 memcpy(tmp2, in, AES_BLOCK_SIZE); 124 /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ 125 /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ 126 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 127 tmp[n] ^= iv2[n]; 128 /* hexdump(stdout, "in ^ iv2", tmp, AES_BLOCK_SIZE); */ 129 AES_decrypt(tmp, out, key); 130 /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ 131 /* hexdump(stdout, "iv", ivec, AES_BLOCK_SIZE); */ 132 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 133 out[n] ^= ivec[n]; 134 /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ 135 memcpy(ivec, tmp2, AES_BLOCK_SIZE); 136 iv2 = out; 137 len -= AES_BLOCK_SIZE; 138 in += AES_BLOCK_SIZE; 139 out += AES_BLOCK_SIZE; 140 } 141 memcpy(ivec + AES_BLOCK_SIZE, iv2, AES_BLOCK_SIZE); 142 } 143 } 144 145/* 146 * Note that its effectively impossible to do biIGE in anything other 147 * than a single pass, so no provision is made for chaining. 148 */ 149 150/* N.B. The IV for this mode is _four times_ the block size */ 151 152void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, 153 const unsigned long length, const AES_KEY *key, 154 const AES_KEY *key2, const unsigned char *ivec, 155 const int enc) 156 { 157 unsigned long n; 158 unsigned long len = length; 159 unsigned char tmp[AES_BLOCK_SIZE]; 160 unsigned char tmp2[AES_BLOCK_SIZE]; 161 unsigned char tmp3[AES_BLOCK_SIZE]; 162 unsigned char prev[AES_BLOCK_SIZE]; 163 const unsigned char *iv; 164 const unsigned char *iv2; 165 166 OPENSSL_assert(in && out && key && ivec); 167 OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); 168 OPENSSL_assert((length%AES_BLOCK_SIZE) == 0); 169 170 if (AES_ENCRYPT == enc) 171 { 172 /* XXX: Do a separate case for when in != out (strictly should 173 check for overlap, too) */ 174 175 /* First the forward pass */ 176 iv = ivec; 177 iv2 = ivec + AES_BLOCK_SIZE; 178 while (len >= AES_BLOCK_SIZE) 179 { 180 /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ 181 /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ 182 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 183 out[n] = in[n] ^ iv[n]; 184 /* hexdump(stdout, "in ^ iv", out, AES_BLOCK_SIZE); */ 185 AES_encrypt(out, out, key); 186 /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ 187 /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ 188 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 189 out[n] ^= iv2[n]; 190 /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ 191 iv = out; 192 memcpy(prev, in, AES_BLOCK_SIZE); 193 iv2 = prev; 194 len -= AES_BLOCK_SIZE; 195 in += AES_BLOCK_SIZE; 196 out += AES_BLOCK_SIZE; 197 } 198 199 /* And now backwards */ 200 iv = ivec + AES_BLOCK_SIZE*2; 201 iv2 = ivec + AES_BLOCK_SIZE*3; 202 len = length; 203 while(len >= AES_BLOCK_SIZE) 204 { 205 out -= AES_BLOCK_SIZE; 206 /* hexdump(stdout, "intermediate", out, AES_BLOCK_SIZE); */ 207 /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ 208 /* XXX: reduce copies by alternating between buffers */ 209 memcpy(tmp, out, AES_BLOCK_SIZE); 210 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 211 out[n] ^= iv[n]; 212 /* hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE); */ 213 AES_encrypt(out, out, key); 214 /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ 215 /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ 216 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 217 out[n] ^= iv2[n]; 218 /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ 219 iv = out; 220 memcpy(prev, tmp, AES_BLOCK_SIZE); 221 iv2 = prev; 222 len -= AES_BLOCK_SIZE; 223 } 224 } 225 else 226 { 227 /* First backwards */ 228 iv = ivec + AES_BLOCK_SIZE*2; 229 iv2 = ivec + AES_BLOCK_SIZE*3; 230 in += length; 231 out += length; 232 while (len >= AES_BLOCK_SIZE) 233 { 234 in -= AES_BLOCK_SIZE; 235 out -= AES_BLOCK_SIZE; 236 memcpy(tmp, in, AES_BLOCK_SIZE); 237 memcpy(tmp2, in, AES_BLOCK_SIZE); 238 /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ 239 /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ 240 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 241 tmp[n] ^= iv2[n]; 242 /* hexdump(stdout, "in ^ iv2", tmp, AES_BLOCK_SIZE); */ 243 AES_decrypt(tmp, out, key); 244 /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ 245 /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ 246 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 247 out[n] ^= iv[n]; 248 /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ 249 memcpy(tmp3, tmp2, AES_BLOCK_SIZE); 250 iv = tmp3; 251 iv2 = out; 252 len -= AES_BLOCK_SIZE; 253 } 254 255 /* And now forwards */ 256 iv = ivec; 257 iv2 = ivec + AES_BLOCK_SIZE; 258 len = length; 259 while (len >= AES_BLOCK_SIZE) 260 { 261 memcpy(tmp, out, AES_BLOCK_SIZE); 262 memcpy(tmp2, out, AES_BLOCK_SIZE); 263 /* hexdump(stdout, "intermediate", out, AES_BLOCK_SIZE); */ 264 /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ 265 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 266 tmp[n] ^= iv2[n]; 267 /* hexdump(stdout, "out ^ iv2", tmp, AES_BLOCK_SIZE); */ 268 AES_decrypt(tmp, out, key); 269 /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ 270 /* hexdump(stdout, "iv", ivec, AES_BLOCK_SIZE); */ 271 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) 272 out[n] ^= iv[n]; 273 /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ 274 memcpy(tmp3, tmp2, AES_BLOCK_SIZE); 275 iv = tmp3; 276 iv2 = out; 277 len -= AES_BLOCK_SIZE; 278 in += AES_BLOCK_SIZE; 279 out += AES_BLOCK_SIZE; 280 } 281 282 } 283 } 284