1221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* ====================================================================
2221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
3221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
4221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Redistribution and use in source and binary forms, with or without
5221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * modification, are permitted provided that the following conditions
6221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * are met:
7221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
8221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 1. Redistributions of source code must retain the above copyright
9221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    notice, this list of conditions and the following disclaimer.
10221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
11221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 2. Redistributions in binary form must reproduce the above copyright
12221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    notice, this list of conditions and the following disclaimer in
13221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    the documentation and/or other materials provided with the
14221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    distribution.
15221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
16221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 3. All advertising materials mentioning features or use of this
17221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    software must display the following acknowledgment:
18221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
19221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
21221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    endorse or promote products derived from this software without
23221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    prior written permission. For written permission, please contact
24221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    openssl-core@openssl.org.
25221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
26221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 5. Products derived from this software may not be called "OpenSSL"
27221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    nor may "OpenSSL" appear in their names without prior written
28221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    permission of the OpenSSL Project.
29221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
30221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 6. Redistributions of any form whatsoever must retain the following
31221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    acknowledgment:
32221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
33221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
35221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * OF THE POSSIBILITY OF SUCH DAMAGE.
47221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ====================================================================
48221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
49221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */
50221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
51392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <openssl/crypto.h>
52392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include "modes_lcl.h"
53221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <string.h>
54221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
55221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#ifndef MODES_DEBUG
56221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom# ifndef NDEBUG
57221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#  define NDEBUG
58221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom# endif
59221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
60221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <assert.h>
61221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
62392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef STRICT_ALIGNMENT
63221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#  define STRICT_ALIGNMENT 0
64221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
65221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
66221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromvoid CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,
67221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			size_t len, const void *key,
68221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			unsigned char ivec[16], block128_f block)
69221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom{
70221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	size_t n;
71221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *iv = ivec;
72221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
73221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	assert(in && out && key && ivec);
74221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
75221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if !defined(OPENSSL_SMALL_FOOTPRINT)
76221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (STRICT_ALIGNMENT &&
77221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	    ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) {
78221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		while (len>=16) {
79221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			for(n=0; n<16; ++n)
80221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				out[n] = in[n] ^ iv[n];
81221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			(*block)(out, out, key);
82221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			iv = out;
83221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			len -= 16;
84221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			in  += 16;
85221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			out += 16;
86221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
87221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	} else {
88221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		while (len>=16) {
89221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			for(n=0; n<16; n+=sizeof(size_t))
90221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				*(size_t*)(out+n) =
91221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				*(size_t*)(in+n) ^ *(size_t*)(iv+n);
92221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			(*block)(out, out, key);
93221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			iv = out;
94221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			len -= 16;
95221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			in  += 16;
96221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			out += 16;
97221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
98221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
99221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
100221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	while (len) {
101221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		for(n=0; n<16 && n<len; ++n)
102221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			out[n] = in[n] ^ iv[n];
103221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		for(; n<16; ++n)
104221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			out[n] = iv[n];
105221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		(*block)(out, out, key);
106221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		iv = out;
107221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (len<=16) break;
108221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		len -= 16;
109221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		in  += 16;
110221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		out += 16;
111221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
112221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	memcpy(ivec,iv,16);
113221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
114221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
115221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromvoid CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
116221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			size_t len, const void *key,
117221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			unsigned char ivec[16], block128_f block)
118221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom{
119221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	size_t n;
120ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root	union { size_t t[16/sizeof(size_t)]; unsigned char c[16]; } tmp;
121221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
122221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	assert(in && out && key && ivec);
123221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
124221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if !defined(OPENSSL_SMALL_FOOTPRINT)
125221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (in != out) {
126221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		const unsigned char *iv = ivec;
127221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
128221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (STRICT_ALIGNMENT &&
129221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		    ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) {
130221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			while (len>=16) {
131221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				(*block)(in, out, key);
132221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				for(n=0; n<16; ++n)
133221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					out[n] ^= iv[n];
134221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				iv = in;
135221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				len -= 16;
136221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				in  += 16;
137221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				out += 16;
138221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
139221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
140ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		else  if (16%sizeof(size_t) == 0) { /* always true */
141221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			while (len>=16) {
142ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				size_t *out_t=(size_t *)out, *iv_t=(size_t *)iv;
143ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
144221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				(*block)(in, out, key);
145ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				for(n=0; n<16/sizeof(size_t); n++)
146ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root					out_t[n] ^= iv_t[n];
147221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				iv = in;
148221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				len -= 16;
149221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				in  += 16;
150221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				out += 16;
151221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
152221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
153221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memcpy(ivec,iv,16);
154221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	} else {
155221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (STRICT_ALIGNMENT &&
156221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		    ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0) {
157221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			unsigned char c;
158221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			while (len>=16) {
159221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				(*block)(in, tmp.c, key);
160221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				for(n=0; n<16; ++n) {
161221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					c = in[n];
162221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					out[n] = tmp.c[n] ^ ivec[n];
163221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					ivec[n] = c;
164221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				}
165221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				len -= 16;
166221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				in  += 16;
167221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				out += 16;
168221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
169221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
170ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		else if (16%sizeof(size_t) == 0) { /* always true */
171221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			while (len>=16) {
172ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				size_t c, *out_t=(size_t *)out, *ivec_t=(size_t *)ivec;
173ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				const size_t *in_t=(const size_t *)in;
174ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
175221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				(*block)(in, tmp.c, key);
176ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				for(n=0; n<16/sizeof(size_t); n++) {
177ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root					c = in_t[n];
178ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root					out_t[n] = tmp.t[n] ^ ivec_t[n];
179ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root					ivec_t[n] = c;
180221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				}
181221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				len -= 16;
182221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				in  += 16;
183221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				out += 16;
184221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
185221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
186221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
187221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
188221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	while (len) {
189221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		unsigned char c;
190221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		(*block)(in, tmp.c, key);
191221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		for(n=0; n<16 && n<len; ++n) {
192221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			c = in[n];
193221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			out[n] = tmp.c[n] ^ ivec[n];
194221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			ivec[n] = c;
195221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
196221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (len<=16) {
197221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			for (; n<16; ++n)
198221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				ivec[n] = in[n];
199221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			break;
200221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
201221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		len -= 16;
202221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		in  += 16;
203221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		out += 16;
204221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
205221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom}
206