1/*
2 * md5.c --
3 *
4 *	Implements and registers message digest generator MD5.
5 *
6 *
7 * Copyright (c) 1996 Andreas Kupries (a.kupries@westend.com)
8 * All rights reserved.
9 *
10 * Permission is hereby granted, without written agreement and without
11 * license or royalty fees, to use, copy, modify, and distribute this
12 * software and its documentation for any purpose, provided that the
13 * above copyright notice and the following two paragraphs appear in
14 * all copies of this software.
15 *
16 * IN NO EVENT SHALL I LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
17 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
18 * SOFTWARE AND ITS DOCUMENTATION, EVEN IF I HAVE BEEN ADVISED OF THE
19 * POSSIBILITY OF SUCH DAMAGE.
20 *
21 * I SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
24 * I HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
25 * ENHANCEMENTS, OR MODIFICATIONS.
26 *
27 * CVS: $Id: md5dig.c,v 1.5 2008/12/11 19:04:25 andreas_kupries Exp $
28 */
29
30#include "loadman.h"
31
32/*
33 * Generator description
34 * ---------------------
35 *
36 * The MD5 alogrithm is used to compute a cryptographically strong
37 * message digest.
38 */
39
40#define MD5_CTXP (MD5_CTX*)
41
42#ifndef OTP
43#define DIGEST_SIZE               (16)
44#else
45#define DIGEST_SIZE               (8)
46#endif
47#define CTX_TYPE                  MD5_CTX
48
49/*
50 * Declarations of internal procedures.
51 */
52
53static void MDmd5_Start     _ANSI_ARGS_ ((VOID* context));
54static void MDmd5_Update    _ANSI_ARGS_ ((VOID* context, unsigned int character));
55static void MDmd5_UpdateBuf _ANSI_ARGS_ ((VOID* context,
56				       unsigned char* buffer, int bufLen));
57static void MDmd5_Final     _ANSI_ARGS_ ((VOID* context, VOID* digest));
58static int  MDmd5_Check     _ANSI_ARGS_ ((Tcl_Interp* interp));
59
60/*
61 * Generator definition.
62 */
63
64static Trf_MessageDigestDescription
65mdDescription = { /* THREADING: constant, read-only => safe */
66#ifndef OTP
67  "md5",
68#else
69  "otp_md5",
70#endif
71  sizeof (CTX_TYPE),
72  DIGEST_SIZE,
73  MDmd5_Start,
74  MDmd5_Update,
75  MDmd5_UpdateBuf,
76  MDmd5_Final,
77  MDmd5_Check
78};
79
80/*
81 *------------------------------------------------------*
82 *
83 *	TrfInit_MD5 --
84 *
85 *	------------------------------------------------*
86 *	Register the generator implemented in this file.
87 *	------------------------------------------------*
88 *
89 *	Sideeffects:
90 *		As of 'Trf_Register'.
91 *
92 *	Result:
93 *		A standard Tcl error code.
94 *
95 *------------------------------------------------------*
96 */
97
98int
99#ifndef	OTP
100TrfInit_MD5 (interp)
101#else
102TrfInit_OTP_MD5 (interp)
103#endif
104Tcl_Interp* interp;
105{
106  return Trf_RegisterMessageDigest (interp, &mdDescription);
107}
108
109/*
110 *------------------------------------------------------*
111 *
112 *	MDmd5_Start --
113 *
114 *	------------------------------------------------*
115 *	Initialize the internal state of the message
116 *	digest generator.
117 *	------------------------------------------------*
118 *
119 *	Sideeffects:
120 *		As of the called procedure.
121 *
122 *	Result:
123 *		None.
124 *
125 *------------------------------------------------------*
126 */
127
128static void
129MDmd5_Start (context)
130VOID* context;
131{
132  /*  MD5Init ((MD5_CTX*) context);*/
133  md5f.init (MD5_CTXP context);
134
135#ifdef TRF_DEBUG
136  {
137    MD5_CTX* c = MD5_CTXP context;
138    PRINT ("Init ABCD = %d %d %d %d\n", c->A, c->B, c->C, c->D); FL;
139  }
140#endif
141}
142
143/*
144 *------------------------------------------------------*
145 *
146 *	MDmd5_Update --
147 *
148 *	------------------------------------------------*
149 *	Update the internal state of the message digest
150 *	generator for a single character.
151 *	------------------------------------------------*
152 *
153 *	Sideeffects:
154 *		As of the called procedure.
155 *
156 *	Result:
157 *		None.
158 *
159 *------------------------------------------------------*
160 */
161
162static void
163MDmd5_Update (context, character)
164VOID* context;
165unsigned int   character;
166{
167  unsigned char buf = character;
168
169  /*  MD5Update ((MD5_CTX*) context, &buf, 1); */
170
171  md5f.update (MD5_CTXP context, &buf, 1);
172}
173
174/*
175 *------------------------------------------------------*
176 *
177 *	MDmd5_UpdateBuf --
178 *
179 *	------------------------------------------------*
180 *	Update the internal state of the message digest
181 *	generator for a character buffer.
182 *	------------------------------------------------*
183 *
184 *	Sideeffects:
185 *		As of the called procedure.
186 *
187 *	Result:
188 *		None.
189 *
190 *------------------------------------------------------*
191 */
192
193static void
194MDmd5_UpdateBuf (context, buffer, bufLen)
195VOID* context;
196unsigned char* buffer;
197int   bufLen;
198{
199  /*  MD5Update ((MD5_CTX*) context, (unsigned char*) buffer, bufLen);*/
200
201  PRTSTR ("update by %d (%s)\n", bufLen, buffer);
202#ifdef TRF_DEBUG
203  {
204    MD5_CTX* c = MD5_CTXP context;
205    PRINT ("Upd1 ABCD = %d %d %d %d\n", c->A, c->B, c->C, c->D); FL;
206  }
207#endif
208
209  md5f.update (MD5_CTXP context, (unsigned char*) buffer, bufLen);
210
211#ifdef TRF_DEBUG
212  {
213    MD5_CTX* c = MD5_CTXP context;
214    PRINT ("Upd2 ABCD = %d %d %d %d\n", c->A, c->B, c->C, c->D); FL;
215  }
216#endif
217}
218
219/*
220 *------------------------------------------------------*
221 *
222 *	MDmd5_Final --
223 *
224 *	------------------------------------------------*
225 *	Generate the digest from the internal state of
226 *	the message digest generator.
227 *	------------------------------------------------*
228 *
229 *	Sideeffects:
230 *		As of the called procedure.
231 *
232 *	Result:
233 *		None.
234 *
235 *------------------------------------------------------*
236 */
237
238static void
239MDmd5_Final (context, digest)
240VOID* context;
241VOID* digest;
242{
243#ifndef OTP
244  /*  MD5Final ((unsigned char*) digest, (MD5_CTX*) context); */
245  md5f.final ((unsigned char*) digest, MD5_CTXP context);
246#else
247    int    i;
248    unsigned char result[16];
249
250    /*    MD5Final ((unsigned char*) result, (MD5_CTX*) context);*/
251    md5f.final ((unsigned char*) result, MD5_CTXP context);
252
253    for (i = 0; i < 8; i++)
254        result[i] ^= result[i + 8];
255
256    memcpy ((VOID *) digest, (VOID *) result, DIGEST_SIZE);
257#endif
258
259#ifdef TRF_DEBUG
260  {
261    MD5_CTX* c = MD5_CTXP context;
262    PRINT ("Flsh ABCD = %d %d %d %d\n", c->A, c->B, c->C, c->D); FL;
263  }
264#endif
265}
266
267/*
268 *------------------------------------------------------*
269 *
270 *	MDmd5_Check --
271 *
272 *	------------------------------------------------*
273 *	Do global one-time initializations of the message
274 *	digest generator.
275 *	------------------------------------------------*
276 *
277 *	Sideeffects:
278 *		Loads the shared library containing the
279 *		SHA1 functionality
280 *
281 *	Result:
282 *		A standard Tcl error code.
283 *
284 *------------------------------------------------------*
285 */
286
287static int
288MDmd5_Check (interp)
289Tcl_Interp* interp;
290{
291  return TrfLoadMD5 (interp);
292#ifdef MD5_STATIC_BUILD
293  /*return TCL_OK;*/
294#else
295#endif
296}
297
298#if 0
299/* Import the MD5 code in case of static linkage.
300 */
301#ifdef MD5_STATIC_BUILD
302/*
303 * External code from here on.
304 */
305
306#ifndef OTP
307#include "../md5-crypt/md5.c" /* THREADING: import of one constant var, read-only => safe */
308#endif
309
310md5Functions md5f = {
311  0,
312  md5_init_ctx,
313  md5_process_bytes,
314  md5_finish_ctx,
315  0, /* no crypt code! */
316};
317
318#endif
319#endif
320