]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/crypto/camellia/cmll_cbc.c
Fix multiple OpenSSL vulnerabilities.
[FreeBSD/releng/9.3.git] / crypto / openssl / crypto / camellia / cmll_cbc.c
1 /* crypto/camellia/camellia_cbc.c -*- mode:C; c-file-style: "eay" -*- */
2 /* ====================================================================
3  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    openssl-core@openssl.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  */
51
52 #ifndef CAMELLIA_DEBUG
53 # ifndef NDEBUG
54 #  define NDEBUG
55 # endif
56 #endif
57 #include <assert.h>
58 #include <stdio.h>
59 #include <string.h>
60
61 #include <openssl/camellia.h>
62 #include "cmll_locl.h"
63
64 void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out,
65                           const unsigned long length, const CAMELLIA_KEY *key,
66                           unsigned char *ivec, const int enc)
67 {
68
69     unsigned long n;
70     unsigned long len = length;
71     const unsigned char *iv = ivec;
72     union {
73         u32 t32[CAMELLIA_BLOCK_SIZE / sizeof(u32)];
74         u8 t8[CAMELLIA_BLOCK_SIZE];
75     } tmp;
76     const union {
77         long one;
78         char little;
79     } camellia_endian = {
80         1
81     };
82
83     assert(in && out && key && ivec);
84     assert((CAMELLIA_ENCRYPT == enc) || (CAMELLIA_DECRYPT == enc));
85
86     if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(u32) == 0) {
87         if (CAMELLIA_ENCRYPT == enc) {
88             while (len >= CAMELLIA_BLOCK_SIZE) {
89                 XOR4WORD2((u32 *)out, (u32 *)in, (u32 *)iv);
90                 if (camellia_endian.little)
91                     SWAP4WORD((u32 *)out);
92                 key->enc(key->rd_key, (u32 *)out);
93                 if (camellia_endian.little)
94                     SWAP4WORD((u32 *)out);
95                 iv = out;
96                 len -= CAMELLIA_BLOCK_SIZE;
97                 in += CAMELLIA_BLOCK_SIZE;
98                 out += CAMELLIA_BLOCK_SIZE;
99             }
100             if (len) {
101                 for (n = 0; n < len; ++n)
102                     out[n] = in[n] ^ iv[n];
103                 for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n)
104                     out[n] = iv[n];
105                 if (camellia_endian.little)
106                     SWAP4WORD((u32 *)out);
107                 key->enc(key->rd_key, (u32 *)out);
108                 if (camellia_endian.little)
109                     SWAP4WORD((u32 *)out);
110                 iv = out;
111             }
112             memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
113         } else if (in != out) {
114             while (len >= CAMELLIA_BLOCK_SIZE) {
115                 memcpy(out, in, CAMELLIA_BLOCK_SIZE);
116                 if (camellia_endian.little)
117                     SWAP4WORD((u32 *)out);
118                 key->dec(key->rd_key, (u32 *)out);
119                 if (camellia_endian.little)
120                     SWAP4WORD((u32 *)out);
121                 XOR4WORD((u32 *)out, (u32 *)iv);
122                 iv = in;
123                 len -= CAMELLIA_BLOCK_SIZE;
124                 in += CAMELLIA_BLOCK_SIZE;
125                 out += CAMELLIA_BLOCK_SIZE;
126             }
127             if (len) {
128                 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
129                 if (camellia_endian.little)
130                     SWAP4WORD(tmp.t32);
131                 key->dec(key->rd_key, tmp.t32);
132                 if (camellia_endian.little)
133                     SWAP4WORD(tmp.t32);
134                 for (n = 0; n < len; ++n)
135                     out[n] = tmp.t8[n] ^ iv[n];
136                 iv = in;
137             }
138             memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
139         } else {                /* in == out */
140
141             while (len >= CAMELLIA_BLOCK_SIZE) {
142                 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
143                 if (camellia_endian.little)
144                     SWAP4WORD((u32 *)out);
145                 key->dec(key->rd_key, (u32 *)out);
146                 if (camellia_endian.little)
147                     SWAP4WORD((u32 *)out);
148                 XOR4WORD((u32 *)out, (u32 *)ivec);
149                 memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE);
150                 len -= CAMELLIA_BLOCK_SIZE;
151                 in += CAMELLIA_BLOCK_SIZE;
152                 out += CAMELLIA_BLOCK_SIZE;
153             }
154             if (len) {
155                 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
156                 if (camellia_endian.little)
157                     SWAP4WORD((u32 *)out);
158                 key->dec(key->rd_key, (u32 *)out);
159                 if (camellia_endian.little)
160                     SWAP4WORD((u32 *)out);
161                 for (n = 0; n < len; ++n)
162                     out[n] ^= ivec[n];
163                 for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n)
164                     out[n] = tmp.t8[n];
165                 memcpy(ivec, tmp.t8, CAMELLIA_BLOCK_SIZE);
166             }
167         }
168     } else {                    /* no aligned */
169
170         if (CAMELLIA_ENCRYPT == enc) {
171             while (len >= CAMELLIA_BLOCK_SIZE) {
172                 for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n)
173                     tmp.t8[n] = in[n] ^ iv[n];
174                 if (camellia_endian.little)
175                     SWAP4WORD(tmp.t32);
176                 key->enc(key->rd_key, tmp.t32);
177                 if (camellia_endian.little)
178                     SWAP4WORD(tmp.t32);
179                 memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
180                 iv = out;
181                 len -= CAMELLIA_BLOCK_SIZE;
182                 in += CAMELLIA_BLOCK_SIZE;
183                 out += CAMELLIA_BLOCK_SIZE;
184             }
185             if (len) {
186                 for (n = 0; n < len; ++n)
187                     tmp.t8[n] = in[n] ^ iv[n];
188                 for (n = len; n < CAMELLIA_BLOCK_SIZE; ++n)
189                     tmp.t8[n] = iv[n];
190                 if (camellia_endian.little)
191                     SWAP4WORD(tmp.t32);
192                 key->enc(key->rd_key, tmp.t32);
193                 if (camellia_endian.little)
194                     SWAP4WORD(tmp.t32);
195                 memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
196                 iv = out;
197             }
198             memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
199         } else if (in != out) {
200             while (len >= CAMELLIA_BLOCK_SIZE) {
201                 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
202                 if (camellia_endian.little)
203                     SWAP4WORD(tmp.t32);
204                 key->dec(key->rd_key, tmp.t32);
205                 if (camellia_endian.little)
206                     SWAP4WORD(tmp.t32);
207                 for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n)
208                     out[n] = tmp.t8[n] ^ iv[n];
209                 iv = in;
210                 len -= CAMELLIA_BLOCK_SIZE;
211                 in += CAMELLIA_BLOCK_SIZE;
212                 out += CAMELLIA_BLOCK_SIZE;
213             }
214             if (len) {
215                 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
216                 if (camellia_endian.little)
217                     SWAP4WORD(tmp.t32);
218                 key->dec(key->rd_key, tmp.t32);
219                 if (camellia_endian.little)
220                     SWAP4WORD(tmp.t32);
221                 for (n = 0; n < len; ++n)
222                     out[n] = tmp.t8[n] ^ iv[n];
223                 iv = in;
224             }
225             memcpy(ivec, iv, CAMELLIA_BLOCK_SIZE);
226         } else {
227             while (len >= CAMELLIA_BLOCK_SIZE) {
228                 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
229                 if (camellia_endian.little)
230                     SWAP4WORD(tmp.t32);
231                 key->dec(key->rd_key, tmp.t32);
232                 if (camellia_endian.little)
233                     SWAP4WORD(tmp.t32);
234                 for (n = 0; n < CAMELLIA_BLOCK_SIZE; ++n)
235                     tmp.t8[n] ^= ivec[n];
236                 memcpy(ivec, in, CAMELLIA_BLOCK_SIZE);
237                 memcpy(out, tmp.t8, CAMELLIA_BLOCK_SIZE);
238                 len -= CAMELLIA_BLOCK_SIZE;
239                 in += CAMELLIA_BLOCK_SIZE;
240                 out += CAMELLIA_BLOCK_SIZE;
241             }
242             if (len) {
243                 memcpy(tmp.t8, in, CAMELLIA_BLOCK_SIZE);
244                 if (camellia_endian.little)
245                     SWAP4WORD(tmp.t32);
246                 key->dec(key->rd_key, tmp.t32);
247                 if (camellia_endian.little)
248                     SWAP4WORD(tmp.t32);
249                 for (n = 0; n < len; ++n)
250                     tmp.t8[n] ^= ivec[n];
251                 memcpy(ivec, in, CAMELLIA_BLOCK_SIZE);
252                 memcpy(out, tmp.t8, len);
253             }
254         }
255     }
256 }