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