md2.c

Go to the documentation of this file.
00001 
00049 /*#*
00050  *#* $Log$
00051  *#* Revision 1.17  2007/06/07 16:06:39  batt
00052  *#* Fix some doxygen errors.
00053  *#*
00054  *#* Revision 1.16  2007/02/15 13:29:49  asterix
00055  *#* Add MD2_DIGEST_LEN macro.
00056  *#*
00057  *#* Revision 1.15  2007/02/06 15:53:34  asterix
00058  *#* Add ROTR macro in m2d_perm, add comments, typos.
00059  *#*
00060  *#* Revision 1.13  2007/02/05 18:44:42  asterix
00061  *#* Add md2_perm function.
00062  *#*
00063  *#* Revision 1.12  2007/02/05 16:52:44  asterix
00064  *#* Add define for harvard architecture.
00065  *#*
00066  *#* Revision 1.11  2007/02/02 18:15:31  asterix
00067  *#* Add function MD2_test. Fix bug in md2_update function.
00068  *#*
00069  *#* Revision 1.9  2007/02/02 13:10:01  asterix
00070  *#* Fix some bugs in md2_pad and md2_update fuction.
00071  *#*
00072  *#* Revision 1.8  2007/02/01 14:45:56  asterix
00073  *#* Rewrite md2_update function and fix some bug.
00074  *#*
00075  *#* Revision 1.7  2007/01/31 18:04:15  asterix
00076  *#* Write md2_end function
00077  *#*
00078  *#* Revision 1.4  2007/01/31 13:51:57  asterix
00079  *#* Write md2_compute function.
00080  *#*
00081  *#* Revision 1.2  2007/01/30 17:31:44  asterix
00082  *#* Add function prototypes.
00083  *#*
00084  *#* Revision 1.1  2007/01/30 15:53:26  batt
00085  *#* Add first md2 skel.
00086  *#*
00087  *#*/
00088 
00089 #include "md2.h"
00090 
00091 #include <string.h>           //memset(), memcpy();
00092 #include <cfg/compiler.h>
00093 #include <cfg/debug.h>        //ASSERT()
00094 #include <cfg/macros.h>       //MIN(), countof(), ROTR();
00095 #include <cpu/pgm.h>
00096 
00097 
00098 #if CONFIG_MD2_STD_PERM
00099     /*
00100     * Official array of 256 byte pemutation contructed from digits of pi, defined
00101     * in the RFC 1319.
00102     */
00103     static const uint8_t PGM_ATTR md2_perm[256] =
00104     {
00105     41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
00106     19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
00107     76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
00108     138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
00109     245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
00110     148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
00111     39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
00112     181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
00113     150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
00114     112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
00115     96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
00116     85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
00117     234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
00118     129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
00119     8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
00120     203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
00121     166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
00122     31, 26, 219, 153, 141, 51, 159, 17, 131, 20
00123     };
00124 
00125     #define MD2_PERM(x) PGM_READ_CHAR(&md2_perm[x])
00126 #else
00127 
00135     #define K1 5
00136     #define K2 3
00137     #define R  2
00138     #define X  172
00139     /*\}*/
00140 
00141     static uint8_t md2_perm(uint8_t i)
00142     {
00143 
00144         i = i * K1;
00145         i = ROTR(i, R);
00146         i ^=  X;
00147         i = i * K2;
00148 
00149         return i;
00150     }
00151 
00152     #define MD2_PERM(x) md2_perm(x)
00153 
00154 #endif
00155 
00156 
00161 static void md2_pad(void *_block, size_t len_pad)
00162 {
00163     uint8_t *block;
00164 
00165     block = (uint8_t *)_block;
00166 
00167     ASSERT(len_pad <= CONFIG_MD2_BLOCK_LEN);
00168 
00169     /*
00170      * Fill input block with len_pad char.
00171      */
00172     memset(block, len_pad, len_pad);
00173 
00174 }
00175 
00176 static void md2_compute(void *_state, void *_checksum, void *_block)
00177 {
00178     int i = 0;
00179     uint16_t t = 0;
00180     uint8_t compute_array[COMPUTE_ARRAY_LEN];
00181     uint8_t *state;
00182     uint8_t *checksum;
00183     uint8_t *block;
00184 
00185     state = (uint8_t *)_state;
00186     checksum  = (uint8_t *)_checksum;
00187     block = (uint8_t *)_block;
00188 
00189     /*
00190      * Copy state and checksum context in compute array.
00191      */
00192     memcpy(compute_array, state, CONFIG_MD2_BLOCK_LEN);
00193     memcpy(compute_array + CONFIG_MD2_BLOCK_LEN, block, CONFIG_MD2_BLOCK_LEN);
00194 
00195     /*
00196      * Fill compute array with state XOR block
00197      */
00198     for(i = 0; i < CONFIG_MD2_BLOCK_LEN; i++)
00199         compute_array[i + (CONFIG_MD2_BLOCK_LEN * 2)] = state[i] ^ block[i];
00200 
00201     /*
00202      * Encryt block.
00203      */
00204     for(i = 0; i < NUM_COMPUTE_ROUNDS; i++)
00205     {
00206         for(int j = 0; j < COMPUTE_ARRAY_LEN; j++)
00207         {
00208             compute_array[j] ^= MD2_PERM(t);
00209             t = compute_array[j];
00210         }
00211 
00212         t = (t + i) & 0xff; //modulo 256.
00213     }
00214     /*
00215      * Update checksum.
00216      */
00217     t = checksum[CONFIG_MD2_BLOCK_LEN - 1];
00218 
00219     for(i = 0; i < CONFIG_MD2_BLOCK_LEN; i++)
00220     {
00221         checksum[i]  ^= MD2_PERM(block[i] ^ t);
00222         t = checksum[i];
00223     }
00224 
00225     /*
00226      * Update state and clean compute array.
00227      */
00228     memcpy(state, compute_array, CONFIG_MD2_BLOCK_LEN);
00229     memset(compute_array, 0, sizeof(compute_array));
00230 }
00231 
00237 void md2_init(Md2Context *context)
00238 {
00239 
00240     memset(context, 0, sizeof(Md2Context));
00241 
00242 }
00243 
00247 void md2_update(Md2Context *context, const void *_block_in, size_t block_len)
00248 {
00249 
00250     const uint8_t *block_in;
00251     size_t cpy_len;
00252 
00253 
00254     block_in = (const uint8_t *)_block_in;
00255 
00256     while(block_len > 0)
00257     {
00258         /*
00259          * Choose a number of block that fill input context buffer.
00260          */
00261         cpy_len = MIN(block_len, CONFIG_MD2_BLOCK_LEN - context->counter);
00262 
00263 
00264         /*
00265          * Copy in the buffer input block.
00266          */
00267         memcpy(&context->buffer[context->counter], block_in, cpy_len);
00268 
00269         /*
00270          * Update a context counter, input block length and remaning
00271          * context buffer block lenght.
00272          */
00273         context->counter += cpy_len;
00274         block_len -= cpy_len;
00275         block_in += cpy_len;
00276 
00277         /*
00278          * If buffer is full, compute it.
00279          */
00280         if (context->counter >= CONFIG_MD2_BLOCK_LEN)
00281         {
00282             md2_compute(context->state, context->checksum, context->buffer);
00283             context->counter = 0;
00284         }
00285     }
00286 
00287 
00288 }
00297 uint8_t  *md2_end(Md2Context *context)
00298 {
00299 
00300     uint8_t buf[CONFIG_MD2_BLOCK_LEN];
00301 
00302     /*
00303      * Fill remaning empty context buffer.
00304      */
00305     md2_pad(buf, CONFIG_MD2_BLOCK_LEN - context->counter);
00306 
00307     /*
00308      * Update context buffer and compute it.
00309      */
00310     md2_update(context, buf, CONFIG_MD2_BLOCK_LEN - context->counter);
00311 
00312     /*
00313      * Add context checksum to message input.
00314      */
00315     md2_update(context, context->checksum, CONFIG_MD2_BLOCK_LEN);
00316 
00317 
00318     return context->state; //return a pointer to message digest.
00319 }
00329 bool md2_test(void)
00330 {
00331 
00332     Md2Context context;
00333 
00334     const char *test[] =
00335     {
00336         "",
00337         "message digest",
00338         "abcdefghijklmnopqrstuvwxyz",
00339         "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
00340     };
00341 
00342 
00343     const char *result[] = {
00344         "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69\x27\x73",
00345         "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe\x06\xb0",
00346         "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47\x94\x0b",
00347         "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3\xef\xd8",
00348     };
00349 
00350 
00351     for (size_t i = 0; i < countof(test); i++)
00352     {
00353         md2_init(&context);
00354         md2_update(&context, test[i], strlen(test[i]));
00355 
00356         if(memcmp(result[i], md2_end(&context), MD2_DIGEST_LEN))
00357             return false;
00358     }
00359 
00360     return true;
00361 }
00362 
00363 #if 0
00364 
00365 #include <stdio.h>
00366 int main(int argc, char * argv[])
00367 {
00368 
00369     if(md2_test())
00370         printf("MD2 algorithm work well!\n");
00371     else
00372         printf("MD2 algorithm doesn't work well.\n");
00373 
00374 }
00375 
00376 #endif
00377