security/nss/lib/freebl/md5.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #ifdef FREEBL_NO_DEPEND
michael@0 6 #include "stubs.h"
michael@0 7 #endif
michael@0 8
michael@0 9 #include "prerr.h"
michael@0 10 #include "secerr.h"
michael@0 11
michael@0 12 #include "prtypes.h"
michael@0 13 #include "prlong.h"
michael@0 14
michael@0 15 #include "blapi.h"
michael@0 16
michael@0 17 #define MD5_HASH_LEN 16
michael@0 18 #define MD5_BUFFER_SIZE 64
michael@0 19 #define MD5_END_BUFFER (MD5_BUFFER_SIZE - 8)
michael@0 20
michael@0 21 #define CV0_1 0x67452301
michael@0 22 #define CV0_2 0xefcdab89
michael@0 23 #define CV0_3 0x98badcfe
michael@0 24 #define CV0_4 0x10325476
michael@0 25
michael@0 26 #define T1_0 0xd76aa478
michael@0 27 #define T1_1 0xe8c7b756
michael@0 28 #define T1_2 0x242070db
michael@0 29 #define T1_3 0xc1bdceee
michael@0 30 #define T1_4 0xf57c0faf
michael@0 31 #define T1_5 0x4787c62a
michael@0 32 #define T1_6 0xa8304613
michael@0 33 #define T1_7 0xfd469501
michael@0 34 #define T1_8 0x698098d8
michael@0 35 #define T1_9 0x8b44f7af
michael@0 36 #define T1_10 0xffff5bb1
michael@0 37 #define T1_11 0x895cd7be
michael@0 38 #define T1_12 0x6b901122
michael@0 39 #define T1_13 0xfd987193
michael@0 40 #define T1_14 0xa679438e
michael@0 41 #define T1_15 0x49b40821
michael@0 42
michael@0 43 #define T2_0 0xf61e2562
michael@0 44 #define T2_1 0xc040b340
michael@0 45 #define T2_2 0x265e5a51
michael@0 46 #define T2_3 0xe9b6c7aa
michael@0 47 #define T2_4 0xd62f105d
michael@0 48 #define T2_5 0x02441453
michael@0 49 #define T2_6 0xd8a1e681
michael@0 50 #define T2_7 0xe7d3fbc8
michael@0 51 #define T2_8 0x21e1cde6
michael@0 52 #define T2_9 0xc33707d6
michael@0 53 #define T2_10 0xf4d50d87
michael@0 54 #define T2_11 0x455a14ed
michael@0 55 #define T2_12 0xa9e3e905
michael@0 56 #define T2_13 0xfcefa3f8
michael@0 57 #define T2_14 0x676f02d9
michael@0 58 #define T2_15 0x8d2a4c8a
michael@0 59
michael@0 60 #define T3_0 0xfffa3942
michael@0 61 #define T3_1 0x8771f681
michael@0 62 #define T3_2 0x6d9d6122
michael@0 63 #define T3_3 0xfde5380c
michael@0 64 #define T3_4 0xa4beea44
michael@0 65 #define T3_5 0x4bdecfa9
michael@0 66 #define T3_6 0xf6bb4b60
michael@0 67 #define T3_7 0xbebfbc70
michael@0 68 #define T3_8 0x289b7ec6
michael@0 69 #define T3_9 0xeaa127fa
michael@0 70 #define T3_10 0xd4ef3085
michael@0 71 #define T3_11 0x04881d05
michael@0 72 #define T3_12 0xd9d4d039
michael@0 73 #define T3_13 0xe6db99e5
michael@0 74 #define T3_14 0x1fa27cf8
michael@0 75 #define T3_15 0xc4ac5665
michael@0 76
michael@0 77 #define T4_0 0xf4292244
michael@0 78 #define T4_1 0x432aff97
michael@0 79 #define T4_2 0xab9423a7
michael@0 80 #define T4_3 0xfc93a039
michael@0 81 #define T4_4 0x655b59c3
michael@0 82 #define T4_5 0x8f0ccc92
michael@0 83 #define T4_6 0xffeff47d
michael@0 84 #define T4_7 0x85845dd1
michael@0 85 #define T4_8 0x6fa87e4f
michael@0 86 #define T4_9 0xfe2ce6e0
michael@0 87 #define T4_10 0xa3014314
michael@0 88 #define T4_11 0x4e0811a1
michael@0 89 #define T4_12 0xf7537e82
michael@0 90 #define T4_13 0xbd3af235
michael@0 91 #define T4_14 0x2ad7d2bb
michael@0 92 #define T4_15 0xeb86d391
michael@0 93
michael@0 94 #define R1B0 0
michael@0 95 #define R1B1 1
michael@0 96 #define R1B2 2
michael@0 97 #define R1B3 3
michael@0 98 #define R1B4 4
michael@0 99 #define R1B5 5
michael@0 100 #define R1B6 6
michael@0 101 #define R1B7 7
michael@0 102 #define R1B8 8
michael@0 103 #define R1B9 9
michael@0 104 #define R1B10 10
michael@0 105 #define R1B11 11
michael@0 106 #define R1B12 12
michael@0 107 #define R1B13 13
michael@0 108 #define R1B14 14
michael@0 109 #define R1B15 15
michael@0 110
michael@0 111 #define R2B0 1
michael@0 112 #define R2B1 6
michael@0 113 #define R2B2 11
michael@0 114 #define R2B3 0
michael@0 115 #define R2B4 5
michael@0 116 #define R2B5 10
michael@0 117 #define R2B6 15
michael@0 118 #define R2B7 4
michael@0 119 #define R2B8 9
michael@0 120 #define R2B9 14
michael@0 121 #define R2B10 3
michael@0 122 #define R2B11 8
michael@0 123 #define R2B12 13
michael@0 124 #define R2B13 2
michael@0 125 #define R2B14 7
michael@0 126 #define R2B15 12
michael@0 127
michael@0 128 #define R3B0 5
michael@0 129 #define R3B1 8
michael@0 130 #define R3B2 11
michael@0 131 #define R3B3 14
michael@0 132 #define R3B4 1
michael@0 133 #define R3B5 4
michael@0 134 #define R3B6 7
michael@0 135 #define R3B7 10
michael@0 136 #define R3B8 13
michael@0 137 #define R3B9 0
michael@0 138 #define R3B10 3
michael@0 139 #define R3B11 6
michael@0 140 #define R3B12 9
michael@0 141 #define R3B13 12
michael@0 142 #define R3B14 15
michael@0 143 #define R3B15 2
michael@0 144
michael@0 145 #define R4B0 0
michael@0 146 #define R4B1 7
michael@0 147 #define R4B2 14
michael@0 148 #define R4B3 5
michael@0 149 #define R4B4 12
michael@0 150 #define R4B5 3
michael@0 151 #define R4B6 10
michael@0 152 #define R4B7 1
michael@0 153 #define R4B8 8
michael@0 154 #define R4B9 15
michael@0 155 #define R4B10 6
michael@0 156 #define R4B11 13
michael@0 157 #define R4B12 4
michael@0 158 #define R4B13 11
michael@0 159 #define R4B14 2
michael@0 160 #define R4B15 9
michael@0 161
michael@0 162 #define S1_0 7
michael@0 163 #define S1_1 12
michael@0 164 #define S1_2 17
michael@0 165 #define S1_3 22
michael@0 166
michael@0 167 #define S2_0 5
michael@0 168 #define S2_1 9
michael@0 169 #define S2_2 14
michael@0 170 #define S2_3 20
michael@0 171
michael@0 172 #define S3_0 4
michael@0 173 #define S3_1 11
michael@0 174 #define S3_2 16
michael@0 175 #define S3_3 23
michael@0 176
michael@0 177 #define S4_0 6
michael@0 178 #define S4_1 10
michael@0 179 #define S4_2 15
michael@0 180 #define S4_3 21
michael@0 181
michael@0 182 struct MD5ContextStr {
michael@0 183 PRUint32 lsbInput;
michael@0 184 PRUint32 msbInput;
michael@0 185 PRUint32 cv[4];
michael@0 186 union {
michael@0 187 PRUint8 b[64];
michael@0 188 PRUint32 w[16];
michael@0 189 } u;
michael@0 190 };
michael@0 191
michael@0 192 #define inBuf u.b
michael@0 193
michael@0 194 SECStatus
michael@0 195 MD5_Hash(unsigned char *dest, const char *src)
michael@0 196 {
michael@0 197 return MD5_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
michael@0 198 }
michael@0 199
michael@0 200 SECStatus
michael@0 201 MD5_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
michael@0 202 {
michael@0 203 unsigned int len;
michael@0 204 MD5Context cx;
michael@0 205
michael@0 206 MD5_Begin(&cx);
michael@0 207 MD5_Update(&cx, src, src_length);
michael@0 208 MD5_End(&cx, dest, &len, MD5_HASH_LEN);
michael@0 209 memset(&cx, 0, sizeof cx);
michael@0 210 return SECSuccess;
michael@0 211 }
michael@0 212
michael@0 213 MD5Context *
michael@0 214 MD5_NewContext(void)
michael@0 215 {
michael@0 216 /* no need to ZAlloc, MD5_Begin will init the context */
michael@0 217 MD5Context *cx = (MD5Context *)PORT_Alloc(sizeof(MD5Context));
michael@0 218 if (cx == NULL) {
michael@0 219 PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
michael@0 220 return NULL;
michael@0 221 }
michael@0 222 return cx;
michael@0 223 }
michael@0 224
michael@0 225 void
michael@0 226 MD5_DestroyContext(MD5Context *cx, PRBool freeit)
michael@0 227 {
michael@0 228 memset(cx, 0, sizeof *cx);
michael@0 229 if (freeit) {
michael@0 230 PORT_Free(cx);
michael@0 231 }
michael@0 232 }
michael@0 233
michael@0 234 void
michael@0 235 MD5_Begin(MD5Context *cx)
michael@0 236 {
michael@0 237 cx->lsbInput = 0;
michael@0 238 cx->msbInput = 0;
michael@0 239 /* memset(cx->inBuf, 0, sizeof(cx->inBuf)); */
michael@0 240 cx->cv[0] = CV0_1;
michael@0 241 cx->cv[1] = CV0_2;
michael@0 242 cx->cv[2] = CV0_3;
michael@0 243 cx->cv[3] = CV0_4;
michael@0 244 }
michael@0 245
michael@0 246 #define cls(i32, s) (tmp = i32, tmp << s | tmp >> (32 - s))
michael@0 247
michael@0 248 #if defined(SOLARIS) || defined(HPUX)
michael@0 249 #define addto64(sumhigh, sumlow, addend) \
michael@0 250 sumlow += addend; sumhigh += (sumlow < addend);
michael@0 251 #else
michael@0 252 #define addto64(sumhigh, sumlow, addend) \
michael@0 253 sumlow += addend; if (sumlow < addend) ++sumhigh;
michael@0 254 #endif
michael@0 255
michael@0 256 #define MASK 0x00ff00ff
michael@0 257 #ifdef IS_LITTLE_ENDIAN
michael@0 258 #define lendian(i32) \
michael@0 259 (i32)
michael@0 260 #else
michael@0 261 #define lendian(i32) \
michael@0 262 (tmp = i32 >> 16 | i32 << 16, (tmp & MASK) << 8 | tmp >> 8 & MASK)
michael@0 263 #endif
michael@0 264
michael@0 265 #ifndef IS_LITTLE_ENDIAN
michael@0 266
michael@0 267 #define lebytes(b4) \
michael@0 268 ((b4)[3] << 24 | (b4)[2] << 16 | (b4)[1] << 8 | (b4)[0])
michael@0 269
michael@0 270 static void
michael@0 271 md5_prep_state_le(MD5Context *cx)
michael@0 272 {
michael@0 273 PRUint32 tmp;
michael@0 274 cx->u.w[0] = lendian(cx->u.w[0]);
michael@0 275 cx->u.w[1] = lendian(cx->u.w[1]);
michael@0 276 cx->u.w[2] = lendian(cx->u.w[2]);
michael@0 277 cx->u.w[3] = lendian(cx->u.w[3]);
michael@0 278 cx->u.w[4] = lendian(cx->u.w[4]);
michael@0 279 cx->u.w[5] = lendian(cx->u.w[5]);
michael@0 280 cx->u.w[6] = lendian(cx->u.w[6]);
michael@0 281 cx->u.w[7] = lendian(cx->u.w[7]);
michael@0 282 cx->u.w[8] = lendian(cx->u.w[8]);
michael@0 283 cx->u.w[9] = lendian(cx->u.w[9]);
michael@0 284 cx->u.w[10] = lendian(cx->u.w[10]);
michael@0 285 cx->u.w[11] = lendian(cx->u.w[11]);
michael@0 286 cx->u.w[12] = lendian(cx->u.w[12]);
michael@0 287 cx->u.w[13] = lendian(cx->u.w[13]);
michael@0 288 cx->u.w[14] = lendian(cx->u.w[14]);
michael@0 289 cx->u.w[15] = lendian(cx->u.w[15]);
michael@0 290 }
michael@0 291
michael@0 292 static void
michael@0 293 md5_prep_buffer_le(MD5Context *cx, const PRUint8 *beBuf)
michael@0 294 {
michael@0 295 cx->u.w[0] = lebytes(&beBuf[0]);
michael@0 296 cx->u.w[1] = lebytes(&beBuf[4]);
michael@0 297 cx->u.w[2] = lebytes(&beBuf[8]);
michael@0 298 cx->u.w[3] = lebytes(&beBuf[12]);
michael@0 299 cx->u.w[4] = lebytes(&beBuf[16]);
michael@0 300 cx->u.w[5] = lebytes(&beBuf[20]);
michael@0 301 cx->u.w[6] = lebytes(&beBuf[24]);
michael@0 302 cx->u.w[7] = lebytes(&beBuf[28]);
michael@0 303 cx->u.w[8] = lebytes(&beBuf[32]);
michael@0 304 cx->u.w[9] = lebytes(&beBuf[36]);
michael@0 305 cx->u.w[10] = lebytes(&beBuf[40]);
michael@0 306 cx->u.w[11] = lebytes(&beBuf[44]);
michael@0 307 cx->u.w[12] = lebytes(&beBuf[48]);
michael@0 308 cx->u.w[13] = lebytes(&beBuf[52]);
michael@0 309 cx->u.w[14] = lebytes(&beBuf[56]);
michael@0 310 cx->u.w[15] = lebytes(&beBuf[60]);
michael@0 311 }
michael@0 312 #endif
michael@0 313
michael@0 314
michael@0 315 #define F(X, Y, Z) \
michael@0 316 ((X & Y) | ((~X) & Z))
michael@0 317
michael@0 318 #define G(X, Y, Z) \
michael@0 319 ((X & Z) | (Y & (~Z)))
michael@0 320
michael@0 321 #define H(X, Y, Z) \
michael@0 322 (X ^ Y ^ Z)
michael@0 323
michael@0 324 #define I(X, Y, Z) \
michael@0 325 (Y ^ (X | (~Z)))
michael@0 326
michael@0 327 #define FF(a, b, c, d, bufint, s, ti) \
michael@0 328 a = b + cls(a + F(b, c, d) + bufint + ti, s)
michael@0 329
michael@0 330 #define GG(a, b, c, d, bufint, s, ti) \
michael@0 331 a = b + cls(a + G(b, c, d) + bufint + ti, s)
michael@0 332
michael@0 333 #define HH(a, b, c, d, bufint, s, ti) \
michael@0 334 a = b + cls(a + H(b, c, d) + bufint + ti, s)
michael@0 335
michael@0 336 #define II(a, b, c, d, bufint, s, ti) \
michael@0 337 a = b + cls(a + I(b, c, d) + bufint + ti, s)
michael@0 338
michael@0 339 static void
michael@0 340 md5_compress(MD5Context *cx, const PRUint32 *wBuf)
michael@0 341 {
michael@0 342 PRUint32 a, b, c, d;
michael@0 343 PRUint32 tmp;
michael@0 344 a = cx->cv[0];
michael@0 345 b = cx->cv[1];
michael@0 346 c = cx->cv[2];
michael@0 347 d = cx->cv[3];
michael@0 348 FF(a, b, c, d, wBuf[R1B0 ], S1_0, T1_0);
michael@0 349 FF(d, a, b, c, wBuf[R1B1 ], S1_1, T1_1);
michael@0 350 FF(c, d, a, b, wBuf[R1B2 ], S1_2, T1_2);
michael@0 351 FF(b, c, d, a, wBuf[R1B3 ], S1_3, T1_3);
michael@0 352 FF(a, b, c, d, wBuf[R1B4 ], S1_0, T1_4);
michael@0 353 FF(d, a, b, c, wBuf[R1B5 ], S1_1, T1_5);
michael@0 354 FF(c, d, a, b, wBuf[R1B6 ], S1_2, T1_6);
michael@0 355 FF(b, c, d, a, wBuf[R1B7 ], S1_3, T1_7);
michael@0 356 FF(a, b, c, d, wBuf[R1B8 ], S1_0, T1_8);
michael@0 357 FF(d, a, b, c, wBuf[R1B9 ], S1_1, T1_9);
michael@0 358 FF(c, d, a, b, wBuf[R1B10], S1_2, T1_10);
michael@0 359 FF(b, c, d, a, wBuf[R1B11], S1_3, T1_11);
michael@0 360 FF(a, b, c, d, wBuf[R1B12], S1_0, T1_12);
michael@0 361 FF(d, a, b, c, wBuf[R1B13], S1_1, T1_13);
michael@0 362 FF(c, d, a, b, wBuf[R1B14], S1_2, T1_14);
michael@0 363 FF(b, c, d, a, wBuf[R1B15], S1_3, T1_15);
michael@0 364 GG(a, b, c, d, wBuf[R2B0 ], S2_0, T2_0);
michael@0 365 GG(d, a, b, c, wBuf[R2B1 ], S2_1, T2_1);
michael@0 366 GG(c, d, a, b, wBuf[R2B2 ], S2_2, T2_2);
michael@0 367 GG(b, c, d, a, wBuf[R2B3 ], S2_3, T2_3);
michael@0 368 GG(a, b, c, d, wBuf[R2B4 ], S2_0, T2_4);
michael@0 369 GG(d, a, b, c, wBuf[R2B5 ], S2_1, T2_5);
michael@0 370 GG(c, d, a, b, wBuf[R2B6 ], S2_2, T2_6);
michael@0 371 GG(b, c, d, a, wBuf[R2B7 ], S2_3, T2_7);
michael@0 372 GG(a, b, c, d, wBuf[R2B8 ], S2_0, T2_8);
michael@0 373 GG(d, a, b, c, wBuf[R2B9 ], S2_1, T2_9);
michael@0 374 GG(c, d, a, b, wBuf[R2B10], S2_2, T2_10);
michael@0 375 GG(b, c, d, a, wBuf[R2B11], S2_3, T2_11);
michael@0 376 GG(a, b, c, d, wBuf[R2B12], S2_0, T2_12);
michael@0 377 GG(d, a, b, c, wBuf[R2B13], S2_1, T2_13);
michael@0 378 GG(c, d, a, b, wBuf[R2B14], S2_2, T2_14);
michael@0 379 GG(b, c, d, a, wBuf[R2B15], S2_3, T2_15);
michael@0 380 HH(a, b, c, d, wBuf[R3B0 ], S3_0, T3_0);
michael@0 381 HH(d, a, b, c, wBuf[R3B1 ], S3_1, T3_1);
michael@0 382 HH(c, d, a, b, wBuf[R3B2 ], S3_2, T3_2);
michael@0 383 HH(b, c, d, a, wBuf[R3B3 ], S3_3, T3_3);
michael@0 384 HH(a, b, c, d, wBuf[R3B4 ], S3_0, T3_4);
michael@0 385 HH(d, a, b, c, wBuf[R3B5 ], S3_1, T3_5);
michael@0 386 HH(c, d, a, b, wBuf[R3B6 ], S3_2, T3_6);
michael@0 387 HH(b, c, d, a, wBuf[R3B7 ], S3_3, T3_7);
michael@0 388 HH(a, b, c, d, wBuf[R3B8 ], S3_0, T3_8);
michael@0 389 HH(d, a, b, c, wBuf[R3B9 ], S3_1, T3_9);
michael@0 390 HH(c, d, a, b, wBuf[R3B10], S3_2, T3_10);
michael@0 391 HH(b, c, d, a, wBuf[R3B11], S3_3, T3_11);
michael@0 392 HH(a, b, c, d, wBuf[R3B12], S3_0, T3_12);
michael@0 393 HH(d, a, b, c, wBuf[R3B13], S3_1, T3_13);
michael@0 394 HH(c, d, a, b, wBuf[R3B14], S3_2, T3_14);
michael@0 395 HH(b, c, d, a, wBuf[R3B15], S3_3, T3_15);
michael@0 396 II(a, b, c, d, wBuf[R4B0 ], S4_0, T4_0);
michael@0 397 II(d, a, b, c, wBuf[R4B1 ], S4_1, T4_1);
michael@0 398 II(c, d, a, b, wBuf[R4B2 ], S4_2, T4_2);
michael@0 399 II(b, c, d, a, wBuf[R4B3 ], S4_3, T4_3);
michael@0 400 II(a, b, c, d, wBuf[R4B4 ], S4_0, T4_4);
michael@0 401 II(d, a, b, c, wBuf[R4B5 ], S4_1, T4_5);
michael@0 402 II(c, d, a, b, wBuf[R4B6 ], S4_2, T4_6);
michael@0 403 II(b, c, d, a, wBuf[R4B7 ], S4_3, T4_7);
michael@0 404 II(a, b, c, d, wBuf[R4B8 ], S4_0, T4_8);
michael@0 405 II(d, a, b, c, wBuf[R4B9 ], S4_1, T4_9);
michael@0 406 II(c, d, a, b, wBuf[R4B10], S4_2, T4_10);
michael@0 407 II(b, c, d, a, wBuf[R4B11], S4_3, T4_11);
michael@0 408 II(a, b, c, d, wBuf[R4B12], S4_0, T4_12);
michael@0 409 II(d, a, b, c, wBuf[R4B13], S4_1, T4_13);
michael@0 410 II(c, d, a, b, wBuf[R4B14], S4_2, T4_14);
michael@0 411 II(b, c, d, a, wBuf[R4B15], S4_3, T4_15);
michael@0 412 cx->cv[0] += a;
michael@0 413 cx->cv[1] += b;
michael@0 414 cx->cv[2] += c;
michael@0 415 cx->cv[3] += d;
michael@0 416 }
michael@0 417
michael@0 418 void
michael@0 419 MD5_Update(MD5Context *cx, const unsigned char *input, unsigned int inputLen)
michael@0 420 {
michael@0 421 PRUint32 bytesToConsume;
michael@0 422 PRUint32 inBufIndex = cx->lsbInput & 63;
michael@0 423 const PRUint32 *wBuf;
michael@0 424
michael@0 425 /* Add the number of input bytes to the 64-bit input counter. */
michael@0 426 addto64(cx->msbInput, cx->lsbInput, inputLen);
michael@0 427 if (inBufIndex) {
michael@0 428 /* There is already data in the buffer. Fill with input. */
michael@0 429 bytesToConsume = PR_MIN(inputLen, MD5_BUFFER_SIZE - inBufIndex);
michael@0 430 memcpy(&cx->inBuf[inBufIndex], input, bytesToConsume);
michael@0 431 if (inBufIndex + bytesToConsume >= MD5_BUFFER_SIZE) {
michael@0 432 /* The buffer is filled. Run the compression function. */
michael@0 433 #ifndef IS_LITTLE_ENDIAN
michael@0 434 md5_prep_state_le(cx);
michael@0 435 #endif
michael@0 436 md5_compress(cx, cx->u.w);
michael@0 437 }
michael@0 438 /* Remaining input. */
michael@0 439 inputLen -= bytesToConsume;
michael@0 440 input += bytesToConsume;
michael@0 441 }
michael@0 442
michael@0 443 /* Iterate over 64-byte chunks of the message. */
michael@0 444 while (inputLen >= MD5_BUFFER_SIZE) {
michael@0 445 #ifdef IS_LITTLE_ENDIAN
michael@0 446 #ifdef NSS_X86_OR_X64
michael@0 447 /* x86 can handle arithmetic on non-word-aligned buffers */
michael@0 448 wBuf = (PRUint32 *)input;
michael@0 449 #else
michael@0 450 if ((ptrdiff_t)input & 0x3) {
michael@0 451 /* buffer not aligned, copy it to force alignment */
michael@0 452 memcpy(cx->inBuf, input, MD5_BUFFER_SIZE);
michael@0 453 wBuf = cx->u.w;
michael@0 454 } else {
michael@0 455 /* buffer is aligned */
michael@0 456 wBuf = (PRUint32 *)input;
michael@0 457 }
michael@0 458 #endif
michael@0 459 #else
michael@0 460 md5_prep_buffer_le(cx, input);
michael@0 461 wBuf = cx->u.w;
michael@0 462 #endif
michael@0 463 md5_compress(cx, wBuf);
michael@0 464 inputLen -= MD5_BUFFER_SIZE;
michael@0 465 input += MD5_BUFFER_SIZE;
michael@0 466 }
michael@0 467
michael@0 468 /* Tail of message (message bytes mod 64). */
michael@0 469 if (inputLen)
michael@0 470 memcpy(cx->inBuf, input, inputLen);
michael@0 471 }
michael@0 472
michael@0 473 static const unsigned char padbytes[] = {
michael@0 474 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
michael@0 485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
michael@0 486 };
michael@0 487
michael@0 488 void
michael@0 489 MD5_End(MD5Context *cx, unsigned char *digest,
michael@0 490 unsigned int *digestLen, unsigned int maxDigestLen)
michael@0 491 {
michael@0 492 #ifndef IS_LITTLE_ENDIAN
michael@0 493 PRUint32 tmp;
michael@0 494 #endif
michael@0 495 PRUint32 lowInput, highInput;
michael@0 496 PRUint32 inBufIndex = cx->lsbInput & 63;
michael@0 497
michael@0 498 if (maxDigestLen < MD5_HASH_LEN) {
michael@0 499 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 500 return;
michael@0 501 }
michael@0 502
michael@0 503 /* Copy out the length of bits input before padding. */
michael@0 504 lowInput = cx->lsbInput;
michael@0 505 highInput = (cx->msbInput << 3) | (lowInput >> 29);
michael@0 506 lowInput <<= 3;
michael@0 507
michael@0 508 if (inBufIndex < MD5_END_BUFFER) {
michael@0 509 MD5_Update(cx, padbytes, MD5_END_BUFFER - inBufIndex);
michael@0 510 } else {
michael@0 511 MD5_Update(cx, padbytes,
michael@0 512 MD5_END_BUFFER + MD5_BUFFER_SIZE - inBufIndex);
michael@0 513 }
michael@0 514
michael@0 515 /* Store the number of bytes input (before padding) in final 64 bits. */
michael@0 516 cx->u.w[14] = lendian(lowInput);
michael@0 517 cx->u.w[15] = lendian(highInput);
michael@0 518
michael@0 519 /* Final call to compress. */
michael@0 520 #ifndef IS_LITTLE_ENDIAN
michael@0 521 md5_prep_state_le(cx);
michael@0 522 #endif
michael@0 523 md5_compress(cx, cx->u.w);
michael@0 524
michael@0 525 /* Copy the resulting values out of the chain variables into return buf. */
michael@0 526 if (digestLen)
michael@0 527 *digestLen = MD5_HASH_LEN;
michael@0 528 #ifndef IS_LITTLE_ENDIAN
michael@0 529 cx->cv[0] = lendian(cx->cv[0]);
michael@0 530 cx->cv[1] = lendian(cx->cv[1]);
michael@0 531 cx->cv[2] = lendian(cx->cv[2]);
michael@0 532 cx->cv[3] = lendian(cx->cv[3]);
michael@0 533 #endif
michael@0 534 memcpy(digest, cx->cv, MD5_HASH_LEN);
michael@0 535 }
michael@0 536
michael@0 537 void
michael@0 538 MD5_EndRaw(MD5Context *cx, unsigned char *digest,
michael@0 539 unsigned int *digestLen, unsigned int maxDigestLen)
michael@0 540 {
michael@0 541 #ifndef IS_LITTLE_ENDIAN
michael@0 542 PRUint32 tmp;
michael@0 543 #endif
michael@0 544 PRUint32 cv[4];
michael@0 545
michael@0 546 if (maxDigestLen < MD5_HASH_LEN) {
michael@0 547 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 548 return;
michael@0 549 }
michael@0 550
michael@0 551 memcpy(cv, cx->cv, sizeof(cv));
michael@0 552 #ifndef IS_LITTLE_ENDIAN
michael@0 553 cv[0] = lendian(cv[0]);
michael@0 554 cv[1] = lendian(cv[1]);
michael@0 555 cv[2] = lendian(cv[2]);
michael@0 556 cv[3] = lendian(cv[3]);
michael@0 557 #endif
michael@0 558 memcpy(digest, cv, MD5_HASH_LEN);
michael@0 559 if (digestLen)
michael@0 560 *digestLen = MD5_HASH_LEN;
michael@0 561 }
michael@0 562
michael@0 563 unsigned int
michael@0 564 MD5_FlattenSize(MD5Context *cx)
michael@0 565 {
michael@0 566 return sizeof(*cx);
michael@0 567 }
michael@0 568
michael@0 569 SECStatus
michael@0 570 MD5_Flatten(MD5Context *cx, unsigned char *space)
michael@0 571 {
michael@0 572 memcpy(space, cx, sizeof(*cx));
michael@0 573 return SECSuccess;
michael@0 574 }
michael@0 575
michael@0 576 MD5Context *
michael@0 577 MD5_Resurrect(unsigned char *space, void *arg)
michael@0 578 {
michael@0 579 MD5Context *cx = MD5_NewContext();
michael@0 580 if (cx)
michael@0 581 memcpy(cx, space, sizeof(*cx));
michael@0 582 return cx;
michael@0 583 }
michael@0 584
michael@0 585 void MD5_Clone(MD5Context *dest, MD5Context *src)
michael@0 586 {
michael@0 587 memcpy(dest, src, sizeof *dest);
michael@0 588 }
michael@0 589
michael@0 590 void
michael@0 591 MD5_TraceState(MD5Context *cx)
michael@0 592 {
michael@0 593 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
michael@0 594 }

mercurial