Line data Source code
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 : */
50 :
51 : #include <openssl/crypto.h>
52 : #include "modes_lcl.h"
53 : #include <string.h>
54 :
55 : #ifndef MODES_DEBUG
56 : # ifndef NDEBUG
57 : # define NDEBUG
58 : # endif
59 : #endif
60 : #include <assert.h>
61 :
62 : /*
63 : * The input and output encrypted as though 128bit cfb mode is being used.
64 : * The extra state information to record how much of the 128bit block we have
65 : * used is contained in *num;
66 : */
67 0 : void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out,
68 : size_t len, const void *key,
69 : unsigned char ivec[16], int *num,
70 : int enc, block128_f block)
71 : {
72 : unsigned int n;
73 : size_t l = 0;
74 :
75 : assert(in && out && key && ivec && num);
76 :
77 0 : n = *num;
78 :
79 0 : if (enc) {
80 : #if !defined(OPENSSL_SMALL_FOOTPRINT)
81 : if (16 % sizeof(size_t) == 0) { /* always true actually */
82 : do {
83 0 : while (n && len) {
84 0 : *(out++) = ivec[n] ^= *(in++);
85 0 : --len;
86 0 : n = (n + 1) % 16;
87 : }
88 : # if defined(STRICT_ALIGNMENT)
89 : if (((size_t)in | (size_t)out | (size_t)ivec) %
90 : sizeof(size_t) != 0)
91 : break;
92 : # endif
93 0 : while (len >= 16) {
94 0 : (*block) (ivec, ivec, key);
95 0 : for (; n < 16; n += sizeof(size_t)) {
96 0 : *(size_t *)(out + n) =
97 0 : *(size_t *)(ivec + n) ^= *(size_t *)(in + n);
98 : }
99 0 : len -= 16;
100 0 : out += 16;
101 0 : in += 16;
102 : n = 0;
103 : }
104 0 : if (len) {
105 0 : (*block) (ivec, ivec, key);
106 0 : while (len--) {
107 0 : out[n] = ivec[n] ^= in[n];
108 0 : ++n;
109 : }
110 : }
111 0 : *num = n;
112 0 : return;
113 : } while (0);
114 : }
115 : /* the rest would be commonly eliminated by x86* compiler */
116 : #endif
117 : while (l < len) {
118 : if (n == 0) {
119 : (*block) (ivec, ivec, key);
120 : }
121 : out[l] = ivec[n] ^= in[l];
122 : ++l;
123 : n = (n + 1) % 16;
124 : }
125 : *num = n;
126 : } else {
127 : #if !defined(OPENSSL_SMALL_FOOTPRINT)
128 : if (16 % sizeof(size_t) == 0) { /* always true actually */
129 : do {
130 0 : while (n && len) {
131 : unsigned char c;
132 0 : *(out++) = ivec[n] ^ (c = *(in++));
133 0 : ivec[n] = c;
134 0 : --len;
135 0 : n = (n + 1) % 16;
136 : }
137 : # if defined(STRICT_ALIGNMENT)
138 : if (((size_t)in | (size_t)out | (size_t)ivec) %
139 : sizeof(size_t) != 0)
140 : break;
141 : # endif
142 0 : while (len >= 16) {
143 0 : (*block) (ivec, ivec, key);
144 0 : for (; n < 16; n += sizeof(size_t)) {
145 0 : size_t t = *(size_t *)(in + n);
146 0 : *(size_t *)(out + n) = *(size_t *)(ivec + n) ^ t;
147 0 : *(size_t *)(ivec + n) = t;
148 : }
149 0 : len -= 16;
150 0 : out += 16;
151 0 : in += 16;
152 : n = 0;
153 : }
154 0 : if (len) {
155 0 : (*block) (ivec, ivec, key);
156 0 : while (len--) {
157 : unsigned char c;
158 0 : out[n] = ivec[n] ^ (c = in[n]);
159 0 : ivec[n] = c;
160 0 : ++n;
161 : }
162 : }
163 0 : *num = n;
164 0 : return;
165 : } while (0);
166 : }
167 : /* the rest would be commonly eliminated by x86* compiler */
168 : #endif
169 : while (l < len) {
170 : unsigned char c;
171 : if (n == 0) {
172 : (*block) (ivec, ivec, key);
173 : }
174 : out[l] = ivec[n] ^ (c = in[l]);
175 : ivec[n] = c;
176 : ++l;
177 : n = (n + 1) % 16;
178 : }
179 : *num = n;
180 : }
181 : }
182 :
183 : /*
184 : * This expects a single block of size nbits for both in and out. Note that
185 : * it corrupts any extra bits in the last byte of out
186 : */
187 0 : static void cfbr_encrypt_block(const unsigned char *in, unsigned char *out,
188 : int nbits, const void *key,
189 : unsigned char ivec[16], int enc,
190 : block128_f block)
191 : {
192 : int n, rem, num;
193 : unsigned char ovec[16 * 2 + 1]; /* +1 because we dererefence (but don't
194 : * use) one byte off the end */
195 :
196 0 : if (nbits <= 0 || nbits > 128)
197 0 : return;
198 :
199 : /* fill in the first half of the new IV with the current IV */
200 : memcpy(ovec, ivec, 16);
201 : /* construct the new IV */
202 0 : (*block) (ivec, ivec, key);
203 0 : num = (nbits + 7) / 8;
204 0 : if (enc) /* encrypt the input */
205 0 : for (n = 0; n < num; ++n)
206 0 : out[n] = (ovec[16 + n] = in[n] ^ ivec[n]);
207 : else /* decrypt the input */
208 0 : for (n = 0; n < num; ++n)
209 0 : out[n] = (ovec[16 + n] = in[n]) ^ ivec[n];
210 : /* shift ovec left... */
211 0 : rem = nbits % 8;
212 0 : num = nbits / 8;
213 0 : if (rem == 0)
214 0 : memcpy(ivec, ovec + num, 16);
215 : else
216 0 : for (n = 0; n < 16; ++n)
217 0 : ivec[n] = ovec[n + num] << rem | ovec[n + num + 1] >> (8 - rem);
218 :
219 : /* it is not necessary to cleanse ovec, since the IV is not secret */
220 : }
221 :
222 : /* N.B. This expects the input to be packed, MS bit first */
223 0 : void CRYPTO_cfb128_1_encrypt(const unsigned char *in, unsigned char *out,
224 : size_t bits, const void *key,
225 : unsigned char ivec[16], int *num,
226 : int enc, block128_f block)
227 : {
228 : size_t n;
229 : unsigned char c[1], d[1];
230 :
231 : assert(in && out && key && ivec && num);
232 : assert(*num == 0);
233 :
234 0 : for (n = 0; n < bits; ++n) {
235 0 : c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
236 0 : cfbr_encrypt_block(c, d, 1, key, ivec, enc, block);
237 0 : out[n / 8] = (out[n / 8] & ~(1 << (unsigned int)(7 - n % 8))) |
238 0 : ((d[0] & 0x80) >> (unsigned int)(n % 8));
239 : }
240 0 : }
241 :
242 0 : void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out,
243 : size_t length, const void *key,
244 : unsigned char ivec[16], int *num,
245 : int enc, block128_f block)
246 : {
247 : size_t n;
248 :
249 : assert(in && out && key && ivec && num);
250 : assert(*num == 0);
251 :
252 0 : for (n = 0; n < length; ++n)
253 0 : cfbr_encrypt_block(&in[n], &out[n], 8, key, ivec, enc, block);
254 0 : }
|