Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers md2.c Source File

md2.c

Go to the documentation of this file.
00001 /**
00002  * @file md2.c
00003  * @brief MD2 (Message-Digest Algorithm)
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneCrypto Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @section Description
00026  *
00027  * The MD2 algorithm takes as input a message of arbitrary length and produces
00028  * as output a 128-bit message digest of the input. Refer to RFC 1319
00029  *
00030  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00031  * @version 1.7.6
00032  **/
00033 
00034 //Switch to the appropriate trace level
00035 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
00036 
00037 //Dependencies
00038 #include <string.h>
00039 #include "crypto.h"
00040 #include "md2.h"
00041 
00042 //Check crypto library configuration
00043 #if (MD2_SUPPORT == ENABLED)
00044 
00045 //MD2 constants
00046 static const uint8_t s[256] =
00047 {
00048    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
00049    0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
00050    0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
00051    0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
00052    0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
00053    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
00054    0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
00055    0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
00056    0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
00057    0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
00058    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
00059    0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
00060    0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
00061    0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
00062    0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
00063    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14,
00064 };
00065 
00066 //MD2 object identifier (1.2.840.113549.2.2)
00067 static const uint8_t md2Oid[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02};
00068 
00069 //Common interface for hash algorithms
00070 const HashAlgo md2HashAlgo =
00071 {
00072    "MD2",
00073    md2Oid,
00074    sizeof(md2Oid),
00075    sizeof(Md2Context),
00076    MD2_BLOCK_SIZE,
00077    MD2_DIGEST_SIZE,
00078    (HashAlgoCompute) md2Compute,
00079    (HashAlgoInit) md2Init,
00080    (HashAlgoUpdate) md2Update,
00081    (HashAlgoFinal) md2Final
00082 };
00083 
00084 
00085 /**
00086  * @brief Digest a message using MD2
00087  * @param[in] data Pointer to the message being hashed
00088  * @param[in] length Length of the message
00089  * @param[out] digest Pointer to the calculated digest
00090  * @return Error code
00091  **/
00092 
00093 error_t md2Compute(const void *data, size_t length, uint8_t *digest)
00094 {
00095    //Allocate a memory buffer to hold the MD2 context
00096    Md2Context *context = cryptoAllocMem(sizeof(Md2Context));
00097    //Failed to allocate memory?
00098    if(context == NULL)
00099       return ERROR_OUT_OF_MEMORY;
00100 
00101    //Initialize the MD2 context
00102    md2Init(context);
00103    //Digest the message
00104    md2Update(context, data, length);
00105    //Finalize the MD2 message digest
00106    md2Final(context, digest);
00107 
00108    //Free previously allocated memory
00109    cryptoFreeMem(context);
00110    //Successful processing
00111    return NO_ERROR;
00112 }
00113 
00114 
00115 /**
00116  * @brief Initialize MD2 message digest context
00117  * @param[in] context Pointer to the MD2 context to initialize
00118  **/
00119 
00120 void md2Init(Md2Context *context)
00121 {
00122    //Initialize the 48-byte buffer X
00123    memset(context->x, 0, 48);
00124    //Clear checksum
00125    memset(context->c, 0, 16);
00126    //Number of bytes in the buffer
00127    context->size = 0;
00128 }
00129 
00130 
00131 /**
00132  * @brief Update the MD2 context with a portion of the message being hashed
00133  * @param[in] context Pointer to the MD2 context
00134  * @param[in] data Pointer to the buffer being hashed
00135  * @param[in] length Length of the buffer
00136  **/
00137 
00138 void md2Update(Md2Context *context, const void *data, size_t length)
00139 {
00140    size_t n;
00141 
00142    //Process the incoming data
00143    while(length > 0)
00144    {
00145       //The buffer can hold at most 16 bytes
00146       n = MIN(length, 16 - context->size);
00147 
00148       //Copy the data to the buffer
00149       memcpy(context->m + context->size, data, n);
00150 
00151       //Update the MD2 context
00152       context->size += n;
00153       //Advance the data pointer
00154       data = (uint8_t *) data + n;
00155       //Remaining bytes to process
00156       length -= n;
00157 
00158       //Process message in 16-word blocks
00159       if(context->size == 16)
00160       {
00161          //Transform the 16-word block
00162          md2ProcessBlock(context->m, context->x, context->c);
00163          //Empty the buffer
00164          context->size = 0;
00165       }
00166    }
00167 }
00168 
00169 
00170 /**
00171  * @brief Finish the MD2 message digest
00172  * @param[in] context Pointer to the MD2 context
00173  * @param[out] digest Calculated digest (optional parameter)
00174  **/
00175 
00176 void md2Final(Md2Context *context, uint8_t *digest)
00177 {
00178    uint_t n;
00179 
00180    //Pad the message so that its length is congruent to 0 modulo 16
00181    n = 16 - context->size;
00182 
00183    //Append padding bytes
00184    memset(context->m + context->size, n, n);
00185    //Transform the 16-word block
00186    md2ProcessBlock(context->m, context->x, context->c);
00187 
00188    //Append the checksum
00189    memcpy(context->m, context->c, 16);
00190    //Transform the 16-word block
00191    md2ProcessBlock(context->m, context->x, context->c);
00192 
00193    //Copy the resulting digest
00194    if(digest != NULL)
00195       memcpy(digest, context->digest, MD2_DIGEST_SIZE);
00196 }
00197 
00198 
00199 /**
00200  * @brief Process message in 16-word blocks
00201  * @param[in] m 16-byte data block to process
00202  * @param[in,out] x 48-byte buffer
00203  * @param[in,out] c 16-byte checksum
00204  **/
00205 
00206 void md2ProcessBlock(const uint8_t *m, uint8_t *x, uint8_t *c)
00207 {
00208    uint_t j;
00209    uint_t k;
00210    uint8_t t;
00211 
00212    //Update checksum
00213    for(t = c[15], j = 0; j < 16; j++)
00214    {
00215       c[j] ^= s[m[j] ^ t];
00216       t = c[j];
00217    }
00218 
00219    //Copy current block into X
00220    for(j = 0; j < 16; j++)
00221    {
00222       x[16 + j] = m[j];
00223       x[32 + j] = x[16 + j] ^ x[j];
00224    }
00225 
00226    //Encrypt block (18 rounds)
00227    for(t = 0, j = 0; j < 18; j++)
00228    {
00229       //Round j
00230       for(k = 0; k < 48; k++)
00231       {
00232          x[k] ^= s[t];
00233          t = x[k];
00234       }
00235 
00236       //Set t to (t + j) modulo 256
00237       t = (t + j) & 0xFF;
00238    }
00239 }
00240 
00241 #endif
00242