Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers md5.c Source File

md5.c

Go to the documentation of this file.
00001 /**
00002  * @file md5.c
00003  * @brief MD5 (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 MD5 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 1321
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 "md5.h"
00041 
00042 //Check crypto library configuration
00043 #if (MD5_SUPPORT == ENABLED)
00044 
00045 //MD5 auxiliary functions
00046 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00047 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00048 #define H(x, y, z) ((x) ^ (y) ^ (z))
00049 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00050 
00051 #define FF(a, b, c, d, x, s, k) a += F(b, c, d) + (x) + (k), a = ROL32(a, s) + (b)
00052 #define GG(a, b, c, d, x, s, k) a += G(b, c, d) + (x) + (k), a = ROL32(a, s) + (b)
00053 #define HH(a, b, c, d, x, s, k) a += H(b, c, d) + (x) + (k), a = ROL32(a, s) + (b)
00054 #define II(a, b, c, d, x, s, k) a += I(b, c, d) + (x) + (k), a = ROL32(a, s) + (b)
00055 
00056 //MD5 padding
00057 static const uint8_t padding[64] =
00058 {
00059    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00060    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00061    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00062    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00063 };
00064 
00065 //MD5 constants
00066 static const uint32_t k[64] =
00067 {
00068    0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
00069    0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
00070    0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
00071    0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
00072    0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
00073    0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
00074    0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
00075    0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
00076 };
00077 
00078 //MD5 object identifier (1.2.840.113549.2.5)
00079 static const uint8_t md5Oid[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05};
00080 
00081 //Common interface for hash algorithms
00082 const HashAlgo md5HashAlgo =
00083 {
00084    "MD5",
00085    md5Oid,
00086    sizeof(md5Oid),
00087    sizeof(Md5Context),
00088    MD5_BLOCK_SIZE,
00089    MD5_DIGEST_SIZE,
00090    (HashAlgoCompute) md5Compute,
00091    (HashAlgoInit) md5Init,
00092    (HashAlgoUpdate) md5Update,
00093    (HashAlgoFinal) md5Final
00094 };
00095 
00096 
00097 /**
00098  * @brief Digest a message using MD5
00099  * @param[in] data Pointer to the message being hashed
00100  * @param[in] length Length of the message
00101  * @param[out] digest Pointer to the calculated digest
00102  * @return Error code
00103  **/
00104 
00105 error_t md5Compute(const void *data, size_t length, uint8_t *digest)
00106 {
00107    //Allocate a memory buffer to hold the MD5 context
00108    Md5Context *context = cryptoAllocMem(sizeof(Md5Context));
00109    //Failed to allocate memory?
00110    if(context == NULL)
00111       return ERROR_OUT_OF_MEMORY;
00112 
00113    //Initialize the MD5 context
00114    md5Init(context);
00115    //Digest the message
00116    md5Update(context, data, length);
00117    //Finalize the MD5 message digest
00118    md5Final(context, digest);
00119 
00120    //Free previously allocated memory
00121    cryptoFreeMem(context);
00122    //Successful processing
00123    return NO_ERROR;
00124 }
00125 
00126 
00127 /**
00128  * @brief Initialize MD5 message digest context
00129  * @param[in] context Pointer to the MD5 context to initialize
00130  **/
00131 
00132 void md5Init(Md5Context *context)
00133 {
00134    //Set initial hash value
00135    context->h[0] = 0x67452301;
00136    context->h[1] = 0xEFCDAB89;
00137    context->h[2] = 0x98BADCFE;
00138    context->h[3] = 0x10325476;
00139 
00140    //Number of bytes in the buffer
00141    context->size = 0;
00142    //Total length of the message
00143    context->totalSize = 0;
00144 }
00145 
00146 
00147 /**
00148  * @brief Update the MD5 context with a portion of the message being hashed
00149  * @param[in] context Pointer to the MD5 context
00150  * @param[in] data Pointer to the buffer being hashed
00151  * @param[in] length Length of the buffer
00152  **/
00153 
00154 void md5Update(Md5Context *context, const void *data, size_t length)
00155 {
00156    size_t n;
00157 
00158    //Process the incoming data
00159    while(length > 0)
00160    {
00161       //The buffer can hold at most 64 bytes
00162       n = MIN(length, 64 - context->size);
00163 
00164       //Copy the data to the buffer
00165       memcpy(context->buffer + context->size, data, n);
00166 
00167       //Update the MD5 context
00168       context->size += n;
00169       context->totalSize += n;
00170       //Advance the data pointer
00171       data = (uint8_t *) data + n;
00172       //Remaining bytes to process
00173       length -= n;
00174 
00175       //Process message in 16-word blocks
00176       if(context->size == 64)
00177       {
00178          //Transform the 16-word block
00179          md5ProcessBlock(context);
00180          //Empty the buffer
00181          context->size = 0;
00182       }
00183    }
00184 }
00185 
00186 
00187 /**
00188  * @brief Finish the MD5 message digest
00189  * @param[in] context Pointer to the MD5 context
00190  * @param[out] digest Calculated digest (optional parameter)
00191  **/
00192 
00193 void md5Final(Md5Context *context, uint8_t *digest)
00194 {
00195    uint_t i;
00196    size_t paddingSize;
00197    uint64_t totalSize;
00198 
00199    //Length of the original message (before padding)
00200    totalSize = context->totalSize * 8;
00201 
00202    //Pad the message so that its length is congruent to 56 modulo 64
00203    if(context->size < 56)
00204       paddingSize = 56 - context->size;
00205    else
00206       paddingSize = 64 + 56 - context->size;
00207 
00208    //Append padding
00209    md5Update(context, padding, paddingSize);
00210 
00211    //Append the length of the original message
00212    context->x[14] = htole32((uint32_t) totalSize);
00213    context->x[15] = htole32((uint32_t) (totalSize >> 32));
00214 
00215    //Calculate the message digest
00216    md5ProcessBlock(context);
00217 
00218    //Convert from host byte order to little-endian byte order
00219    for(i = 0; i < 4; i++)
00220       context->h[i] = htole32(context->h[i]);
00221 
00222    //Copy the resulting digest
00223    if(digest != NULL)
00224       memcpy(digest, context->digest, MD5_DIGEST_SIZE);
00225 }
00226 
00227 
00228 /**
00229  * @brief Process message in 16-word blocks
00230  * @param[in] context Pointer to the MD5 context
00231  **/
00232 
00233 void md5ProcessBlock(Md5Context *context)
00234 {
00235    uint_t i;
00236 
00237    //Initialize the 4 working registers
00238    uint32_t a = context->h[0];
00239    uint32_t b = context->h[1];
00240    uint32_t c = context->h[2];
00241    uint32_t d = context->h[3];
00242 
00243    //Process message in 16-word blocks
00244    uint32_t *x = context->x;
00245 
00246    //Convert from little-endian byte order to host byte order
00247    for(i = 0; i < 16; i++)
00248       x[i] = letoh32(x[i]);
00249 
00250    //Round 1
00251    FF(a, b, c, d, x[0],  7,  k[0]);
00252    FF(d, a, b, c, x[1],  12, k[1]);
00253    FF(c, d, a, b, x[2],  17, k[2]);
00254    FF(b, c, d, a, x[3],  22, k[3]);
00255    FF(a, b, c, d, x[4],  7,  k[4]);
00256    FF(d, a, b, c, x[5],  12, k[5]);
00257    FF(c, d, a, b, x[6],  17, k[6]);
00258    FF(b, c, d, a, x[7],  22, k[7]);
00259    FF(a, b, c, d, x[8],  7,  k[8]);
00260    FF(d, a, b, c, x[9],  12, k[9]);
00261    FF(c, d, a, b, x[10], 17, k[10]);
00262    FF(b, c, d, a, x[11], 22, k[11]);
00263    FF(a, b, c, d, x[12], 7,  k[12]);
00264    FF(d, a, b, c, x[13], 12, k[13]);
00265    FF(c, d, a, b, x[14], 17, k[14]);
00266    FF(b, c, d, a, x[15], 22, k[15]);
00267 
00268    //Round 2
00269    GG(a, b, c, d, x[1],  5,  k[16]);
00270    GG(d, a, b, c, x[6],  9,  k[17]);
00271    GG(c, d, a, b, x[11], 14, k[18]);
00272    GG(b, c, d, a, x[0],  20, k[19]);
00273    GG(a, b, c, d, x[5],  5,  k[20]);
00274    GG(d, a, b, c, x[10], 9,  k[21]);
00275    GG(c, d, a, b, x[15], 14, k[22]);
00276    GG(b, c, d, a, x[4],  20, k[23]);
00277    GG(a, b, c, d, x[9],  5,  k[24]);
00278    GG(d, a, b, c, x[14], 9,  k[25]);
00279    GG(c, d, a, b, x[3],  14, k[26]);
00280    GG(b, c, d, a, x[8],  20, k[27]);
00281    GG(a, b, c, d, x[13], 5,  k[28]);
00282    GG(d, a, b, c, x[2],  9,  k[29]);
00283    GG(c, d, a, b, x[7],  14, k[30]);
00284    GG(b, c, d, a, x[12], 20, k[31]);
00285 
00286    //Round 3
00287    HH(a, b, c, d, x[5],  4,  k[32]);
00288    HH(d, a, b, c, x[8],  11, k[33]);
00289    HH(c, d, a, b, x[11], 16, k[34]);
00290    HH(b, c, d, a, x[14], 23, k[35]);
00291    HH(a, b, c, d, x[1],  4,  k[36]);
00292    HH(d, a, b, c, x[4],  11, k[37]);
00293    HH(c, d, a, b, x[7],  16, k[38]);
00294    HH(b, c, d, a, x[10], 23, k[39]);
00295    HH(a, b, c, d, x[13], 4,  k[40]);
00296    HH(d, a, b, c, x[0],  11, k[41]);
00297    HH(c, d, a, b, x[3],  16, k[42]);
00298    HH(b, c, d, a, x[6],  23, k[43]);
00299    HH(a, b, c, d, x[9],  4,  k[44]);
00300    HH(d, a, b, c, x[12], 11, k[45]);
00301    HH(c, d, a, b, x[15], 16, k[46]);
00302    HH(b, c, d, a, x[2],  23, k[47]);
00303 
00304    //Round 4
00305    II(a, b, c, d, x[0],  6,  k[48]);
00306    II(d, a, b, c, x[7],  10, k[49]);
00307    II(c, d, a, b, x[14], 15, k[50]);
00308    II(b, c, d, a, x[5],  21, k[51]);
00309    II(a, b, c, d, x[12], 6,  k[52]);
00310    II(d, a, b, c, x[3],  10, k[53]);
00311    II(c, d, a, b, x[10], 15, k[54]);
00312    II(b, c, d, a, x[1],  21, k[55]);
00313    II(a, b, c, d, x[8],  6,  k[56]);
00314    II(d, a, b, c, x[15], 10, k[57]);
00315    II(c, d, a, b, x[6],  15, k[58]);
00316    II(b, c, d, a, x[13], 21, k[59]);
00317    II(a, b, c, d, x[4],  6,  k[60]);
00318    II(d, a, b, c, x[11], 10, k[61]);
00319    II(c, d, a, b, x[2],  15, k[62]);
00320    II(b, c, d, a, x[9],  21, k[63]);
00321 
00322    //Update the hash value
00323    context->h[0] += a;
00324    context->h[1] += b;
00325    context->h[2] += c;
00326    context->h[3] += d;
00327 }
00328 
00329 #endif
00330