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.cpp#3 $ */
10/* $DateTime: 2012/07/11 10:36:56 $ */
11/* $Change: 838485 $ */
12/* $Author: tknoll $ */
13
14/*****************************************************************************/
15
16#include "dng_fingerprint.h"
17
18#include "dng_assertions.h"
19#include "dng_flags.h"
20
21/*****************************************************************************/
22
23dng_fingerprint::dng_fingerprint ()
24 {
25
26 for (uint32 j = 0; j < 16; j++)
27 {
28
29 data [j] = 0;
30
31 }
32
33 }
34
35/*****************************************************************************/
36
37bool dng_fingerprint::IsNull () const
38 {
39
40 for (uint32 j = 0; j < 16; j++)
41 {
42
43 if (data [j] != 0)
44 {
45
46 return false;
47
48 }
49
50 }
51
52 return true;
53
54 }
55
56/*****************************************************************************/
57
58bool dng_fingerprint::operator== (const dng_fingerprint &print) const
59 {
60
61 for (uint32 j = 0; j < 16; j++)
62 {
63
64 if (data [j] != print.data [j])
65 {
66
67 return false;
68
69 }
70
71 }
72
73 return true;
74
75 }
76
77/******************************************************************************/
78
79uint32 dng_fingerprint::Collapse32 () const
80 {
81
82 uint32 x = 0;
83
84 for (uint32 j = 0; j < 4; j++)
85 {
86
87 uint32 y = 0;
88
89 for (uint32 k = 0; k < 4; k++)
90 {
91
92 y = (y << 8) + (uint32) data [j * 4 + k];
93
94 }
95
96 x = x ^ y;
97
98 }
99
100 return x;
101
102 }
103
104/******************************************************************************/
105
106static char NumToHexChar (unsigned int c)
107 {
108
109 if (c < 10)
110 {
111 return (char) ('0' + c);
112 }
113
114 else
115 {
116 return (char) ('A' + c - 10);
117 }
118
119 }
120
121/*****************************************************************************/
122
123void dng_fingerprint::ToUtf8HexString (char resultStr [2 * kDNGFingerprintSize + 1]) const
124 {
125
126 for (size_t i = 0; i < kDNGFingerprintSize; i++)
127 {
128
129 unsigned char c = data [i];
130
131 resultStr [i * 2] = NumToHexChar (c >> 4);
132 resultStr [i * 2 + 1] = NumToHexChar (c & 15);
133
134 }
135
136 resultStr [kDNGFingerprintSize * 2] = '\0';
137
138 }
139
140/******************************************************************************/
141
142static int HexCharToNum (char hexChar)
143 {
144
145 if (hexChar >= '0' && hexChar <= '9')
146 {
147 return hexChar - '0';
148 }
149
150 else if (hexChar >= 'A' && hexChar <= 'F')
151 {
152 return hexChar - 'A' + 10;
153 }
154
155 else if (hexChar >= 'a' && hexChar <= 'f')
156 {
157 return hexChar - 'a' + 10;
158 }
159
160 return -1;
161
162 }
163
164/*****************************************************************************/
165
166bool dng_fingerprint::FromUtf8HexString (const char inputStr [2 * kDNGFingerprintSize + 1])
167 {
168
169 for (size_t i = 0; i < kDNGFingerprintSize; i++)
170 {
171
172 int highNibble = HexCharToNum (inputStr [i * 2]);
173
174 if (highNibble < 0)
175 {
176 return false;
177 }
178
179 int lowNibble = HexCharToNum (inputStr [i * 2 + 1]);
180
181 if (lowNibble < 0)
182 {
183 return false;
184 }
185
186 data [i] = (uint8) ((highNibble << 4) + lowNibble);
187
188 }
189
190 return true;
191
192 }
193
194/******************************************************************************/
195
196// Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
197
198// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
199// rights reserved.
200//
201// License to copy and use this software is granted provided that it
202// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
203// Algorithm" in all material mentioning or referencing this software
204// or this function.
205//
206// License is also granted to make and use derivative works provided
207// that such works are identified as "derived from the RSA Data
208// Security, Inc. MD5 Message-Digest Algorithm" in all material
209// mentioning or referencing the derived work.
210//
211// RSA Data Security, Inc. makes no representations concerning either
212// the merchantability of this software or the suitability of this
213// software for any particular purpose. It is provided "as is"
214// without express or implied warranty of any kind.
215//
216// These notices must be retained in any copies of any part of this
217// documentation and/or software.
218
219/******************************************************************************/
220
221dng_md5_printer::dng_md5_printer ()
222
223 : final (false)
224 , result ()
225
226 {
227
228 Reset ();
229
230 }
231
232/******************************************************************************/
233
234void dng_md5_printer::Reset ()
235 {
236
237 // No bits processed yet.
238
239 count [0] = 0;
240 count [1] = 0;
241
242 // Load magic initialization constants.
243
244 state [0] = 0x67452301;
245 state [1] = 0xefcdab89;
246 state [2] = 0x98badcfe;
247 state [3] = 0x10325476;
248
249 // Not finalized yet.
250
251 final = false;
252
253 }
254
255/******************************************************************************/
256
257void dng_md5_printer::Process (const void *data,
258 uint32 inputLen)
259 {
260
261 DNG_ASSERT (!final, "Fingerprint already finalized!");
262
263 const uint8 *input = (const uint8 *) data;
264
265 // Compute number of bytes mod 64
266
267 uint32 index = (count [0] >> 3) & 0x3F;
268
269 // Update number of bits
270
271 if ((count [0] += inputLen << 3) < (inputLen << 3))
272 {
273 count [1]++;
274 }
275
276 count [1] += inputLen >> 29;
277
278 // Transform as many times as possible.
279
280 uint32 i = 0;
281
282 uint32 partLen = 64 - index;
283
284 if (inputLen >= partLen)
285 {
286
287 memcpy (&buffer [index],
288 input,
289 partLen);
290
291 MD5Transform (state, buffer);
292
293 for (i = partLen; i + 63 < inputLen; i += 64)
294 {
295
296 MD5Transform (state, &input [i]);
297
298 }
299
300 index = 0;
301
302 }
303
304 // Buffer remaining input
305
306 memcpy (&buffer [index],
307 &input [i],
308 inputLen - i);
309
310 }
311
312/******************************************************************************/
313
314const dng_fingerprint & dng_md5_printer::Result ()
315 {
316
317 if (!final)
318 {
319
320 static uint8 PADDING [64] =
321 {
322 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
323 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
325 };
326
327 // Save number of bits
328
329 uint8 bits [8];
330
331 Encode (bits, count, 8);
332
333 // Pad out to 56 mod 64.
334
335 uint32 index = (count [0] >> 3) & 0x3f;
336
337 uint32 padLen = (index < 56) ? (56 - index) : (120 - index);
338
339 Process (PADDING, padLen);
340
341 // Append length (before padding)
342
343 Process (bits, 8);
344
345 // Store state in digest
346
347 Encode (result.data, state, 16);
348
349 // We are now finalized.
350
351 final = true;
352
353 }
354
355 return result;
356
357 }
358
359/******************************************************************************/
360
361// Encodes input (uint32) into output (uint8). Assumes len is
362// a multiple of 4.
363
364void dng_md5_printer::Encode (uint8 *output,
365 const uint32 *input,
366 uint32 len)
367 {
368
369 uint32 i, j;
370
371 for (i = 0, j = 0; j < len; i++, j += 4)
372 {
373 output [j ] = (uint8) ((input [i] ) & 0xff);
374 output [j+1] = (uint8) ((input [i] >> 8) & 0xff);
375 output [j+2] = (uint8) ((input [i] >> 16) & 0xff);
376 output [j+3] = (uint8) ((input [i] >> 24) & 0xff);
377 }
378
379 }
380
381/******************************************************************************/
382
383// Decodes input (uint8) into output (uint32). Assumes len is
384// a multiple of 4.
385
386void dng_md5_printer::Decode (uint32 *output,
387 const uint8 *input,
388 uint32 len)
389 {
390
391 // Check for non-aligned case.
392
393 if (((uintptr) input) & 3)
394 {
395
396 uint32 i, j;
397
398 for (i = 0, j = 0; j < len; i++, j += 4)
399 {
400
401 output [i] = (((uint32) input [j ]) ) |
402 (((uint32) input [j+1]) << 8) |
403 (((uint32) input [j+2]) << 16) |
404 (((uint32) input [j+3]) << 24);
405
406 }
407
408 }
409
410 // Else use optimized code for aligned case.
411
412 else
413 {
414
415 len = len >> 2;
416
417 const uint32 *sPtr = (const uint32 *) input;
418
419 uint32 *dPtr = output;
420
421 while (len--)
422 {
423
424 #if qDNGBigEndian
425
426 uint32 data = *(sPtr++);
427
428 data = (data >> 24) |
429 ((data >> 8) & 0x0000FF00) |
430 ((data << 8) & 0x00FF0000) |
431 (data << 24);
432
433 *(dPtr++) = data;
434
435 #else
436
437 *(dPtr++) = *(sPtr++);
438
439 #endif
440
441 }
442
443 }
444
445 }
446
447/******************************************************************************/
448
449// MD5 basic transformation. Transforms state based on block.
450
451#if defined(__clang__) && defined(__has_attribute)
452#if __has_attribute(no_sanitize)
453__attribute__((no_sanitize("unsigned-integer-overflow")))
454#endif
455#endif
456void dng_md5_printer::MD5Transform (uint32 state [4],
457 const uint8 block [64])
458 {
459
460 enum
461 {
462 S11 = 7,
463 S12 = 12,
464 S13 = 17,
465 S14 = 22,
466 S21 = 5,
467 S22 = 9,
468 S23 = 14,
469 S24 = 20,
470 S31 = 4,
471 S32 = 11,
472 S33 = 16,
473 S34 = 23,
474 S41 = 6,
475 S42 = 10,
476 S43 = 15,
477 S44 = 21
478 };
479
480 #if qDNGBigEndian
481
482 uint32 x [16];
483
484 Decode (x, block, 64);
485
486 #else
487
488 uint32 temp [16];
489
490 const uint32 *x;
491
492 if (((uintptr) block) & 3)
493 {
494
495 Decode (temp, block, 64);
496
497 x = temp;
498
499 }
500
501 else
502 x = (const uint32 *) block;
503
504 #endif
505
506 uint32 a = state [0];
507 uint32 b = state [1];
508 uint32 c = state [2];
509 uint32 d = state [3];
510
511 /* Round 1 */
512 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
513 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
514 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
515 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
516 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
517 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
518 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
519 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
520 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
521 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
522 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
523 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
524 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
525 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
526 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
527 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
528
529 /* Round 2 */
530 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
531 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
532 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
533 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
534 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
535 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
536 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
537 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
538 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
539 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
540 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
541 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
542 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
543 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
544 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
545 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
546
547 /* Round 3 */
548 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
549 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
550 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
551 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
552 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
553 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
554 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
555 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
556 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
557 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
558 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
559 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
560 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
561 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
562 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
563 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
564
565 /* Round 4 */
566 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
567 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
568 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
569 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
570 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
571 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
572 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
573 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
574 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
575 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
576 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
577 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
578 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
579 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
580 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
581 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
582
583 state [0] += a;
584 state [1] += b;
585 state [2] += c;
586 state [3] += d;
587
588 }
589
590/*****************************************************************************/
591
592// End of RSA Data Security, Inc. derived code.
593
594/*****************************************************************************/
595