1 /* ====================================================================
2 * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgment:
18 * "This product includes software developed by the OpenSSL Project
19 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20 *
21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22 * endorse or promote products derived from this software without
23 * prior written permission. For written permission, please contact
24 * openssl-core@openssl.org.
25 *
26 * 5. Products derived from this software may not be called "OpenSSL"
27 * nor may "OpenSSL" appear in their names without prior written
28 * permission of the OpenSSL Project.
29 *
30 * 6. Redistributions of any form whatsoever must retain the following
31 * acknowledgment:
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46 * OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ==================================================================== */
48
49 #include <assert.h>
50 #include <string.h>
51
52 #include "internal.h"
53
54
CRYPTO_cbc128_encrypt(const uint8_t * in,uint8_t * out,size_t len,const void * key,uint8_t ivec[16],block128_f block)55 void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
56 const void *key, uint8_t ivec[16],
57 block128_f block) {
58 size_t n;
59 const uint8_t *iv = ivec;
60
61 assert(key != NULL && ivec != NULL);
62 assert(len == 0 || (in != NULL && out != NULL));
63
64 if (STRICT_ALIGNMENT &&
65 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
66 while (len >= 16) {
67 for (n = 0; n < 16; ++n) {
68 out[n] = in[n] ^ iv[n];
69 }
70 (*block)(out, out, key);
71 iv = out;
72 len -= 16;
73 in += 16;
74 out += 16;
75 }
76 } else {
77 while (len >= 16) {
78 for (n = 0; n < 16; n += sizeof(size_t)) {
79 *(size_t *)(out + n) = *(size_t *)(in + n) ^ *(size_t *)(iv + n);
80 }
81 (*block)(out, out, key);
82 iv = out;
83 len -= 16;
84 in += 16;
85 out += 16;
86 }
87 }
88
89 while (len) {
90 for (n = 0; n < 16 && n < len; ++n) {
91 out[n] = in[n] ^ iv[n];
92 }
93 for (; n < 16; ++n) {
94 out[n] = iv[n];
95 }
96 (*block)(out, out, key);
97 iv = out;
98 if (len <= 16) {
99 break;
100 }
101 len -= 16;
102 in += 16;
103 out += 16;
104 }
105
106 OPENSSL_memcpy(ivec, iv, 16);
107 }
108
CRYPTO_cbc128_decrypt(const uint8_t * in,uint8_t * out,size_t len,const void * key,uint8_t ivec[16],block128_f block)109 void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
110 const void *key, uint8_t ivec[16],
111 block128_f block) {
112 size_t n;
113 union {
114 size_t t[16 / sizeof(size_t)];
115 uint8_t c[16];
116 } tmp;
117
118 assert(key != NULL && ivec != NULL);
119 assert(len == 0 || (in != NULL && out != NULL));
120
121 const uintptr_t inptr = (uintptr_t) in;
122 const uintptr_t outptr = (uintptr_t) out;
123 /* If |in| and |out| alias, |in| must be ahead. */
124 assert(inptr >= outptr || inptr + len <= outptr);
125
126 if ((inptr >= 32 && outptr <= inptr - 32) || inptr < outptr) {
127 /* If |out| is at least two blocks behind |in| or completely disjoint, there
128 * is no need to decrypt to a temporary block. */
129 const uint8_t *iv = ivec;
130
131 if (STRICT_ALIGNMENT &&
132 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
133 while (len >= 16) {
134 (*block)(in, out, key);
135 for (n = 0; n < 16; ++n) {
136 out[n] ^= iv[n];
137 }
138 iv = in;
139 len -= 16;
140 in += 16;
141 out += 16;
142 }
143 } else if (16 % sizeof(size_t) == 0) { /* always true */
144 while (len >= 16) {
145 size_t *out_t = (size_t *)out, *iv_t = (size_t *)iv;
146
147 (*block)(in, out, key);
148 for (n = 0; n < 16 / sizeof(size_t); n++) {
149 out_t[n] ^= iv_t[n];
150 }
151 iv = in;
152 len -= 16;
153 in += 16;
154 out += 16;
155 }
156 }
157 OPENSSL_memcpy(ivec, iv, 16);
158 } else {
159 /* |out| is less than two blocks behind |in|. Decrypting an input block
160 * directly to |out| would overwrite a ciphertext block before it is used as
161 * the next block's IV. Decrypt to a temporary block instead. */
162 if (STRICT_ALIGNMENT &&
163 ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
164 uint8_t c;
165 while (len >= 16) {
166 (*block)(in, tmp.c, key);
167 for (n = 0; n < 16; ++n) {
168 c = in[n];
169 out[n] = tmp.c[n] ^ ivec[n];
170 ivec[n] = c;
171 }
172 len -= 16;
173 in += 16;
174 out += 16;
175 }
176 } else if (16 % sizeof(size_t) == 0) { /* always true */
177 while (len >= 16) {
178 size_t c, *out_t = (size_t *)out, *ivec_t = (size_t *)ivec;
179 const size_t *in_t = (const size_t *)in;
180
181 (*block)(in, tmp.c, key);
182 for (n = 0; n < 16 / sizeof(size_t); n++) {
183 c = in_t[n];
184 out_t[n] = tmp.t[n] ^ ivec_t[n];
185 ivec_t[n] = c;
186 }
187 len -= 16;
188 in += 16;
189 out += 16;
190 }
191 }
192 }
193
194 while (len) {
195 uint8_t c;
196 (*block)(in, tmp.c, key);
197 for (n = 0; n < 16 && n < len; ++n) {
198 c = in[n];
199 out[n] = tmp.c[n] ^ ivec[n];
200 ivec[n] = c;
201 }
202 if (len <= 16) {
203 for (; n < 16; ++n) {
204 ivec[n] = in[n];
205 }
206 break;
207 }
208 len -= 16;
209 in += 16;
210 out += 16;
211 }
212 }
213