xts128.c revision 296341
1/* ==================================================================== 2 * Copyright (c) 2011 The OpenSSL Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * 3. All advertising materials mentioning features or use of this 17 * software must display the following acknowledgment: 18 * "This product includes software developed by the OpenSSL Project 19 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 20 * 21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22 * endorse or promote products derived from this software without 23 * prior written permission. For written permission, please contact 24 * openssl-core@openssl.org. 25 * 26 * 5. Products derived from this software may not be called "OpenSSL" 27 * nor may "OpenSSL" appear in their names without prior written 28 * permission of the OpenSSL Project. 29 * 30 * 6. Redistributions of any form whatsoever must retain the following 31 * acknowledgment: 32 * "This product includes software developed by the OpenSSL Project 33 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46 * OF THE POSSIBILITY OF SUCH DAMAGE. 47 * ==================================================================== 48 */ 49 50#include <openssl/crypto.h> 51#include "modes_lcl.h" 52#include <string.h> 53 54#ifndef MODES_DEBUG 55# ifndef NDEBUG 56# define NDEBUG 57# endif 58#endif 59#include <assert.h> 60 61int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, 62 const unsigned char iv[16], 63 const unsigned char *inp, unsigned char *out, 64 size_t len, int enc) 65{ 66 const union { 67 long one; 68 char little; 69 } is_endian = { 70 1 71 }; 72 union { 73 u64 u[2]; 74 u32 d[4]; 75 u8 c[16]; 76 } tweak, scratch; 77 unsigned int i; 78 79 if (len < 16) 80 return -1; 81 82 memcpy(tweak.c, iv, 16); 83 84 (*ctx->block2) (tweak.c, tweak.c, ctx->key2); 85 86 if (!enc && (len % 16)) 87 len -= 16; 88 89 while (len >= 16) { 90#if defined(STRICT_ALIGNMENT) 91 memcpy(scratch.c, inp, 16); 92 scratch.u[0] ^= tweak.u[0]; 93 scratch.u[1] ^= tweak.u[1]; 94#else 95 scratch.u[0] = ((u64 *)inp)[0] ^ tweak.u[0]; 96 scratch.u[1] = ((u64 *)inp)[1] ^ tweak.u[1]; 97#endif 98 (*ctx->block1) (scratch.c, scratch.c, ctx->key1); 99#if defined(STRICT_ALIGNMENT) 100 scratch.u[0] ^= tweak.u[0]; 101 scratch.u[1] ^= tweak.u[1]; 102 memcpy(out, scratch.c, 16); 103#else 104 ((u64 *)out)[0] = scratch.u[0] ^= tweak.u[0]; 105 ((u64 *)out)[1] = scratch.u[1] ^= tweak.u[1]; 106#endif 107 inp += 16; 108 out += 16; 109 len -= 16; 110 111 if (len == 0) 112 return 0; 113 114 if (is_endian.little) { 115 unsigned int carry, res; 116 117 res = 0x87 & (((int)tweak.d[3]) >> 31); 118 carry = (unsigned int)(tweak.u[0] >> 63); 119 tweak.u[0] = (tweak.u[0] << 1) ^ res; 120 tweak.u[1] = (tweak.u[1] << 1) | carry; 121 } else { 122 size_t c; 123 124 for (c = 0, i = 0; i < 16; ++i) { 125 /* 126 * + substitutes for |, because c is 1 bit 127 */ 128 c += ((size_t)tweak.c[i]) << 1; 129 tweak.c[i] = (u8)c; 130 c = c >> 8; 131 } 132 tweak.c[0] ^= (u8)(0x87 & (0 - c)); 133 } 134 } 135 if (enc) { 136 for (i = 0; i < len; ++i) { 137 u8 c = inp[i]; 138 out[i] = scratch.c[i]; 139 scratch.c[i] = c; 140 } 141 scratch.u[0] ^= tweak.u[0]; 142 scratch.u[1] ^= tweak.u[1]; 143 (*ctx->block1) (scratch.c, scratch.c, ctx->key1); 144 scratch.u[0] ^= tweak.u[0]; 145 scratch.u[1] ^= tweak.u[1]; 146 memcpy(out - 16, scratch.c, 16); 147 } else { 148 union { 149 u64 u[2]; 150 u8 c[16]; 151 } tweak1; 152 153 if (is_endian.little) { 154 unsigned int carry, res; 155 156 res = 0x87 & (((int)tweak.d[3]) >> 31); 157 carry = (unsigned int)(tweak.u[0] >> 63); 158 tweak1.u[0] = (tweak.u[0] << 1) ^ res; 159 tweak1.u[1] = (tweak.u[1] << 1) | carry; 160 } else { 161 size_t c; 162 163 for (c = 0, i = 0; i < 16; ++i) { 164 /* 165 * + substitutes for |, because c is 1 bit 166 */ 167 c += ((size_t)tweak.c[i]) << 1; 168 tweak1.c[i] = (u8)c; 169 c = c >> 8; 170 } 171 tweak1.c[0] ^= (u8)(0x87 & (0 - c)); 172 } 173#if defined(STRICT_ALIGNMENT) 174 memcpy(scratch.c, inp, 16); 175 scratch.u[0] ^= tweak1.u[0]; 176 scratch.u[1] ^= tweak1.u[1]; 177#else 178 scratch.u[0] = ((u64 *)inp)[0] ^ tweak1.u[0]; 179 scratch.u[1] = ((u64 *)inp)[1] ^ tweak1.u[1]; 180#endif 181 (*ctx->block1) (scratch.c, scratch.c, ctx->key1); 182 scratch.u[0] ^= tweak1.u[0]; 183 scratch.u[1] ^= tweak1.u[1]; 184 185 for (i = 0; i < len; ++i) { 186 u8 c = inp[16 + i]; 187 out[16 + i] = scratch.c[i]; 188 scratch.c[i] = c; 189 } 190 scratch.u[0] ^= tweak.u[0]; 191 scratch.u[1] ^= tweak.u[1]; 192 (*ctx->block1) (scratch.c, scratch.c, ctx->key1); 193#if defined(STRICT_ALIGNMENT) 194 scratch.u[0] ^= tweak.u[0]; 195 scratch.u[1] ^= tweak.u[1]; 196 memcpy(out, scratch.c, 16); 197#else 198 ((u64 *)out)[0] = scratch.u[0] ^ tweak.u[0]; 199 ((u64 *)out)[1] = scratch.u[1] ^ tweak.u[1]; 200#endif 201 } 202 203 return 0; 204} 205