md2c.c revision 19099
1/* MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm
2 * $FreeBSD: head/lib/libmd/md2c.c 19099 1996-10-22 16:27:47Z phk $
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 finalization. Ends an MD2 message-digest operation, writing the
135     message digest and zeroizing the context.
136 */
137void MD2Final (digest, context)
138unsigned char digest[16];                         /* message digest */
139MD2_CTX *context;                                        /* context */
140{
141  unsigned int index, padLen;
142
143  /* Pad out to multiple of 16.
144   */
145  index = context->count;
146  padLen = 16 - index;
147  MD2Update (context, PADDING[padLen], padLen);
148
149  /* Extend with checksum */
150  MD2Update (context, context->checksum, 16);
151
152  /* Store state in digest */
153  memcpy ((POINTER)digest, (POINTER)context->state, 16);
154
155  /* Zeroize sensitive information.
156   */
157  memset ((POINTER)context, 0, sizeof (*context));
158}
159
160/* MD2 basic transformation. Transforms state and updates checksum
161     based on block.
162 */
163static void MD2Transform (state, checksum, block)
164unsigned char state[16];
165unsigned char checksum[16];
166const unsigned char block[16];
167{
168  unsigned int i, j, t;
169  unsigned char x[48];
170
171  /* Form encryption block from state, block, state ^ block.
172   */
173  memcpy ((POINTER)x, (POINTER)state, 16);
174  memcpy ((POINTER)x+16, (POINTER)block, 16);
175  for (i = 0; i < 16; i++)
176    x[i+32] = state[i] ^ block[i];
177
178  /* Encrypt block (18 rounds).
179   */
180  t = 0;
181  for (i = 0; i < 18; i++) {
182    for (j = 0; j < 48; j++)
183      t = x[j] ^= PI_SUBST[t];
184    t = (t + i) & 0xff;
185  }
186
187  /* Save new state */
188  memcpy ((POINTER)state, (POINTER)x, 16);
189
190  /* Update checksum.
191   */
192  t = checksum[15];
193  for (i = 0; i < 16; i++)
194    t = checksum[i] ^= PI_SUBST[block[i] ^ t];
195
196  /* Zeroize sensitive information.
197   */
198  memset ((POINTER)x, 0, sizeof (x));
199}
200