Merge from vendor branch OPENSSL:
[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.11 2006/01/17 15:35:56 phk Exp $
3  * $DragonFly: src/lib/libmd/md2c.c,v 1.3 2008/09/11 20:25:34 swildner 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 <sys/types.h>
25 #include <string.h>
26 #include "md2.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, in, inputLen)
102 MD2_CTX *context;                                        /* context */
103 const void *in;                                /* input block */
104 unsigned int inputLen;                     /* length of input block */
105 {
106   unsigned int i, idx, partLen;
107   const unsigned char *input = in;
108
109   /* Update number of bytes mod 16 */
110   idx = context->count;
111   context->count = (idx + inputLen) & 0xf;
112
113   partLen = 16 - idx;
114
115   /* Transform as many times as possible.
116     */
117   if (inputLen >= partLen) {
118     memcpy
119       ((POINTER)&context->buffer[idx], (POINTER)input, partLen);
120     MD2Transform (context->state, context->checksum, context->buffer);
121
122     for (i = partLen; i + 15 < inputLen; i += 16)
123       MD2Transform (context->state, context->checksum, &input[i]);
124
125     idx = 0;
126   }
127   else
128     i = 0;
129
130   /* Buffer remaining input */
131   memcpy
132     ((POINTER)&context->buffer[idx], (POINTER)&input[i],
133      inputLen-i);
134 }
135
136 /* MD2 padding.
137  */
138 void MD2Pad (context)
139 MD2_CTX *context;                                        /* context */
140 {
141   unsigned int idx, padLen;
142
143   /* Pad out to multiple of 16.
144    */
145   idx = context->count;
146   padLen = 16 - idx;
147   MD2Update (context, PADDING[padLen], padLen);
148
149   /* Extend with checksum */
150   MD2Update (context, context->checksum, 16);
151 }
152
153 /* MD2 finalization. Ends an MD2 message-digest operation, writing the
154      message digest and zeroizing the context.
155  */
156 void MD2Final (digest, context)
157 unsigned char digest[16];                         /* message digest */
158 MD2_CTX *context;                                        /* context */
159 {
160   /* Do padding */
161   MD2Pad (context);
162
163   /* Store state in digest */
164   memcpy ((POINTER)digest, (POINTER)context->state, 16);
165
166   /* Zeroize sensitive information.
167    */
168   memset ((POINTER)context, 0, sizeof (*context));
169 }
170
171 /* MD2 basic transformation. Transforms state and updates checksum
172      based on block.
173  */
174 static void MD2Transform (state, checksum, block)
175 unsigned char state[16];
176 unsigned char checksum[16];
177 const unsigned char block[16];
178 {
179   unsigned int i, j, t;
180   unsigned char x[48];
181
182   /* Form encryption block from state, block, state ^ block.
183    */
184   memcpy ((POINTER)x, (POINTER)state, 16);
185   memcpy ((POINTER)x+16, (POINTER)block, 16);
186   for (i = 0; i < 16; i++)
187     x[i+32] = state[i] ^ block[i];
188
189   /* Encrypt block (18 rounds).
190    */
191   t = 0;
192   for (i = 0; i < 18; i++) {
193     for (j = 0; j < 48; j++)
194       t = x[j] ^= PI_SUBST[t];
195     t = (t + i) & 0xff;
196   }
197
198   /* Save new state */
199   memcpy ((POINTER)state, (POINTER)x, 16);
200
201   /* Update checksum.
202    */
203   t = checksum[15];
204   for (i = 0; i < 16; i++)
205     t = checksum[i] ^= PI_SUBST[block[i] ^ t];
206
207   /* Zeroize sensitive information.
208    */
209   memset ((POINTER)x, 0, sizeof (x));
210 }