Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / freebl / md2.c
blobddc7a9d7e7f9470ad5e963364dcb86ad804a2c5e
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 #include "prerr.h"
38 #include "secerr.h"
40 #include "prtypes.h"
42 #include "blapi.h"
44 #define MD2_DIGEST_LEN 16
45 #define MD2_BUFSIZE 16
46 #define MD2_X_SIZE 48 /* The X array, [CV | INPUT | TMP VARS] */
47 #define MD2_CV 0 /* index into X for chaining variables */
48 #define MD2_INPUT 16 /* index into X for input */
49 #define MD2_TMPVARS 32 /* index into X for temporary variables */
50 #define MD2_CHECKSUM_SIZE 16
52 struct MD2ContextStr {
53 unsigned char checksum[MD2_BUFSIZE];
54 unsigned char X[MD2_X_SIZE];
55 PRUint8 unusedBuffer;
58 static const PRUint8 MD2S[256] = {
59 0051, 0056, 0103, 0311, 0242, 0330, 0174, 0001,
60 0075, 0066, 0124, 0241, 0354, 0360, 0006, 0023,
61 0142, 0247, 0005, 0363, 0300, 0307, 0163, 0214,
62 0230, 0223, 0053, 0331, 0274, 0114, 0202, 0312,
63 0036, 0233, 0127, 0074, 0375, 0324, 0340, 0026,
64 0147, 0102, 0157, 0030, 0212, 0027, 0345, 0022,
65 0276, 0116, 0304, 0326, 0332, 0236, 0336, 0111,
66 0240, 0373, 0365, 0216, 0273, 0057, 0356, 0172,
67 0251, 0150, 0171, 0221, 0025, 0262, 0007, 0077,
68 0224, 0302, 0020, 0211, 0013, 0042, 0137, 0041,
69 0200, 0177, 0135, 0232, 0132, 0220, 0062, 0047,
70 0065, 0076, 0314, 0347, 0277, 0367, 0227, 0003,
71 0377, 0031, 0060, 0263, 0110, 0245, 0265, 0321,
72 0327, 0136, 0222, 0052, 0254, 0126, 0252, 0306,
73 0117, 0270, 0070, 0322, 0226, 0244, 0175, 0266,
74 0166, 0374, 0153, 0342, 0234, 0164, 0004, 0361,
75 0105, 0235, 0160, 0131, 0144, 0161, 0207, 0040,
76 0206, 0133, 0317, 0145, 0346, 0055, 0250, 0002,
77 0033, 0140, 0045, 0255, 0256, 0260, 0271, 0366,
78 0034, 0106, 0141, 0151, 0064, 0100, 0176, 0017,
79 0125, 0107, 0243, 0043, 0335, 0121, 0257, 0072,
80 0303, 0134, 0371, 0316, 0272, 0305, 0352, 0046,
81 0054, 0123, 0015, 0156, 0205, 0050, 0204, 0011,
82 0323, 0337, 0315, 0364, 0101, 0201, 0115, 0122,
83 0152, 0334, 0067, 0310, 0154, 0301, 0253, 0372,
84 0044, 0341, 0173, 0010, 0014, 0275, 0261, 0112,
85 0170, 0210, 0225, 0213, 0343, 0143, 0350, 0155,
86 0351, 0313, 0325, 0376, 0073, 0000, 0035, 0071,
87 0362, 0357, 0267, 0016, 0146, 0130, 0320, 0344,
88 0246, 0167, 0162, 0370, 0353, 0165, 0113, 0012,
89 0061, 0104, 0120, 0264, 0217, 0355, 0037, 0032,
90 0333, 0231, 0215, 0063, 0237, 0021, 0203, 0024
93 SECStatus
94 MD2_Hash(unsigned char *dest, const char *src)
96 unsigned int len;
97 MD2Context *cx = MD2_NewContext();
98 if (!cx) {
99 PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
100 return SECFailure;
102 MD2_Begin(cx);
103 MD2_Update(cx, (unsigned char *)src, PL_strlen(src));
104 MD2_End(cx, dest, &len, MD2_DIGEST_LEN);
105 MD2_DestroyContext(cx, PR_TRUE);
106 return SECSuccess;
109 MD2Context *
110 MD2_NewContext(void)
112 MD2Context *cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context));
113 if (cx == NULL) {
114 PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
115 return NULL;
117 return cx;
120 void
121 MD2_DestroyContext(MD2Context *cx, PRBool freeit)
123 if (freeit)
124 PORT_ZFree(cx, sizeof(*cx));
127 void
128 MD2_Begin(MD2Context *cx)
130 memset(cx, 0, sizeof(*cx));
131 cx->unusedBuffer = MD2_BUFSIZE;
134 static void
135 md2_compress(MD2Context *cx)
137 int j;
138 unsigned char P;
139 P = cx->checksum[MD2_CHECKSUM_SIZE-1];
140 /* Compute the running checksum, and set the tmp variables to be
141 * CV[i] XOR input[i]
143 #define CKSUMFN(n) \
144 P = cx->checksum[n] ^ MD2S[cx->X[MD2_INPUT+n] ^ P]; \
145 cx->checksum[n] = P; \
146 cx->X[MD2_TMPVARS+n] = cx->X[n] ^ cx->X[MD2_INPUT+n];
147 CKSUMFN(0);
148 CKSUMFN(1);
149 CKSUMFN(2);
150 CKSUMFN(3);
151 CKSUMFN(4);
152 CKSUMFN(5);
153 CKSUMFN(6);
154 CKSUMFN(7);
155 CKSUMFN(8);
156 CKSUMFN(9);
157 CKSUMFN(10);
158 CKSUMFN(11);
159 CKSUMFN(12);
160 CKSUMFN(13);
161 CKSUMFN(14);
162 CKSUMFN(15);
163 /* The compression function. */
164 #define COMPRESS(n) \
165 P = cx->X[n] ^ MD2S[P]; \
166 cx->X[n] = P;
167 P = 0x00;
168 for (j=0; j<18; j++) {
169 COMPRESS(0);
170 COMPRESS(1);
171 COMPRESS(2);
172 COMPRESS(3);
173 COMPRESS(4);
174 COMPRESS(5);
175 COMPRESS(6);
176 COMPRESS(7);
177 COMPRESS(8);
178 COMPRESS(9);
179 COMPRESS(10);
180 COMPRESS(11);
181 COMPRESS(12);
182 COMPRESS(13);
183 COMPRESS(14);
184 COMPRESS(15);
185 COMPRESS(16);
186 COMPRESS(17);
187 COMPRESS(18);
188 COMPRESS(19);
189 COMPRESS(20);
190 COMPRESS(21);
191 COMPRESS(22);
192 COMPRESS(23);
193 COMPRESS(24);
194 COMPRESS(25);
195 COMPRESS(26);
196 COMPRESS(27);
197 COMPRESS(28);
198 COMPRESS(29);
199 COMPRESS(30);
200 COMPRESS(31);
201 COMPRESS(32);
202 COMPRESS(33);
203 COMPRESS(34);
204 COMPRESS(35);
205 COMPRESS(36);
206 COMPRESS(37);
207 COMPRESS(38);
208 COMPRESS(39);
209 COMPRESS(40);
210 COMPRESS(41);
211 COMPRESS(42);
212 COMPRESS(43);
213 COMPRESS(44);
214 COMPRESS(45);
215 COMPRESS(46);
216 COMPRESS(47);
217 P = (P + j) % 256;
219 cx->unusedBuffer = MD2_BUFSIZE;
222 void
223 MD2_Update(MD2Context *cx, const unsigned char *input, unsigned int inputLen)
225 PRUint32 bytesToConsume;
227 /* Fill the remaining input buffer. */
228 if (cx->unusedBuffer != MD2_BUFSIZE) {
229 bytesToConsume = PR_MIN(inputLen, cx->unusedBuffer);
230 memcpy(&cx->X[MD2_INPUT + (MD2_BUFSIZE - cx->unusedBuffer)],
231 input, bytesToConsume);
232 if (cx->unusedBuffer + bytesToConsume >= MD2_BUFSIZE)
233 md2_compress(cx);
234 inputLen -= bytesToConsume;
235 input += bytesToConsume;
238 /* Iterate over 16-byte chunks of the input. */
239 while (inputLen >= MD2_BUFSIZE) {
240 memcpy(&cx->X[MD2_INPUT], input, MD2_BUFSIZE);
241 md2_compress(cx);
242 inputLen -= MD2_BUFSIZE;
243 input += MD2_BUFSIZE;
246 /* Copy any input that remains into the buffer. */
247 if (inputLen)
248 memcpy(&cx->X[MD2_INPUT], input, inputLen);
249 cx->unusedBuffer = MD2_BUFSIZE - inputLen;
252 void
253 MD2_End(MD2Context *cx, unsigned char *digest,
254 unsigned int *digestLen, unsigned int maxDigestLen)
256 PRUint8 padStart;
257 if (maxDigestLen < MD2_BUFSIZE) {
258 PORT_SetError(SEC_ERROR_INVALID_ARGS);
259 return;
261 padStart = MD2_BUFSIZE - cx->unusedBuffer;
262 memset(&cx->X[MD2_INPUT + padStart], cx->unusedBuffer,
263 cx->unusedBuffer);
264 md2_compress(cx);
265 memcpy(&cx->X[MD2_INPUT], cx->checksum, MD2_BUFSIZE);
266 md2_compress(cx);
267 *digestLen = MD2_DIGEST_LEN;
268 memcpy(digest, &cx->X[MD2_CV], MD2_DIGEST_LEN);
271 unsigned int
272 MD2_FlattenSize(MD2Context *cx)
274 return sizeof(*cx);
277 SECStatus
278 MD2_Flatten(MD2Context *cx, unsigned char *space)
280 memcpy(space, cx, sizeof(*cx));
281 return SECSuccess;
284 MD2Context *
285 MD2_Resurrect(unsigned char *space, void *arg)
287 MD2Context *cx = MD2_NewContext();
288 if (cx)
289 memcpy(cx, space, sizeof(*cx));
290 return cx;
293 void MD2_Clone(MD2Context *dest, MD2Context *src)
295 memcpy(dest, src, sizeof *dest);