]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libmd/md2c.c
Move OBJFORMAT hack to the correct line; what can I say, it was very
[FreeBSD/FreeBSD.git] / lib / libmd / md2c.c
1 /* MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm
2  * $Id: md2c.c,v 1.5 1997/02/22 15:07:15 peter Exp $
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
28 typedef unsigned char *POINTER;
29 typedef u_int16_t UINT2;
30 typedef u_int32_t UINT4;
31
32 #define PROTO_LIST(list) list
33
34 static 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  */
40 static 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
61 static 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  */
87 void MD2Init (context)
88 MD2_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  */
100 void MD2Update (context, input, inputLen)
101 MD2_CTX *context;                                        /* context */
102 const unsigned char *input;                                /* input block */
103 unsigned 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  */
136 void MD2Pad (context)
137 MD2_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  */
154 void MD2Final (digest, context)
155 unsigned char digest[16];                         /* message digest */
156 MD2_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  */
172 static void MD2Transform (state, checksum, block)
173 unsigned char state[16];
174 unsigned char checksum[16];
175 const 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 }