Coverage Report

Created: 2025-07-01 06:35

/src/lcms/src/cmsmd5.c
Line
Count
Source (jump to first uncovered line)
1
//---------------------------------------------------------------------------------
2
//
3
//  Little Color Management System
4
//  Copyright (c) 1998-2024 Marti Maria Saguer
5
//
6
// Permission is hereby granted, free of charge, to any person obtaining
7
// a copy of this software and associated documentation files (the "Software"),
8
// to deal in the Software without restriction, including without limitation
9
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
// and/or sell copies of the Software, and to permit persons to whom the Software
11
// is furnished to do so, subject to the following conditions:
12
//
13
// The above copyright notice and this permission notice shall be included in
14
// all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
//
24
//---------------------------------------------------------------------------------
25
26
27
#include "lcms2_internal.h"
28
29
#ifdef CMS_USE_BIG_ENDIAN
30
31
static
32
void byteReverse(cmsUInt8Number * buf, cmsUInt32Number longs)
33
{
34
    do {
35
36
        cmsUInt32Number t = _cmsAdjustEndianess32(*(cmsUInt32Number *) buf);
37
        *(cmsUInt32Number *) buf = t;
38
        buf += sizeof(cmsUInt32Number);
39
40
    } while (--longs);
41
42
}
43
44
#else
45
#define byteReverse(buf, len)
46
#endif
47
48
49
typedef struct {
50
51
    cmsUInt32Number buf[4];
52
    cmsUInt32Number bits[2];
53
    cmsUInt8Number in[64];
54
    cmsContext ContextID;
55
56
} _cmsMD5;
57
58
38.8M
#define F1(x, y, z) (z ^ (x & (y ^ z)))
59
19.4M
#define F2(x, y, z) F1(z, x, y)
60
19.4M
#define F3(x, y, z) (x ^ y ^ z)
61
19.4M
#define F4(x, y, z) (y ^ (x | ~z))
62
63
#define STEP(f, w, x, y, z, data, s) \
64
77.7M
    ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
65
66
67
static
68
void cmsMD5_Transform(cmsUInt32Number buf[4], cmsUInt32Number in[16])
69
1.21M
{
70
1.21M
    CMSREGISTER cmsUInt32Number a, b, c, d;
71
72
1.21M
    a = buf[0];
73
1.21M
    b = buf[1];
74
1.21M
    c = buf[2];
75
1.21M
    d = buf[3];
76
77
1.21M
    STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
78
1.21M
    STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
79
1.21M
    STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
80
1.21M
    STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
81
1.21M
    STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
82
1.21M
    STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
83
1.21M
    STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
84
1.21M
    STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
85
1.21M
    STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
86
1.21M
    STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
87
1.21M
    STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
88
1.21M
    STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
89
1.21M
    STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
90
1.21M
    STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
91
1.21M
    STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
92
1.21M
    STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
93
94
1.21M
    STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
95
1.21M
    STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
96
1.21M
    STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
97
1.21M
    STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
98
1.21M
    STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
99
1.21M
    STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
100
1.21M
    STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
101
1.21M
    STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
102
1.21M
    STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
103
1.21M
    STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
104
1.21M
    STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
105
1.21M
    STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
106
1.21M
    STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
107
1.21M
    STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
108
1.21M
    STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
109
1.21M
    STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
110
111
1.21M
    STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
112
1.21M
    STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
113
1.21M
    STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
114
1.21M
    STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
115
1.21M
    STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
116
1.21M
    STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
117
1.21M
    STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
118
1.21M
    STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
119
1.21M
    STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
120
1.21M
    STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
121
1.21M
    STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
122
1.21M
    STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
123
1.21M
    STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
124
1.21M
    STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
125
1.21M
    STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
126
1.21M
    STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
127
128
1.21M
    STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
129
1.21M
    STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
130
1.21M
    STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
131
1.21M
    STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
132
1.21M
    STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
133
1.21M
    STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
134
1.21M
    STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
135
1.21M
    STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
136
1.21M
    STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
137
1.21M
    STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
138
1.21M
    STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
139
1.21M
    STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
140
1.21M
    STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
141
1.21M
    STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
142
1.21M
    STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
143
1.21M
    STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
144
145
1.21M
    buf[0] += a;
146
1.21M
    buf[1] += b;
147
1.21M
    buf[2] += c;
148
1.21M
    buf[3] += d;
149
1.21M
}
150
151
152
// Create a MD5 object
153
154
cmsHANDLE CMSEXPORT cmsMD5alloc(cmsContext ContextID)
155
349
{
156
349
    _cmsMD5* ctx = (_cmsMD5*) _cmsMallocZero(ContextID, sizeof(_cmsMD5));
157
349
    if (ctx == NULL) return NULL;
158
159
349
    ctx ->ContextID = ContextID;
160
161
349
    ctx->buf[0] = 0x67452301;
162
349
    ctx->buf[1] = 0xefcdab89;
163
349
    ctx->buf[2] = 0x98badcfe;
164
349
    ctx->buf[3] = 0x10325476;
165
166
349
    ctx->bits[0] = 0;
167
349
    ctx->bits[1] = 0;
168
169
349
    return (cmsHANDLE) ctx;
170
349
}
171
172
void CMSEXPORT cmsMD5add(cmsHANDLE Handle, const cmsUInt8Number* buf, cmsUInt32Number len)
173
349
{
174
349
    _cmsMD5* ctx = (_cmsMD5*) Handle;
175
349
    cmsUInt32Number t;
176
177
349
    t = ctx->bits[0];
178
349
    if ((ctx->bits[0] = t + (len << 3)) < t)
179
0
        ctx->bits[1]++;
180
181
349
    ctx->bits[1] += len >> 29;
182
183
349
    t = (t >> 3) & 0x3f;
184
185
349
    if (t) {
186
187
0
        cmsUInt8Number *p = (cmsUInt8Number *) ctx->in + t;
188
189
0
        t = 64 - t;
190
0
        if (len < t) {
191
0
            memmove(p, buf, len);
192
0
            return;
193
0
        }
194
195
0
        memmove(p, buf, t);
196
0
        byteReverse(ctx->in, 16);
197
198
0
        cmsMD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in);
199
0
        buf += t;
200
0
        len -= t;
201
0
    }
202
203
1.21M
    while (len >= 64) {
204
1.21M
        memmove(ctx->in, buf, 64);
205
1.21M
        byteReverse(ctx->in, 16);
206
1.21M
        cmsMD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in);
207
1.21M
        buf += 64;
208
1.21M
        len -= 64;
209
1.21M
    }
210
211
349
    memmove(ctx->in, buf, len);
212
349
}
213
214
// Destroy the object and return the checksum
215
void CMSEXPORT cmsMD5finish(cmsProfileID* ProfileID,  cmsHANDLE Handle)
216
349
{
217
349
    _cmsMD5* ctx = (_cmsMD5*) Handle;
218
349
    cmsUInt32Number count;
219
349
    cmsUInt8Number *p;
220
221
349
    count = (ctx->bits[0] >> 3) & 0x3F;
222
223
349
    p = ctx->in + count;
224
349
    *p++ = 0x80;
225
226
349
    count = 64 - 1 - count;
227
228
349
    if (count < 8) {
229
230
51
        memset(p, 0, count);
231
51
        byteReverse(ctx->in, 16);
232
51
        cmsMD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in);
233
234
51
        memset(ctx->in, 0, 56);
235
298
    } else {
236
298
        memset(p, 0, count - 8);
237
298
    }
238
349
    byteReverse(ctx->in, 14);
239
240
349
    ((cmsUInt32Number *) ctx->in)[14] = ctx->bits[0];
241
349
    ((cmsUInt32Number *) ctx->in)[15] = ctx->bits[1];
242
243
349
    cmsMD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in);
244
245
349
    byteReverse((cmsUInt8Number *) ctx->buf, 4);
246
349
    memmove(ProfileID ->ID8, ctx->buf, 16);
247
248
349
    _cmsFree(ctx ->ContextID, ctx);
249
349
}
250
251
252
253
// Assuming io points to an ICC profile, compute and store MD5 checksum
254
// In the header, rendering intentent, flags and ID should be set to zero
255
// before computing MD5 checksum (per 7.2.18 of ICC spec 4.4)
256
257
cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
258
349
{
259
349
    cmsContext   ContextID;
260
349
    cmsUInt32Number BytesNeeded;
261
349
    cmsUInt8Number* Mem = NULL;
262
349
    cmsHANDLE  MD5 = NULL;
263
349
    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
264
349
    _cmsICCPROFILE Keep;
265
266
349
    _cmsAssert(hProfile != NULL);
267
268
349
    ContextID = cmsGetProfileContextID(hProfile);
269
270
    // Save a copy of the profile header
271
349
    memmove(&Keep, Icc, sizeof(_cmsICCPROFILE));
272
273
    // Set RI, flags and ID
274
349
    Icc ->flags = 0;
275
349
    Icc ->RenderingIntent = 0;
276
349
    memset(&Icc ->ProfileID, 0, sizeof(Icc ->ProfileID));
277
278
    // Compute needed storage
279
349
    if (!cmsSaveProfileToMem(hProfile, NULL, &BytesNeeded)) goto Error;
280
281
    // Allocate memory
282
349
    Mem = (cmsUInt8Number*) _cmsMalloc(ContextID, BytesNeeded);
283
349
    if (Mem == NULL) goto Error;
284
285
    // Save to temporary storage
286
349
    if (!cmsSaveProfileToMem(hProfile, Mem, &BytesNeeded)) goto Error;
287
288
    // Create MD5 object
289
349
    MD5 = cmsMD5alloc(ContextID);
290
349
    if (MD5 == NULL) goto Error;
291
292
    // Add all bytes
293
349
    cmsMD5add(MD5, Mem, BytesNeeded);
294
295
    // Temp storage is no longer needed
296
349
    _cmsFree(ContextID, Mem);
297
298
    // Restore header
299
349
    memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
300
301
    // And store the ID
302
349
    cmsMD5finish(&Icc ->ProfileID,  MD5);
303
349
    return TRUE;
304
305
0
Error:
306
307
    // Free resources as something went wrong
308
    // "MD5" cannot be other than NULL here, so no need to free it
309
0
    if (Mem != NULL) _cmsFree(ContextID, Mem);
310
0
    memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
311
0
    return FALSE;
312
349
}
313