Embed:
(wiki syntax)
Show/hide line numbers
md4.c
Go to the documentation of this file.
00001 /** 00002 * @file md4.c 00003 * @brief MD4 (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 MD4 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 1320 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 "md4.h" 00041 00042 //Check crypto library configuration 00043 #if (MD4_SUPPORT == ENABLED) 00044 00045 //MD4 auxiliary functions 00046 #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) 00047 #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 00048 #define H(x, y, z) ((x) ^ (y) ^ (z)) 00049 00050 #define FF(a, b, c, d, x, s) a += F(b, c, d) + (x), a = ROL32(a, s) 00051 #define GG(a, b, c, d, x, s) a += G(b, c, d) + (x) + 0x5A827999, a = ROL32(a, s) 00052 #define HH(a, b, c, d, x, s) a += H(b, c, d) + (x) + 0x6ED9EBA1, a = ROL32(a, s) 00053 00054 //MD4 padding 00055 static const uint8_t padding[64] = 00056 { 00057 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00058 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00059 0x00, 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 }; 00062 00063 //MD4 object identifier (1.2.840.113549.2.4) 00064 static const uint8_t md4Oid[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x04}; 00065 00066 //Common interface for hash algorithms 00067 const HashAlgo md4HashAlgo = 00068 { 00069 "MD4", 00070 md4Oid, 00071 sizeof(md4Oid), 00072 sizeof(Md4Context), 00073 MD4_BLOCK_SIZE, 00074 MD4_DIGEST_SIZE, 00075 (HashAlgoCompute) md4Compute, 00076 (HashAlgoInit) md4Init, 00077 (HashAlgoUpdate) md4Update, 00078 (HashAlgoFinal) md4Final 00079 }; 00080 00081 00082 /** 00083 * @brief Digest a message using MD4 00084 * @param[in] data Pointer to the message being hashed 00085 * @param[in] length Length of the message 00086 * @param[out] digest Pointer to the calculated digest 00087 * @return Error code 00088 **/ 00089 00090 error_t md4Compute(const void *data, size_t length, uint8_t *digest) 00091 { 00092 //Allocate a memory buffer to hold the MD4 context 00093 Md4Context *context = cryptoAllocMem(sizeof(Md4Context)); 00094 //Failed to allocate memory? 00095 if(context == NULL) 00096 return ERROR_OUT_OF_MEMORY; 00097 00098 //Initialize the MD4 context 00099 md4Init(context); 00100 //Digest the message 00101 md4Update(context, data, length); 00102 //Finalize the MD4 message digest 00103 md4Final(context, digest); 00104 00105 //Free previously allocated memory 00106 cryptoFreeMem(context); 00107 //Successful processing 00108 return NO_ERROR; 00109 } 00110 00111 00112 /** 00113 * @brief Initialize MD4 message digest context 00114 * @param[in] context Pointer to the MD4 context to initialize 00115 **/ 00116 00117 void md4Init(Md4Context *context) 00118 { 00119 //Set initial hash value 00120 context->h[0] = 0x67452301; 00121 context->h[1] = 0xEFCDAB89; 00122 context->h[2] = 0x98BADCFE; 00123 context->h[3] = 0x10325476; 00124 00125 //Number of bytes in the buffer 00126 context->size = 0; 00127 //Total length of the message 00128 context->totalSize = 0; 00129 } 00130 00131 00132 /** 00133 * @brief Update the MD4 context with a portion of the message being hashed 00134 * @param[in] context Pointer to the MD4 context 00135 * @param[in] data Pointer to the buffer being hashed 00136 * @param[in] length Length of the buffer 00137 **/ 00138 00139 void md4Update(Md4Context *context, const void *data, size_t length) 00140 { 00141 size_t n; 00142 00143 //Process the incoming data 00144 while(length > 0) 00145 { 00146 //The buffer can hold at most 64 bytes 00147 n = MIN(length, 64 - context->size); 00148 00149 //Copy the data to the buffer 00150 memcpy(context->buffer + context->size, data, n); 00151 00152 //Update the MD4 context 00153 context->size += n; 00154 context->totalSize += n; 00155 //Advance the data pointer 00156 data = (uint8_t *) data + n; 00157 //Remaining bytes to process 00158 length -= n; 00159 00160 //Process message in 16-word blocks 00161 if(context->size == 64) 00162 { 00163 //Transform the 16-word block 00164 md4ProcessBlock(context); 00165 //Empty the buffer 00166 context->size = 0; 00167 } 00168 } 00169 } 00170 00171 00172 /** 00173 * @brief Finish the MD4 message digest 00174 * @param[in] context Pointer to the MD4 context 00175 * @param[out] digest Calculated digest (optional parameter) 00176 **/ 00177 00178 void md4Final(Md4Context *context, uint8_t *digest) 00179 { 00180 uint_t i; 00181 size_t paddingSize; 00182 uint64_t totalSize; 00183 00184 //Length of the original message (before padding) 00185 totalSize = context->totalSize * 8; 00186 00187 //Pad the message so that its length is congruent to 56 modulo 64 00188 if(context->size < 56) 00189 paddingSize = 56 - context->size; 00190 else 00191 paddingSize = 64 + 56 - context->size; 00192 00193 //Append padding 00194 md4Update(context, padding, paddingSize); 00195 00196 //Append the length of the original message 00197 context->x[14] = htole32((uint32_t) totalSize); 00198 context->x[15] = htole32((uint32_t) (totalSize >> 32)); 00199 00200 //Calculate the message digest 00201 md4ProcessBlock(context); 00202 00203 //Convert from host byte order to little-endian byte order 00204 for(i = 0; i < 4; i++) 00205 context->h[i] = htole32(context->h[i]); 00206 00207 //Copy the resulting digest 00208 if(digest != NULL) 00209 memcpy(digest, context->digest, MD4_DIGEST_SIZE); 00210 } 00211 00212 00213 /** 00214 * @brief Process message in 16-word blocks 00215 * @param[in] context Pointer to the MD4 context 00216 **/ 00217 00218 void md4ProcessBlock(Md4Context *context) 00219 { 00220 uint_t i; 00221 00222 //Initialize the 4 working registers 00223 uint32_t a = context->h[0]; 00224 uint32_t b = context->h[1]; 00225 uint32_t c = context->h[2]; 00226 uint32_t d = context->h[3]; 00227 00228 //Process message in 16-word blocks 00229 uint32_t *x = context->x; 00230 00231 //Convert from little-endian byte order to host byte order 00232 for(i = 0; i < 16; i++) 00233 x[i] = letoh32(x[i]); 00234 00235 //Round 1 00236 FF(a, b, c, d, x[0], 3); 00237 FF(d, a, b, c, x[1], 7); 00238 FF(c, d, a, b, x[2], 11); 00239 FF(b, c, d, a, x[3], 19); 00240 FF(a, b, c, d, x[4], 3); 00241 FF(d, a, b, c, x[5], 7); 00242 FF(c, d, a, b, x[6], 11); 00243 FF(b, c, d, a, x[7], 19); 00244 FF(a, b, c, d, x[8], 3); 00245 FF(d, a, b, c, x[9], 7); 00246 FF(c, d, a, b, x[10], 11); 00247 FF(b, c, d, a, x[11], 19); 00248 FF(a, b, c, d, x[12], 3); 00249 FF(d, a, b, c, x[13], 7); 00250 FF(c, d, a, b, x[14], 11); 00251 FF(b, c, d, a, x[15], 19); 00252 00253 //Round 2 00254 GG(a, b, c, d, x[0], 3); 00255 GG(d, a, b, c, x[4], 5); 00256 GG(c, d, a, b, x[8], 9); 00257 GG(b, c, d, a, x[12], 13); 00258 GG(a, b, c, d, x[1], 3); 00259 GG(d, a, b, c, x[5], 5); 00260 GG(c, d, a, b, x[9], 9); 00261 GG(b, c, d, a, x[13], 13); 00262 GG(a, b, c, d, x[2], 3); 00263 GG(d, a, b, c, x[6], 5); 00264 GG(c, d, a, b, x[10], 9); 00265 GG(b, c, d, a, x[14], 13); 00266 GG(a, b, c, d, x[3], 3); 00267 GG(d, a, b, c, x[7], 5); 00268 GG(c, d, a, b, x[11], 9); 00269 GG(b, c, d, a, x[15], 13); 00270 00271 //Round 3 00272 HH(a, b, c, d, x[0], 3); 00273 HH(d, a, b, c, x[8], 9); 00274 HH(c, d, a, b, x[4], 11); 00275 HH(b, c, d, a, x[12], 15); 00276 HH(a, b, c, d, x[2], 3); 00277 HH(d, a, b, c, x[10], 9); 00278 HH(c, d, a, b, x[6], 11); 00279 HH(b, c, d, a, x[14], 15); 00280 HH(a, b, c, d, x[1], 3); 00281 HH(d, a, b, c, x[9], 9); 00282 HH(c, d, a, b, x[5], 11); 00283 HH(b, c, d, a, x[13], 15); 00284 HH(a, b, c, d, x[3], 3); 00285 HH(d, a, b, c, x[11], 9); 00286 HH(c, d, a, b, x[7], 11); 00287 HH(b, c, d, a, x[15], 15); 00288 00289 //Update the hash value 00290 context->h[0] += a; 00291 context->h[1] += b; 00292 context->h[2] += c; 00293 context->h[3] += d; 00294 } 00295 00296 #endif 00297
Generated on Tue Jul 12 2022 17:10:14 by
