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 |