1/* $OpenBSD: xts128.c,v 1.12 2023/07/08 14:56:54 beck Exp $ */ 2/* ==================================================================== 3 * Copyright (c) 2011 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#include <openssl/crypto.h> 52#include "modes_local.h" 53 54#include <endian.h> 55#include <string.h> 56 57#ifndef MODES_DEBUG 58# ifndef NDEBUG 59# define NDEBUG 60# endif 61#endif 62 63int 64CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, const unsigned char iv[16], 65 const unsigned char *inp, unsigned char *out, 66 size_t len, int enc) 67{ 68 union { 69 u64 u[2]; 70 u32 d[4]; 71 u8 c[16]; 72 } tweak, scratch; 73 unsigned int i; 74 75 if (len < 16) 76 return -1; 77 78 memcpy(tweak.c, iv, 16); 79 80 (*ctx->block2)(tweak.c, tweak.c, ctx->key2); 81 82 if (!enc && (len % 16)) 83 len -= 16; 84 85 while (len >= 16) { 86#ifdef __STRICT_ALIGNMENT 87 memcpy(scratch.c, inp, 16); 88 scratch.u[0] ^= tweak.u[0]; 89 scratch.u[1] ^= tweak.u[1]; 90#else 91 scratch.u[0] = ((u64 *)inp)[0] ^ tweak.u[0]; 92 scratch.u[1] = ((u64 *)inp)[1] ^ tweak.u[1]; 93#endif 94 (*ctx->block1)(scratch.c, scratch.c, ctx->key1); 95#ifdef __STRICT_ALIGNMENT 96 scratch.u[0] ^= tweak.u[0]; 97 scratch.u[1] ^= tweak.u[1]; 98 memcpy(out, scratch.c, 16); 99#else 100 ((u64 *)out)[0] = scratch.u[0] ^= tweak.u[0]; 101 ((u64 *)out)[1] = scratch.u[1] ^= tweak.u[1]; 102#endif 103 inp += 16; 104 out += 16; 105 len -= 16; 106 107 if (len == 0) 108 return 0; 109 110#if BYTE_ORDER == LITTLE_ENDIAN 111 unsigned int carry, res; 112 113 res = 0x87 & (((int)tweak.d[3]) >> 31); 114 carry = (unsigned int)(tweak.u[0] >> 63); 115 tweak.u[0] = (tweak.u[0] << 1) ^ res; 116 tweak.u[1] = (tweak.u[1] << 1)|carry; 117#else /* BIG_ENDIAN */ 118 size_t c; 119 120 for (c = 0, i = 0; i < 16; ++i) { 121 /*+ substitutes for |, because c is 1 bit */ 122 c += ((size_t)tweak.c[i]) << 1; 123 tweak.c[i] = (u8)c; 124 c = c >> 8; 125 } 126 tweak.c[0] ^= (u8)(0x87 & (0 - c)); 127#endif 128 } 129 if (enc) { 130 for (i = 0; i < len; ++i) { 131 u8 ch = inp[i]; 132 out[i] = scratch.c[i]; 133 scratch.c[i] = ch; 134 } 135 scratch.u[0] ^= tweak.u[0]; 136 scratch.u[1] ^= tweak.u[1]; 137 (*ctx->block1)(scratch.c, scratch.c, ctx->key1); 138 scratch.u[0] ^= tweak.u[0]; 139 scratch.u[1] ^= tweak.u[1]; 140 memcpy(out - 16, scratch.c, 16); 141 } else { 142 union { 143 u64 u[2]; 144 u8 c[16]; 145 } tweak1; 146 147#if BYTE_ORDER == LITTLE_ENDIAN 148 unsigned int carry, res; 149 150 res = 0x87 & (((int)tweak.d[3]) >> 31); 151 carry = (unsigned int)(tweak.u[0] >> 63); 152 tweak1.u[0] = (tweak.u[0] << 1) ^ res; 153 tweak1.u[1] = (tweak.u[1] << 1)|carry; 154#else 155 size_t c; 156 157 for (c = 0, i = 0; i < 16; ++i) { 158 /*+ substitutes for |, because c is 1 bit */ 159 c += ((size_t)tweak.c[i]) << 1; 160 tweak1.c[i] = (u8)c; 161 c = c >> 8; 162 } 163 tweak1.c[0] ^= (u8)(0x87 & (0 - c)); 164#endif 165#ifdef __STRICT_ALIGNMENT 166 memcpy(scratch.c, inp, 16); 167 scratch.u[0] ^= tweak1.u[0]; 168 scratch.u[1] ^= tweak1.u[1]; 169#else 170 scratch.u[0] = ((u64 *)inp)[0] ^ tweak1.u[0]; 171 scratch.u[1] = ((u64 *)inp)[1] ^ tweak1.u[1]; 172#endif 173 (*ctx->block1)(scratch.c, scratch.c, ctx->key1); 174 scratch.u[0] ^= tweak1.u[0]; 175 scratch.u[1] ^= tweak1.u[1]; 176 177 for (i = 0; i < len; ++i) { 178 u8 ch = inp[16 + i]; 179 out[16 + i] = scratch.c[i]; 180 scratch.c[i] = ch; 181 } 182 scratch.u[0] ^= tweak.u[0]; 183 scratch.u[1] ^= tweak.u[1]; 184 (*ctx->block1)(scratch.c, scratch.c, ctx->key1); 185#ifdef __STRICT_ALIGNMENT 186 scratch.u[0] ^= tweak.u[0]; 187 scratch.u[1] ^= tweak.u[1]; 188 memcpy(out, scratch.c, 16); 189#else 190 ((u64 *)out)[0] = scratch.u[0] ^ tweak.u[0]; 191 ((u64 *)out)[1] = scratch.u[1] ^ tweak.u[1]; 192#endif 193 } 194 195 return 0; 196} 197LCRYPTO_ALIAS(CRYPTO_xts128_encrypt); 198