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