OLD | NEW |
| (Empty) |
1 Index: mozilla/security/nss/lib/freebl/arcfour.c | |
2 =================================================================== | |
3 --- mozilla/security/nss/lib/freebl/arcfour.c (revision 181529) | |
4 +++ mozilla/security/nss/lib/freebl/arcfour.c (working copy) | |
5 @@ -4,8 +4,6 @@ | |
6 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
8 | |
9 -/* See NOTES ON UMRs, Unititialized Memory Reads, below. */ | |
10 - | |
11 #ifdef FREEBL_NO_DEPEND | |
12 #include "stubs.h" | |
13 #endif | |
14 @@ -18,7 +16,7 @@ | |
15 | |
16 /* Architecture-dependent defines */ | |
17 | |
18 -#if defined(SOLARIS) || defined(HPUX) || defined(i386) || defined(IRIX) || \ | |
19 +#if defined(SOLARIS) || defined(HPUX) || defined(NSS_X86) || \ | |
20 defined(_WIN64) | |
21 /* Convert the byte-stream to a word-stream */ | |
22 #define CONVERT_TO_WORDS | |
23 @@ -119,7 +117,7 @@ | |
24 const unsigned char * unused1, int unused2, | |
25 unsigned int unused3, unsigned int unused4) | |
26 { | |
27 - int i; | |
28 + unsigned int i; | |
29 PRUint8 j, tmp; | |
30 PRUint8 K[256]; | |
31 PRUint8 *L; | |
32 @@ -127,7 +125,7 @@ | |
33 /* verify the key length. */ | |
34 PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE); | |
35 if (len == 0 || len >= ARCFOUR_STATE_SIZE) { | |
36 - PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
37 + PORT_SetError(SEC_ERROR_BAD_KEY); | |
38 return SECFailure; | |
39 } | |
40 if (cx == NULL) { | |
41 @@ -215,7 +213,7 @@ | |
42 unsigned int index; | |
43 PORT_Assert(maxOutputLen >= inputLen); | |
44 if (maxOutputLen < inputLen) { | |
45 - PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
46 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); | |
47 return SECFailure; | |
48 } | |
49 for (index=0; index < inputLen; index++) { | |
50 @@ -248,7 +246,7 @@ | |
51 int index; | |
52 PORT_Assert(maxOutputLen >= inputLen); | |
53 if (maxOutputLen < inputLen) { | |
54 - PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
55 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); | |
56 return SECFailure; | |
57 } | |
58 for (index = inputLen / 8; index-- > 0; input += 8, output += 8) { | |
59 @@ -349,40 +347,26 @@ | |
60 #define LSH << | |
61 #endif | |
62 | |
63 +#ifdef IS_LITTLE_ENDIAN | |
64 +#define LEFTMOST_BYTE_SHIFT 0 | |
65 +#define NEXT_BYTE_SHIFT(shift) shift + 8 | |
66 +#else | |
67 +#define LEFTMOST_BYTE_SHIFT 8*(WORDSIZE - 1) | |
68 +#define NEXT_BYTE_SHIFT(shift) shift - 8 | |
69 +#endif | |
70 + | |
71 #ifdef CONVERT_TO_WORDS | |
72 -/* NOTE about UMRs, Uninitialized Memory Reads. | |
73 - * | |
74 - * This code reads all input data a WORD at a time, rather than byte at | |
75 - * a time, and writes all output data a WORD at a time. Shifting and | |
76 - * masking is used to remove unwanted data and realign bytes when | |
77 - * needed. The first and last words of output are read, modified, and | |
78 - * written when needed to preserve any unchanged bytes. This is a huge | |
79 - * win on machines with high memory latency. | |
80 - * | |
81 - * However, when the input and output buffers do not begin and end on WORD | |
82 - * boundaries, and the WORDS in memory that contain the first and last | |
83 - * bytes of those buffers contain uninitialized data, then this code will | |
84 - * read those uninitialized bytes, causing a UMR error to be reported by | |
85 - * some tools. | |
86 - * | |
87 - * These UMRs are NOT a problem, NOT errors, and do NOT need to be "fixed". | |
88 - * | |
89 - * All the words read and written contain at least one byte that is | |
90 - * part of the input data or output data. No words are read or written | |
91 - * that do not contain data that is part of the buffer. Therefore, | |
92 - * these UMRs cannot cause page faults or other problems unless the | |
93 - * buffers have been assigned to improper addresses that would cause | |
94 - * page faults with or without UMRs. | |
95 - */ | |
96 static SECStatus | |
97 rc4_wordconv(RC4Context *cx, unsigned char *output, | |
98 unsigned int *outputLen, unsigned int maxOutputLen, | |
99 const unsigned char *input, unsigned int inputLen) | |
100 { | |
101 - ptrdiff_t inOffset = (ptrdiff_t)input % WORDSIZE; | |
102 - ptrdiff_t outOffset = (ptrdiff_t)output % WORDSIZE; | |
103 - register WORD streamWord, mask; | |
104 - register WORD *pInWord, *pOutWord; | |
105 + PR_STATIC_ASSERT(sizeof(PRUword) == sizeof(ptrdiff_t)); | |
106 + unsigned int inOffset = (PRUword)input % WORDSIZE; | |
107 + unsigned int outOffset = (PRUword)output % WORDSIZE; | |
108 + register WORD streamWord; | |
109 + register const WORD *pInWord; | |
110 + register WORD *pOutWord; | |
111 register WORD inWord, nextInWord; | |
112 PRUint8 t; | |
113 register Stype tmpSi, tmpSj; | |
114 @@ -390,11 +374,13 @@ | |
115 register PRUint8 tmpj = cx->j; | |
116 unsigned int byteCount; | |
117 unsigned int bufShift, invBufShift; | |
118 - int i; | |
119 + unsigned int i; | |
120 + const unsigned char *finalIn; | |
121 + unsigned char *finalOut; | |
122 | |
123 PORT_Assert(maxOutputLen >= inputLen); | |
124 if (maxOutputLen < inputLen) { | |
125 - PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
126 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); | |
127 return SECFailure; | |
128 } | |
129 if (inputLen < 2*WORDSIZE) { | |
130 @@ -402,7 +388,8 @@ | |
131 return rc4_no_opt(cx, output, outputLen, maxOutputLen, input, in
putLen); | |
132 } | |
133 *outputLen = inputLen; | |
134 - pInWord = (WORD *)(input - inOffset); | |
135 + pInWord = (const WORD *)(input - inOffset); | |
136 + pOutWord = (WORD *)(output - outOffset); | |
137 if (inOffset < outOffset) { | |
138 bufShift = 8*(outOffset - inOffset); | |
139 invBufShift = 8*WORDSIZE - bufShift; | |
140 @@ -419,52 +406,42 @@ | |
141 /* least one partial word of input should ALWAYS be loaded. */ | |
142 /*****************************************************************/ | |
143 if (outOffset) { | |
144 - /* Generate input and stream words aligned relative to the | |
145 - * partial output buffer. | |
146 - */ | |
147 byteCount = WORDSIZE - outOffset; | |
148 - pOutWord = (WORD *)(output - outOffset); | |
149 - mask = streamWord = 0; | |
150 -#ifdef IS_LITTLE_ENDIAN | |
151 - for (i = WORDSIZE - byteCount; i < WORDSIZE; i++) { | |
152 -#else | |
153 - for (i = byteCount - 1; i >= 0; --i) { | |
154 -#endif | |
155 + for (i = 0; i < byteCount; i++) { | |
156 ARCFOUR_NEXT_BYTE(); | |
157 - streamWord |= (WORD)(cx->S[t]) << 8*i; | |
158 - mask |= MASK1BYTE << 8*i; | |
159 - } /* } */ | |
160 - inWord = *pInWord++; /* UMR? see comments above. */ | |
161 + output[i] = cx->S[t] ^ input[i]; | |
162 + } | |
163 + /* Consumed byteCount bytes of input */ | |
164 + inputLen -= byteCount; | |
165 + pInWord++; | |
166 + | |
167 + /* move to next word of output */ | |
168 + pOutWord++; | |
169 + | |
170 /* If buffers are relatively misaligned, shift the bytes in inWo
rd | |
171 * to be aligned to the output buffer. | |
172 */ | |
173 - nextInWord = 0; | |
174 if (inOffset < outOffset) { | |
175 - /* Have more bytes than needed, shift remainder into nex
tInWord */ | |
176 - nextInWord = inWord LSH 8*(inOffset + byteCount); | |
177 - inWord = inWord RSH bufShift; | |
178 + /* The first input word (which may be partial) has more
bytes | |
179 + * than needed. Copy the remainder to inWord. | |
180 + */ | |
181 + unsigned int shift = LEFTMOST_BYTE_SHIFT; | |
182 + inWord = 0; | |
183 + for (i = 0; i < outOffset - inOffset; i++) { | |
184 + inWord |= (WORD)input[byteCount + i] << shift; | |
185 + shift = NEXT_BYTE_SHIFT(shift); | |
186 + } | |
187 } else if (inOffset > outOffset) { | |
188 - /* Didn't get enough bytes from current input word, load
another | |
189 - * word and then shift remainder into nextInWord. | |
190 + /* Consumed some bytes in the second input word. Copy t
he | |
191 + * remainder to inWord. | |
192 */ | |
193 - nextInWord = *pInWord++; | |
194 - inWord = (inWord LSH invBufShift) | | |
195 - (nextInWord RSH bufShift); | |
196 - nextInWord = nextInWord LSH invBufShift; | |
197 + inWord = *pInWord++; | |
198 + inWord = inWord LSH invBufShift; | |
199 + } else { | |
200 + inWord = 0; | |
201 } | |
202 - /* Store output of first partial word */ | |
203 - *pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask)
; | |
204 - /* UMR? See comments above. */ | |
205 - | |
206 - /* Consumed byteCount bytes of input */ | |
207 - inputLen -= byteCount; | |
208 - /* move to next word of output */ | |
209 - pOutWord++; | |
210 - /* inWord has been consumed, but there may be bytes in nextInWor
d */ | |
211 - inWord = nextInWord; | |
212 } else { | |
213 /* output is word-aligned */ | |
214 - pOutWord = (WORD *)output; | |
215 if (inOffset) { | |
216 /* Input is not word-aligned. The first word load of in
put | |
217 * will not produce a full word of input bytes, so one w
ord | |
218 @@ -474,8 +451,13 @@ | |
219 * loop must execute at least once because the input mus
t | |
220 * be at least two words. | |
221 */ | |
222 - inWord = *pInWord++; /* UMR? see comments above. */ | |
223 - inWord = inWord LSH invBufShift; | |
224 + unsigned int shift = LEFTMOST_BYTE_SHIFT; | |
225 + inWord = 0; | |
226 + for (i = 0; i < WORDSIZE - inOffset; i++) { | |
227 + inWord |= (WORD)input[i] << shift; | |
228 + shift = NEXT_BYTE_SHIFT(shift); | |
229 + } | |
230 + pInWord++; | |
231 } else { | |
232 /* Input is word-aligned. The first word load of input | |
233 * will produce a full word of input bytes, so nothing | |
234 @@ -510,12 +492,7 @@ | |
235 cx->j = tmpj; | |
236 return SECSuccess; | |
237 } | |
238 - /* If the amount of remaining input is greater than the amount | |
239 - * bytes pulled from the current input word, need to do another | |
240 - * word load. What's left in inWord will be consumed in step 3. | |
241 - */ | |
242 - if (inputLen > WORDSIZE - inOffset) | |
243 - inWord |= *pInWord RSH bufShift; /* UMR? See above. */ | |
244 + finalIn = (const unsigned char *)pInWord - WORDSIZE + inOffset; | |
245 } else { | |
246 for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) { | |
247 inWord = *pInWord++; | |
248 @@ -527,31 +504,18 @@ | |
249 cx->i = tmpi; | |
250 cx->j = tmpj; | |
251 return SECSuccess; | |
252 - } else { | |
253 - /* A partial input word remains at the tail. Load it. | |
254 - * The relevant bytes will be consumed in step 3. | |
255 - */ | |
256 - inWord = *pInWord; /* UMR? See comments above */ | |
257 } | |
258 + finalIn = (const unsigned char *)pInWord; | |
259 } | |
260 /*****************************************************************/ | |
261 /* Step 3: */ | |
262 - /* A partial word of input remains, and it is already loaded */ | |
263 - /* into nextInWord. Shift appropriately and consume the bytes */ | |
264 - /* used in the partial word. */ | |
265 + /* Do the remaining partial word of input one byte at a time. */ | |
266 /*****************************************************************/ | |
267 - mask = streamWord = 0; | |
268 -#ifdef IS_LITTLE_ENDIAN | |
269 - for (i = 0; i < inputLen; ++i) { | |
270 -#else | |
271 - for (i = WORDSIZE - 1; i >= WORDSIZE - inputLen; --i) { | |
272 -#endif | |
273 + finalOut = (unsigned char *)pOutWord; | |
274 + for (i = 0; i < inputLen; i++) { | |
275 ARCFOUR_NEXT_BYTE(); | |
276 - streamWord |= (WORD)(cx->S[t]) << 8*i; | |
277 - mask |= MASK1BYTE << 8*i; | |
278 - } /* } */ | |
279 - /* UMR? See comments above. */ | |
280 - *pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask); | |
281 + finalOut[i] = cx->S[t] ^ finalIn[i]; | |
282 + } | |
283 cx->i = tmpi; | |
284 cx->j = tmpj; | |
285 return SECSuccess; | |
286 @@ -566,7 +530,7 @@ | |
287 { | |
288 PORT_Assert(maxOutputLen >= inputLen); | |
289 if (maxOutputLen < inputLen) { | |
290 - PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
291 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); | |
292 return SECFailure; | |
293 } | |
294 #if defined(NSS_BEVAND_ARCFOUR) | |
295 @@ -588,7 +552,7 @@ | |
296 { | |
297 PORT_Assert(maxOutputLen >= inputLen); | |
298 if (maxOutputLen < inputLen) { | |
299 - PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
300 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); | |
301 return SECFailure; | |
302 } | |
303 /* decrypt and encrypt are same operation. */ | |
OLD | NEW |