4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
33 * \brief MD2 Message-Digest algorithm.
35 * The MD2 algorithm work with a constant array of 256 permutationt
36 * defined in RFC1319. If you don't want to use a standard array of
37 * permutatione you can use a md2_perm() function that generate an
38 * array of 256 "casual" permutation. To swich from a standard array
39 * to md2_perm function you must chanche CONFIG_MD2_STD_PERM defined in
41 * If you need to store array in program memory you must define
42 * a macro _PROGMEM (for more info see mware/pgm.h).
46 * \author Daniele Basile <asterix@develer.com>
51 *#* Revision 1.17 2007/06/07 16:06:39 batt
52 *#* Fix some doxygen errors.
54 *#* Revision 1.16 2007/02/15 13:29:49 asterix
55 *#* Add MD2_DIGEST_LEN macro.
57 *#* Revision 1.15 2007/02/06 15:53:34 asterix
58 *#* Add ROTR macro in m2d_perm, add comments, typos.
60 *#* Revision 1.13 2007/02/05 18:44:42 asterix
61 *#* Add md2_perm function.
63 *#* Revision 1.12 2007/02/05 16:52:44 asterix
64 *#* Add define for harvard architecture.
66 *#* Revision 1.11 2007/02/02 18:15:31 asterix
67 *#* Add function MD2_test. Fix bug in md2_update function.
69 *#* Revision 1.9 2007/02/02 13:10:01 asterix
70 *#* Fix some bugs in md2_pad and md2_update fuction.
72 *#* Revision 1.8 2007/02/01 14:45:56 asterix
73 *#* Rewrite md2_update function and fix some bug.
75 *#* Revision 1.7 2007/01/31 18:04:15 asterix
76 *#* Write md2_end function
78 *#* Revision 1.4 2007/01/31 13:51:57 asterix
79 *#* Write md2_compute function.
81 *#* Revision 1.2 2007/01/30 17:31:44 asterix
82 *#* Add function prototypes.
84 *#* Revision 1.1 2007/01/30 15:53:26 batt
85 *#* Add first md2 skel.
91 #include <string.h> //memset(), memcpy();
92 #include <cfg/compiler.h>
93 #include <cfg/debug.h> //ASSERT()
94 #include <cfg/macros.h> //MIN(), countof(), ROTR();
95 #include <mware/pgm.h>
98 #if CONFIG_MD2_STD_PERM
100 * Official array of 256 byte pemutation contructed from digits of pi, defined
103 static const uint8_t PGM_ATTR md2_perm[256] =
105 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
106 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
107 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
108 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
109 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
110 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
111 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
112 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
113 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
114 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
115 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
116 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
117 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
118 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
119 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
120 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
121 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
122 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
125 #define MD2_PERM(x) PGM_READ_CHAR(&md2_perm[x])
128 * Md2_perm() function generate an array of 256 "casual" permutation.
132 * Costant define for computing an array of 256 "casual" permutation.
141 static uint8_t md2_perm(uint8_t i)
152 #define MD2_PERM(x) md2_perm(x)
158 * Pad function. Put len_pad unsigned char in
161 static void md2_pad(void *_block, size_t len_pad)
165 block = (uint8_t *)_block;
167 ASSERT(len_pad <= CONFIG_MD2_BLOCK_LEN);
170 * Fill input block with len_pad char.
172 memset(block, len_pad, len_pad);
176 static void md2_compute(void *_state, void *_checksum, void *_block)
180 uint8_t compute_array[COMPUTE_ARRAY_LEN];
185 state = (uint8_t *)_state;
186 checksum = (uint8_t *)_checksum;
187 block = (uint8_t *)_block;
190 * Copy state and checksum context in compute array.
192 memcpy(compute_array, state, CONFIG_MD2_BLOCK_LEN);
193 memcpy(compute_array + CONFIG_MD2_BLOCK_LEN, block, CONFIG_MD2_BLOCK_LEN);
196 * Fill compute array with state XOR block
198 for(i = 0; i < CONFIG_MD2_BLOCK_LEN; i++)
199 compute_array[i + (CONFIG_MD2_BLOCK_LEN * 2)] = state[i] ^ block[i];
204 for(i = 0; i < NUM_COMPUTE_ROUNDS; i++)
206 for(int j = 0; j < COMPUTE_ARRAY_LEN; j++)
208 compute_array[j] ^= MD2_PERM(t);
209 t = compute_array[j];
212 t = (t + i) & 0xff; //modulo 256.
217 t = checksum[CONFIG_MD2_BLOCK_LEN - 1];
219 for(i = 0; i < CONFIG_MD2_BLOCK_LEN; i++)
221 checksum[i] ^= MD2_PERM(block[i] ^ t);
226 * Update state and clean compute array.
228 memcpy(state, compute_array, CONFIG_MD2_BLOCK_LEN);
229 memset(compute_array, 0, sizeof(compute_array));
233 * Algorithm initialization.
235 * \param context empty context.
237 void md2_init(Md2Context *context)
240 memset(context, 0, sizeof(Md2Context));
247 void md2_update(Md2Context *context, const void *_block_in, size_t block_len)
250 const uint8_t *block_in;
254 block_in = (const uint8_t *)_block_in;
259 * Choose a number of block that fill input context buffer.
261 cpy_len = MIN(block_len, CONFIG_MD2_BLOCK_LEN - context->counter);
265 * Copy in the buffer input block.
267 memcpy(&context->buffer[context->counter], block_in, cpy_len);
270 * Update a context counter, input block length and remaning
271 * context buffer block lenght.
273 context->counter += cpy_len;
274 block_len -= cpy_len;
278 * If buffer is full, compute it.
280 if (context->counter >= CONFIG_MD2_BLOCK_LEN)
282 md2_compute(context->state, context->checksum, context->buffer);
283 context->counter = 0;
290 * Ends an MD2 message digest operation.
291 * This fuction take an context and return a pointer
294 * \param context in input.
295 * \return a pointer to context state (message digest).
297 uint8_t *md2_end(Md2Context *context)
300 uint8_t buf[CONFIG_MD2_BLOCK_LEN];
303 * Fill remaning empty context buffer.
305 md2_pad(buf, CONFIG_MD2_BLOCK_LEN - context->counter);
308 * Update context buffer and compute it.
310 md2_update(context, buf, CONFIG_MD2_BLOCK_LEN - context->counter);
313 * Add context checksum to message input.
315 md2_update(context, context->checksum, CONFIG_MD2_BLOCK_LEN);
318 return context->state; //return a pointer to message digest.
322 * This function test MD2 algorithm with a standard string specified
325 * \note This test work with official array of 256 byte pemutation
326 * contructed from digits of pi, defined in the RFC 1319.
338 "abcdefghijklmnopqrstuvwxyz",
339 "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
343 const uint8_t *result[] = {
344 "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69\x27\x73",
345 "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe\x06\xb0",
346 "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47\x94\x0b",
347 "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3\xef\xd8",
351 for (int i = 0; i < countof(test); i++)
354 md2_update(&context, test[i], strlen(test[i]));
356 if(memcmp(result[i], md2_end(&context), MD2_DIGEST_LEN))
366 int main(int argc, char * argv[])
370 printf("MD2 algorithm work well!\n");
372 printf("MD2 algorithm doesn't work well.\n");