Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 | |
michael@0 | 14 | #include "blapi.h" |
michael@0 | 15 | |
michael@0 | 16 | #define MD2_DIGEST_LEN 16 |
michael@0 | 17 | #define MD2_BUFSIZE 16 |
michael@0 | 18 | #define MD2_X_SIZE 48 /* The X array, [CV | INPUT | TMP VARS] */ |
michael@0 | 19 | #define MD2_CV 0 /* index into X for chaining variables */ |
michael@0 | 20 | #define MD2_INPUT 16 /* index into X for input */ |
michael@0 | 21 | #define MD2_TMPVARS 32 /* index into X for temporary variables */ |
michael@0 | 22 | #define MD2_CHECKSUM_SIZE 16 |
michael@0 | 23 | |
michael@0 | 24 | struct MD2ContextStr { |
michael@0 | 25 | unsigned char checksum[MD2_BUFSIZE]; |
michael@0 | 26 | unsigned char X[MD2_X_SIZE]; |
michael@0 | 27 | PRUint8 unusedBuffer; |
michael@0 | 28 | }; |
michael@0 | 29 | |
michael@0 | 30 | static const PRUint8 MD2S[256] = { |
michael@0 | 31 | 0051, 0056, 0103, 0311, 0242, 0330, 0174, 0001, |
michael@0 | 32 | 0075, 0066, 0124, 0241, 0354, 0360, 0006, 0023, |
michael@0 | 33 | 0142, 0247, 0005, 0363, 0300, 0307, 0163, 0214, |
michael@0 | 34 | 0230, 0223, 0053, 0331, 0274, 0114, 0202, 0312, |
michael@0 | 35 | 0036, 0233, 0127, 0074, 0375, 0324, 0340, 0026, |
michael@0 | 36 | 0147, 0102, 0157, 0030, 0212, 0027, 0345, 0022, |
michael@0 | 37 | 0276, 0116, 0304, 0326, 0332, 0236, 0336, 0111, |
michael@0 | 38 | 0240, 0373, 0365, 0216, 0273, 0057, 0356, 0172, |
michael@0 | 39 | 0251, 0150, 0171, 0221, 0025, 0262, 0007, 0077, |
michael@0 | 40 | 0224, 0302, 0020, 0211, 0013, 0042, 0137, 0041, |
michael@0 | 41 | 0200, 0177, 0135, 0232, 0132, 0220, 0062, 0047, |
michael@0 | 42 | 0065, 0076, 0314, 0347, 0277, 0367, 0227, 0003, |
michael@0 | 43 | 0377, 0031, 0060, 0263, 0110, 0245, 0265, 0321, |
michael@0 | 44 | 0327, 0136, 0222, 0052, 0254, 0126, 0252, 0306, |
michael@0 | 45 | 0117, 0270, 0070, 0322, 0226, 0244, 0175, 0266, |
michael@0 | 46 | 0166, 0374, 0153, 0342, 0234, 0164, 0004, 0361, |
michael@0 | 47 | 0105, 0235, 0160, 0131, 0144, 0161, 0207, 0040, |
michael@0 | 48 | 0206, 0133, 0317, 0145, 0346, 0055, 0250, 0002, |
michael@0 | 49 | 0033, 0140, 0045, 0255, 0256, 0260, 0271, 0366, |
michael@0 | 50 | 0034, 0106, 0141, 0151, 0064, 0100, 0176, 0017, |
michael@0 | 51 | 0125, 0107, 0243, 0043, 0335, 0121, 0257, 0072, |
michael@0 | 52 | 0303, 0134, 0371, 0316, 0272, 0305, 0352, 0046, |
michael@0 | 53 | 0054, 0123, 0015, 0156, 0205, 0050, 0204, 0011, |
michael@0 | 54 | 0323, 0337, 0315, 0364, 0101, 0201, 0115, 0122, |
michael@0 | 55 | 0152, 0334, 0067, 0310, 0154, 0301, 0253, 0372, |
michael@0 | 56 | 0044, 0341, 0173, 0010, 0014, 0275, 0261, 0112, |
michael@0 | 57 | 0170, 0210, 0225, 0213, 0343, 0143, 0350, 0155, |
michael@0 | 58 | 0351, 0313, 0325, 0376, 0073, 0000, 0035, 0071, |
michael@0 | 59 | 0362, 0357, 0267, 0016, 0146, 0130, 0320, 0344, |
michael@0 | 60 | 0246, 0167, 0162, 0370, 0353, 0165, 0113, 0012, |
michael@0 | 61 | 0061, 0104, 0120, 0264, 0217, 0355, 0037, 0032, |
michael@0 | 62 | 0333, 0231, 0215, 0063, 0237, 0021, 0203, 0024 |
michael@0 | 63 | }; |
michael@0 | 64 | |
michael@0 | 65 | SECStatus |
michael@0 | 66 | MD2_Hash(unsigned char *dest, const char *src) |
michael@0 | 67 | { |
michael@0 | 68 | unsigned int len; |
michael@0 | 69 | MD2Context *cx = MD2_NewContext(); |
michael@0 | 70 | if (!cx) { |
michael@0 | 71 | PORT_SetError(PR_OUT_OF_MEMORY_ERROR); |
michael@0 | 72 | return SECFailure; |
michael@0 | 73 | } |
michael@0 | 74 | MD2_Begin(cx); |
michael@0 | 75 | MD2_Update(cx, (const unsigned char *)src, PORT_Strlen(src)); |
michael@0 | 76 | MD2_End(cx, dest, &len, MD2_DIGEST_LEN); |
michael@0 | 77 | MD2_DestroyContext(cx, PR_TRUE); |
michael@0 | 78 | return SECSuccess; |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | MD2Context * |
michael@0 | 82 | MD2_NewContext(void) |
michael@0 | 83 | { |
michael@0 | 84 | MD2Context *cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context)); |
michael@0 | 85 | if (cx == NULL) { |
michael@0 | 86 | PORT_SetError(PR_OUT_OF_MEMORY_ERROR); |
michael@0 | 87 | return NULL; |
michael@0 | 88 | } |
michael@0 | 89 | return cx; |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | void |
michael@0 | 93 | MD2_DestroyContext(MD2Context *cx, PRBool freeit) |
michael@0 | 94 | { |
michael@0 | 95 | if (freeit) |
michael@0 | 96 | PORT_ZFree(cx, sizeof(*cx)); |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | void |
michael@0 | 100 | MD2_Begin(MD2Context *cx) |
michael@0 | 101 | { |
michael@0 | 102 | memset(cx, 0, sizeof(*cx)); |
michael@0 | 103 | cx->unusedBuffer = MD2_BUFSIZE; |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | static void |
michael@0 | 107 | md2_compress(MD2Context *cx) |
michael@0 | 108 | { |
michael@0 | 109 | int j; |
michael@0 | 110 | unsigned char P; |
michael@0 | 111 | P = cx->checksum[MD2_CHECKSUM_SIZE-1]; |
michael@0 | 112 | /* Compute the running checksum, and set the tmp variables to be |
michael@0 | 113 | * CV[i] XOR input[i] |
michael@0 | 114 | */ |
michael@0 | 115 | #define CKSUMFN(n) \ |
michael@0 | 116 | P = cx->checksum[n] ^ MD2S[cx->X[MD2_INPUT+n] ^ P]; \ |
michael@0 | 117 | cx->checksum[n] = P; \ |
michael@0 | 118 | cx->X[MD2_TMPVARS+n] = cx->X[n] ^ cx->X[MD2_INPUT+n]; |
michael@0 | 119 | CKSUMFN(0); |
michael@0 | 120 | CKSUMFN(1); |
michael@0 | 121 | CKSUMFN(2); |
michael@0 | 122 | CKSUMFN(3); |
michael@0 | 123 | CKSUMFN(4); |
michael@0 | 124 | CKSUMFN(5); |
michael@0 | 125 | CKSUMFN(6); |
michael@0 | 126 | CKSUMFN(7); |
michael@0 | 127 | CKSUMFN(8); |
michael@0 | 128 | CKSUMFN(9); |
michael@0 | 129 | CKSUMFN(10); |
michael@0 | 130 | CKSUMFN(11); |
michael@0 | 131 | CKSUMFN(12); |
michael@0 | 132 | CKSUMFN(13); |
michael@0 | 133 | CKSUMFN(14); |
michael@0 | 134 | CKSUMFN(15); |
michael@0 | 135 | /* The compression function. */ |
michael@0 | 136 | #define COMPRESS(n) \ |
michael@0 | 137 | P = cx->X[n] ^ MD2S[P]; \ |
michael@0 | 138 | cx->X[n] = P; |
michael@0 | 139 | P = 0x00; |
michael@0 | 140 | for (j=0; j<18; j++) { |
michael@0 | 141 | COMPRESS(0); |
michael@0 | 142 | COMPRESS(1); |
michael@0 | 143 | COMPRESS(2); |
michael@0 | 144 | COMPRESS(3); |
michael@0 | 145 | COMPRESS(4); |
michael@0 | 146 | COMPRESS(5); |
michael@0 | 147 | COMPRESS(6); |
michael@0 | 148 | COMPRESS(7); |
michael@0 | 149 | COMPRESS(8); |
michael@0 | 150 | COMPRESS(9); |
michael@0 | 151 | COMPRESS(10); |
michael@0 | 152 | COMPRESS(11); |
michael@0 | 153 | COMPRESS(12); |
michael@0 | 154 | COMPRESS(13); |
michael@0 | 155 | COMPRESS(14); |
michael@0 | 156 | COMPRESS(15); |
michael@0 | 157 | COMPRESS(16); |
michael@0 | 158 | COMPRESS(17); |
michael@0 | 159 | COMPRESS(18); |
michael@0 | 160 | COMPRESS(19); |
michael@0 | 161 | COMPRESS(20); |
michael@0 | 162 | COMPRESS(21); |
michael@0 | 163 | COMPRESS(22); |
michael@0 | 164 | COMPRESS(23); |
michael@0 | 165 | COMPRESS(24); |
michael@0 | 166 | COMPRESS(25); |
michael@0 | 167 | COMPRESS(26); |
michael@0 | 168 | COMPRESS(27); |
michael@0 | 169 | COMPRESS(28); |
michael@0 | 170 | COMPRESS(29); |
michael@0 | 171 | COMPRESS(30); |
michael@0 | 172 | COMPRESS(31); |
michael@0 | 173 | COMPRESS(32); |
michael@0 | 174 | COMPRESS(33); |
michael@0 | 175 | COMPRESS(34); |
michael@0 | 176 | COMPRESS(35); |
michael@0 | 177 | COMPRESS(36); |
michael@0 | 178 | COMPRESS(37); |
michael@0 | 179 | COMPRESS(38); |
michael@0 | 180 | COMPRESS(39); |
michael@0 | 181 | COMPRESS(40); |
michael@0 | 182 | COMPRESS(41); |
michael@0 | 183 | COMPRESS(42); |
michael@0 | 184 | COMPRESS(43); |
michael@0 | 185 | COMPRESS(44); |
michael@0 | 186 | COMPRESS(45); |
michael@0 | 187 | COMPRESS(46); |
michael@0 | 188 | COMPRESS(47); |
michael@0 | 189 | P = (P + j) % 256; |
michael@0 | 190 | } |
michael@0 | 191 | cx->unusedBuffer = MD2_BUFSIZE; |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | void |
michael@0 | 195 | MD2_Update(MD2Context *cx, const unsigned char *input, unsigned int inputLen) |
michael@0 | 196 | { |
michael@0 | 197 | PRUint32 bytesToConsume; |
michael@0 | 198 | |
michael@0 | 199 | /* Fill the remaining input buffer. */ |
michael@0 | 200 | if (cx->unusedBuffer != MD2_BUFSIZE) { |
michael@0 | 201 | bytesToConsume = PR_MIN(inputLen, cx->unusedBuffer); |
michael@0 | 202 | memcpy(&cx->X[MD2_INPUT + (MD2_BUFSIZE - cx->unusedBuffer)], |
michael@0 | 203 | input, bytesToConsume); |
michael@0 | 204 | if (cx->unusedBuffer + bytesToConsume >= MD2_BUFSIZE) |
michael@0 | 205 | md2_compress(cx); |
michael@0 | 206 | inputLen -= bytesToConsume; |
michael@0 | 207 | input += bytesToConsume; |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | /* Iterate over 16-byte chunks of the input. */ |
michael@0 | 211 | while (inputLen >= MD2_BUFSIZE) { |
michael@0 | 212 | memcpy(&cx->X[MD2_INPUT], input, MD2_BUFSIZE); |
michael@0 | 213 | md2_compress(cx); |
michael@0 | 214 | inputLen -= MD2_BUFSIZE; |
michael@0 | 215 | input += MD2_BUFSIZE; |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | /* Copy any input that remains into the buffer. */ |
michael@0 | 219 | if (inputLen) |
michael@0 | 220 | memcpy(&cx->X[MD2_INPUT], input, inputLen); |
michael@0 | 221 | cx->unusedBuffer = MD2_BUFSIZE - inputLen; |
michael@0 | 222 | } |
michael@0 | 223 | |
michael@0 | 224 | void |
michael@0 | 225 | MD2_End(MD2Context *cx, unsigned char *digest, |
michael@0 | 226 | unsigned int *digestLen, unsigned int maxDigestLen) |
michael@0 | 227 | { |
michael@0 | 228 | PRUint8 padStart; |
michael@0 | 229 | if (maxDigestLen < MD2_BUFSIZE) { |
michael@0 | 230 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
michael@0 | 231 | return; |
michael@0 | 232 | } |
michael@0 | 233 | padStart = MD2_BUFSIZE - cx->unusedBuffer; |
michael@0 | 234 | memset(&cx->X[MD2_INPUT + padStart], cx->unusedBuffer, |
michael@0 | 235 | cx->unusedBuffer); |
michael@0 | 236 | md2_compress(cx); |
michael@0 | 237 | memcpy(&cx->X[MD2_INPUT], cx->checksum, MD2_BUFSIZE); |
michael@0 | 238 | md2_compress(cx); |
michael@0 | 239 | *digestLen = MD2_DIGEST_LEN; |
michael@0 | 240 | memcpy(digest, &cx->X[MD2_CV], MD2_DIGEST_LEN); |
michael@0 | 241 | } |
michael@0 | 242 | |
michael@0 | 243 | unsigned int |
michael@0 | 244 | MD2_FlattenSize(MD2Context *cx) |
michael@0 | 245 | { |
michael@0 | 246 | return sizeof(*cx); |
michael@0 | 247 | } |
michael@0 | 248 | |
michael@0 | 249 | SECStatus |
michael@0 | 250 | MD2_Flatten(MD2Context *cx, unsigned char *space) |
michael@0 | 251 | { |
michael@0 | 252 | memcpy(space, cx, sizeof(*cx)); |
michael@0 | 253 | return SECSuccess; |
michael@0 | 254 | } |
michael@0 | 255 | |
michael@0 | 256 | MD2Context * |
michael@0 | 257 | MD2_Resurrect(unsigned char *space, void *arg) |
michael@0 | 258 | { |
michael@0 | 259 | MD2Context *cx = MD2_NewContext(); |
michael@0 | 260 | if (cx) |
michael@0 | 261 | memcpy(cx, space, sizeof(*cx)); |
michael@0 | 262 | return cx; |
michael@0 | 263 | } |
michael@0 | 264 | |
michael@0 | 265 | void MD2_Clone(MD2Context *dest, MD2Context *src) |
michael@0 | 266 | { |
michael@0 | 267 | memcpy(dest, src, sizeof *dest); |
michael@0 | 268 | } |