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