md2.c

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