1 /* 2 * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "internal/cryptlib.h" 11 12 #include <openssl/aes.h> 13 #include "aes_local.h" 14 15 #define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long)) 16 typedef struct { 17 unsigned long data[N_WORDS]; 18 } aes_block_t; 19 20 /* XXX: probably some better way to do this */ 21 #if defined(__i386__) || defined(__x86_64__) 22 # define UNALIGNED_MEMOPS_ARE_FAST 1 23 #else 24 # define UNALIGNED_MEMOPS_ARE_FAST 0 25 #endif 26 27 #if UNALIGNED_MEMOPS_ARE_FAST 28 # define load_block(d, s) (d) = *(const aes_block_t *)(s) 29 # define store_block(d, s) *(aes_block_t *)(d) = (s) 30 #else 31 # define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE) 32 # define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE) 33 #endif 34 35 /* N.B. The IV for this mode is _twice_ the block size */ 36 37 void AES_ige_encrypt(const unsigned char *in, unsigned char *out, 38 size_t length, const AES_KEY *key, 39 unsigned char *ivec, const int enc) 40 { 41 size_t n; 42 size_t len = length; 43 44 if (length == 0) 45 return; 46 47 OPENSSL_assert(in && out && key && ivec); 48 OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); 49 OPENSSL_assert((length % AES_BLOCK_SIZE) == 0); 50 51 len = length / AES_BLOCK_SIZE; 52 53 if (AES_ENCRYPT == enc) { 54 if (in != out && 55 (UNALIGNED_MEMOPS_ARE_FAST 56 || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) == 57 0)) { 58 aes_block_t *ivp = (aes_block_t *) ivec; 59 aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE); 60 61 while (len) { 62 aes_block_t *inp = (aes_block_t *) in; 63 aes_block_t *outp = (aes_block_t *) out; 64 65 for (n = 0; n < N_WORDS; ++n) 66 outp->data[n] = inp->data[n] ^ ivp->data[n]; 67 AES_encrypt((unsigned char *)outp->data, 68 (unsigned char *)outp->data, key); 69 for (n = 0; n < N_WORDS; ++n) 70 outp->data[n] ^= iv2p->data[n]; 71 ivp = outp; 72 iv2p = inp; 73 --len; 74 in += AES_BLOCK_SIZE; 75 out += AES_BLOCK_SIZE; 76 } 77 memcpy(ivec, ivp->data, AES_BLOCK_SIZE); 78 memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); 79 } else { 80 aes_block_t tmp, tmp2; 81 aes_block_t iv; 82 aes_block_t iv2; 83 84 load_block(iv, ivec); 85 load_block(iv2, ivec + AES_BLOCK_SIZE); 86 87 while (len) { 88 load_block(tmp, in); 89 for (n = 0; n < N_WORDS; ++n) 90 tmp2.data[n] = tmp.data[n] ^ iv.data[n]; 91 AES_encrypt((unsigned char *)tmp2.data, 92 (unsigned char *)tmp2.data, key); 93 for (n = 0; n < N_WORDS; ++n) 94 tmp2.data[n] ^= iv2.data[n]; 95 store_block(out, tmp2); 96 iv = tmp2; 97 iv2 = tmp; 98 --len; 99 in += AES_BLOCK_SIZE; 100 out += AES_BLOCK_SIZE; 101 } 102 memcpy(ivec, iv.data, AES_BLOCK_SIZE); 103 memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); 104 } 105 } else { 106 if (in != out && 107 (UNALIGNED_MEMOPS_ARE_FAST 108 || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) == 109 0)) { 110 aes_block_t *ivp = (aes_block_t *) ivec; 111 aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE); 112 113 while (len) { 114 aes_block_t tmp; 115 aes_block_t *inp = (aes_block_t *) in; 116 aes_block_t *outp = (aes_block_t *) out; 117 118 for (n = 0; n < N_WORDS; ++n) 119 tmp.data[n] = inp->data[n] ^ iv2p->data[n]; 120 AES_decrypt((unsigned char *)tmp.data, 121 (unsigned char *)outp->data, key); 122 for (n = 0; n < N_WORDS; ++n) 123 outp->data[n] ^= ivp->data[n]; 124 ivp = inp; 125 iv2p = outp; 126 --len; 127 in += AES_BLOCK_SIZE; 128 out += AES_BLOCK_SIZE; 129 } 130 memcpy(ivec, ivp->data, AES_BLOCK_SIZE); 131 memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); 132 } else { 133 aes_block_t tmp, tmp2; 134 aes_block_t iv; 135 aes_block_t iv2; 136 137 load_block(iv, ivec); 138 load_block(iv2, ivec + AES_BLOCK_SIZE); 139 140 while (len) { 141 load_block(tmp, in); 142 tmp2 = tmp; 143 for (n = 0; n < N_WORDS; ++n) 144 tmp.data[n] ^= iv2.data[n]; 145 AES_decrypt((unsigned char *)tmp.data, 146 (unsigned char *)tmp.data, key); 147 for (n = 0; n < N_WORDS; ++n) 148 tmp.data[n] ^= iv.data[n]; 149 store_block(out, tmp); 150 iv = tmp2; 151 iv2 = tmp; 152 --len; 153 in += AES_BLOCK_SIZE; 154 out += AES_BLOCK_SIZE; 155 } 156 memcpy(ivec, iv.data, AES_BLOCK_SIZE); 157 memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); 158 } 159 } 160 } 161 162 /* 163 * Note that its effectively impossible to do biIGE in anything other 164 * than a single pass, so no provision is made for chaining. 165 */ 166 167 /* N.B. The IV for this mode is _four times_ the block size */ 168 169 void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, 170 size_t length, const AES_KEY *key, 171 const AES_KEY *key2, const unsigned char *ivec, 172 const int enc) 173 { 174 size_t n; 175 size_t len = length; 176 unsigned char tmp[AES_BLOCK_SIZE]; 177 unsigned char tmp2[AES_BLOCK_SIZE]; 178 unsigned char tmp3[AES_BLOCK_SIZE]; 179 unsigned char prev[AES_BLOCK_SIZE]; 180 const unsigned char *iv; 181 const unsigned char *iv2; 182 183 OPENSSL_assert(in && out && key && ivec); 184 OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); 185 OPENSSL_assert((length % AES_BLOCK_SIZE) == 0); 186 187 if (AES_ENCRYPT == enc) { 188 /* 189 * XXX: Do a separate case for when in != out (strictly should check 190 * for overlap, too) 191 */ 192 193 /* First the forward pass */ 194 iv = ivec; 195 iv2 = ivec + AES_BLOCK_SIZE; 196 while (len >= AES_BLOCK_SIZE) { 197 for (n = 0; n < AES_BLOCK_SIZE; ++n) 198 out[n] = in[n] ^ iv[n]; 199 AES_encrypt(out, out, key); 200 for (n = 0; n < AES_BLOCK_SIZE; ++n) 201 out[n] ^= iv2[n]; 202 iv = out; 203 memcpy(prev, in, AES_BLOCK_SIZE); 204 iv2 = prev; 205 len -= AES_BLOCK_SIZE; 206 in += AES_BLOCK_SIZE; 207 out += AES_BLOCK_SIZE; 208 } 209 210 /* And now backwards */ 211 iv = ivec + AES_BLOCK_SIZE * 2; 212 iv2 = ivec + AES_BLOCK_SIZE * 3; 213 len = length; 214 while (len >= AES_BLOCK_SIZE) { 215 out -= AES_BLOCK_SIZE; 216 /* 217 * XXX: reduce copies by alternating between buffers 218 */ 219 memcpy(tmp, out, AES_BLOCK_SIZE); 220 for (n = 0; n < AES_BLOCK_SIZE; ++n) 221 out[n] ^= iv[n]; 222 /* 223 * hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE); 224 */ 225 AES_encrypt(out, out, key); 226 /* 227 * hexdump(stdout,"enc", out, AES_BLOCK_SIZE); 228 */ 229 /* 230 * hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); 231 */ 232 for (n = 0; n < AES_BLOCK_SIZE; ++n) 233 out[n] ^= iv2[n]; 234 /* 235 * hexdump(stdout,"out", out, AES_BLOCK_SIZE); 236 */ 237 iv = out; 238 memcpy(prev, tmp, AES_BLOCK_SIZE); 239 iv2 = prev; 240 len -= AES_BLOCK_SIZE; 241 } 242 } else { 243 /* First backwards */ 244 iv = ivec + AES_BLOCK_SIZE * 2; 245 iv2 = ivec + AES_BLOCK_SIZE * 3; 246 in += length; 247 out += length; 248 while (len >= AES_BLOCK_SIZE) { 249 in -= AES_BLOCK_SIZE; 250 out -= AES_BLOCK_SIZE; 251 memcpy(tmp, in, AES_BLOCK_SIZE); 252 memcpy(tmp2, in, AES_BLOCK_SIZE); 253 for (n = 0; n < AES_BLOCK_SIZE; ++n) 254 tmp[n] ^= iv2[n]; 255 AES_decrypt(tmp, out, key); 256 for (n = 0; n < AES_BLOCK_SIZE; ++n) 257 out[n] ^= iv[n]; 258 memcpy(tmp3, tmp2, AES_BLOCK_SIZE); 259 iv = tmp3; 260 iv2 = out; 261 len -= AES_BLOCK_SIZE; 262 } 263 264 /* And now forwards */ 265 iv = ivec; 266 iv2 = ivec + AES_BLOCK_SIZE; 267 len = length; 268 while (len >= AES_BLOCK_SIZE) { 269 memcpy(tmp, out, AES_BLOCK_SIZE); 270 memcpy(tmp2, out, AES_BLOCK_SIZE); 271 for (n = 0; n < AES_BLOCK_SIZE; ++n) 272 tmp[n] ^= iv2[n]; 273 AES_decrypt(tmp, out, key); 274 for (n = 0; n < AES_BLOCK_SIZE; ++n) 275 out[n] ^= iv[n]; 276 memcpy(tmp3, tmp2, AES_BLOCK_SIZE); 277 iv = tmp3; 278 iv2 = out; 279 len -= AES_BLOCK_SIZE; 280 in += AES_BLOCK_SIZE; 281 out += AES_BLOCK_SIZE; 282 } 283 } 284 } 285