1392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* ==================================================================== 2392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Copyright (c) 2011 The OpenSSL Project. All rights reserved. 3392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 4392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Redistribution and use in source and binary forms, with or without 5392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * modification, are permitted provided that the following conditions 6392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * are met: 7392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 8392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 1. Redistributions of source code must retain the above copyright 9392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * notice, this list of conditions and the following disclaimer. 10392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 11392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 2. Redistributions in binary form must reproduce the above copyright 12392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * notice, this list of conditions and the following disclaimer in 13392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * the documentation and/or other materials provided with the 14392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * distribution. 15392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 16392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 3. All advertising materials mentioning features or use of this 17392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * software must display the following acknowledgment: 18392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * "This product includes software developed by the OpenSSL Project 19392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 20392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 21392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * endorse or promote products derived from this software without 23392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * prior written permission. For written permission, please contact 24392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * openssl-core@openssl.org. 25392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 26392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 5. Products derived from this software may not be called "OpenSSL" 27392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * nor may "OpenSSL" appear in their names without prior written 28392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * permission of the OpenSSL Project. 29392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 30392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 6. Redistributions of any form whatsoever must retain the following 31392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * acknowledgment: 32392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * "This product includes software developed by the OpenSSL Project 33392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 34392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 35392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * OF THE POSSIBILITY OF SUCH DAMAGE. 47392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * ==================================================================== 48392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom */ 49392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 50392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <openssl/crypto.h> 51392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include "modes_lcl.h" 52392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <string.h> 53392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 54392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef MODES_DEBUG 55392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifndef NDEBUG 56392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# define NDEBUG 57392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif 58392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif 59392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <assert.h> 60392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 61392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, const unsigned char iv[16], 62392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom const unsigned char *inp, unsigned char *out, 63392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom size_t len, int enc) 64392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{ 65392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom const union { long one; char little; } is_endian = {1}; 66392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom union { u64 u[2]; u32 d[4]; u8 c[16]; } tweak, scratch; 67392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom unsigned int i; 68392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 69392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom if (len<16) return -1; 70392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 71392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom memcpy(tweak.c, iv, 16); 72392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 73392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom (*ctx->block2)(tweak.c,tweak.c,ctx->key2); 74392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 75392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom if (!enc && (len%16)) len-=16; 76392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 77392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom while (len>=16) { 78392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(STRICT_ALIGNMENT) 79392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom memcpy(scratch.c,inp,16); 80392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[0] ^= tweak.u[0]; 81392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[1] ^= tweak.u[1]; 82392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else 83392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[0] = ((u64*)inp)[0]^tweak.u[0]; 84392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[1] = ((u64*)inp)[1]^tweak.u[1]; 85392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif 86392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom (*ctx->block1)(scratch.c,scratch.c,ctx->key1); 87392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(STRICT_ALIGNMENT) 88392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[0] ^= tweak.u[0]; 89392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[1] ^= tweak.u[1]; 90392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom memcpy(out,scratch.c,16); 91392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else 92392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom ((u64*)out)[0] = scratch.u[0]^=tweak.u[0]; 93392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom ((u64*)out)[1] = scratch.u[1]^=tweak.u[1]; 94392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif 95392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom inp += 16; 96392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom out += 16; 97392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom len -= 16; 98392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 99392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom if (len==0) return 0; 100392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 101392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom if (is_endian.little) { 102392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom unsigned int carry,res; 103392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 104392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom res = 0x87&(((int)tweak.d[3])>>31); 105392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom carry = (unsigned int)(tweak.u[0]>>63); 106392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom tweak.u[0] = (tweak.u[0]<<1)^res; 107392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom tweak.u[1] = (tweak.u[1]<<1)|carry; 108392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 109392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom else { 110392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom size_t c; 111392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 112392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom for (c=0,i=0;i<16;++i) { 113392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom /*+ substitutes for |, because c is 1 bit */ 114392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom c += ((size_t)tweak.c[i])<<1; 115392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom tweak.c[i] = (u8)c; 116392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom c = c>>8; 117392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 118392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom tweak.c[0] ^= (u8)(0x87&(0-c)); 119392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 120392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 121392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom if (enc) { 122392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom for (i=0;i<len;++i) { 123392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom u8 c = inp[i]; 124392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom out[i] = scratch.c[i]; 125392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.c[i] = c; 126392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 127392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[0] ^= tweak.u[0]; 128392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[1] ^= tweak.u[1]; 129392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom (*ctx->block1)(scratch.c,scratch.c,ctx->key1); 130392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[0] ^= tweak.u[0]; 131392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[1] ^= tweak.u[1]; 132392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom memcpy(out-16,scratch.c,16); 133392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 134392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom else { 135392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom union { u64 u[2]; u8 c[16]; } tweak1; 136392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 137392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom if (is_endian.little) { 138392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom unsigned int carry,res; 139392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 140392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom res = 0x87&(((int)tweak.d[3])>>31); 141392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom carry = (unsigned int)(tweak.u[0]>>63); 142392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom tweak1.u[0] = (tweak.u[0]<<1)^res; 143392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom tweak1.u[1] = (tweak.u[1]<<1)|carry; 144392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 145392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom else { 146392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom size_t c; 147392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 148392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom for (c=0,i=0;i<16;++i) { 149392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom /*+ substitutes for |, because c is 1 bit */ 150392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom c += ((size_t)tweak.c[i])<<1; 151392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom tweak1.c[i] = (u8)c; 152392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom c = c>>8; 153392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 154392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom tweak1.c[0] ^= (u8)(0x87&(0-c)); 155392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 156392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(STRICT_ALIGNMENT) 157392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom memcpy(scratch.c,inp,16); 158392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[0] ^= tweak1.u[0]; 159392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[1] ^= tweak1.u[1]; 160392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else 161392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[0] = ((u64*)inp)[0]^tweak1.u[0]; 162392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[1] = ((u64*)inp)[1]^tweak1.u[1]; 163392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif 164392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom (*ctx->block1)(scratch.c,scratch.c,ctx->key1); 165392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[0] ^= tweak1.u[0]; 166392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[1] ^= tweak1.u[1]; 167392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 168392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom for (i=0;i<len;++i) { 169392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom u8 c = inp[16+i]; 170392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom out[16+i] = scratch.c[i]; 171392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.c[i] = c; 172392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 173392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[0] ^= tweak.u[0]; 174392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[1] ^= tweak.u[1]; 175392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom (*ctx->block1)(scratch.c,scratch.c,ctx->key1); 176392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(STRICT_ALIGNMENT) 177392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[0] ^= tweak.u[0]; 178392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom scratch.u[1] ^= tweak.u[1]; 179392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom memcpy (out,scratch.c,16); 180392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else 181392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom ((u64*)out)[0] = scratch.u[0]^tweak.u[0]; 182392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom ((u64*)out)[1] = scratch.u[1]^tweak.u[1]; 183392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif 184392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom } 185392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom 186392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom return 0; 187392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom} 188