Coverage Report

Created: 2025-07-11 06:42

/src/dng_sdk/source/dng_fingerprint.h
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************/
2
// Copyright 2006-2007 Adobe Systems Incorporated
3
// All Rights Reserved.
4
//
5
// NOTICE:  Adobe permits you to use, modify, and distribute this file in
6
// accordance with the terms of the Adobe license agreement accompanying it.
7
/*****************************************************************************/
8
9
/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_fingerprint.h#2 $ */ 
10
/* $DateTime: 2012/07/11 10:36:56 $ */
11
/* $Change: 838485 $ */
12
/* $Author: tknoll $ */
13
14
/** \file
15
 * Fingerprint (cryptographic hashing) support for generating strong hashes of image
16
 * data.
17
 */
18
19
/*****************************************************************************/
20
21
#ifndef __dng_fingerprint__
22
#define __dng_fingerprint__
23
24
/*****************************************************************************/
25
26
#include "dng_exceptions.h"
27
#include "dng_types.h"
28
#include "dng_stream.h"
29
30
#include <cstring>
31
32
/*****************************************************************************/
33
34
/// \brief Container fingerprint (MD5 only at present).
35
36
class dng_fingerprint
37
  {
38
  
39
  public:
40
  
41
    static const size_t kDNGFingerprintSize = 16;
42
43
    uint8 data [kDNGFingerprintSize];
44
    
45
  public:
46
  
47
    dng_fingerprint ();
48
    
49
    /// Check if fingerprint is all zeros.
50
51
    bool IsNull () const;
52
53
    /// Same as IsNull but expresses intention of testing validity.
54
55
    bool IsValid () const
56
275k
      {
57
275k
      return !IsNull ();
58
275k
      }
59
60
    /// Set to all zeros, a value used to indicate an invalid fingerprint.
61
62
    void Clear ()
63
235k
      {
64
235k
      *this = dng_fingerprint ();
65
235k
      }
66
67
    /// Test if two fingerprints are equal.
68
      
69
    bool operator== (const dng_fingerprint &print) const;
70
    
71
    /// Test if two fingerprints are not equal.
72
73
    bool operator!= (const dng_fingerprint &print) const
74
372
      {
75
372
      return !(*this == print);
76
372
      }
77
      
78
    /// Produce a 32-bit hash value from fingerprint used for faster hashing of
79
    /// fingerprints.
80
      
81
    uint32 Collapse32 () const; 
82
83
    /// Convert fingerprint to UTF-8 string.
84
    ///
85
    /// \param resultStr The output array to which the UTF-8 encoding of the
86
    /// fingerprint will be written.
87
88
    void ToUtf8HexString (char resultStr [2 * kDNGFingerprintSize + 1]) const;
89
90
    /// Convert UTF-8 string to fingerprint. Returns true on success, false on
91
    /// failure.
92
    ///
93
    /// \param inputStr The input array from which the UTF-8 encoding of the
94
    /// fingerprint will be read.
95
    ///
96
    /// \retval True indicates success.
97
98
    bool FromUtf8HexString (const char inputStr [2 * kDNGFingerprintSize + 1]);
99
100
  };
101
102
/*****************************************************************************/
103
104
/// \brief Utility to compare fingerprints (e.g., for sorting).
105
106
struct dng_fingerprint_less_than
107
  {
108
109
  /// Less-than comparison.
110
111
  bool operator() (const dng_fingerprint &a, 
112
           const dng_fingerprint &b) const
113
0
    {
114
0
115
0
    return memcmp (a.data, 
116
0
             b.data, 
117
0
             sizeof (a.data)) < 0;
118
0
119
0
    }
120
121
  };
122
123
/******************************************************************************/
124
125
// Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
126
127
// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
128
// rights reserved.
129
// 
130
// License to copy and use this software is granted provided that it
131
// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
132
// Algorithm" in all material mentioning or referencing this software
133
// or this function.
134
// 
135
// License is also granted to make and use derivative works provided
136
// that such works are identified as "derived from the RSA Data
137
// Security, Inc. MD5 Message-Digest Algorithm" in all material
138
// mentioning or referencing the derived work.
139
// 
140
// RSA Data Security, Inc. makes no representations concerning either
141
// the merchantability of this software or the suitability of this
142
// software for any particular purpose. It is provided "as is"
143
// without express or implied warranty of any kind.
144
// 
145
// These notices must be retained in any copies of any part of this
146
// documentation and/or software.
147
148
/// \brief Class to hash binary data to a fingerprint using the MD5 Message-Digest
149
/// Algorithm.
150
151
class dng_md5_printer
152
  {
153
  
154
  public:
155
  
156
    dng_md5_printer ();
157
    
158
    virtual ~dng_md5_printer ()
159
192k
      {
160
192k
      }
161
    
162
    /// Reset the fingerprint.
163
164
    void Reset ();
165
    
166
    /// Append the data to the stream to be hashed.
167
    /// \param data The data to be hashed.
168
    /// \param inputLen The length of data, in bytes.
169
170
    void Process (const void *data,
171
            uint32 inputLen);
172
            
173
    /// Append the string to the stream to be hashed.
174
    /// \param text The string to be hashed.
175
176
    void Process (const char *text)
177
0
      {
178
0
      
179
0
      Process (text, (uint32) strlen (text));
180
0
      
181
0
      }
182
    
183
    /// Get the fingerprint (i.e., result of the hash).
184
185
    const dng_fingerprint & Result ();
186
    
187
  private:
188
  
189
    static void Encode (uint8 *output,
190
              const uint32 *input,
191
              uint32 len);
192
193
    static void Decode (uint32 *output,
194
              const uint8 *input,
195
              uint32 len);
196
              
197
    // F, G, H and I are basic MD5 functions.
198
199
    static inline uint32 F (uint32 x,
200
                uint32 y,
201
                uint32 z)
202
2.31G
      {
203
2.31G
      return (x & y) | (~x & z);
204
2.31G
      }
205
      
206
    static inline uint32 G (uint32 x,
207
                uint32 y,
208
                uint32 z)
209
2.31G
      {
210
2.31G
      return (x & z) | (y & ~z);
211
2.31G
      }
212
      
213
    static inline uint32 H (uint32 x,
214
                uint32 y,
215
                uint32 z)
216
2.31G
      {
217
2.31G
      return x ^ y ^ z;
218
2.31G
      }
219
      
220
    static inline uint32 I (uint32 x,
221
                uint32 y,
222
                uint32 z)
223
2.31G
      {
224
2.31G
      return y ^ (x | ~z);
225
2.31G
      }
226
      
227
    // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
228
    
229
#if defined(__clang__) && defined(__has_attribute)
230
#if __has_attribute(no_sanitize)
231
    __attribute__((no_sanitize("unsigned-integer-overflow")))
232
#endif
233
#endif
234
    static inline void FF (uint32 &a,
235
                 uint32 b,
236
                 uint32 c,
237
                 uint32 d,
238
                 uint32 x,
239
                 uint32 s,
240
                 uint32 ac)
241
2.31G
      {
242
2.31G
      a += F (b, c, d) + x + ac;
243
2.31G
      a = (a << s) | (a >> (32 - s));
244
2.31G
      a += b;
245
2.31G
      }
246
247
#if defined(__clang__) && defined(__has_attribute)
248
#if __has_attribute(no_sanitize)
249
    __attribute__((no_sanitize("unsigned-integer-overflow")))
250
#endif
251
#endif
252
    static inline void GG (uint32 &a,
253
                 uint32 b,
254
                 uint32 c,
255
                 uint32 d,
256
                 uint32 x,
257
                 uint32 s,
258
                 uint32 ac)
259
2.31G
      {
260
2.31G
      a += G (b, c, d) + x + ac;
261
2.31G
      a = (a << s) | (a >> (32 - s));
262
2.31G
      a += b;
263
2.31G
      }
264
265
#if defined(__clang__) && defined(__has_attribute)
266
#if __has_attribute(no_sanitize)
267
    __attribute__((no_sanitize("unsigned-integer-overflow")))
268
#endif
269
#endif
270
    static inline void HH (uint32 &a,
271
                 uint32 b,
272
                 uint32 c,
273
                 uint32 d,
274
                 uint32 x,
275
                 uint32 s,
276
                 uint32 ac)
277
2.31G
      {
278
2.31G
      a += H (b, c, d) + x + ac;
279
2.31G
      a = (a << s) | (a >> (32 - s));
280
2.31G
      a += b;
281
2.31G
      }
282
283
#if defined(__clang__) && defined(__has_attribute)
284
#if __has_attribute(no_sanitize)
285
    __attribute__((no_sanitize("unsigned-integer-overflow")))
286
#endif
287
#endif
288
    static inline void II (uint32 &a,
289
                 uint32 b,
290
                 uint32 c,
291
                 uint32 d,
292
                 uint32 x,
293
                 uint32 s,
294
                 uint32 ac)
295
2.31G
      {
296
2.31G
      a += I (b, c, d) + x + ac;
297
2.31G
      a = (a << s) | (a >> (32 - s));
298
2.31G
      a += b;
299
2.31G
      }
300
301
    static void MD5Transform (uint32 state [4],
302
                  const uint8 block [64]);
303
    
304
  private:
305
  
306
      uint32 state [4];
307
      
308
      uint32 count [2];
309
      
310
      uint8 buffer [64];
311
    
312
    bool final;
313
    
314
    dng_fingerprint result;
315
    
316
  };
317
318
/*****************************************************************************/
319
320
/// \brief A dng_stream based interface to the MD5 printing logic.
321
322
class dng_md5_printer_stream : public dng_stream, dng_md5_printer
323
  {
324
  
325
  private:
326
  
327
    uint64 fNextOffset;
328
329
  public:
330
331
    /// Create an empty MD5 printer stream.
332
333
    dng_md5_printer_stream ()
334
    
335
17.0k
      : fNextOffset (0)
336
      
337
17.0k
      {
338
17.0k
      }
339
340
    virtual uint64 DoGetLength ()
341
13.6k
      {
342
      
343
13.6k
      return fNextOffset;
344
      
345
13.6k
      }
346
  
347
    virtual void DoRead (void * /* data */,
348
               uint32 /* count */,
349
               uint64 /* offset */)
350
0
      {
351
      
352
0
      ThrowProgramError ();
353
      
354
0
      }
355
               
356
    virtual void DoSetLength (uint64 length)
357
0
      {
358
      
359
0
      if (length != fNextOffset)
360
0
        {
361
0
        ThrowProgramError ();
362
0
        }
363
        
364
0
      }
365
               
366
    virtual void DoWrite (const void *data,
367
                uint32 count2,
368
                uint64 offset)
369
13.7k
      {
370
      
371
13.7k
      if (offset != fNextOffset)
372
0
        {
373
0
        ThrowProgramError ();
374
0
        }
375
        
376
13.7k
      Process (data, count2);
377
      
378
13.7k
      fNextOffset += count2;
379
      
380
13.7k
      }
381
382
    const dng_fingerprint & Result ()
383
17.0k
      {
384
      
385
17.0k
      Flush ();
386
      
387
17.0k
      return dng_md5_printer::Result ();
388
      
389
17.0k
      }
390
391
  };
392
393
/*****************************************************************************/
394
395
#endif
396
  
397
/*****************************************************************************/