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