NeoMutt  2020-06-26-89-g172cd3
Teaching an old dog new tricks
DOXYGEN
md5.c File Reference

Calculate the MD5 checksum of a buffer. More...

#include "config.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "md5.h"
+ Include dependency graph for md5.c:

Go to the source code of this file.

Macros

#define SWAP(n)   (n)
 
#define FF(b, c, d)   (d ^ (b & (c ^ d)))
 
#define FG(b, c, d)   FF(d, b, c)
 
#define FH(b, c, d)   (b ^ c ^ d)
 
#define FI(b, c, d)   (c ^ (b | ~d))
 
#define OP(a, b, c, d, s, T)
 
#define CYCLIC(w, s)   (w = (w << s) | (w >> (32 - s)))
 
#define OP(f, a, b, c, d, k, s, T)
 
#define alignof(type)
 
#define UNALIGNED_P(p)   (((size_t) p) % alignof(md5_uint32) != 0)
 

Functions

static void mutt_md5_process_block (const void *buffer, size_t len, struct Md5Ctx *md5ctx)
 Process a block with MD5. More...
 
static void set_uint32 (char *cp, md5_uint32 v)
 Write a 32 bit number. More...
 
static void * mutt_md5_read_ctx (const struct Md5Ctx *md5ctx, void *resbuf)
 Read from the context into a buffer. More...
 
void mutt_md5_init_ctx (struct Md5Ctx *md5ctx)
 Initialise the MD5 computation. More...
 
void * mutt_md5_finish_ctx (struct Md5Ctx *md5ctx, void *resbuf)
 Process the remaining bytes in the buffer. More...
 
void * mutt_md5 (const char *str, void *buf)
 Calculate the MD5 hash of a NULL-terminated string. More...
 
void * mutt_md5_bytes (const void *buffer, size_t len, void *resbuf)
 Calculate the MD5 hash of a buffer. More...
 
void mutt_md5_process (const char *str, struct Md5Ctx *md5ctx)
 Process a NULL-terminated string. More...
 
void mutt_md5_process_bytes (const void *buf, size_t buflen, struct Md5Ctx *md5ctx)
 Process a block of data. More...
 
void mutt_md5_toascii (const void *digest, char *resbuf)
 Convert a binary MD5 digest into ASCII Hexadecimal. More...
 

Variables

static const unsigned char fillbuf [64] = { 0x80, 0 }
 

Detailed Description

Calculate the MD5 checksum of a buffer.

Authors
  • Ulrich Drepper
  • Free Software Foundation, Inc.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file md5.c.

Macro Definition Documentation

◆ SWAP

#define SWAP (   n)    (n)

Definition at line 41 of file md5.c.

◆ FF

#define FF (   b,
  c,
 
)    (d ^ (b & (c ^ d)))

Definition at line 52 of file md5.c.

◆ FG

#define FG (   b,
  c,
 
)    FF(d, b, c)

Definition at line 53 of file md5.c.

◆ FH

#define FH (   b,
  c,
 
)    (b ^ c ^ d)

Definition at line 54 of file md5.c.

◆ FI

#define FI (   b,
  c,
 
)    (c ^ (b | ~d))

Definition at line 55 of file md5.c.

◆ OP [1/2]

#define OP (   a,
  b,
  c,
  d,
  s,
 
)
Value:
do \
{ \
a += FF(b, c, d) + (*cwp++ = SWAP(*words)) + T; \
words++; \
CYCLIC(a, s); \
a += b; \
} while (false)
#define SWAP(n)
Definition: md5.c:41
#define FF(b, c, d)
Definition: md5.c:52

◆ CYCLIC

#define CYCLIC (   w,
 
)    (w = (w << s) | (w >> (32 - s)))

◆ OP [2/2]

#define OP (   f,
  a,
  b,
  c,
  d,
  k,
  s,
 
)
Value:
do \
{ \
a += f(b, c, d) + correct_words[k] + T; \
CYCLIC(a, s); \
a += b; \
} while (false)

◆ alignof

#define alignof (   type)
Value:
offsetof( \
struct { \
char c; \
type x; \
}, \
x)

◆ UNALIGNED_P

#define UNALIGNED_P (   p)    (((size_t) p) % alignof(md5_uint32) != 0)

Function Documentation

◆ mutt_md5_process_block()

static void mutt_md5_process_block ( const void *  buffer,
size_t  len,
struct Md5Ctx md5ctx 
)
static

Process a block with MD5.

Parameters
bufferBuffer to hash
lenLength of buffer
md5ctxMD5 context

Process LEN bytes of Buffer, accumulating context into MD5CTX. LEN must be a multiple of 64.

Definition at line 66 of file md5.c.

67 {
68  md5_uint32 correct_words[16];
69  const md5_uint32 *words = buffer;
70  size_t nwords = len / sizeof(md5_uint32);
71  const md5_uint32 *endp = words + nwords;
72  md5_uint32 A = md5ctx->A;
73  md5_uint32 B = md5ctx->B;
74  md5_uint32 C = md5ctx->C;
75  md5_uint32 D = md5ctx->D;
76 
77  /* First increment the byte count. RFC1321 specifies the possible length of
78  * the file up to 2^64 bits. Here we only compute the number of bytes. Do a
79  * double word increment. */
80  md5ctx->total[0] += len;
81  if (md5ctx->total[0] < len)
82  md5ctx->total[1]++;
83 
84  /* Process all bytes in the buffer with 64 bytes in each round of the loop. */
85  while (words < endp)
86  {
87  md5_uint32 *cwp = correct_words;
88  md5_uint32 save_A = A;
89  md5_uint32 save_B = B;
90  md5_uint32 save_C = C;
91  md5_uint32 save_D = D;
92 
93  /* First round: using the given function, the context and a constant the
94  * next context is computed. Because the algorithms processing unit is a
95  * 32-bit word and it is determined to work on words in little endian byte
96  * order we perhaps have to change the byte order before the computation.
97  * To reduce the work for the next steps we store the swapped words in the
98  * array CORRECT_WORDS. */
99 
100 #define OP(a, b, c, d, s, T) \
101  do \
102  { \
103  a += FF(b, c, d) + (*cwp++ = SWAP(*words)) + T; \
104  words++; \
105  CYCLIC(a, s); \
106  a += b; \
107  } while (false)
108 
109 /* It is unfortunate that C does not provide an operator for
110  * cyclic rotation. Hope the C compiler is smart enough. */
111 #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
112 
113  /* Before we start, one word to the strange constants.
114  * They are defined in RFC1321 as
115  * T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
116  * Here is an equivalent invocation using Perl:
117  * perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}'
118  */
119 
120  /* Round 1. */
121  OP(A, B, C, D, 7, 0xd76aa478);
122  OP(D, A, B, C, 12, 0xe8c7b756);
123  OP(C, D, A, B, 17, 0x242070db);
124  OP(B, C, D, A, 22, 0xc1bdceee);
125  OP(A, B, C, D, 7, 0xf57c0faf);
126  OP(D, A, B, C, 12, 0x4787c62a);
127  OP(C, D, A, B, 17, 0xa8304613);
128  OP(B, C, D, A, 22, 0xfd469501);
129  OP(A, B, C, D, 7, 0x698098d8);
130  OP(D, A, B, C, 12, 0x8b44f7af);
131  OP(C, D, A, B, 17, 0xffff5bb1);
132  OP(B, C, D, A, 22, 0x895cd7be);
133  OP(A, B, C, D, 7, 0x6b901122);
134  OP(D, A, B, C, 12, 0xfd987193);
135  OP(C, D, A, B, 17, 0xa679438e);
136  OP(B, C, D, A, 22, 0x49b40821);
137 
138 /* For the second to fourth round we have the possibly swapped words
139  * in CORRECT_WORDS. Redefine the macro to take an additional first
140  * argument specifying the function to use. */
141 #undef OP
142 #define OP(f, a, b, c, d, k, s, T) \
143  do \
144  { \
145  a += f(b, c, d) + correct_words[k] + T; \
146  CYCLIC(a, s); \
147  a += b; \
148  } while (false)
149 
150  /* Round 2. */
151  OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
152  OP(FG, D, A, B, C, 6, 9, 0xc040b340);
153  OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
154  OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
155  OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
156  OP(FG, D, A, B, C, 10, 9, 0x02441453);
157  OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
158  OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
159  OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
160  OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
161  OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
162  OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
163  OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
164  OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
165  OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
166  OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
167 
168  /* Round 3. */
169  OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
170  OP(FH, D, A, B, C, 8, 11, 0x8771f681);
171  OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
172  OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
173  OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
174  OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
175  OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
176  OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
177  OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
178  OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
179  OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
180  OP(FH, B, C, D, A, 6, 23, 0x04881d05);
181  OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
182  OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
183  OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
184  OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
185 
186  /* Round 4. */
187  OP(FI, A, B, C, D, 0, 6, 0xf4292244);
188  OP(FI, D, A, B, C, 7, 10, 0x432aff97);
189  OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
190  OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
191  OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
192  OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
193  OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
194  OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
195  OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
196  OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
197  OP(FI, C, D, A, B, 6, 15, 0xa3014314);
198  OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
199  OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
200  OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
201  OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
202  OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
203 
204  /* Add the starting values of the context. */
205  A += save_A;
206  B += save_B;
207  C += save_C;
208  D += save_D;
209  }
210 
211  /* Put checksum in context given as argument. */
212  md5ctx->A = A;
213  md5ctx->B = B;
214  md5ctx->C = C;
215  md5ctx->D = D;
216 }
#define C
#define FG(b, c, d)
Definition: md5.c:53
md5_uint32 A
Definition: md5.h:38
#define FI(b, c, d)
Definition: md5.c:55
#define OP(a, b, c, d, s, T)
#define FH(b, c, d)
Definition: md5.c:54
md5_uint32 D
Definition: md5.h:41
uint32_t md5_uint32
Definition: md5.h:29
static int const char char buffer[256]
Definition: acutest.h:489
md5_uint32 total[2]
Definition: md5.h:43
md5_uint32 C
Definition: md5.h:40
md5_uint32 B
Definition: md5.h:39
+ Here is the caller graph for this function:

◆ set_uint32()

static void set_uint32 ( char *  cp,
md5_uint32  v 
)
inlinestatic

Write a 32 bit number.

Parameters
cpDestination for data
vValue to write

Copy the 4 byte value from v into the memory location pointed to by *cp, If your architecture allows unaligned access this is equivalent to *(md5_uint32*) cp = v

Definition at line 227 of file md5.c.

228 {
229  memcpy(cp, &v, sizeof(v));
230 }
+ Here is the caller graph for this function:

◆ mutt_md5_read_ctx()

static void* mutt_md5_read_ctx ( const struct Md5Ctx md5ctx,
void *  resbuf 
)
static

Read from the context into a buffer.

Parameters
md5ctxMD5 context
resbufBuffer for result
Return values
ptrResults buffer

Put result from MD5CTX in first 16 bytes following RESBUF. The result must be in little endian byte order.

Definition at line 241 of file md5.c.

242 {
243  if (!md5ctx || !resbuf)
244  return NULL;
245 
246  char *r = resbuf;
247 
248  set_uint32(r + 0 * sizeof(md5ctx->A), SWAP(md5ctx->A));
249  set_uint32(r + 1 * sizeof(md5ctx->B), SWAP(md5ctx->B));
250  set_uint32(r + 2 * sizeof(md5ctx->C), SWAP(md5ctx->C));
251  set_uint32(r + 3 * sizeof(md5ctx->D), SWAP(md5ctx->D));
252 
253  return resbuf;
254 }
#define SWAP(n)
Definition: md5.c:41
md5_uint32 A
Definition: md5.h:38
md5_uint32 D
Definition: md5.h:41
md5_uint32 C
Definition: md5.h:40
md5_uint32 B
Definition: md5.h:39
static void set_uint32(char *cp, md5_uint32 v)
Write a 32 bit number.
Definition: md5.c:227
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_md5_init_ctx()

void mutt_md5_init_ctx ( struct Md5Ctx md5ctx)

Initialise the MD5 computation.

Parameters
md5ctxMD5 context

RFC1321, 3.3: Step 3

Definition at line 262 of file md5.c.

263 {
264  if (!md5ctx)
265  return;
266 
267  md5ctx->A = 0x67452301;
268  md5ctx->B = 0xefcdab89;
269  md5ctx->C = 0x98badcfe;
270  md5ctx->D = 0x10325476;
271 
272  md5ctx->total[0] = 0;
273  md5ctx->total[1] = 0;
274  md5ctx->buflen = 0;
275 }
md5_uint32 A
Definition: md5.h:38
md5_uint32 D
Definition: md5.h:41
md5_uint32 total[2]
Definition: md5.h:43
md5_uint32 buflen
Definition: md5.h:44
md5_uint32 C
Definition: md5.h:40
md5_uint32 B
Definition: md5.h:39
+ Here is the caller graph for this function:

◆ mutt_md5_finish_ctx()

void* mutt_md5_finish_ctx ( struct Md5Ctx md5ctx,
void *  resbuf 
)

Process the remaining bytes in the buffer.

Parameters
md5ctxMD5 context
resbufBuffer for result
Return values
ptrResults buffer

Process the remaining bytes in the internal buffer and the usual prologue according to the standard and write the result to RESBUF.

Definition at line 286 of file md5.c.

287 {
288  if (!md5ctx)
289  return NULL;
290 
291  /* Take yet unprocessed bytes into account. */
292  md5_uint32 bytes = md5ctx->buflen;
293  size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4;
294 
295  /* Now count remaining bytes. */
296  md5ctx->total[0] += bytes;
297  if (md5ctx->total[0] < bytes)
298  md5ctx->total[1]++;
299 
300  /* Put the 64-bit file length in *bits* at the end of the buffer. */
301  md5ctx->buffer[size - 2] = SWAP(md5ctx->total[0] << 3);
302  md5ctx->buffer[size - 1] = SWAP((md5ctx->total[1] << 3) | (md5ctx->total[0] >> 29));
303 
304  memcpy(&((char *) md5ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes);
305 
306  /* Process last bytes. */
307  mutt_md5_process_block(md5ctx->buffer, size * 4, md5ctx);
308 
309  return mutt_md5_read_ctx(md5ctx, resbuf);
310 }
#define SWAP(n)
Definition: md5.c:41
static const unsigned char fillbuf[64]
Definition: md5.c:46
uint32_t md5_uint32
Definition: md5.h:29
md5_uint32 total[2]
Definition: md5.h:43
md5_uint32 buflen
Definition: md5.h:44
md5_uint32 buffer[32]
Definition: md5.h:45
static void * mutt_md5_read_ctx(const struct Md5Ctx *md5ctx, void *resbuf)
Read from the context into a buffer.
Definition: md5.c:241
static void mutt_md5_process_block(const void *buffer, size_t len, struct Md5Ctx *md5ctx)
Process a block with MD5.
Definition: md5.c:66
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_md5()

void* mutt_md5 ( const char *  str,
void *  buf 
)

Calculate the MD5 hash of a NULL-terminated string.

Parameters
strString to hash
bufBuffer for result

Definition at line 317 of file md5.c.

318 {
319  if (!str)
320  return NULL;
321 
322  return mutt_md5_bytes(str, strlen(str), buf);
323 }
void * mutt_md5_bytes(const void *buffer, size_t len, void *resbuf)
Calculate the MD5 hash of a buffer.
Definition: md5.c:336
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_md5_bytes()

void* mutt_md5_bytes ( const void *  buffer,
size_t  len,
void *  resbuf 
)

Calculate the MD5 hash of a buffer.

Parameters
bufferBuffer to hash
lenLength of buffer
resbufBuffer for result
Return values
ptrResults buffer

Compute MD5 message digest for LEN bytes beginning at Buffer. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest.

Definition at line 336 of file md5.c.

337 {
338  struct Md5Ctx md5ctx;
339 
340  /* Initialize the computation context. */
341  mutt_md5_init_ctx(&md5ctx);
342 
343  /* Process whole buffer but last len % 64 bytes. */
344  mutt_md5_process_bytes(buffer, len, &md5ctx);
345 
346  /* Put result in desired memory area. */
347  return mutt_md5_finish_ctx(&md5ctx, resbuf);
348 }
Cursor for the MD5 hashing.
Definition: md5.h:36
void mutt_md5_init_ctx(struct Md5Ctx *md5ctx)
Initialise the MD5 computation.
Definition: md5.c:262
void * mutt_md5_finish_ctx(struct Md5Ctx *md5ctx, void *resbuf)
Process the remaining bytes in the buffer.
Definition: md5.c:286
static int const char char buffer[256]
Definition: acutest.h:489
void mutt_md5_process_bytes(const void *buf, size_t buflen, struct Md5Ctx *md5ctx)
Process a block of data.
Definition: md5.c:373
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_md5_process()

void mutt_md5_process ( const char *  str,
struct Md5Ctx md5ctx 
)

Process a NULL-terminated string.

Parameters
strString to process
md5ctxMD5 context

Definition at line 355 of file md5.c.

356 {
357  if (!str)
358  return;
359 
360  mutt_md5_process_bytes(str, strlen(str), md5ctx);
361 }
void mutt_md5_process_bytes(const void *buf, size_t buflen, struct Md5Ctx *md5ctx)
Process a block of data.
Definition: md5.c:373
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_md5_process_bytes()

void mutt_md5_process_bytes ( const void *  buf,
size_t  buflen,
struct Md5Ctx md5ctx 
)

Process a block of data.

Parameters
bufBuffer to process
buflenLength of buffer
md5ctxMD5 context

Starting with the result of former calls of this function (or the initialization function update the context for the next BUFLEN bytes starting at Buffer. It is NOT required that BUFLEN is a multiple of 64.

Definition at line 373 of file md5.c.

374 {
375  if (!buf || !md5ctx)
376  return;
377 
378  /* When we already have some bits in our internal buffer concatenate both
379  * inputs first. */
380  if (md5ctx->buflen != 0)
381  {
382  size_t left_over = md5ctx->buflen;
383  size_t add = ((128 - left_over) > buflen) ? buflen : (128 - left_over);
384 
385  memcpy(&((char *) md5ctx->buffer)[left_over], buf, add);
386  md5ctx->buflen += add;
387 
388  if (md5ctx->buflen > 64)
389  {
390  mutt_md5_process_block(md5ctx->buffer, md5ctx->buflen & ~63, md5ctx);
391 
392  md5ctx->buflen &= 63;
393  /* The regions in the following copy operation can't overlap. */
394  memcpy(md5ctx->buffer, &((char *) md5ctx->buffer)[(left_over + add) & ~63],
395  md5ctx->buflen);
396  }
397 
398  buf = (const char *) buf + add;
399  buflen -= add;
400  }
401 
402  /* Process available complete blocks. */
403  if (buflen >= 64)
404  {
405 #if !defined(_STRING_ARCH_unaligned)
406 #define alignof(type) \
407  offsetof( \
408  struct { \
409  char c; \
410  type x; \
411  }, \
412  x)
413 #define UNALIGNED_P(p) (((size_t) p) % alignof(md5_uint32) != 0)
414  if (UNALIGNED_P(buf))
415  {
416  while (buflen > 64)
417  {
418  mutt_md5_process_block(memcpy(md5ctx->buffer, buf, 64), 64, md5ctx);
419  buf = (const char *) buf + 64;
420  buflen -= 64;
421  }
422  }
423  else
424 #endif
425  {
426  mutt_md5_process_block(buf, buflen & ~63, md5ctx);
427  buf = (const char *) buf + (buflen & ~63);
428  buflen &= 63;
429  }
430  }
431 
432  /* Move remaining bytes in internal buffer. */
433  if (buflen > 0)
434  {
435  size_t left_over = md5ctx->buflen;
436 
437  memcpy(&((char *) md5ctx->buffer)[left_over], buf, buflen);
438  left_over += buflen;
439  if (left_over >= 64)
440  {
441  mutt_md5_process_block(md5ctx->buffer, 64, md5ctx);
442  left_over -= 64;
443  memmove(md5ctx->buffer, &md5ctx->buffer[16], left_over);
444  }
445  md5ctx->buflen = left_over;
446  }
447 }
#define UNALIGNED_P(p)
md5_uint32 buflen
Definition: md5.h:44
md5_uint32 buffer[32]
Definition: md5.h:45
static void mutt_md5_process_block(const void *buffer, size_t len, struct Md5Ctx *md5ctx)
Process a block with MD5.
Definition: md5.c:66
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_md5_toascii()

void mutt_md5_toascii ( const void *  digest,
char *  resbuf 
)

Convert a binary MD5 digest into ASCII Hexadecimal.

Parameters
digestBinary MD5 digest
resbufBuffer for the ASCII result
Note
refbuf must be at least 33 bytes long.

Definition at line 456 of file md5.c.

457 {
458  if (!digest || !resbuf)
459  return;
460 
461  const unsigned char *c = digest;
462  sprintf(resbuf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
463  c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10],
464  c[11], c[12], c[13], c[14], c[15]);
465 }
+ Here is the caller graph for this function:

Variable Documentation

◆ fillbuf

const unsigned char fillbuf[64] = { 0x80, 0 }
static

Definition at line 46 of file md5.c.