md4.c
Go to the documentation of this file.
1 /**
2  * @file md4.c
3  * @brief MD4 (Message-Digest Algorithm)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @section Description
26  *
27  * The MD4 algorithm takes as input a message of arbitrary length and produces
28  * as output a 128-bit message digest of the input. Refer to RFC 1320
29  *
30  * @author Oryx Embedded SARL (www.oryx-embedded.com)
31  * @version 1.9.0
32  **/
33 
34 //Switch to the appropriate trace level
35 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
36 
37 //Dependencies
38 #include "core/crypto.h"
39 #include "hash/md4.h"
40 
41 //Check crypto library configuration
42 #if (MD4_SUPPORT == ENABLED)
43 
44 //MD4 auxiliary functions
45 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
46 #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
47 #define H(x, y, z) ((x) ^ (y) ^ (z))
48 
49 #define FF(a, b, c, d, x, s) a += F(b, c, d) + (x), a = ROL32(a, s)
50 #define GG(a, b, c, d, x, s) a += G(b, c, d) + (x) + 0x5A827999, a = ROL32(a, s)
51 #define HH(a, b, c, d, x, s) a += H(b, c, d) + (x) + 0x6ED9EBA1, a = ROL32(a, s)
52 
53 //MD4 padding
54 static const uint8_t padding[64] =
55 {
56  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
60 };
61 
62 //MD4 object identifier (1.2.840.113549.2.4)
63 const uint8_t md4Oid[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x04};
64 
65 //Common interface for hash algorithms
67 {
68  "MD4",
69  md4Oid,
70  sizeof(md4Oid),
71  sizeof(Md4Context),
78 };
79 
80 
81 /**
82  * @brief Digest a message using MD4
83  * @param[in] data Pointer to the message being hashed
84  * @param[in] length Length of the message
85  * @param[out] digest Pointer to the calculated digest
86  * @return Error code
87  **/
88 
89 error_t md4Compute(const void *data, size_t length, uint8_t *digest)
90 {
91  //Allocate a memory buffer to hold the MD4 context
92  Md4Context *context = cryptoAllocMem(sizeof(Md4Context));
93  //Failed to allocate memory?
94  if(context == NULL)
95  return ERROR_OUT_OF_MEMORY;
96 
97  //Initialize the MD4 context
98  md4Init(context);
99  //Digest the message
100  md4Update(context, data, length);
101  //Finalize the MD4 message digest
102  md4Final(context, digest);
103 
104  //Free previously allocated memory
105  cryptoFreeMem(context);
106  //Successful processing
107  return NO_ERROR;
108 }
109 
110 
111 /**
112  * @brief Initialize MD4 message digest context
113  * @param[in] context Pointer to the MD4 context to initialize
114  **/
115 
116 void md4Init(Md4Context *context)
117 {
118  //Set initial hash value
119  context->h[0] = 0x67452301;
120  context->h[1] = 0xEFCDAB89;
121  context->h[2] = 0x98BADCFE;
122  context->h[3] = 0x10325476;
123 
124  //Number of bytes in the buffer
125  context->size = 0;
126  //Total length of the message
127  context->totalSize = 0;
128 }
129 
130 
131 /**
132  * @brief Update the MD4 context with a portion of the message being hashed
133  * @param[in] context Pointer to the MD4 context
134  * @param[in] data Pointer to the buffer being hashed
135  * @param[in] length Length of the buffer
136  **/
137 
138 void md4Update(Md4Context *context, const void *data, size_t length)
139 {
140  size_t n;
141 
142  //Process the incoming data
143  while(length > 0)
144  {
145  //The buffer can hold at most 64 bytes
146  n = MIN(length, 64 - context->size);
147 
148  //Copy the data to the buffer
149  cryptoMemcpy(context->buffer + context->size, data, n);
150 
151  //Update the MD4 context
152  context->size += n;
153  context->totalSize += n;
154  //Advance the data pointer
155  data = (uint8_t *) data + n;
156  //Remaining bytes to process
157  length -= n;
158 
159  //Process message in 16-word blocks
160  if(context->size == 64)
161  {
162  //Transform the 16-word block
163  md4ProcessBlock(context);
164  //Empty the buffer
165  context->size = 0;
166  }
167  }
168 }
169 
170 
171 /**
172  * @brief Finish the MD4 message digest
173  * @param[in] context Pointer to the MD4 context
174  * @param[out] digest Calculated digest (optional parameter)
175  **/
176 
177 void md4Final(Md4Context *context, uint8_t *digest)
178 {
179  uint_t i;
180  size_t paddingSize;
181  uint64_t totalSize;
182 
183  //Length of the original message (before padding)
184  totalSize = context->totalSize * 8;
185 
186  //Pad the message so that its length is congruent to 56 modulo 64
187  if(context->size < 56)
188  paddingSize = 56 - context->size;
189  else
190  paddingSize = 64 + 56 - context->size;
191 
192  //Append padding
193  md4Update(context, padding, paddingSize);
194 
195  //Append the length of the original message
196  context->x[14] = htole32((uint32_t) totalSize);
197  context->x[15] = htole32((uint32_t) (totalSize >> 32));
198 
199  //Calculate the message digest
200  md4ProcessBlock(context);
201 
202  //Convert from host byte order to little-endian byte order
203  for(i = 0; i < 4; i++)
204  context->h[i] = htole32(context->h[i]);
205 
206  //Copy the resulting digest
207  if(digest != NULL)
208  cryptoMemcpy(digest, context->digest, MD4_DIGEST_SIZE);
209 }
210 
211 
212 /**
213  * @brief Process message in 16-word blocks
214  * @param[in] context Pointer to the MD4 context
215  **/
216 
218 {
219  uint_t i;
220 
221  //Initialize the 4 working registers
222  uint32_t a = context->h[0];
223  uint32_t b = context->h[1];
224  uint32_t c = context->h[2];
225  uint32_t d = context->h[3];
226 
227  //Process message in 16-word blocks
228  uint32_t *x = context->x;
229 
230  //Convert from little-endian byte order to host byte order
231  for(i = 0; i < 16; i++)
232  x[i] = letoh32(x[i]);
233 
234  //Round 1
235  FF(a, b, c, d, x[0], 3);
236  FF(d, a, b, c, x[1], 7);
237  FF(c, d, a, b, x[2], 11);
238  FF(b, c, d, a, x[3], 19);
239  FF(a, b, c, d, x[4], 3);
240  FF(d, a, b, c, x[5], 7);
241  FF(c, d, a, b, x[6], 11);
242  FF(b, c, d, a, x[7], 19);
243  FF(a, b, c, d, x[8], 3);
244  FF(d, a, b, c, x[9], 7);
245  FF(c, d, a, b, x[10], 11);
246  FF(b, c, d, a, x[11], 19);
247  FF(a, b, c, d, x[12], 3);
248  FF(d, a, b, c, x[13], 7);
249  FF(c, d, a, b, x[14], 11);
250  FF(b, c, d, a, x[15], 19);
251 
252  //Round 2
253  GG(a, b, c, d, x[0], 3);
254  GG(d, a, b, c, x[4], 5);
255  GG(c, d, a, b, x[8], 9);
256  GG(b, c, d, a, x[12], 13);
257  GG(a, b, c, d, x[1], 3);
258  GG(d, a, b, c, x[5], 5);
259  GG(c, d, a, b, x[9], 9);
260  GG(b, c, d, a, x[13], 13);
261  GG(a, b, c, d, x[2], 3);
262  GG(d, a, b, c, x[6], 5);
263  GG(c, d, a, b, x[10], 9);
264  GG(b, c, d, a, x[14], 13);
265  GG(a, b, c, d, x[3], 3);
266  GG(d, a, b, c, x[7], 5);
267  GG(c, d, a, b, x[11], 9);
268  GG(b, c, d, a, x[15], 13);
269 
270  //Round 3
271  HH(a, b, c, d, x[0], 3);
272  HH(d, a, b, c, x[8], 9);
273  HH(c, d, a, b, x[4], 11);
274  HH(b, c, d, a, x[12], 15);
275  HH(a, b, c, d, x[2], 3);
276  HH(d, a, b, c, x[10], 9);
277  HH(c, d, a, b, x[6], 11);
278  HH(b, c, d, a, x[14], 15);
279  HH(a, b, c, d, x[1], 3);
280  HH(d, a, b, c, x[9], 9);
281  HH(c, d, a, b, x[5], 11);
282  HH(b, c, d, a, x[13], 15);
283  HH(a, b, c, d, x[3], 3);
284  HH(d, a, b, c, x[11], 9);
285  HH(c, d, a, b, x[7], 11);
286  HH(b, c, d, a, x[15], 15);
287 
288  //Update the hash value
289  context->h[0] += a;
290  context->h[1] += b;
291  context->h[2] += c;
292  context->h[3] += d;
293 }
294 
295 #endif
#define MD4_DIGEST_SIZE
Definition: md4.h:38
uint8_t c
Definition: ndp.h:510
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:590
void md4Final(Md4Context *context, uint8_t *digest)
Finish the MD4 message digest.
Definition: md4.c:177
#define cryptoFreeMem(p)
Definition: crypto.h:578
#define GG(a, b, c, d, x, s)
Definition: md4.c:50
error_t(* HashAlgoCompute)(const void *data, size_t length, uint8_t *digest)
Definition: crypto.h:1020
#define cryptoAllocMem(size)
Definition: crypto.h:573
General definitions for cryptographic algorithms.
const HashAlgo md4HashAlgo
Definition: md4.c:66
uint32_t h[4]
Definition: md4.h:58
uint32_t totalSize
uint8_t a
Definition: ndp.h:407
void(* HashAlgoInit)(void *context)
Definition: crypto.h:1021
#define htole32(value)
Definition: cpu_endian.h:404
size_t size
Definition: md4.h:66
const uint8_t md4Oid[8]
Definition: md4.c:63
MD4 algorithm context.
Definition: md4.h:54
error_t md4Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using MD4.
Definition: md4.c:89
#define MIN(a, b)
Definition: os_port.h:60
void md4ProcessBlock(Md4Context *context)
Process message in 16-word blocks.
Definition: md4.c:217
#define HH(a, b, c, d, x, s)
Definition: md4.c:51
#define FF(a, b, c, d, x, s)
Definition: md4.c:49
void(* HashAlgoUpdate)(void *context, const void *data, size_t length)
Definition: crypto.h:1022
Success.
Definition: error.h:42
#define MD4_BLOCK_SIZE
Definition: md4.h:36
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
uint8_t data[]
Definition: dtls_misc.h:167
void md4Update(Md4Context *context, const void *data, size_t length)
Update the MD4 context with a portion of the message being hashed.
Definition: md4.c:138
uint8_t buffer[64]
Definition: md4.h:64
uint8_t digest[16]
Definition: md4.h:59
#define letoh32(value)
Definition: cpu_endian.h:412
void md4Init(Md4Context *context)
Initialize MD4 message digest context.
Definition: md4.c:116
uint32_t x[16]
Definition: md4.h:63
MD4 (Message-Digest Algorithm)
Common interface for hash algorithms.
Definition: crypto.h:1054
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
uint8_t b[6]
Definition: dtls_misc.h:130
void(* HashAlgoFinal)(void *context, uint8_t *digest)
Definition: crypto.h:1023
uint64_t totalSize
Definition: md4.h:67