1 /*
2  * adler.c --
3  *
4  *	Implements and registers message digest generator ADLER32.
5  *
6  *
7  * Copyright (c) 1996 Andreas Kupries (andreas_kupries@users.sourceforge.net)
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: adler.c,v 1.8 2003/01/09 21:27:09 andreas_kupries Exp $
28  */
29 
30 #include "transformInt.h"
31 #include <zlib.h>
32 
33 /*
34  * Generator description
35  * ---------------------
36  *
37  * The ADLER32 algorithm (contained in library 'zlib')
38  * is used to compute a message digest.
39  */
40 
41 #define DIGEST_SIZE               4 /* byte == 32 bit */
42 #define CTX_TYPE                  uLong
43 
44 /*
45  * Declarations of internal procedures.
46  */
47 
48 static void MDAdler_Start     _ANSI_ARGS_ ((VOID* context));
49 static void MDAdler_Update    _ANSI_ARGS_ ((VOID* context, unsigned int character));
50 static void MDAdler_UpdateBuf _ANSI_ARGS_ ((VOID* context, unsigned char* buffer, size_t bufLen));
51 static void MDAdler_Final     _ANSI_ARGS_ ((VOID* digest, VOID* context));
52 
53 /*
54  * Generator definition.
55  */
56 
57 static Trf_MessageDigestDescription mdDescription = { /* THREADING: constant, read-only => safe */
58   "adler",
59   sizeof (CTX_TYPE),
60   DIGEST_SIZE,
61   MDAdler_Start,
62   MDAdler_Update,
63   MDAdler_UpdateBuf,
64   MDAdler_Final,
65   NULL
66 };
67 
68 #define ADLER (*((uLong*) context))
69 
70 /*
71  *------------------------------------------------------*
72  *
73  *	TrfInit_ADLER --
74  *
75  *	------------------------------------------------*
76  *	Register the generator implemented in this file.
77  *	------------------------------------------------*
78  *
79  *	Sideeffects:
80  *		As of 'Trf_Register'.
81  *
82  *	Result:
83  *		A standard Tcl error code.
84  *
85  *------------------------------------------------------*
86  */
87 
88 int
TrfInit_ADLER(interp)89 TrfInit_ADLER (interp)
90 Tcl_Interp* interp;
91 {
92   return Trf_RegisterMessageDigest (interp, &mdDescription);
93 }
94 
95 /*
96  *------------------------------------------------------*
97  *
98  *	MDAdler_Start --
99  *
100  *	------------------------------------------------*
101  *	Initialize the internal state of the message
102  *	digest generator.
103  *	------------------------------------------------*
104  *
105  *	Sideeffects:
106  *		As of the called procedure.
107  *
108  *	Result:
109  *		None.
110  *
111  *------------------------------------------------------*
112  */
113 
114 static void
MDAdler_Start(context)115 MDAdler_Start (context)
116 VOID* context;
117 {
118   START (MDAdler_Start);
119   PRINT ("Context = %p, Zf = %p\n", context, &zf);
120 
121   /* call md specific initialization here */
122 
123   ADLER = adler32 (0L, Z_NULL, 0);
124 
125   DONE (MDAdler_Start);
126 }
127 
128 /*
129  *------------------------------------------------------*
130  *
131  *	MDAdler_Update --
132  *
133  *	------------------------------------------------*
134  *	Update the internal state of the message digest
135  *	generator for a single character.
136  *	------------------------------------------------*
137  *
138  *	Sideeffects:
139  *		As of the called procedure.
140  *
141  *	Result:
142  *		None.
143  *
144  *------------------------------------------------------*
145  */
146 
147 static void
MDAdler_Update(context,character)148 MDAdler_Update (context, character)
149 VOID* context;
150 unsigned int   character;
151 {
152   /* call md specific update here */
153 
154   unsigned char buf = character;
155 
156   ADLER = adler32 (ADLER, &buf, 1);
157 }
158 
159 /*
160  *------------------------------------------------------*
161  *
162  *	MDAdler_UpdateBuf --
163  *
164  *	------------------------------------------------*
165  *	Update the internal state of the message digest
166  *	generator for a character buffer.
167  *	------------------------------------------------*
168  *
169  *	Sideeffects:
170  *		As of the called procedure.
171  *
172  *	Result:
173  *		None.
174  *
175  *------------------------------------------------------*
176  */
177 
178 static void
MDAdler_UpdateBuf(context,buffer,bufLen)179 MDAdler_UpdateBuf (context, buffer, bufLen)
180 VOID* context;
181 unsigned char* buffer;
182 size_t   bufLen;
183 {
184   /* call md specific update here */
185 
186   ADLER = adler32 (ADLER, buffer, bufLen);
187 }
188 
189 /*
190  *------------------------------------------------------*
191  *
192  *	MDAdler_Final --
193  *
194  *	------------------------------------------------*
195  *	Generate the digest from the internal state of
196  *	the message digest generator.
197  *	------------------------------------------------*
198  *
199  *	Sideeffects:
200  *		As of the called procedure.
201  *
202  *	Result:
203  *		None.
204  *
205  *------------------------------------------------------*
206  */
207 
208 static void
MDAdler_Final(digest,context)209 MDAdler_Final (digest, context)
210 VOID* context;
211 VOID* digest;
212 {
213   /* call md specific finalization here */
214 
215   uLong adler = ADLER;
216   char*   out = (char*) digest;
217 
218   /* BIGENDIAN output */
219   out [0] = (char) ((adler >> 24) & 0xff);
220   out [1] = (char) ((adler >> 16) & 0xff);
221   out [2] = (char) ((adler >>  8) & 0xff);
222   out [3] = (char) ((adler >>  0) & 0xff);
223 }
224