BeRTOS
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