1238384Sjkim/* ==================================================================== 2238384Sjkim * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 3238384Sjkim * 4238384Sjkim * Redistribution and use in source and binary forms, with or without 5238384Sjkim * modification, are permitted provided that the following conditions 6238384Sjkim * are met: 7238384Sjkim * 8238384Sjkim * 1. Redistributions of source code must retain the above copyright 9238384Sjkim * notice, this list of conditions and the following disclaimer. 10238384Sjkim * 11238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 12238384Sjkim * notice, this list of conditions and the following disclaimer in 13238384Sjkim * the documentation and/or other materials provided with the 14238384Sjkim * distribution. 15238384Sjkim * 16238384Sjkim * 3. All advertising materials mentioning features or use of this 17238384Sjkim * software must display the following acknowledgment: 18238384Sjkim * "This product includes software developed by the OpenSSL Project 19238384Sjkim * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 20238384Sjkim * 21238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22238384Sjkim * endorse or promote products derived from this software without 23238384Sjkim * prior written permission. For written permission, please contact 24238384Sjkim * openssl-core@openssl.org. 25238384Sjkim * 26238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 27238384Sjkim * nor may "OpenSSL" appear in their names without prior written 28238384Sjkim * permission of the OpenSSL Project. 29238384Sjkim * 30238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 31238384Sjkim * acknowledgment: 32238384Sjkim * "This product includes software developed by the OpenSSL Project 33238384Sjkim * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 34238384Sjkim * 35238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 47238384Sjkim * ==================================================================== 48238384Sjkim * 49238384Sjkim */ 50238384Sjkim 51238384Sjkim#include <openssl/crypto.h> 52238384Sjkim#include "modes_lcl.h" 53238384Sjkim#include <string.h> 54238384Sjkim 55238384Sjkim#ifndef MODES_DEBUG 56238384Sjkim# ifndef NDEBUG 57238384Sjkim# define NDEBUG 58238384Sjkim# endif 59238384Sjkim#endif 60238384Sjkim#include <assert.h> 61238384Sjkim 62238384Sjkim#ifndef STRICT_ALIGNMENT 63238384Sjkim# define STRICT_ALIGNMENT 0 64238384Sjkim#endif 65238384Sjkim 66238384Sjkimvoid CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out, 67238384Sjkim size_t len, const void *key, 68238384Sjkim unsigned char ivec[16], block128_f block) 69238384Sjkim{ 70238384Sjkim size_t n; 71238384Sjkim const unsigned char *iv = ivec; 72238384Sjkim 73238384Sjkim assert(in && out && key && ivec); 74238384Sjkim 75238384Sjkim#if !defined(OPENSSL_SMALL_FOOTPRINT) 76238384Sjkim if (STRICT_ALIGNMENT && 77238384Sjkim ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) { 78238384Sjkim while (len>=16) { 79238384Sjkim for(n=0; n<16; ++n) 80238384Sjkim out[n] = in[n] ^ iv[n]; 81238384Sjkim (*block)(out, out, key); 82238384Sjkim iv = out; 83238384Sjkim len -= 16; 84238384Sjkim in += 16; 85238384Sjkim out += 16; 86238384Sjkim } 87238384Sjkim } else { 88238384Sjkim while (len>=16) { 89238384Sjkim for(n=0; n<16; n+=sizeof(size_t)) 90238384Sjkim *(size_t*)(out+n) = 91238384Sjkim *(size_t*)(in+n) ^ *(size_t*)(iv+n); 92238384Sjkim (*block)(out, out, key); 93238384Sjkim iv = out; 94238384Sjkim len -= 16; 95238384Sjkim in += 16; 96238384Sjkim out += 16; 97238384Sjkim } 98238384Sjkim } 99238384Sjkim#endif 100238384Sjkim while (len) { 101238384Sjkim for(n=0; n<16 && n<len; ++n) 102238384Sjkim out[n] = in[n] ^ iv[n]; 103238384Sjkim for(; n<16; ++n) 104238384Sjkim out[n] = iv[n]; 105238384Sjkim (*block)(out, out, key); 106238384Sjkim iv = out; 107238384Sjkim if (len<=16) break; 108238384Sjkim len -= 16; 109238384Sjkim in += 16; 110238384Sjkim out += 16; 111238384Sjkim } 112238384Sjkim memcpy(ivec,iv,16); 113238384Sjkim} 114238384Sjkim 115238384Sjkimvoid CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, 116238384Sjkim size_t len, const void *key, 117238384Sjkim unsigned char ivec[16], block128_f block) 118238384Sjkim{ 119238384Sjkim size_t n; 120279264Sdelphij union { size_t t[16/sizeof(size_t)]; unsigned char c[16]; } tmp; 121238384Sjkim 122238384Sjkim assert(in && out && key && ivec); 123238384Sjkim 124238384Sjkim#if !defined(OPENSSL_SMALL_FOOTPRINT) 125238384Sjkim if (in != out) { 126238384Sjkim const unsigned char *iv = ivec; 127238384Sjkim 128238384Sjkim if (STRICT_ALIGNMENT && 129238384Sjkim ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) { 130238384Sjkim while (len>=16) { 131238384Sjkim (*block)(in, out, key); 132238384Sjkim for(n=0; n<16; ++n) 133238384Sjkim out[n] ^= iv[n]; 134238384Sjkim iv = in; 135238384Sjkim len -= 16; 136238384Sjkim in += 16; 137238384Sjkim out += 16; 138238384Sjkim } 139238384Sjkim } 140279264Sdelphij else if (16%sizeof(size_t) == 0) { /* always true */ 141238384Sjkim while (len>=16) { 142279264Sdelphij size_t *out_t=(size_t *)out, *iv_t=(size_t *)iv; 143279264Sdelphij 144238384Sjkim (*block)(in, out, key); 145279264Sdelphij for(n=0; n<16/sizeof(size_t); n++) 146279264Sdelphij out_t[n] ^= iv_t[n]; 147238384Sjkim iv = in; 148238384Sjkim len -= 16; 149238384Sjkim in += 16; 150238384Sjkim out += 16; 151238384Sjkim } 152238384Sjkim } 153238384Sjkim memcpy(ivec,iv,16); 154238384Sjkim } else { 155238384Sjkim if (STRICT_ALIGNMENT && 156238384Sjkim ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) { 157238384Sjkim unsigned char c; 158238384Sjkim while (len>=16) { 159238384Sjkim (*block)(in, tmp.c, key); 160238384Sjkim for(n=0; n<16; ++n) { 161238384Sjkim c = in[n]; 162238384Sjkim out[n] = tmp.c[n] ^ ivec[n]; 163238384Sjkim ivec[n] = c; 164238384Sjkim } 165238384Sjkim len -= 16; 166238384Sjkim in += 16; 167238384Sjkim out += 16; 168238384Sjkim } 169238384Sjkim } 170279264Sdelphij else if (16%sizeof(size_t) == 0) { /* always true */ 171238384Sjkim while (len>=16) { 172279264Sdelphij size_t c, *out_t=(size_t *)out, *ivec_t=(size_t *)ivec; 173279264Sdelphij const size_t *in_t=(const size_t *)in; 174279264Sdelphij 175238384Sjkim (*block)(in, tmp.c, key); 176279264Sdelphij for(n=0; n<16/sizeof(size_t); n++) { 177279264Sdelphij c = in_t[n]; 178279264Sdelphij out_t[n] = tmp.t[n] ^ ivec_t[n]; 179279264Sdelphij ivec_t[n] = c; 180238384Sjkim } 181238384Sjkim len -= 16; 182238384Sjkim in += 16; 183238384Sjkim out += 16; 184238384Sjkim } 185238384Sjkim } 186238384Sjkim } 187238384Sjkim#endif 188238384Sjkim while (len) { 189238384Sjkim unsigned char c; 190238384Sjkim (*block)(in, tmp.c, key); 191238384Sjkim for(n=0; n<16 && n<len; ++n) { 192238384Sjkim c = in[n]; 193238384Sjkim out[n] = tmp.c[n] ^ ivec[n]; 194238384Sjkim ivec[n] = c; 195238384Sjkim } 196238384Sjkim if (len<=16) { 197238384Sjkim for (; n<16; ++n) 198238384Sjkim ivec[n] = in[n]; 199238384Sjkim break; 200238384Sjkim } 201238384Sjkim len -= 16; 202238384Sjkim in += 16; 203238384Sjkim out += 16; 204238384Sjkim } 205238384Sjkim} 206