Coverage Report

Created: 2025-06-13 06:46

/src/Fast-DDS/src/cpp/utils/md5.cpp
Line
Count
Source (jump to first uncovered line)
1
2
/* MD5
3
   converted to C++ class by Frank Thilo (thilo@unix-ag.org)
4
   for bzflag (http://www.bzflag.org)
5
6
   based on:
7
8
   md5.h and md5.c
9
   reference implemantion of RFC 1321
10
11
   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
12
   rights reserved.
13
14
   License to copy and use this software is granted provided that it
15
   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
16
   Algorithm" in all material mentioning or referencing this software
17
   or this function.
18
19
   License is also granted to make and use derivative works provided
20
   that such works are identified as "derived from the RSA Data
21
   Security, Inc. MD5 Message-Digest Algorithm" in all material
22
   mentioning or referencing the derived work.
23
24
   RSA Data Security, Inc. makes no representations concerning either
25
   the merchantability of this software or the suitability of this
26
   software for any particular purpose. It is provided "as is"
27
   without express or implied warranty of any kind.
28
29
   These notices must be retained in any copies of any part of this
30
   documentation and/or software.
31
32
 */
33
34
/* interface header */
35
#include <fastdds/utils/md5.hpp>
36
37
/* system implementation headers */
38
#include <cstdio>
39
#include <stdio.h>
40
41
namespace eprosima {
42
namespace fastdds {
43
44
// Constants for MD5Transform routine.
45
0
#define S11 7
46
0
#define S12 12
47
0
#define S13 17
48
0
#define S14 22
49
0
#define S21 5
50
0
#define S22 9
51
0
#define S23 14
52
0
#define S24 20
53
0
#define S31 4
54
0
#define S32 11
55
0
#define S33 16
56
0
#define S34 23
57
0
#define S41 6
58
0
#define S42 10
59
0
#define S43 15
60
0
#define S44 21
61
62
///////////////////////////////////////////////
63
64
// F, G, H and I are basic MD5 functions.
65
inline MD5::uint4 MD5::F(
66
        uint4 x,
67
        uint4 y,
68
        uint4 z)
69
0
{
70
0
    return (x & y) | (~x & z);
71
0
}
72
73
inline MD5::uint4 MD5::G(
74
        uint4 x,
75
        uint4 y,
76
        uint4 z)
77
0
{
78
0
    return (x & z) | (y & ~z);
79
0
}
80
81
inline MD5::uint4 MD5::H(
82
        uint4 x,
83
        uint4 y,
84
        uint4 z)
85
0
{
86
0
    return x ^ y ^ z;
87
0
}
88
89
inline MD5::uint4 MD5::I(
90
        uint4 x,
91
        uint4 y,
92
        uint4 z)
93
0
{
94
0
    return y ^ (x | ~z);
95
0
}
96
97
// rotate_left rotates x left n bits.
98
inline MD5::uint4 MD5::rotate_left(
99
        uint4 x,
100
        int n)
101
0
{
102
0
    return (x << n) | (x >> (32 - n));
103
0
}
104
105
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
106
// Rotation is separate from addition to prevent recomputation.
107
inline void MD5::FF(
108
        uint4& a,
109
        uint4 b,
110
        uint4 c,
111
        uint4 d,
112
        uint4 x,
113
        uint4 s,
114
        uint4 ac)
115
0
{
116
0
    a = rotate_left(a + F(b, c, d) + x + ac, s) + b;
117
0
}
118
119
inline void MD5::GG(
120
        uint4& a,
121
        uint4 b,
122
        uint4 c,
123
        uint4 d,
124
        uint4 x,
125
        uint4 s,
126
        uint4 ac)
127
0
{
128
0
    a = rotate_left(a + G(b, c, d) + x + ac, s) + b;
129
0
}
130
131
inline void MD5::HH(
132
        uint4& a,
133
        uint4 b,
134
        uint4 c,
135
        uint4 d,
136
        uint4 x,
137
        uint4 s,
138
        uint4 ac)
139
0
{
140
0
    a = rotate_left(a + H(b, c, d) + x + ac, s) + b;
141
0
}
142
143
inline void MD5::II(
144
        uint4& a,
145
        uint4 b,
146
        uint4 c,
147
        uint4 d,
148
        uint4 x,
149
        uint4 s,
150
        uint4 ac)
151
0
{
152
0
    a = rotate_left(a + I(b, c, d) + x + ac, s) + b;
153
0
}
154
155
//////////////////////////////////////////////
156
157
// default ctor, just initailize
158
MD5::MD5()
159
0
{
160
0
    init();
161
0
}
162
163
//////////////////////////////////////////////
164
165
// nifty shortcut ctor, compute MD5 for string and finalize it right away
166
MD5::MD5(
167
        const std::string& text)
168
0
{
169
0
    init();
170
0
    update(text.c_str(), (unsigned int)text.length());
171
0
    finalize();
172
0
}
173
174
//////////////////////////////
175
176
void MD5::init()
177
0
{
178
0
    finalized = false;
179
180
0
    count[0] = 0;
181
0
    count[1] = 0;
182
183
    // load magic initialization constants.
184
0
    state[0] = 0x67452301;
185
0
    state[1] = 0xefcdab89;
186
0
    state[2] = 0x98badcfe;
187
0
    state[3] = 0x10325476;
188
0
}
189
190
//////////////////////////////
191
192
// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
193
void MD5::decode(
194
        uint4 output[],
195
        const uint1 input[],
196
        size_type len)
197
0
{
198
0
    for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
199
0
    {
200
0
        output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) |
201
0
                (((uint4)input[j + 2]) << 16) | (((uint4)input[j + 3]) << 24);
202
0
    }
203
0
}
204
205
//////////////////////////////
206
207
// encodes input (uint4) into output (unsigned char). Assumes len is
208
// a multiple of 4.
209
void MD5::encode(
210
        uint1 output[],
211
        const uint4 input[],
212
        size_type len)
213
0
{
214
0
    for (size_type i = 0, j = 0; j < len; i++, j += 4)
215
0
    {
216
0
        output[j] = input[i] & 0xff;
217
0
        output[j + 1] = (input[i] >> 8) & 0xff;
218
0
        output[j + 2] = (input[i] >> 16) & 0xff;
219
0
        output[j + 3] = (input[i] >> 24) & 0xff;
220
0
    }
221
0
}
222
223
//////////////////////////////
224
225
// apply MD5 algo on a block
226
void MD5::transform(
227
        const uint1 block[blocksize])
228
0
{
229
0
    uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
230
0
    decode (x, block, blocksize);
231
232
    /* Round 1 */
233
0
    FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
234
0
    FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
235
0
    FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
236
0
    FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
237
0
    FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
238
0
    FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
239
0
    FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
240
0
    FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
241
0
    FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
242
0
    FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
243
0
    FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
244
0
    FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
245
0
    FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
246
0
    FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
247
0
    FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
248
0
    FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
249
250
    /* Round 2 */
251
0
    GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
252
0
    GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
253
0
    GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
254
0
    GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
255
0
    GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
256
0
    GG (d, a, b, c, x[10], S22,  0x2441453);/* 22 */
257
0
    GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
258
0
    GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
259
0
    GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
260
0
    GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
261
0
    GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
262
0
    GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
263
0
    GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
264
0
    GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
265
0
    GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
266
0
    GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
267
268
    /* Round 3 */
269
0
    HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
270
0
    HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
271
0
    HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
272
0
    HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
273
0
    HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
274
0
    HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
275
0
    HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
276
0
    HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
277
0
    HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
278
0
    HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
279
0
    HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
280
0
    HH (b, c, d, a, x[ 6], S34,  0x4881d05);/* 44 */
281
0
    HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
282
0
    HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
283
0
    HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
284
0
    HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
285
286
    /* Round 4 */
287
0
    II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
288
0
    II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
289
0
    II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
290
0
    II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
291
0
    II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
292
0
    II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
293
0
    II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
294
0
    II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
295
0
    II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
296
0
    II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
297
0
    II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
298
0
    II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
299
0
    II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
300
0
    II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
301
0
    II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
302
0
    II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
303
304
0
    state[0] += a;
305
0
    state[1] += b;
306
0
    state[2] += c;
307
0
    state[3] += d;
308
309
    // Zeroize sensitive information.
310
0
    memset(x, 0, sizeof x);
311
0
}
312
313
//////////////////////////////
314
315
// MD5 block update operation. Continues an MD5 message-digest
316
// operation, processing another message block
317
void MD5::update(
318
        const unsigned char input[],
319
        size_type length)
320
0
{
321
    // compute number of bytes mod 64
322
0
    size_type index = count[0] / 8 % blocksize;
323
324
    // Update number of bits
325
0
    if ((count[0] += (length << 3)) < (length << 3))
326
0
    {
327
0
        count[1]++;
328
0
    }
329
0
    count[1] += (length >> 29);
330
331
    // number of bytes we need to fill in buffer
332
0
    size_type firstpart = 64 - index;
333
334
0
    size_type i;
335
336
    // transform as many times as possible.
337
0
    if (length >= firstpart)
338
0
    {
339
        // fill buffer first, transform
340
0
        memcpy(&buffer[index], input, firstpart);
341
0
        transform(buffer);
342
343
        // transform chunks of blocksize (64 bytes)
344
0
        for (i = firstpart; i + blocksize <= length; i += blocksize)
345
0
        {
346
0
            transform(&input[i]);
347
0
        }
348
349
0
        index = 0;
350
0
    }
351
0
    else
352
0
    {
353
0
        i = 0;
354
0
    }
355
356
    // buffer remaining input
357
0
    memcpy(&buffer[index], &input[i], length - i);
358
0
}
359
360
//////////////////////////////
361
362
// for convenience provide a verson with signed char
363
void MD5::update(
364
        const char input[],
365
        size_type length)
366
0
{
367
0
    update((const unsigned char*)input, length);
368
0
}
369
370
//////////////////////////////
371
372
// MD5 finalization. Ends an MD5 message-digest operation, writing the
373
// the message digest and zeroizing the context.
374
MD5& MD5::finalize()
375
0
{
376
0
    static unsigned char padding[64] = {
377
0
        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
378
0
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
379
0
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
380
0
    };
381
382
0
    if (!finalized)
383
0
    {
384
        // Save number of bits
385
0
        unsigned char bits[8];
386
0
        encode(bits, count, 8);
387
388
        // pad out to 56 mod 64.
389
0
        size_type index = count[0] / 8 % 64;
390
0
        size_type padLen = (index < 56) ? (56 - index) : (120 - index);
391
0
        update(padding, padLen);
392
393
        // Append length (before padding)
394
0
        update(bits, 8);
395
396
        // Store state in digest
397
0
        encode(digest, state, 16);
398
399
        // Zeroize sensitive information.
400
0
        memset(buffer, 0, sizeof buffer);
401
0
        memset(count, 0, sizeof count);
402
403
0
        finalized = true;
404
0
    }
405
406
0
    return *this;
407
0
}
408
409
//////////////////////////////
410
411
// return hex representation of digest as string
412
std::string MD5::hexdigest() const
413
0
{
414
0
    if (!finalized)
415
0
    {
416
0
        return "";
417
0
    }
418
419
0
    constexpr size_t buf_len {33};
420
0
    char buf[buf_len];
421
#if defined(_WIN32)
422
    for (int i = 0; i < 16; i++)
423
    {
424
        sprintf_s(buf + i * 2, 32, "%02x", digest[i]);
425
    }
426
#else
427
0
    for (int i = 0; i < 16; i++)
428
0
    {
429
0
        snprintf(buf + i * 2, buf_len, "%02x", digest[i]);
430
0
    }
431
0
#endif // if defined(_WIN32)
432
0
    buf[32] = 0;
433
434
0
    return std::string(buf);
435
0
}
436
437
//////////////////////////////
438
439
std::ostream& operator <<(
440
        std::ostream& out,
441
        MD5& md5)
442
0
{
443
444
0
    return out << md5.hexdigest().c_str();
445
0
}
446
447
//////////////////////////////
448
449
std::string md5(
450
        const std::string str)
451
0
{
452
0
    MD5 md5 = MD5(str);
453
454
0
    return md5.hexdigest();
455
0
}
456
457
}   // namespace fastdds
458
}   // namespace eprosima