11558Srgrimes/* ====================================================================
21558Srgrimes * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
31558Srgrimes *
41558Srgrimes * Redistribution and use in source and binary forms, with or without
51558Srgrimes * modification, are permitted provided that the following conditions
61558Srgrimes * are met:
71558Srgrimes *
81558Srgrimes * 1. Redistributions of source code must retain the above copyright
91558Srgrimes *    notice, this list of conditions and the following disclaimer.
101558Srgrimes *
111558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
121558Srgrimes *    notice, this list of conditions and the following disclaimer in
131558Srgrimes *    the documentation and/or other materials provided with the
141558Srgrimes *    distribution.
151558Srgrimes *
161558Srgrimes * 3. All advertising materials mentioning features or use of this
171558Srgrimes *    software must display the following acknowledgment:
181558Srgrimes *    "This product includes software developed by the OpenSSL Project
191558Srgrimes *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
201558Srgrimes *
211558Srgrimes * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
221558Srgrimes *    endorse or promote products derived from this software without
231558Srgrimes *    prior written permission. For written permission, please contact
241558Srgrimes *    openssl-core@openssl.org.
251558Srgrimes *
261558Srgrimes * 5. Products derived from this software may not be called "OpenSSL"
271558Srgrimes *    nor may "OpenSSL" appear in their names without prior written
281558Srgrimes *    permission of the OpenSSL Project.
291558Srgrimes *
301558Srgrimes * 6. Redistributions of any form whatsoever must retain the following
311558Srgrimes *    acknowledgment:
321558Srgrimes *    "This product includes software developed by the OpenSSL Project
331558Srgrimes *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
341558Srgrimes *
3537909Scharnier * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
361558Srgrimes * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
371558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
381558Srgrimes * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
391558Srgrimes * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
401558Srgrimes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4137909Scharnier * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
421558Srgrimes * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4337909Scharnier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4437909Scharnier * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4547095Sluoqi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
461558Srgrimes * OF THE POSSIBILITY OF SUCH DAMAGE.
471558Srgrimes * ====================================================================
481558Srgrimes *
491558Srgrimes */
501558Srgrimes
511558Srgrimes#include <openssl/crypto.h>
5247095Sluoqi#include "modes_lcl.h"
531558Srgrimes#include <string.h>
541599Srgrimes
551618Srgrimes#ifndef MODES_DEBUG
5612806Speter# ifndef NDEBUG
571599Srgrimes#  define NDEBUG
581558Srgrimes# endif
591558Srgrimes#endif
601558Srgrimes#include <assert.h>
611558Srgrimes
621558Srgrimes#ifndef STRICT_ALIGNMENT
631558Srgrimes#  define STRICT_ALIGNMENT 0
641558Srgrimes#endif
651558Srgrimes
661558Srgrimesvoid CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,
6717717Swosch			size_t len, const void *key,
681558Srgrimes			unsigned char ivec[16], block128_f block)
6944688Sgallatin{
7044688Sgallatin	size_t n;
7144688Sgallatin	const unsigned char *iv = ivec;
7244688Sgallatin
7344688Sgallatin	assert(in && out && key && ivec);
741558Srgrimes
7544688Sgallatin#if !defined(OPENSSL_SMALL_FOOTPRINT)
761558Srgrimes	if (STRICT_ALIGNMENT &&
771558Srgrimes	    ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) {
7847095Sluoqi		while (len>=16) {
791558Srgrimes			for(n=0; n<16; ++n)
8047095Sluoqi				out[n] = in[n] ^ iv[n];
8134963Sphk			(*block)(out, out, key);
8247095Sluoqi			iv = out;
831558Srgrimes			len -= 16;
8447095Sluoqi			in  += 16;
851558Srgrimes			out += 16;
8647095Sluoqi		}
871558Srgrimes	} else {
8847095Sluoqi		while (len>=16) {
891558Srgrimes			for(n=0; n<16; n+=sizeof(size_t))
901558Srgrimes				*(size_t*)(out+n) =
911558Srgrimes				*(size_t*)(in+n) ^ *(size_t*)(iv+n);
9247095Sluoqi			(*block)(out, out, key);
931558Srgrimes			iv = out;
941558Srgrimes			len -= 16;
951558Srgrimes			in  += 16;
9647095Sluoqi			out += 16;
9747095Sluoqi		}
981558Srgrimes	}
991558Srgrimes#endif
1001558Srgrimes	while (len) {
1011558Srgrimes		for(n=0; n<16 && n<len; ++n)
1021558Srgrimes			out[n] = in[n] ^ iv[n];
1031558Srgrimes		for(; n<16; ++n)
1041558Srgrimes			out[n] = iv[n];
1051558Srgrimes		(*block)(out, out, key);
1061558Srgrimes		iv = out;
1071558Srgrimes		if (len<=16) break;
1081558Srgrimes		len -= 16;
1091558Srgrimes		in  += 16;
1101856Sdg		out += 16;
1111558Srgrimes	}
1121558Srgrimes	memcpy(ivec,iv,16);
1131558Srgrimes}
1141558Srgrimes
1151558Srgrimesvoid CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
1161558Srgrimes			size_t len, const void *key,
1171558Srgrimes			unsigned char ivec[16], block128_f block)
1181558Srgrimes{
1191558Srgrimes	size_t n;
1201558Srgrimes	union { size_t t[16/sizeof(size_t)]; unsigned char c[16]; } tmp;
1211558Srgrimes
1221558Srgrimes	assert(in && out && key && ivec);
1231558Srgrimes
1241558Srgrimes#if !defined(OPENSSL_SMALL_FOOTPRINT)
1251558Srgrimes	if (in != out) {
1261558Srgrimes		const unsigned char *iv = ivec;
1271558Srgrimes
1281558Srgrimes		if (STRICT_ALIGNMENT &&
12918916Sjoerg		    ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) {
1301558Srgrimes			while (len>=16) {
1311558Srgrimes				(*block)(in, out, key);
1321558Srgrimes				for(n=0; n<16; ++n)
1333041Swollman					out[n] ^= iv[n];
1341558Srgrimes				iv = in;
1351558Srgrimes				len -= 16;
1361558Srgrimes				in  += 16;
1371558Srgrimes				out += 16;
1381558Srgrimes			}
1391558Srgrimes		}
1401558Srgrimes		else  if (16%sizeof(size_t) == 0) { /* always true */
1411558Srgrimes			while (len>=16) {
1421558Srgrimes				size_t *out_t=(size_t *)out, *iv_t=(size_t *)iv;
1431558Srgrimes
1441558Srgrimes				(*block)(in, out, key);
1451558Srgrimes				for(n=0; n<16/sizeof(size_t); n++)
1461558Srgrimes					out_t[n] ^= iv_t[n];
1471558Srgrimes				iv = in;
1481558Srgrimes				len -= 16;
14924359Simp				in  += 16;
1501558Srgrimes				out += 16;
1511558Srgrimes			}
1521558Srgrimes		}
1531558Srgrimes		memcpy(ivec,iv,16);
1541558Srgrimes	} else {
1551558Srgrimes		if (STRICT_ALIGNMENT &&
1561558Srgrimes		    ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) {
1571558Srgrimes			unsigned char c;
1581558Srgrimes			while (len>=16) {
1591558Srgrimes				(*block)(in, tmp.c, key);
1601558Srgrimes				for(n=0; n<16; ++n) {
1611558Srgrimes					c = in[n];
1621856Sdg					out[n] = tmp.c[n] ^ ivec[n];
1631558Srgrimes					ivec[n] = c;
1641558Srgrimes				}
1651558Srgrimes				len -= 16;
1661558Srgrimes				in  += 16;
1671558Srgrimes				out += 16;
1681558Srgrimes			}
1691558Srgrimes		}
1701558Srgrimes		else if (16%sizeof(size_t) == 0) { /* always true */
1711558Srgrimes			while (len>=16) {
1721558Srgrimes				size_t c, *out_t=(size_t *)out, *ivec_t=(size_t *)ivec;
1731558Srgrimes				const size_t *in_t=(const size_t *)in;
1741558Srgrimes
1751558Srgrimes				(*block)(in, tmp.c, key);
1761558Srgrimes				for(n=0; n<16/sizeof(size_t); n++) {
1771558Srgrimes					c = in_t[n];
1781558Srgrimes					out_t[n] = tmp.t[n] ^ ivec_t[n];
1791558Srgrimes					ivec_t[n] = c;
1801856Sdg				}
1811558Srgrimes				len -= 16;
1821558Srgrimes				in  += 16;
1831558Srgrimes				out += 16;
1841558Srgrimes			}
1851558Srgrimes		}
1861558Srgrimes	}
1871558Srgrimes#endif
1881558Srgrimes	while (len) {
1891558Srgrimes		unsigned char c;
1901558Srgrimes		(*block)(in, tmp.c, key);
1911558Srgrimes		for(n=0; n<16 && n<len; ++n) {
1921558Srgrimes			c = in[n];
1931558Srgrimes			out[n] = tmp.c[n] ^ ivec[n];
1941558Srgrimes			ivec[n] = c;
1951558Srgrimes		}
1961558Srgrimes		if (len<=16) {
1971558Srgrimes			for (; n<16; ++n)
1981558Srgrimes				ivec[n] = in[n];
1991558Srgrimes			break;
20018914Sfenner		}
20118914Sfenner		len -= 16;
2021558Srgrimes		in  += 16;
2031558Srgrimes		out += 16;
2041558Srgrimes	}
2051558Srgrimes}
2061558Srgrimes