1 /* 2 * Copyright 2011-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 <openssl/crypto.h> 11 #include "modes_lcl.h" 12 #include <string.h> 13 14 int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, 15 const unsigned char iv[16], 16 const unsigned char *inp, unsigned char *out, 17 size_t len, int enc) 18 { 19 const union { 20 long one; 21 char little; 22 } is_endian = { 23 1 24 }; 25 union { 26 u64 u[2]; 27 u32 d[4]; 28 u8 c[16]; 29 } tweak, scratch; 30 unsigned int i; 31 32 if (len < 16) 33 return -1; 34 35 memcpy(tweak.c, iv, 16); 36 37 (*ctx->block2) (tweak.c, tweak.c, ctx->key2); 38 39 if (!enc && (len % 16)) 40 len -= 16; 41 42 while (len >= 16) { 43 #if defined(STRICT_ALIGNMENT) 44 memcpy(scratch.c, inp, 16); 45 scratch.u[0] ^= tweak.u[0]; 46 scratch.u[1] ^= tweak.u[1]; 47 #else 48 scratch.u[0] = ((u64 *)inp)[0] ^ tweak.u[0]; 49 scratch.u[1] = ((u64 *)inp)[1] ^ tweak.u[1]; 50 #endif 51 (*ctx->block1) (scratch.c, scratch.c, ctx->key1); 52 #if defined(STRICT_ALIGNMENT) 53 scratch.u[0] ^= tweak.u[0]; 54 scratch.u[1] ^= tweak.u[1]; 55 memcpy(out, scratch.c, 16); 56 #else 57 ((u64 *)out)[0] = scratch.u[0] ^= tweak.u[0]; 58 ((u64 *)out)[1] = scratch.u[1] ^= tweak.u[1]; 59 #endif 60 inp += 16; 61 out += 16; 62 len -= 16; 63 64 if (len == 0) 65 return 0; 66 67 if (is_endian.little) { 68 unsigned int carry, res; 69 70 res = 0x87 & (((int)tweak.d[3]) >> 31); 71 carry = (unsigned int)(tweak.u[0] >> 63); 72 tweak.u[0] = (tweak.u[0] << 1) ^ res; 73 tweak.u[1] = (tweak.u[1] << 1) | carry; 74 } else { 75 size_t c; 76 77 for (c = 0, i = 0; i < 16; ++i) { 78 /* 79 * + substitutes for |, because c is 1 bit 80 */ 81 c += ((size_t)tweak.c[i]) << 1; 82 tweak.c[i] = (u8)c; 83 c = c >> 8; 84 } 85 tweak.c[0] ^= (u8)(0x87 & (0 - c)); 86 } 87 } 88 if (enc) { 89 for (i = 0; i < len; ++i) { 90 u8 c = inp[i]; 91 out[i] = scratch.c[i]; 92 scratch.c[i] = c; 93 } 94 scratch.u[0] ^= tweak.u[0]; 95 scratch.u[1] ^= tweak.u[1]; 96 (*ctx->block1) (scratch.c, scratch.c, ctx->key1); 97 scratch.u[0] ^= tweak.u[0]; 98 scratch.u[1] ^= tweak.u[1]; 99 memcpy(out - 16, scratch.c, 16); 100 } else { 101 union { 102 u64 u[2]; 103 u8 c[16]; 104 } tweak1; 105 106 if (is_endian.little) { 107 unsigned int carry, res; 108 109 res = 0x87 & (((int)tweak.d[3]) >> 31); 110 carry = (unsigned int)(tweak.u[0] >> 63); 111 tweak1.u[0] = (tweak.u[0] << 1) ^ res; 112 tweak1.u[1] = (tweak.u[1] << 1) | carry; 113 } else { 114 size_t c; 115 116 for (c = 0, i = 0; i < 16; ++i) { 117 /* 118 * + substitutes for |, because c is 1 bit 119 */ 120 c += ((size_t)tweak.c[i]) << 1; 121 tweak1.c[i] = (u8)c; 122 c = c >> 8; 123 } 124 tweak1.c[0] ^= (u8)(0x87 & (0 - c)); 125 } 126 #if defined(STRICT_ALIGNMENT) 127 memcpy(scratch.c, inp, 16); 128 scratch.u[0] ^= tweak1.u[0]; 129 scratch.u[1] ^= tweak1.u[1]; 130 #else 131 scratch.u[0] = ((u64 *)inp)[0] ^ tweak1.u[0]; 132 scratch.u[1] = ((u64 *)inp)[1] ^ tweak1.u[1]; 133 #endif 134 (*ctx->block1) (scratch.c, scratch.c, ctx->key1); 135 scratch.u[0] ^= tweak1.u[0]; 136 scratch.u[1] ^= tweak1.u[1]; 137 138 for (i = 0; i < len; ++i) { 139 u8 c = inp[16 + i]; 140 out[16 + i] = scratch.c[i]; 141 scratch.c[i] = c; 142 } 143 scratch.u[0] ^= tweak.u[0]; 144 scratch.u[1] ^= tweak.u[1]; 145 (*ctx->block1) (scratch.c, scratch.c, ctx->key1); 146 #if defined(STRICT_ALIGNMENT) 147 scratch.u[0] ^= tweak.u[0]; 148 scratch.u[1] ^= tweak.u[1]; 149 memcpy(out, scratch.c, 16); 150 #else 151 ((u64 *)out)[0] = scratch.u[0] ^ tweak.u[0]; 152 ((u64 *)out)[1] = scratch.u[1] ^ tweak.u[1]; 153 #endif 154 } 155 156 return 0; 157 } 158