1 | /* Functions to compute MD5 message digest of files or memory blocks. |
2 | according to the definition of MD5 in RFC 1321 from April 1992. |
3 | Copyright (C) 1995-2024 Free Software Foundation, Inc. |
4 | This file is part of the GNU C Library. |
5 | |
6 | The GNU C Library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2.1 of the License, or (at your option) any later version. |
10 | |
11 | The GNU C Library is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Lesser General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Lesser General Public |
17 | License along with the GNU C Library; if not, see |
18 | <https://www.gnu.org/licenses/>. */ |
19 | |
20 | /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ |
21 | |
22 | #include <string.h> |
23 | #include <endian.h> |
24 | #include "md5.h" |
25 | |
26 | #if __BYTE_ORDER == __BIG_ENDIAN |
27 | # define WORDS_BIGENDIAN 1 |
28 | #endif |
29 | |
30 | #ifdef WORDS_BIGENDIAN |
31 | # define SWAP(n) \ |
32 | (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) |
33 | #else |
34 | # define SWAP(n) (n) |
35 | #endif |
36 | |
37 | |
38 | /* This array contains the bytes used to pad the buffer to the next |
39 | 64-byte boundary. (RFC 1321, 3.1: Step 1) */ |
40 | static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; |
41 | |
42 | |
43 | /* Initialize structure containing state of computation. |
44 | (RFC 1321, 3.3: Step 3) */ |
45 | void |
46 | __md5_init_ctx (struct md5_ctx *ctx) |
47 | { |
48 | ctx->A = 0x67452301; |
49 | ctx->B = 0xefcdab89; |
50 | ctx->C = 0x98badcfe; |
51 | ctx->D = 0x10325476; |
52 | |
53 | ctx->total[0] = ctx->total[1] = 0; |
54 | ctx->buflen = 0; |
55 | } |
56 | |
57 | /* Put result from CTX in first 16 bytes following RESBUF. The result |
58 | must be in little endian byte order. |
59 | |
60 | IMPORTANT: On some systems it is required that RESBUF is correctly |
61 | aligned for a 32 bits value. */ |
62 | void * |
63 | __md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) |
64 | { |
65 | ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); |
66 | ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); |
67 | ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); |
68 | ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); |
69 | |
70 | return resbuf; |
71 | } |
72 | |
73 | /* Process the remaining bytes in the internal buffer and the usual |
74 | prolog according to the standard and write the result to RESBUF. |
75 | |
76 | IMPORTANT: On some systems it is required that RESBUF is correctly |
77 | aligned for a 32 bits value. */ |
78 | void * |
79 | __md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) |
80 | { |
81 | /* Take yet unprocessed bytes into account. */ |
82 | md5_uint32 bytes = ctx->buflen; |
83 | size_t pad; |
84 | |
85 | /* Now count remaining bytes. */ |
86 | ctx->total[0] += bytes; |
87 | if (ctx->total[0] < bytes) |
88 | ++ctx->total[1]; |
89 | |
90 | pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; |
91 | memcpy (dest: &ctx->buffer[bytes], src: fillbuf, n: pad); |
92 | |
93 | /* Put the 64-bit file length in *bits* at the end of the buffer. */ |
94 | ctx->buffer32[(bytes + pad) / 4] = SWAP (ctx->total[0] << 3); |
95 | ctx->buffer32[(bytes + pad + 4) / 4] = SWAP ((ctx->total[1] << 3) |
96 | | (ctx->total[0] >> 29)); |
97 | |
98 | /* Process last bytes. */ |
99 | __md5_process_block (buffer: ctx->buffer, len: bytes + pad + 8, ctx); |
100 | |
101 | return __md5_read_ctx (ctx, resbuf); |
102 | } |
103 | |
104 | /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The |
105 | result is always in little endian byte order, so that a byte-wise |
106 | output yields to the wanted ASCII representation of the message |
107 | digest. */ |
108 | void * |
109 | __md5_buffer (const char *buffer, size_t len, void *resblock) |
110 | { |
111 | struct md5_ctx ctx; |
112 | |
113 | /* Initialize the computation context. */ |
114 | __md5_init_ctx (ctx: &ctx); |
115 | |
116 | /* Process whole buffer but last len % 64 bytes. */ |
117 | __md5_process_bytes (buffer, len, ctx: &ctx); |
118 | |
119 | /* Put result in desired memory area. */ |
120 | return __md5_finish_ctx (ctx: &ctx, resbuf: resblock); |
121 | } |
122 | |
123 | |
124 | void |
125 | __md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) |
126 | { |
127 | /* When we already have some bits in our internal buffer concatenate |
128 | both inputs first. */ |
129 | if (ctx->buflen != 0) |
130 | { |
131 | size_t left_over = ctx->buflen; |
132 | size_t add = 128 - left_over > len ? len : 128 - left_over; |
133 | |
134 | memcpy (dest: &ctx->buffer[left_over], src: buffer, n: add); |
135 | ctx->buflen += add; |
136 | |
137 | if (ctx->buflen > 64) |
138 | { |
139 | __md5_process_block (buffer: ctx->buffer, len: ctx->buflen & ~63, ctx); |
140 | |
141 | ctx->buflen &= 63; |
142 | /* The regions in the following copy operation cannot overlap. */ |
143 | memcpy (dest: ctx->buffer, src: &ctx->buffer[(left_over + add) & ~63], |
144 | n: ctx->buflen); |
145 | } |
146 | |
147 | buffer = (const char *) buffer + add; |
148 | len -= add; |
149 | } |
150 | |
151 | /* Process available complete blocks. */ |
152 | if (len >= 64) |
153 | { |
154 | while (len > 64) |
155 | { |
156 | __md5_process_block (buffer: memcpy (dest: ctx->buffer, src: buffer, n: 64), len: 64, ctx); |
157 | buffer = (const char *) buffer + 64; |
158 | len -= 64; |
159 | } |
160 | } |
161 | |
162 | /* Move remaining bytes in internal buffer. */ |
163 | if (len > 0) |
164 | { |
165 | size_t left_over = ctx->buflen; |
166 | |
167 | memcpy (dest: &ctx->buffer[left_over], src: buffer, n: len); |
168 | left_over += len; |
169 | if (left_over >= 64) |
170 | { |
171 | __md5_process_block (buffer: ctx->buffer, len: 64, ctx); |
172 | left_over -= 64; |
173 | memcpy (dest: ctx->buffer, src: &ctx->buffer[64], n: left_over); |
174 | } |
175 | ctx->buflen = left_over; |
176 | } |
177 | } |
178 | |
179 | #include <md5-block.c> |
180 | |