1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sha.c SHA-1 implementation
3 *
4 * Copyright (C) 2003 Red Hat Inc.
5 * Copyright (C) 1995 A. M. Kuchling
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 #include <config.h>
26 #include "dbus-internals.h"
27 #include "dbus-sha.h"
28 #include "dbus-marshal-basic.h" /* for byteswap routines */
29 #include <string.h>
30
31 /* The following comments have the history of where this code
32 * comes from. I actually copied it from GNet in GNOME CVS.
33 * - hp@redhat.com
34 */
35
36 /*
37 * sha.h : Implementation of the Secure Hash Algorithm
38 *
39 * Part of the Python Cryptography Toolkit, version 1.0.0
40 *
41 * Copyright (C) 1995, A.M. Kuchling
42 *
43 * Distribute and use freely; there are no restrictions on further
44 * dissemination and usage except those imposed by the laws of your
45 * country of residence.
46 *
47 */
48
49 /* SHA: NIST's Secure Hash Algorithm */
50
51 /* Based on SHA code originally posted to sci.crypt by Peter Gutmann
52 in message <30ajo5$oe8@ccu2.auckland.ac.nz>.
53 Modified to test for endianness on creation of SHA objects by AMK.
54 Also, the original specification of SHA was found to have a weakness
55 by NSA/NIST. This code implements the fixed version of SHA.
56 */
57
58 /* Here's the first paragraph of Peter Gutmann's posting:
59
60 The following is my SHA (FIPS 180) code updated to allow use of the "fixed"
61 SHA, thanks to Jim Gillogly and an anonymous contributor for the information on
62 what's changed in the new version. The fix is a simple change which involves
63 adding a single rotate in the initial expansion function. It is unknown
64 whether this is an optimal solution to the problem which was discovered in the
65 SHA or whether it's simply a bandaid which fixes the problem with a minimum of
66 effort (for example the reengineering of a great many Capstone chips).
67 */
68
69 /**
70 * @defgroup DBusSHA SHA implementation
71 * @ingroup DBusInternals
72 * @brief SHA-1 hash
73 *
74 * Types and functions related to computing SHA-1 hash.
75 */
76
77 /**
78 * @defgroup DBusSHAInternals SHA implementation details
79 * @ingroup DBusInternals
80 * @brief Internals of SHA implementation.
81 *
82 * The implementation of SHA-1 (see http://www.itl.nist.gov/fipspubs/fip180-1.htm).
83 * This SHA implementation was written by A.M. Kuchling
84 *
85 * @{
86 */
87
88 #ifndef DOXYGEN_SHOULD_SKIP_THIS
89
90 /* The SHA block size and message digest sizes, in bytes */
91
92 #define SHA_DATASIZE 64
93 #define SHA_DIGESTSIZE 20
94
95 /* The SHA f()-functions. The f1 and f3 functions can be optimized to
96 save one boolean operation each - thanks to Rich Schroeppel,
97 rcs@cs.arizona.edu for discovering this */
98
99 /*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) // Rounds 0-19 */
100 #define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */
101 #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */
102 /*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) // Rounds 40-59 */
103 #define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */
104 #define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */
105
106 /* The SHA Mysterious Constants */
107
108 #define K1 0x5A827999L /* Rounds 0-19 */
109 #define K2 0x6ED9EBA1L /* Rounds 20-39 */
110 #define K3 0x8F1BBCDCL /* Rounds 40-59 */
111 #define K4 0xCA62C1D6L /* Rounds 60-79 */
112
113 /* SHA initial values */
114
115 #define h0init 0x67452301L
116 #define h1init 0xEFCDAB89L
117 #define h2init 0x98BADCFEL
118 #define h3init 0x10325476L
119 #define h4init 0xC3D2E1F0L
120
121 /* Note that it may be necessary to add parentheses to these macros if they
122 are to be called with expressions as arguments */
123 /* 32-bit rotate left - kludged with shifts */
124
125 #define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
126
127 /* The initial expanding function. The hash function is defined over an
128 80-word expanded input array W, where the first 16 are copies of the input
129 data, and the remaining 64 are defined by
130
131 W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ]
132
133 This implementation generates these values on the fly in a circular
134 buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this
135 optimization.
136
137 The updated SHA changes the expanding function by adding a rotate of 1
138 bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor
139 for this information */
140
141 #define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \
142 W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) )
143
144
145 /* The prototype SHA sub-round. The fundamental sub-round is:
146
147 a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data;
148 b' = a;
149 c' = ROTL( 30, b );
150 d' = c;
151 e' = d;
152
153 but this is implemented by unrolling the loop 5 times and renaming the
154 variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration.
155 This code is then replicated 20 times for each of the 4 functions, using
156 the next 20 values from the W[] array each time */
157
158 #define subRound(a, b, c, d, e, f, k, data) \
159 ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )
160
161 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
162
163 /* Perform the SHA transformation. Note that this code, like MD5, seems to
164 break some optimizing compilers due to the complexity of the expressions
165 and the size of the basic block. It may be necessary to split it into
166 sections, e.g. based on the four subrounds
167
168 Note that this corrupts the context->data area */
169
170 static void
SHATransform(dbus_uint32_t * digest,dbus_uint32_t * data)171 SHATransform(dbus_uint32_t *digest, dbus_uint32_t *data)
172 {
173 dbus_uint32_t A, B, C, D, E; /* Local vars */
174 dbus_uint32_t eData[16]; /* Expanded data */
175
176 /* Set up first buffer and local data buffer */
177 A = digest[0];
178 B = digest[1];
179 C = digest[2];
180 D = digest[3];
181 E = digest[4];
182 memmove (eData, data, SHA_DATASIZE);
183
184 /* Heavy mangling, in 4 sub-rounds of 20 interations each. */
185 subRound (A, B, C, D, E, f1, K1, eData[0]);
186 subRound (E, A, B, C, D, f1, K1, eData[1]);
187 subRound (D, E, A, B, C, f1, K1, eData[2]);
188 subRound (C, D, E, A, B, f1, K1, eData[3]);
189 subRound (B, C, D, E, A, f1, K1, eData[4]);
190 subRound (A, B, C, D, E, f1, K1, eData[5]);
191 subRound (E, A, B, C, D, f1, K1, eData[6]);
192 subRound (D, E, A, B, C, f1, K1, eData[7]);
193 subRound (C, D, E, A, B, f1, K1, eData[8]);
194 subRound (B, C, D, E, A, f1, K1, eData[9]);
195 subRound (A, B, C, D, E, f1, K1, eData[10]);
196 subRound (E, A, B, C, D, f1, K1, eData[11]);
197 subRound (D, E, A, B, C, f1, K1, eData[12]);
198 subRound (C, D, E, A, B, f1, K1, eData[13]);
199 subRound (B, C, D, E, A, f1, K1, eData[14]);
200 subRound (A, B, C, D, E, f1, K1, eData[15]);
201 subRound (E, A, B, C, D, f1, K1, expand ( eData, 16) );
202 subRound (D, E, A, B, C, f1, K1, expand ( eData, 17) );
203 subRound (C, D, E, A, B, f1, K1, expand ( eData, 18) );
204 subRound (B, C, D, E, A, f1, K1, expand ( eData, 19) );
205
206 subRound (A, B, C, D, E, f2, K2, expand ( eData, 20) );
207 subRound (E, A, B, C, D, f2, K2, expand ( eData, 21) );
208 subRound (D, E, A, B, C, f2, K2, expand ( eData, 22) );
209 subRound (C, D, E, A, B, f2, K2, expand ( eData, 23) );
210 subRound (B, C, D, E, A, f2, K2, expand ( eData, 24) );
211 subRound (A, B, C, D, E, f2, K2, expand ( eData, 25) );
212 subRound (E, A, B, C, D, f2, K2, expand ( eData, 26) );
213 subRound (D, E, A, B, C, f2, K2, expand ( eData, 27) );
214 subRound (C, D, E, A, B, f2, K2, expand ( eData, 28) );
215 subRound (B, C, D, E, A, f2, K2, expand ( eData, 29) );
216 subRound (A, B, C, D, E, f2, K2, expand ( eData, 30) );
217 subRound (E, A, B, C, D, f2, K2, expand ( eData, 31) );
218 subRound (D, E, A, B, C, f2, K2, expand ( eData, 32) );
219 subRound (C, D, E, A, B, f2, K2, expand ( eData, 33) );
220 subRound (B, C, D, E, A, f2, K2, expand ( eData, 34) );
221 subRound (A, B, C, D, E, f2, K2, expand ( eData, 35) );
222 subRound (E, A, B, C, D, f2, K2, expand ( eData, 36) );
223 subRound (D, E, A, B, C, f2, K2, expand ( eData, 37) );
224 subRound (C, D, E, A, B, f2, K2, expand ( eData, 38) );
225 subRound (B, C, D, E, A, f2, K2, expand ( eData, 39) );
226
227 subRound (A, B, C, D, E, f3, K3, expand ( eData, 40) );
228 subRound (E, A, B, C, D, f3, K3, expand ( eData, 41) );
229 subRound (D, E, A, B, C, f3, K3, expand ( eData, 42) );
230 subRound (C, D, E, A, B, f3, K3, expand ( eData, 43) );
231 subRound (B, C, D, E, A, f3, K3, expand ( eData, 44) );
232 subRound (A, B, C, D, E, f3, K3, expand ( eData, 45) );
233 subRound (E, A, B, C, D, f3, K3, expand ( eData, 46) );
234 subRound (D, E, A, B, C, f3, K3, expand ( eData, 47) );
235 subRound (C, D, E, A, B, f3, K3, expand ( eData, 48) );
236 subRound (B, C, D, E, A, f3, K3, expand ( eData, 49) );
237 subRound (A, B, C, D, E, f3, K3, expand ( eData, 50) );
238 subRound (E, A, B, C, D, f3, K3, expand ( eData, 51) );
239 subRound (D, E, A, B, C, f3, K3, expand ( eData, 52) );
240 subRound (C, D, E, A, B, f3, K3, expand ( eData, 53) );
241 subRound (B, C, D, E, A, f3, K3, expand ( eData, 54) );
242 subRound (A, B, C, D, E, f3, K3, expand ( eData, 55) );
243 subRound (E, A, B, C, D, f3, K3, expand ( eData, 56) );
244 subRound (D, E, A, B, C, f3, K3, expand ( eData, 57) );
245 subRound (C, D, E, A, B, f3, K3, expand ( eData, 58) );
246 subRound (B, C, D, E, A, f3, K3, expand ( eData, 59) );
247
248 subRound (A, B, C, D, E, f4, K4, expand ( eData, 60) );
249 subRound (E, A, B, C, D, f4, K4, expand ( eData, 61) );
250 subRound (D, E, A, B, C, f4, K4, expand ( eData, 62) );
251 subRound (C, D, E, A, B, f4, K4, expand ( eData, 63) );
252 subRound (B, C, D, E, A, f4, K4, expand ( eData, 64) );
253 subRound (A, B, C, D, E, f4, K4, expand ( eData, 65) );
254 subRound (E, A, B, C, D, f4, K4, expand ( eData, 66) );
255 subRound (D, E, A, B, C, f4, K4, expand ( eData, 67) );
256 subRound (C, D, E, A, B, f4, K4, expand ( eData, 68) );
257 subRound (B, C, D, E, A, f4, K4, expand ( eData, 69) );
258 subRound (A, B, C, D, E, f4, K4, expand ( eData, 70) );
259 subRound (E, A, B, C, D, f4, K4, expand ( eData, 71) );
260 subRound (D, E, A, B, C, f4, K4, expand ( eData, 72) );
261 subRound (C, D, E, A, B, f4, K4, expand ( eData, 73) );
262 subRound (B, C, D, E, A, f4, K4, expand ( eData, 74) );
263 subRound (A, B, C, D, E, f4, K4, expand ( eData, 75) );
264 subRound (E, A, B, C, D, f4, K4, expand ( eData, 76) );
265 subRound (D, E, A, B, C, f4, K4, expand ( eData, 77) );
266 subRound (C, D, E, A, B, f4, K4, expand ( eData, 78) );
267 subRound (B, C, D, E, A, f4, K4, expand ( eData, 79) );
268
269 /* Build message digest */
270 digest[0] += A;
271 digest[1] += B;
272 digest[2] += C;
273 digest[3] += D;
274 digest[4] += E;
275 }
276
277 /* When run on a little-endian CPU we need to perform byte reversal on an
278 array of longwords. */
279
280 #ifdef WORDS_BIGENDIAN
281 #define swap_words(buffer, byte_count)
282 #else
283 static void
swap_words(dbus_uint32_t * buffer,int byte_count)284 swap_words (dbus_uint32_t *buffer,
285 int byte_count)
286 {
287 byte_count /= sizeof (dbus_uint32_t);
288 while (byte_count--)
289 {
290 *buffer = DBUS_UINT32_SWAP_LE_BE (*buffer);
291 ++buffer;
292 }
293 }
294 #endif
295
296 static void
sha_init(DBusSHAContext * context)297 sha_init (DBusSHAContext *context)
298 {
299 /* Set the h-vars to their initial values */
300 context->digest[0] = h0init;
301 context->digest[1] = h1init;
302 context->digest[2] = h2init;
303 context->digest[3] = h3init;
304 context->digest[4] = h4init;
305
306 /* Initialise bit count */
307 context->count_lo = context->count_hi = 0;
308 }
309
310 static void
sha_append(DBusSHAContext * context,const unsigned char * buffer,unsigned int count)311 sha_append (DBusSHAContext *context,
312 const unsigned char *buffer,
313 unsigned int count)
314 {
315 dbus_uint32_t tmp;
316 unsigned int dataCount;
317
318 /* Update bitcount */
319 tmp = context->count_lo;
320 if (( context->count_lo = tmp + ( ( dbus_uint32_t) count << 3) ) < tmp)
321 context->count_hi++; /* Carry from low to high */
322 context->count_hi += count >> 29;
323
324 /* Get count of bytes already in data */
325 dataCount = (int) (tmp >> 3) & 0x3F;
326
327 /* Handle any leading odd-sized chunks */
328 if (dataCount)
329 {
330 unsigned char *p = (unsigned char *) context->data + dataCount;
331
332 dataCount = SHA_DATASIZE - dataCount;
333 if (count < dataCount)
334 {
335 memmove (p, buffer, count);
336 return;
337 }
338 memmove (p, buffer, dataCount);
339 swap_words (context->data, SHA_DATASIZE);
340 SHATransform (context->digest, context->data);
341 buffer += dataCount;
342 count -= dataCount;
343 }
344
345 /* Process data in SHA_DATASIZE chunks */
346 while (count >= SHA_DATASIZE)
347 {
348 memmove (context->data, buffer, SHA_DATASIZE);
349 swap_words (context->data, SHA_DATASIZE);
350 SHATransform (context->digest, context->data);
351 buffer += SHA_DATASIZE;
352 count -= SHA_DATASIZE;
353 }
354
355 /* Handle any remaining bytes of data. */
356 memmove (context->data, buffer, count);
357 }
358
359
360 /* Final wrapup - pad to SHA_DATASIZE-byte boundary with the bit pattern
361 1 0* (64-bit count of bits processed, MSB-first) */
362
363 static void
sha_finish(DBusSHAContext * context,unsigned char digest[20])364 sha_finish (DBusSHAContext *context, unsigned char digest[20])
365 {
366 int count;
367 unsigned char *data_p;
368
369 /* Compute number of bytes mod 64 */
370 count = (int) context->count_lo;
371 count = (count >> 3) & 0x3F;
372
373 /* Set the first char of padding to 0x80. This is safe since there is
374 always at least one byte free */
375 data_p = (unsigned char *) context->data + count;
376 *data_p++ = 0x80;
377
378 /* Bytes of padding needed to make 64 bytes */
379 count = SHA_DATASIZE - 1 - count;
380
381 /* Pad out to 56 mod 64 */
382 if (count < 8)
383 {
384 /* Two lots of padding: Pad the first block to 64 bytes */
385 memset (data_p, 0, count);
386 swap_words (context->data, SHA_DATASIZE);
387 SHATransform (context->digest, context->data);
388
389 /* Now fill the next block with 56 bytes */
390 memset (context->data, 0, SHA_DATASIZE - 8);
391 }
392 else
393 /* Pad block to 56 bytes */
394 memset (data_p, 0, count - 8);
395
396 /* Append length in bits and transform */
397 context->data[14] = context->count_hi;
398 context->data[15] = context->count_lo;
399
400 swap_words (context->data, SHA_DATASIZE - 8);
401 SHATransform (context->digest, context->data);
402 swap_words (context->digest, SHA_DIGESTSIZE);
403 memmove (digest, context->digest, SHA_DIGESTSIZE);
404 }
405
406 /** @} */ /* End of internals */
407
408 /**
409 * @addtogroup DBusSHA
410 *
411 * @{
412 */
413
414 /**
415 * Initializes the SHA context.
416 *
417 * @param context an uninitialized context, typically on the stack.
418 */
419 void
_dbus_sha_init(DBusSHAContext * context)420 _dbus_sha_init (DBusSHAContext *context)
421 {
422 sha_init (context);
423 }
424
425 /**
426 * Feeds more data into an existing shasum computation.
427 *
428 * @param context the SHA context
429 * @param data the additional data to hash
430 */
431 void
_dbus_sha_update(DBusSHAContext * context,const DBusString * data)432 _dbus_sha_update (DBusSHAContext *context,
433 const DBusString *data)
434 {
435 unsigned int inputLen;
436 const unsigned char *input;
437
438 input = (const unsigned char*) _dbus_string_get_const_data (data);
439 inputLen = _dbus_string_get_length (data);
440
441 sha_append (context, input, inputLen);
442 }
443
444 /**
445 * SHA finalization. Ends an SHA message-digest operation, writing the
446 * the message digest and zeroing the context. The results are
447 * returned as a raw 20-byte digest, not as the ascii-hex-digits
448 * string form of the digest.
449 *
450 * @param context the SHA context
451 * @param results string to append the 20-byte SHA digest to
452 * @returns #FALSE if not enough memory to append the digest
453 *
454 */
455 dbus_bool_t
_dbus_sha_final(DBusSHAContext * context,DBusString * results)456 _dbus_sha_final (DBusSHAContext *context,
457 DBusString *results)
458 {
459 unsigned char digest[20];
460
461 sha_finish (context, digest);
462
463 if (!_dbus_string_append_len (results, (const char *) digest, 20))
464 return FALSE;
465
466 /* some kind of security paranoia, though it seems pointless
467 * to me given the nonzeroed stuff flying around
468 */
469 _DBUS_ZERO(*context);
470
471 return TRUE;
472 }
473
474 /**
475 * Computes the ASCII hex-encoded shasum of the given data and
476 * appends it to the output string.
477 *
478 * @param data input data to be hashed
479 * @param ascii_output string to append ASCII shasum to
480 * @returns #FALSE if not enough memory
481 */
482 dbus_bool_t
_dbus_sha_compute(const DBusString * data,DBusString * ascii_output)483 _dbus_sha_compute (const DBusString *data,
484 DBusString *ascii_output)
485 {
486 DBusSHAContext context;
487 DBusString digest;
488
489 _dbus_sha_init (&context);
490
491 _dbus_sha_update (&context, data);
492
493 if (!_dbus_string_init (&digest))
494 return FALSE;
495
496 if (!_dbus_sha_final (&context, &digest))
497 goto error;
498
499 if (!_dbus_string_hex_encode (&digest, 0, ascii_output,
500 _dbus_string_get_length (ascii_output)))
501 goto error;
502
503 _dbus_string_free (&digest);
504
505 return TRUE;
506
507 error:
508 _dbus_string_free (&digest);
509 return FALSE;
510 }
511
512 /** @} */ /* end of exported functions */
513
514 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
515 #include "dbus-test.h"
516 #include <stdio.h>
517
518 static dbus_bool_t
check_sha_binary(const unsigned char * input,int input_len,const char * expected)519 check_sha_binary (const unsigned char *input,
520 int input_len,
521 const char *expected)
522 {
523 DBusString input_str;
524 DBusString expected_str;
525 DBusString results;
526
527 _dbus_string_init_const_len (&input_str, (const char *) input, input_len);
528 _dbus_string_init_const (&expected_str, expected);
529
530 if (!_dbus_string_init (&results))
531 _dbus_assert_not_reached ("no memory for SHA-1 results");
532
533 if (!_dbus_sha_compute (&input_str, &results))
534 _dbus_assert_not_reached ("no memory for SHA-1 results");
535
536 if (!_dbus_string_equal (&expected_str, &results))
537 {
538 _dbus_warn ("Expected hash %s got %s for SHA-1 sum",
539 expected,
540 _dbus_string_get_const_data (&results));
541 _dbus_string_free (&results);
542 return FALSE;
543 }
544
545 _dbus_string_free (&results);
546 return TRUE;
547 }
548
549 static dbus_bool_t
check_sha_str(const char * input,const char * expected)550 check_sha_str (const char *input,
551 const char *expected)
552 {
553 return check_sha_binary ((unsigned char *) input, strlen (input), expected);
554 }
555
556 static dbus_bool_t
decode_compact_string(const DBusString * line,DBusString * decoded)557 decode_compact_string (const DBusString *line,
558 DBusString *decoded)
559 {
560 int n_bits;
561 dbus_bool_t current_b;
562 int offset;
563 int next;
564 long val;
565 int length_bytes;
566
567 offset = 0;
568 next = 0;
569
570 if (!_dbus_string_parse_int (line, offset, &val, &next))
571 {
572 fprintf (stderr, "could not parse length at start of compact string: %s\n",
573 _dbus_string_get_const_data (line));
574 return FALSE;
575 }
576
577 _dbus_string_skip_blank (line, next, &next);
578
579 offset = next;
580 if (!_dbus_string_parse_int (line, offset, &val, &next))
581 {
582 fprintf (stderr, "could not parse start bit 'b' in compact string: %s\n",
583 _dbus_string_get_const_data (line));
584 return FALSE;
585 }
586
587 if (!(val == 0 || val == 1))
588 {
589 fprintf (stderr, "the value 'b' must be 0 or 1, see sha-1/Readme.txt\n");
590 return FALSE;
591 }
592
593 _dbus_string_skip_blank (line, next, &next);
594
595 current_b = val;
596 n_bits = 0;
597
598 while (next < _dbus_string_get_length (line))
599 {
600 int total_bits;
601
602 offset = next;
603
604 if (_dbus_string_get_byte (line, offset) == '^')
605 break;
606
607 if (!_dbus_string_parse_int (line, offset, &val, &next))
608 {
609 fprintf (stderr, "could not parse bit count in compact string\n");
610 return FALSE;
611 }
612
613 /* We now append "val" copies of "current_b" bits to the string */
614 total_bits = n_bits + val;
615 while (n_bits < total_bits)
616 {
617 int byte_containing_next_bit = n_bits / 8;
618 int bit_containing_next_bit = 7 - (n_bits % 8);
619 unsigned char old_byte;
620
621 if (byte_containing_next_bit >= _dbus_string_get_length (decoded))
622 {
623 if (!_dbus_string_set_length (decoded, byte_containing_next_bit + 1))
624 _dbus_assert_not_reached ("no memory to extend to next byte");
625 }
626
627 old_byte = _dbus_string_get_byte (decoded, byte_containing_next_bit);
628 old_byte |= current_b << bit_containing_next_bit;
629
630 #if 0
631 printf ("Appending bit %d to byte %d at bit %d resulting in byte 0x%x\n",
632 current_b, byte_containing_next_bit,
633 bit_containing_next_bit, old_byte);
634 #endif
635
636 _dbus_string_set_byte (decoded, byte_containing_next_bit, old_byte);
637
638 ++n_bits;
639 }
640
641 _dbus_string_skip_blank (line, next, &next);
642
643 current_b = !current_b;
644 }
645
646 length_bytes = (n_bits / 8 + ((n_bits % 8) ? 1 : 0));
647
648 if (_dbus_string_get_length (decoded) != length_bytes)
649 {
650 fprintf (stderr, "Expected length %d bytes %d bits for compact string, got %d bytes\n",
651 length_bytes, n_bits, _dbus_string_get_length (decoded));
652 return FALSE;
653 }
654 else
655 return TRUE;
656 }
657
658 static dbus_bool_t
get_next_expected_result(DBusString * results,DBusString * result)659 get_next_expected_result (DBusString *results,
660 DBusString *result)
661 {
662 DBusString line;
663 dbus_bool_t retval;
664
665 retval = FALSE;
666
667 if (!_dbus_string_init (&line))
668 _dbus_assert_not_reached ("no memory");
669
670 next_iteration:
671 while (_dbus_string_pop_line (results, &line))
672 {
673 _dbus_string_delete_leading_blanks (&line);
674
675 if (_dbus_string_get_length (&line) == 0)
676 goto next_iteration;
677 else if (_dbus_string_starts_with_c_str (&line, "#"))
678 goto next_iteration;
679 else if (_dbus_string_starts_with_c_str (&line, "H>"))
680 {
681 /* don't print */
682 }
683 else if (_dbus_string_starts_with_c_str (&line, "D>") ||
684 _dbus_string_starts_with_c_str (&line, "<D"))
685 goto next_iteration;
686 else
687 {
688 int i;
689
690 if (!_dbus_string_move (&line, 0, result, 0))
691 _dbus_assert_not_reached ("no memory");
692
693 i = 0;
694 while (i < _dbus_string_get_length (result))
695 {
696 unsigned char c = _dbus_string_get_byte (result, i);
697
698 switch (c)
699 {
700 case 'A':
701 _dbus_string_set_byte (result, i, 'a');
702 break;
703 case 'B':
704 _dbus_string_set_byte (result, i, 'b');
705 break;
706 case 'C':
707 _dbus_string_set_byte (result, i, 'c');
708 break;
709 case 'D':
710 _dbus_string_set_byte (result, i, 'd');
711 break;
712 case 'E':
713 _dbus_string_set_byte (result, i, 'e');
714 break;
715 case 'F':
716 _dbus_string_set_byte (result, i, 'f');
717 break;
718 case '^':
719 case ' ':
720 _dbus_string_delete (result, i, 1);
721 --i; /* to offset ++i below */
722 break;
723 default:
724 if ((c < '0' || c > '9') && (c < 'a' || c > 'f'))
725 _dbus_assert_not_reached ("invalid SHA-1 test script");
726 }
727
728 ++i;
729 }
730
731 break;
732 }
733 }
734
735 retval = TRUE;
736
737 /* out: */
738 _dbus_string_free (&line);
739 return retval;
740 }
741
742 static dbus_bool_t
process_test_data(const char * test_data_dir)743 process_test_data (const char *test_data_dir)
744 {
745 DBusString tests_file;
746 DBusString results_file;
747 DBusString tests;
748 DBusString results;
749 DBusString line;
750 DBusString tmp;
751 int line_no;
752 dbus_bool_t retval;
753 int success_count;
754 DBusError error = DBUS_ERROR_INIT;
755
756 retval = FALSE;
757
758 if (!_dbus_string_init (&tests_file))
759 _dbus_assert_not_reached ("no memory");
760
761 if (!_dbus_string_init (&results_file))
762 _dbus_assert_not_reached ("no memory");
763
764 if (!_dbus_string_init (&tests))
765 _dbus_assert_not_reached ("no memory");
766
767 if (!_dbus_string_init (&results))
768 _dbus_assert_not_reached ("no memory");
769
770 if (!_dbus_string_init (&line))
771 _dbus_assert_not_reached ("no memory");
772
773 if (!_dbus_string_append (&tests_file, test_data_dir))
774 _dbus_assert_not_reached ("no memory");
775
776 if (!_dbus_string_append (&results_file, test_data_dir))
777 _dbus_assert_not_reached ("no memory");
778
779 _dbus_string_init_const (&tmp, "sha-1/byte-messages.sha1");
780 if (!_dbus_concat_dir_and_file (&tests_file, &tmp))
781 _dbus_assert_not_reached ("no memory");
782
783 _dbus_string_init_const (&tmp, "sha-1/byte-hashes.sha1");
784 if (!_dbus_concat_dir_and_file (&results_file, &tmp))
785 _dbus_assert_not_reached ("no memory");
786
787 if (!_dbus_file_get_contents (&tests, &tests_file, &error))
788 {
789 fprintf (stderr, "could not load test data file %s: %s\n",
790 _dbus_string_get_const_data (&tests_file),
791 error.message);
792 dbus_error_free (&error);
793 goto out;
794 }
795
796 if (!_dbus_file_get_contents (&results, &results_file, &error))
797 {
798 fprintf (stderr, "could not load results data file %s: %s\n",
799 _dbus_string_get_const_data (&results_file), error.message);
800 dbus_error_free (&error);
801 goto out;
802 }
803
804 success_count = 0;
805 line_no = 0;
806 next_iteration:
807 while (_dbus_string_pop_line (&tests, &line))
808 {
809 line_no += 1;
810
811 _dbus_string_delete_leading_blanks (&line);
812
813 if (_dbus_string_get_length (&line) == 0)
814 goto next_iteration;
815 else if (_dbus_string_starts_with_c_str (&line, "#"))
816 goto next_iteration;
817 else if (_dbus_string_starts_with_c_str (&line, "H>"))
818 {
819 printf ("SHA-1: %s\n", _dbus_string_get_const_data (&line));
820
821 if (_dbus_string_find (&line, 0, "Type 3", NULL))
822 {
823 /* See sha-1/Readme.txt - the "Type 3" tests are
824 * random seeds, rather than data to be hashed.
825 * we'd have to do a little bit more implementation
826 * to use those tests.
827 */
828
829 printf (" (ending tests due to Type 3 tests seen - this is normal)\n");
830 break;
831 }
832 }
833 else if (_dbus_string_starts_with_c_str (&line, "D>") ||
834 _dbus_string_starts_with_c_str (&line, "<D"))
835 goto next_iteration;
836 else
837 {
838 DBusString test;
839 DBusString result;
840 DBusString next_line;
841 DBusString expected;
842 dbus_bool_t success;
843
844 success = FALSE;
845
846 if (!_dbus_string_init (&next_line))
847 _dbus_assert_not_reached ("no memory");
848
849 if (!_dbus_string_init (&expected))
850 _dbus_assert_not_reached ("no memory");
851
852 if (!_dbus_string_init (&test))
853 _dbus_assert_not_reached ("no memory");
854
855 if (!_dbus_string_init (&result))
856 _dbus_assert_not_reached ("no memory");
857
858 /* the "compact strings" are "^"-terminated not
859 * newline-terminated so readahead to find the
860 * "^"
861 */
862 while (!_dbus_string_find (&line, 0, "^", NULL) &&
863 _dbus_string_pop_line (&tests, &next_line))
864 {
865 if (!_dbus_string_append_byte (&line, ' ') ||
866 !_dbus_string_move (&next_line, 0, &line,
867 _dbus_string_get_length (&line)))
868 _dbus_assert_not_reached ("no memory");
869 }
870
871 if (!decode_compact_string (&line, &test))
872 {
873 fprintf (stderr, "Failed to decode line %d as a compact string\n",
874 line_no);
875 goto failure;
876 }
877
878 if (!_dbus_sha_compute (&test, &result))
879 _dbus_assert_not_reached ("no memory for SHA-1 result");
880
881 if (!get_next_expected_result (&results, &expected))
882 {
883 fprintf (stderr, "Failed to read an expected result\n");
884 goto failure;
885 }
886
887 if (!_dbus_string_equal (&result, &expected))
888 {
889 fprintf (stderr, " for line %d got hash %s expected %s\n",
890 line_no,
891 _dbus_string_get_const_data (&result),
892 _dbus_string_get_const_data (&expected));
893 goto failure;
894 }
895 else
896 {
897 success_count += 1;
898 }
899
900 success = TRUE;
901
902 failure:
903 _dbus_string_free (&test);
904 _dbus_string_free (&result);
905 _dbus_string_free (&next_line);
906 _dbus_string_free (&expected);
907
908 if (!success)
909 goto out;
910 }
911 }
912
913 retval = TRUE;
914
915 printf ("Passed the %d SHA-1 tests in the test file\n",
916 success_count);
917
918 out:
919 _dbus_string_free (&tests_file);
920 _dbus_string_free (&results_file);
921 _dbus_string_free (&tests);
922 _dbus_string_free (&results);
923 _dbus_string_free (&line);
924
925 return retval;
926 }
927
928 /**
929 * @ingroup DBusSHAInternals
930 * Unit test for SHA computation.
931 *
932 * @returns #TRUE on success.
933 */
934 dbus_bool_t
_dbus_sha_test(const char * test_data_dir)935 _dbus_sha_test (const char *test_data_dir)
936 {
937 unsigned char all_bytes[256];
938 int i;
939
940 if (test_data_dir != NULL)
941 {
942 if (!process_test_data (test_data_dir))
943 return FALSE;
944 }
945 else
946 printf ("No test data dir\n");
947
948 i = 0;
949 while (i < 256)
950 {
951 all_bytes[i] = i;
952 ++i;
953 }
954
955 if (!check_sha_binary (all_bytes, 256,
956 "4916d6bdb7f78e6803698cab32d1586ea457dfc8"))
957 return FALSE;
958
959 #define CHECK(input,expected) if (!check_sha_str (input, expected)) return FALSE
960
961 CHECK ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
962 CHECK ("a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
963 CHECK ("abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
964 CHECK ("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3");
965 CHECK ("abcdefghijklmnopqrstuvwxyz", "32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
966 CHECK ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
967 "761c457bf73b14d27e9e9265c46f4b4dda11f940");
968 CHECK ("12345678901234567890123456789012345678901234567890123456789012345678901234567890",
969 "50abf5706a150990a08b2c5ea40fa0e585554732");
970
971 return TRUE;
972 }
973
974 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
975