Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: patches/nss-arcfour.patch

Issue 12226071: Fix RC4 reads/writes outside array bounds. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Add a patch file and update README.chromium Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mozilla/security/nss/lib/freebl/arcfour.c ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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. */
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/freebl/arcfour.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698