]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libmd/md2c.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / lib / libmd / md2c.c
1 /* MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm
2  */
3
4 #include <sys/cdefs.h>
5 __FBSDID("$FreeBSD$");
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
30 typedef unsigned char *POINTER;
31 typedef u_int16_t UINT2;
32 typedef u_int32_t UINT4;
33
34 #define PROTO_LIST(list) list
35
36 static 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  */
42 static 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
63 static 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  */
89 void MD2Init (context)
90 MD2_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  */
102 void MD2Update (context, in, inputLen)
103 MD2_CTX *context;                                        /* context */
104 const void *in;                                /* input block */
105 unsigned 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  */
139 void MD2Pad (context)
140 MD2_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  */
157 void MD2Final (digest, context)
158 unsigned char digest[16];                         /* message digest */
159 MD2_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  */
175 static void MD2Transform (state, checksum, block)
176 unsigned char state[16];
177 unsigned char checksum[16];
178 const 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 }