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