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