/* MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm * $FreeBSD: src/lib/libmd/md2c.c,v 1.11 2006/01/17 15:35:56 phk Exp $ * $DragonFly: src/lib/libmd/md2c.c,v 1.4 2008/09/30 16:57:05 swildner Exp $ */ /* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All rights reserved. License to copy and use this software is granted for non-commercial Internet Privacy-Enhanced Mail provided that it is identified as the "RSA Data Security, Inc. MD2 Message Digest Algorithm" in all material mentioning or referencing this software or this function. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ #include #include #include "md2.h" typedef unsigned char *POINTER; typedef u_int16_t UINT2; typedef u_int32_t UINT4; #define PROTO_LIST(list) list static void MD2Transform PROTO_LIST ((unsigned char [16], unsigned char [16], const unsigned char [16])); /* Permutation of 0..255 constructed from the digits of pi. It gives a "random" nonlinear byte substitution operation. */ static unsigned char PI_SUBST[256] = { 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 }; static unsigned char *PADDING[] = { (unsigned char *)"", (unsigned char *)"\001", (unsigned char *)"\002\002", (unsigned char *)"\003\003\003", (unsigned char *)"\004\004\004\004", (unsigned char *)"\005\005\005\005\005", (unsigned char *)"\006\006\006\006\006\006", (unsigned char *)"\007\007\007\007\007\007\007", (unsigned char *)"\010\010\010\010\010\010\010\010", (unsigned char *)"\011\011\011\011\011\011\011\011\011", (unsigned char *)"\012\012\012\012\012\012\012\012\012\012", (unsigned char *)"\013\013\013\013\013\013\013\013\013\013\013", (unsigned char *)"\014\014\014\014\014\014\014\014\014\014\014\014", (unsigned char *) "\015\015\015\015\015\015\015\015\015\015\015\015\015", (unsigned char *) "\016\016\016\016\016\016\016\016\016\016\016\016\016\016", (unsigned char *) "\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017", (unsigned char *) "\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020" }; /* MD2 initialization. Begins an MD2 operation, writing a new context. */ int MD2Init (MD2_CTX *context) { context->count = 0; memset ((POINTER)context->state, 0, sizeof (context->state)); memset ((POINTER)context->checksum, 0, sizeof (context->checksum)); return 1; } /* MD2 block update operation. Continues an MD2 message-digest operation, processing another message block, and updating the context. */ void MD2Update (MD2_CTX *context, const void *in, unsigned int inputLen) { unsigned int i, idx, partLen; const unsigned char *input = in; /* Update number of bytes mod 16 */ idx = context->count; context->count = (idx + inputLen) & 0xf; partLen = 16 - idx; /* Transform as many times as possible. */ if (inputLen >= partLen) { memcpy ((POINTER)&context->buffer[idx], (POINTER)input, partLen); MD2Transform (context->state, context->checksum, context->buffer); for (i = partLen; i + 15 < inputLen; i += 16) MD2Transform (context->state, context->checksum, &input[i]); idx = 0; } else i = 0; /* Buffer remaining input */ memcpy ((POINTER)&context->buffer[idx], (POINTER)&input[i], inputLen-i); } /* MD2 padding. */ void MD2Pad (MD2_CTX *context) { unsigned int idx, padLen; /* Pad out to multiple of 16. */ idx = context->count; padLen = 16 - idx; MD2Update (context, PADDING[padLen], padLen); /* Extend with checksum */ MD2Update (context, context->checksum, 16); } /* MD2 finalization. Ends an MD2 message-digest operation, writing the message digest and zeroizing the context. */ void MD2Final (unsigned char digest[16], MD2_CTX *context) { /* Do padding */ MD2Pad (context); /* Store state in digest */ memcpy ((POINTER)digest, (POINTER)context->state, 16); /* Zeroize sensitive information. */ memset ((POINTER)context, 0, sizeof (*context)); } /* MD2 basic transformation. Transforms state and updates checksum based on block. */ static void MD2Transform (unsigned char state[16], unsigned char checksum[16], const unsigned char block[16]) { unsigned int i, j, t; unsigned char x[48]; /* Form encryption block from state, block, state ^ block. */ memcpy ((POINTER)x, (POINTER)state, 16); memcpy ((POINTER)x+16, (POINTER)block, 16); for (i = 0; i < 16; i++) x[i+32] = state[i] ^ block[i]; /* Encrypt block (18 rounds). */ t = 0; for (i = 0; i < 18; i++) { for (j = 0; j < 48; j++) t = x[j] ^= PI_SUBST[t]; t = (t + i) & 0xff; } /* Save new state */ memcpy ((POINTER)state, (POINTER)x, 16); /* Update checksum. */ t = checksum[15]; for (i = 0; i < 16; i++) t = checksum[i] ^= PI_SUBST[block[i] ^ t]; /* Zeroize sensitive information. */ memset ((POINTER)x, 0, sizeof (x)); }