00001
00048 #include "md2.h"
00049
00050 #include <string.h>
00051 #include <cfg/compiler.h>
00052 #include <cfg/debug.h>
00053 #include <cfg/macros.h>
00054 #include <cpu/pgm.h>
00055
00056
00057 #if CONFIG_MD2_STD_PERM
00058
00059
00060
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
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
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
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
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;
00172 }
00173
00174
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
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
00219
00220 cpy_len = MIN(block_len, CONFIG_MD2_BLOCK_LEN - context->counter);
00221
00222
00223
00224
00225
00226 memcpy(&context->buffer[context->counter], block_in, cpy_len);
00227
00228
00229
00230
00231
00232 context->counter += cpy_len;
00233 block_len -= cpy_len;
00234 block_in += cpy_len;
00235
00236
00237
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
00263
00264 md2_pad(buf, CONFIG_MD2_BLOCK_LEN - context->counter);
00265
00266
00267
00268
00269 md2_update(context, buf, CONFIG_MD2_BLOCK_LEN - context->counter);
00270
00271
00272
00273
00274 md2_update(context, context->checksum, CONFIG_MD2_BLOCK_LEN);
00275
00276
00277 return context->state;
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