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