Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / lib / libmd / md2c.c
1 /* MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm
2  * $FreeBSD: src/lib/libmd/md2c.c,v 1.7 1999/08/28 00:05:05 peter Exp $
3  * $DragonFly: src/lib/libmd/md2c.c,v 1.2 2003/06/17 04:26:50 dillon Exp $
4  */
5
6 /* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
7    rights reserved.
8
9    License to copy and use this software is granted for
10    non-commercial Internet Privacy-Enhanced Mail provided that it is
11    identified as the "RSA Data Security, Inc. MD2 Message Digest
12    Algorithm" in all material mentioning or referencing this software
13    or this function.
14
15    RSA Data Security, Inc. makes no representations concerning either
16    the merchantability of this software or the suitability of this
17    software for any particular purpose. It is provided "as is"
18    without express or implied warranty of any kind.
19
20    These notices must be retained in any copies of any part of this
21    documentation and/or software.
22  */
23
24 #include "md2.h"
25 #include <string.h>
26 #include <sys/types.h>
27
28
29 typedef unsigned char *POINTER;
30 typedef u_int16_t UINT2;
31 typedef u_int32_t UINT4;
32
33 #define PROTO_LIST(list) list
34
35 static void MD2Transform PROTO_LIST
36   ((unsigned char [16], unsigned char [16], const unsigned char [16]));
37
38 /* Permutation of 0..255 constructed from the digits of pi. It gives a
39    "random" nonlinear byte substitution operation.
40  */
41 static unsigned char PI_SUBST[256] = {
42   41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
43   19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
44   76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
45   138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
46   245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
47   148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
48   39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
49   181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
50   150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
51   112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
52   96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
53   85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
54   234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
55   129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
56   8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
57   203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
58   166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
59   31, 26, 219, 153, 141, 51, 159, 17, 131, 20
60 };
61
62 static unsigned char *PADDING[] = {
63   (unsigned char *)"",
64   (unsigned char *)"\001",
65   (unsigned char *)"\002\002",
66   (unsigned char *)"\003\003\003",
67   (unsigned char *)"\004\004\004\004",
68   (unsigned char *)"\005\005\005\005\005",
69   (unsigned char *)"\006\006\006\006\006\006",
70   (unsigned char *)"\007\007\007\007\007\007\007",
71   (unsigned char *)"\010\010\010\010\010\010\010\010",
72   (unsigned char *)"\011\011\011\011\011\011\011\011\011",
73   (unsigned char *)"\012\012\012\012\012\012\012\012\012\012",
74   (unsigned char *)"\013\013\013\013\013\013\013\013\013\013\013",
75   (unsigned char *)"\014\014\014\014\014\014\014\014\014\014\014\014",
76   (unsigned char *)
77     "\015\015\015\015\015\015\015\015\015\015\015\015\015",
78   (unsigned char *)
79     "\016\016\016\016\016\016\016\016\016\016\016\016\016\016",
80   (unsigned char *)
81     "\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017",
82   (unsigned char *)
83     "\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020"
84 };
85
86 /* MD2 initialization. Begins an MD2 operation, writing a new context.
87  */
88 void MD2Init (context)
89 MD2_CTX *context;                                        /* context */
90 {
91   context->count = 0;
92   memset ((POINTER)context->state, 0, sizeof (context->state));
93   memset
94     ((POINTER)context->checksum, 0, sizeof (context->checksum));
95 }
96
97 /* MD2 block update operation. Continues an MD2 message-digest
98      operation, processing another message block, and updating the
99      context.
100  */
101 void MD2Update (context, input, inputLen)
102 MD2_CTX *context;                                        /* context */
103 const unsigned char *input;                                /* input block */
104 unsigned int inputLen;                     /* length of input block */
105 {
106   unsigned int i, index, partLen;
107
108   /* Update number of bytes mod 16 */
109   index = context->count;
110   context->count = (index + inputLen) & 0xf;
111
112   partLen = 16 - index;
113
114   /* Transform as many times as possible.
115     */
116   if (inputLen >= partLen) {
117     memcpy
118       ((POINTER)&context->buffer[index], (POINTER)input, partLen);
119     MD2Transform (context->state, context->checksum, context->buffer);
120
121     for (i = partLen; i + 15 < inputLen; i += 16)
122       MD2Transform (context->state, context->checksum, &input[i]);
123
124     index = 0;
125   }
126   else
127     i = 0;
128
129   /* Buffer remaining input */
130   memcpy
131     ((POINTER)&context->buffer[index], (POINTER)&input[i],
132      inputLen-i);
133 }
134
135 /* MD2 padding.
136  */
137 void MD2Pad (context)
138 MD2_CTX *context;                                        /* context */
139 {
140   unsigned int index, padLen;
141
142   /* Pad out to multiple of 16.
143    */
144   index = context->count;
145   padLen = 16 - index;
146   MD2Update (context, PADDING[padLen], padLen);
147
148   /* Extend with checksum */
149   MD2Update (context, context->checksum, 16);
150 }
151
152 /* MD2 finalization. Ends an MD2 message-digest operation, writing the
153      message digest and zeroizing the context.
154  */
155 void MD2Final (digest, context)
156 unsigned char digest[16];                         /* message digest */
157 MD2_CTX *context;                                        /* context */
158 {
159   /* Do padding */
160   MD2Pad (context);
161
162   /* Store state in digest */
163   memcpy ((POINTER)digest, (POINTER)context->state, 16);
164
165   /* Zeroize sensitive information.
166    */
167   memset ((POINTER)context, 0, sizeof (*context));
168 }
169
170 /* MD2 basic transformation. Transforms state and updates checksum
171      based on block.
172  */
173 static void MD2Transform (state, checksum, block)
174 unsigned char state[16];
175 unsigned char checksum[16];
176 const unsigned char block[16];
177 {
178   unsigned int i, j, t;
179   unsigned char x[48];
180
181   /* Form encryption block from state, block, state ^ block.
182    */
183   memcpy ((POINTER)x, (POINTER)state, 16);
184   memcpy ((POINTER)x+16, (POINTER)block, 16);
185   for (i = 0; i < 16; i++)
186     x[i+32] = state[i] ^ block[i];
187
188   /* Encrypt block (18 rounds).
189    */
190   t = 0;
191   for (i = 0; i < 18; i++) {
192     for (j = 0; j < 48; j++)
193       t = x[j] ^= PI_SUBST[t];
194     t = (t + i) & 0xff;
195   }
196
197   /* Save new state */
198   memcpy ((POINTER)state, (POINTER)x, 16);
199
200   /* Update checksum.
201    */
202   t = checksum[15];
203   for (i = 0; i < 16; i++)
204     t = checksum[i] ^= PI_SUBST[block[i] ^ t];
205
206   /* Zeroize sensitive information.
207    */
208   memset ((POINTER)x, 0, sizeof (x));
209 }