/src/nss/lib/freebl/md2.c
Line  | Count  | Source (jump to first uncovered line)  | 
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  | 0  | #define MD2_DIGEST_LEN 16  | 
17  | 0  | #define MD2_BUFSIZE 16  | 
18  |  | #define MD2_X_SIZE 48  /* The X array, [CV | INPUT | TMP VARS] */  | 
19  | 0  | #define MD2_CV 0       /* index into X for chaining variables */  | 
20  | 0  | #define MD2_INPUT 16   /* index into X for input */  | 
21  | 0  | #define MD2_TMPVARS 32 /* index into X for temporary variables */  | 
22  | 0  | #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  | 0  | { | 
68  | 0  |     unsigned int len;  | 
69  | 0  |     MD2Context *cx = MD2_NewContext();  | 
70  | 0  |     if (!cx) { | 
71  | 0  |         PORT_SetError(PR_OUT_OF_MEMORY_ERROR);  | 
72  | 0  |         return SECFailure;  | 
73  | 0  |     }  | 
74  | 0  |     MD2_Begin(cx);  | 
75  | 0  |     MD2_Update(cx, (const unsigned char *)src, PORT_Strlen(src));  | 
76  | 0  |     MD2_End(cx, dest, &len, MD2_DIGEST_LEN);  | 
77  | 0  |     MD2_DestroyContext(cx, PR_TRUE);  | 
78  | 0  |     return SECSuccess;  | 
79  | 0  | }  | 
80  |  |  | 
81  |  | MD2Context *  | 
82  |  | MD2_NewContext(void)  | 
83  | 0  | { | 
84  | 0  |     MD2Context *cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context));  | 
85  | 0  |     if (cx == NULL) { | 
86  | 0  |         PORT_SetError(PR_OUT_OF_MEMORY_ERROR);  | 
87  | 0  |         return NULL;  | 
88  | 0  |     }  | 
89  | 0  |     return cx;  | 
90  | 0  | }  | 
91  |  |  | 
92  |  | void  | 
93  |  | MD2_DestroyContext(MD2Context *cx, PRBool freeit)  | 
94  | 0  | { | 
95  | 0  |     if (freeit)  | 
96  | 0  |         PORT_ZFree(cx, sizeof(*cx));  | 
97  | 0  | }  | 
98  |  |  | 
99  |  | void  | 
100  |  | MD2_Begin(MD2Context *cx)  | 
101  | 0  | { | 
102  | 0  |     memset(cx, 0, sizeof(*cx));  | 
103  | 0  |     cx->unusedBuffer = MD2_BUFSIZE;  | 
104  | 0  | }  | 
105  |  |  | 
106  |  | static void  | 
107  |  | md2_compress(MD2Context *cx)  | 
108  | 0  | { | 
109  | 0  |     int j;  | 
110  | 0  |     unsigned char P;  | 
111  | 0  |     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  | 0  | #define CKSUMFN(n)                                        \  | 
116  | 0  |     P = cx->checksum[n] ^ MD2S[cx->X[MD2_INPUT + n] ^ P]; \  | 
117  | 0  |     cx->checksum[n] = P;                                  \  | 
118  | 0  |     cx->X[MD2_TMPVARS + n] = cx->X[n] ^ cx->X[MD2_INPUT + n];  | 
119  | 0  |     CKSUMFN(0);  | 
120  | 0  |     CKSUMFN(1);  | 
121  | 0  |     CKSUMFN(2);  | 
122  | 0  |     CKSUMFN(3);  | 
123  | 0  |     CKSUMFN(4);  | 
124  | 0  |     CKSUMFN(5);  | 
125  | 0  |     CKSUMFN(6);  | 
126  | 0  |     CKSUMFN(7);  | 
127  | 0  |     CKSUMFN(8);  | 
128  | 0  |     CKSUMFN(9);  | 
129  | 0  |     CKSUMFN(10);  | 
130  | 0  |     CKSUMFN(11);  | 
131  | 0  |     CKSUMFN(12);  | 
132  | 0  |     CKSUMFN(13);  | 
133  | 0  |     CKSUMFN(14);  | 
134  | 0  |     CKSUMFN(15);  | 
135  |  | /* The compression function. */  | 
136  | 0  | #define COMPRESS(n)         \  | 
137  | 0  |     P = cx->X[n] ^ MD2S[P]; \  | 
138  | 0  |     cx->X[n] = P;  | 
139  | 0  |     P = 0x00;  | 
140  | 0  |     for (j = 0; j < 18; j++) { | 
141  | 0  |         COMPRESS(0);  | 
142  | 0  |         COMPRESS(1);  | 
143  | 0  |         COMPRESS(2);  | 
144  | 0  |         COMPRESS(3);  | 
145  | 0  |         COMPRESS(4);  | 
146  | 0  |         COMPRESS(5);  | 
147  | 0  |         COMPRESS(6);  | 
148  | 0  |         COMPRESS(7);  | 
149  | 0  |         COMPRESS(8);  | 
150  | 0  |         COMPRESS(9);  | 
151  | 0  |         COMPRESS(10);  | 
152  | 0  |         COMPRESS(11);  | 
153  | 0  |         COMPRESS(12);  | 
154  | 0  |         COMPRESS(13);  | 
155  | 0  |         COMPRESS(14);  | 
156  | 0  |         COMPRESS(15);  | 
157  | 0  |         COMPRESS(16);  | 
158  | 0  |         COMPRESS(17);  | 
159  | 0  |         COMPRESS(18);  | 
160  | 0  |         COMPRESS(19);  | 
161  | 0  |         COMPRESS(20);  | 
162  | 0  |         COMPRESS(21);  | 
163  | 0  |         COMPRESS(22);  | 
164  | 0  |         COMPRESS(23);  | 
165  | 0  |         COMPRESS(24);  | 
166  | 0  |         COMPRESS(25);  | 
167  | 0  |         COMPRESS(26);  | 
168  | 0  |         COMPRESS(27);  | 
169  | 0  |         COMPRESS(28);  | 
170  | 0  |         COMPRESS(29);  | 
171  | 0  |         COMPRESS(30);  | 
172  | 0  |         COMPRESS(31);  | 
173  | 0  |         COMPRESS(32);  | 
174  | 0  |         COMPRESS(33);  | 
175  | 0  |         COMPRESS(34);  | 
176  | 0  |         COMPRESS(35);  | 
177  | 0  |         COMPRESS(36);  | 
178  | 0  |         COMPRESS(37);  | 
179  | 0  |         COMPRESS(38);  | 
180  | 0  |         COMPRESS(39);  | 
181  | 0  |         COMPRESS(40);  | 
182  | 0  |         COMPRESS(41);  | 
183  | 0  |         COMPRESS(42);  | 
184  | 0  |         COMPRESS(43);  | 
185  | 0  |         COMPRESS(44);  | 
186  | 0  |         COMPRESS(45);  | 
187  | 0  |         COMPRESS(46);  | 
188  | 0  |         COMPRESS(47);  | 
189  | 0  |         P = (P + j) % 256;  | 
190  | 0  |     }  | 
191  | 0  |     cx->unusedBuffer = MD2_BUFSIZE;  | 
192  | 0  | }  | 
193  |  |  | 
194  |  | void  | 
195  |  | MD2_Update(MD2Context *cx, const unsigned char *input, unsigned int inputLen)  | 
196  | 0  | { | 
197  | 0  |     PRUint32 bytesToConsume;  | 
198  |  |  | 
199  |  |     /* Fill the remaining input buffer. */  | 
200  | 0  |     if (cx->unusedBuffer != MD2_BUFSIZE) { | 
201  | 0  |         bytesToConsume = PR_MIN(inputLen, cx->unusedBuffer);  | 
202  | 0  |         memcpy(&cx->X[MD2_INPUT + (MD2_BUFSIZE - cx->unusedBuffer)],  | 
203  | 0  |                input, bytesToConsume);  | 
204  | 0  |         if (cx->unusedBuffer + bytesToConsume >= MD2_BUFSIZE)  | 
205  | 0  |             md2_compress(cx);  | 
206  | 0  |         inputLen -= bytesToConsume;  | 
207  | 0  |         input += bytesToConsume;  | 
208  | 0  |     }  | 
209  |  |  | 
210  |  |     /* Iterate over 16-byte chunks of the input. */  | 
211  | 0  |     while (inputLen >= MD2_BUFSIZE) { | 
212  | 0  |         memcpy(&cx->X[MD2_INPUT], input, MD2_BUFSIZE);  | 
213  | 0  |         md2_compress(cx);  | 
214  | 0  |         inputLen -= MD2_BUFSIZE;  | 
215  | 0  |         input += MD2_BUFSIZE;  | 
216  | 0  |     }  | 
217  |  |  | 
218  |  |     /* Copy any input that remains into the buffer. */  | 
219  | 0  |     if (inputLen)  | 
220  | 0  |         memcpy(&cx->X[MD2_INPUT], input, inputLen);  | 
221  | 0  |     cx->unusedBuffer = MD2_BUFSIZE - inputLen;  | 
222  | 0  | }  | 
223  |  |  | 
224  |  | void  | 
225  |  | MD2_End(MD2Context *cx, unsigned char *digest,  | 
226  |  |         unsigned int *digestLen, unsigned int maxDigestLen)  | 
227  | 0  | { | 
228  | 0  |     PRUint8 padStart;  | 
229  | 0  |     if (maxDigestLen < MD2_BUFSIZE) { | 
230  | 0  |         PORT_SetError(SEC_ERROR_INVALID_ARGS);  | 
231  | 0  |         return;  | 
232  | 0  |     }  | 
233  | 0  |     padStart = MD2_BUFSIZE - cx->unusedBuffer;  | 
234  | 0  |     memset(&cx->X[MD2_INPUT + padStart], cx->unusedBuffer,  | 
235  | 0  |            cx->unusedBuffer);  | 
236  | 0  |     md2_compress(cx);  | 
237  | 0  |     memcpy(&cx->X[MD2_INPUT], cx->checksum, MD2_BUFSIZE);  | 
238  | 0  |     md2_compress(cx);  | 
239  | 0  |     *digestLen = MD2_DIGEST_LEN;  | 
240  | 0  |     memcpy(digest, &cx->X[MD2_CV], MD2_DIGEST_LEN);  | 
241  | 0  | }  | 
242  |  |  | 
243  |  | unsigned int  | 
244  |  | MD2_FlattenSize(MD2Context *cx)  | 
245  | 0  | { | 
246  | 0  |     return sizeof(*cx);  | 
247  | 0  | }  | 
248  |  |  | 
249  |  | SECStatus  | 
250  |  | MD2_Flatten(MD2Context *cx, unsigned char *space)  | 
251  | 0  | { | 
252  | 0  |     memcpy(space, cx, sizeof(*cx));  | 
253  | 0  |     return SECSuccess;  | 
254  | 0  | }  | 
255  |  |  | 
256  |  | MD2Context *  | 
257  |  | MD2_Resurrect(unsigned char *space, void *arg)  | 
258  | 0  | { | 
259  | 0  |     MD2Context *cx = MD2_NewContext();  | 
260  | 0  |     if (cx)  | 
261  | 0  |         memcpy(cx, space, sizeof(*cx));  | 
262  | 0  |     return cx;  | 
263  | 0  | }  | 
264  |  |  | 
265  |  | void  | 
266  |  | MD2_Clone(MD2Context *dest, MD2Context *src)  | 
267  | 0  | { | 
268  | 0  |     memcpy(dest, src, sizeof *dest);  | 
269  | 0  | }  |