~widelands-dev/widelands/trunk

« back to all changes in this revision

Viewing changes to src/base/md5.cc

  • Committer: The Widelands Bunnybot
  • Date: 2024-10-30 11:13:48 UTC
  • Revision ID: bunnybot@widelands.org-20241030111348-3o6tpzf9hnpatxs2
Replace MD5 checksumming code with `libmd` (CB #4831 / GH #6469)

Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Widelands Bunnybot <bunnybot@widelands.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-committed-by: Benedikt Straub <benedikt-straub@web.de>

(by bunnybot)
d5effaf37cbe4bc83f74498612dd1b4374fca91b

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2002-2024 by the Widelands Development Team
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU General Public License
6
 
 * as published by the Free Software Foundation; either version 2
7
 
 * of the License, or (at your option) any later version.
8
 
 *
9
 
 * This program is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
16
 
 *
17
 
 */
18
 
 
19
 
/* md5.cc - Functions to compute MD5 message digest of files or memory blocks
20
 
 * according to the definition of MD5 in RFC 1321 from April 1992.
21
 
 *
22
 
 * Thanks to Ulrich Drepper for the md5sum example code.
23
 
 */
24
 
 
25
 
#include "base/md5.h"
26
 
 
27
 
#include "base/macros.h"
28
 
 
29
 
/**
30
 
 * Create a hex string out of the MD5 checksum.
31
 
 */
32
 
std::string Md5Checksum::str() const {
33
 
        std::string s;
34
 
 
35
 
        for (uint8_t d : data) {
36
 
                char buf[3];
37
 
                snprintf(buf, sizeof(buf), "%02x", d);
38
 
                s += buf;
39
 
        }
40
 
 
41
 
        return s;
42
 
}
43
 
 
44
 
/********************************************************************
45
 
 *
46
 
 * Down here: private functions originally from Ulrich Drepper
47
 
 *
48
 
 * From GNU textutils. md5.c
49
 
 *******************************************************************/
50
 
 
51
 
static const uint8_t fillbuf[64] = {0x80, 0 /*, 0, 0, ... 0 */};
52
 
 
53
 
/* Process the remaining bytes in the internal buffer and the usual
54
 
   prolog according to the standard and write the result to RESBUF.
55
 
 
56
 
   IMPORTANT: On some systems it is required that RESBUF is correctly
57
 
   aligned for a 32 bits value.  */
58
 
void* md5_finish_ctx(Md5Ctx* const ctx, void* const resbuf) {
59
 
        /* Take yet unprocessed bytes into account.  */
60
 
        uint32_t bytes = ctx->buflen;
61
 
        uint32_t pad;
62
 
 
63
 
        /* Now count remaining bytes.  */
64
 
        ctx->total[0] += bytes;
65
 
        if (ctx->total[0] < bytes) {
66
 
                ++ctx->total[1];
67
 
        }
68
 
 
69
 
        pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
70
 
        memcpy(&ctx->buffer[bytes], fillbuf, pad);
71
 
 
72
 
        //  Put the 64-bit file length in *bits* at the end of the buffer.
73
 
        GCC_DIAG_OFF("-Wstrict-aliasing");
74
 
        *reinterpret_cast<uint32_t*>(&ctx->buffer[bytes + pad]) = (ctx->total[0] << 3);
75
 
        *reinterpret_cast<uint32_t*>(&ctx->buffer[bytes + pad + 4]) =
76
 
           ((ctx->total[1] << 3) | (ctx->total[0] >> 29));
77
 
        GCC_DIAG_ON("-Wstrict-aliasing");
78
 
 
79
 
        /* Process last bytes.  */
80
 
        md5_process_block(ctx->buffer, bytes + pad + 8, ctx);
81
 
 
82
 
        static_cast<uint32_t*>(resbuf)[0] = ctx->A;
83
 
        static_cast<uint32_t*>(resbuf)[1] = ctx->B;
84
 
        static_cast<uint32_t*>(resbuf)[2] = ctx->C;
85
 
        static_cast<uint32_t*>(resbuf)[3] = ctx->D;
86
 
 
87
 
        return resbuf;
88
 
}
89
 
 
90
 
/* Processes some bytes in the internal buffer */
91
 
void md5_process_bytes(void const* buffer, uint32_t len, struct Md5Ctx* const ctx) {
92
 
        /* When we already have some bits in our internal buffer concatenate
93
 
           both inputs first.  */
94
 
        if (ctx->buflen != 0) {
95
 
                uint32_t left_over = ctx->buflen;
96
 
                uint32_t add = 128 - left_over > len ? len : 128 - left_over;
97
 
 
98
 
                memcpy(&ctx->buffer[left_over], buffer, add);
99
 
                ctx->buflen += add;
100
 
 
101
 
                if (left_over + add > 64) {
102
 
                        md5_process_block(ctx->buffer, (left_over + add) & ~63, ctx);
103
 
                        /* The regions in the following copy operation cannot overlap.  */
104
 
                        memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63], (left_over + add) & 63);
105
 
                        ctx->buflen = (left_over + add) & 63;
106
 
                }
107
 
 
108
 
                buffer = static_cast<const char*>(buffer) + add;
109
 
                len -= add;
110
 
        }
111
 
 
112
 
        /* Process available complete blocks.  */
113
 
        if (len > 64) {
114
 
                md5_process_block(buffer, len & ~63, ctx);
115
 
                buffer = static_cast<const char*>(buffer) + (len & ~63);
116
 
                len &= 63;
117
 
        }
118
 
 
119
 
        /* Move remaining bytes in internal buffer.  */
120
 
        if (len > 0) {
121
 
                memcpy(ctx->buffer, buffer, len);
122
 
                ctx->buflen = len;
123
 
        }
124
 
}
125
 
 
126
 
/* These are the four functions used in the four steps of the MD5 algorithm
127
 
   and defined in the RFC 1321.  The first function is a little bit optimized
128
 
   (as found in Colin Plumbs public domain implementation).  */
129
 
/* #define FF(b, c, d) ((b & c) | (~b & d)) */
130
 
#define FF(b, c, d) (d ^ (b & (c ^ d)))
131
 
#define FG(b, c, d) FF(d, b, c)
132
 
#define FH(b, c, d) (b ^ c ^ d)
133
 
#define FI(b, c, d) (c ^ (b | ~d))
134
 
 
135
 
/* Process LEN bytes of BUFFER, accumulating context into CTX.
136
 
   It is assumed that LEN % 64 == 0.  */
137
 
 
138
 
void md5_process_block(void const* const buffer, uint32_t const len, Md5Ctx* const ctx) {
139
 
        uint32_t correct_words[16];
140
 
        uint32_t const* words = static_cast<uint32_t const*>(buffer);
141
 
        uint32_t const nwords = len / sizeof(uint32_t);
142
 
        uint32_t const* const endp = words + nwords;
143
 
        uint32_t A = ctx->A;
144
 
        uint32_t B = ctx->B;
145
 
        uint32_t C = ctx->C;
146
 
        uint32_t D = ctx->D;
147
 
 
148
 
        /* First increment the byte count.  RFC 1321 specifies the possible
149
 
           length of the file up to 2^64 bits.  Here we only compute the
150
 
           number of bytes.  Do a double word increment.  */
151
 
        ctx->total[0] += len;
152
 
        if (ctx->total[0] < len) {
153
 
                ++ctx->total[1];
154
 
        }
155
 
 
156
 
        /* Process all bytes in the buffer with 64 bytes in each round of
157
 
           the loop.  */
158
 
        while (words < endp) {
159
 
                uint32_t* cwp = correct_words;
160
 
                uint32_t const A_save = A;
161
 
                uint32_t const B_save = B;
162
 
                uint32_t const C_save = C;
163
 
                uint32_t const D_save = D;
164
 
 
165
 
                /* First round: using the given function, the context and a constant
166
 
                the next context is computed.  Because the algorithms processing
167
 
                unit is a 32-bit word and it is determined to work on words in
168
 
                little endian byte order we perhaps have to change the byte order
169
 
                before the computation.  To reduce the work for the next steps
170
 
                we store the swapped words in the array CORRECT_WORDS.  */
171
 
 
172
 
#define OP(a, b, c, d, s, T)                                                                       \
173
 
        do {                                                                                            \
174
 
                a += FF(b, c, d) + (*cwp++ = (*words)) + T;                                                  \
175
 
                ++words;                                                                                     \
176
 
                CYCLIC(a, s);                                                                                \
177
 
                a += b;                                                                                      \
178
 
        } while (false)
179
 
 
180
 
/* It is unfortunate that C does not provide an operator for
181
 
        cyclic rotation.  Hope the C compiler is smart enough.  */
182
 
#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
183
 
 
184
 
                /* Before we start, one word to the strange constants.
185
 
                They are defined in RFC 1321 as
186
 
 
187
 
                T[i] = static_cast<int32_t>(4294967296.0 * fabs (sin (i))), i=1..64
188
 
                */
189
 
 
190
 
                /* Round 1.  */
191
 
                OP(A, B, C, D, 7, 0xd76aa478);
192
 
                OP(D, A, B, C, 12, 0xe8c7b756);
193
 
                OP(C, D, A, B, 17, 0x242070db);
194
 
                OP(B, C, D, A, 22, 0xc1bdceee);
195
 
                OP(A, B, C, D, 7, 0xf57c0faf);
196
 
                OP(D, A, B, C, 12, 0x4787c62a);
197
 
                OP(C, D, A, B, 17, 0xa8304613);
198
 
                OP(B, C, D, A, 22, 0xfd469501);
199
 
                OP(A, B, C, D, 7, 0x698098d8);
200
 
                OP(D, A, B, C, 12, 0x8b44f7af);
201
 
                OP(C, D, A, B, 17, 0xffff5bb1);
202
 
                OP(B, C, D, A, 22, 0x895cd7be);
203
 
                OP(A, B, C, D, 7, 0x6b901122);
204
 
                OP(D, A, B, C, 12, 0xfd987193);
205
 
                OP(C, D, A, B, 17, 0xa679438e);
206
 
                OP(B, C, D, A, 22, 0x49b40821);
207
 
 
208
 
/* For the second to fourth round we have the possibly swapped words
209
 
in CORRECT_WORDS.  Redefine the macro to take an additional first
210
 
argument specifying the function to use.  */
211
 
#undef OP
212
 
#define OP(f, a, b, c, d, k, s, T)                                                                 \
213
 
        do {                                                                                            \
214
 
                a += f(b, c, d) + correct_words[k] + T;                                                      \
215
 
                CYCLIC(a, s);                                                                                \
216
 
                a += b;                                                                                      \
217
 
        } while (false)
218
 
 
219
 
                /* Round 2.  */
220
 
                OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
221
 
                OP(FG, D, A, B, C, 6, 9, 0xc040b340);
222
 
                OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
223
 
                OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
224
 
                OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
225
 
                OP(FG, D, A, B, C, 10, 9, 0x02441453);
226
 
                OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
227
 
                OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
228
 
                OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
229
 
                OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
230
 
                OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
231
 
                OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
232
 
                OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
233
 
                OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
234
 
                OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
235
 
                OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
236
 
 
237
 
                /* Round 3.  */
238
 
                OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
239
 
                OP(FH, D, A, B, C, 8, 11, 0x8771f681);
240
 
                OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
241
 
                OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
242
 
                OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
243
 
                OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
244
 
                OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
245
 
                OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
246
 
                OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
247
 
                OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
248
 
                OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
249
 
                OP(FH, B, C, D, A, 6, 23, 0x04881d05);
250
 
                OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
251
 
                OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
252
 
                OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
253
 
                OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
254
 
 
255
 
                /* Round 4.  */
256
 
                OP(FI, A, B, C, D, 0, 6, 0xf4292244);
257
 
                OP(FI, D, A, B, C, 7, 10, 0x432aff97);
258
 
                OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
259
 
                OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
260
 
                OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
261
 
                OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
262
 
                OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
263
 
                OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
264
 
                OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
265
 
                OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
266
 
                OP(FI, C, D, A, B, 6, 15, 0xa3014314);
267
 
                OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
268
 
                OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
269
 
                OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
270
 
                OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
271
 
                OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
272
 
 
273
 
                /* Add the starting values of the context.  */
274
 
                A += A_save;
275
 
                B += B_save;
276
 
                C += C_save;
277
 
                D += D_save;
278
 
        }
279
 
 
280
 
        /* Put checksum in context given as argument.  */
281
 
        ctx->A = A;
282
 
        ctx->B = B;
283
 
        ctx->C = C;
284
 
        ctx->D = D;
285
 
}