Added missing implementation for _dbus_system_logv().
[platform/upstream/dbus.git] / dbus / dbus-sha.c
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
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
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
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
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
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
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
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
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, 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
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_BUILD_TESTS
515 #include "dbus-test.h"
516 #include <stdio.h>
517
518 static dbus_bool_t
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, 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\n",
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
550 check_sha_str (const char *input,
551                const char *expected)
552 {
553   return check_sha_binary (input, strlen (input), expected);
554 }
555
556 static dbus_bool_t
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
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               switch (_dbus_string_get_byte (result, i))
697                 {
698                 case 'A':
699                   _dbus_string_set_byte (result, i, 'a');
700                   break;
701                 case 'B':
702                   _dbus_string_set_byte (result, i, 'b');
703                   break;
704                 case 'C':
705                   _dbus_string_set_byte (result, i, 'c');
706                   break;
707                 case 'D':
708                   _dbus_string_set_byte (result, i, 'd');
709                   break;
710                 case 'E':
711                   _dbus_string_set_byte (result, i, 'e');
712                   break;
713                 case 'F':
714                   _dbus_string_set_byte (result, i, 'f');
715                   break;
716                 case '^':
717                 case ' ':
718                   _dbus_string_delete (result, i, 1);
719                   --i; /* to offset ++i below */
720                   break;
721                 }
722
723               ++i;
724             }
725           
726           break;
727         }
728     }
729   
730   retval = TRUE;
731   
732   /* out: */
733   _dbus_string_free (&line);
734   return retval;
735 }
736
737 static dbus_bool_t
738 process_test_data (const char *test_data_dir)
739 {
740   DBusString tests_file;
741   DBusString results_file;
742   DBusString tests;
743   DBusString results;
744   DBusString line;
745   DBusString tmp;
746   int line_no;
747   dbus_bool_t retval;
748   int success_count;
749   DBusError error = DBUS_ERROR_INIT;
750
751   retval = FALSE;
752   
753   if (!_dbus_string_init (&tests_file))
754     _dbus_assert_not_reached ("no memory");
755
756   if (!_dbus_string_init (&results_file))
757     _dbus_assert_not_reached ("no memory");
758
759   if (!_dbus_string_init (&tests))
760     _dbus_assert_not_reached ("no memory");
761
762   if (!_dbus_string_init (&results))
763     _dbus_assert_not_reached ("no memory");
764
765   if (!_dbus_string_init (&line))
766     _dbus_assert_not_reached ("no memory");
767   
768   if (!_dbus_string_append (&tests_file, test_data_dir))
769     _dbus_assert_not_reached ("no memory");
770
771   if (!_dbus_string_append (&results_file, test_data_dir))
772     _dbus_assert_not_reached ("no memory");
773
774   _dbus_string_init_const (&tmp, "sha-1/byte-messages.sha1");
775   if (!_dbus_concat_dir_and_file (&tests_file, &tmp))
776     _dbus_assert_not_reached ("no memory");
777
778   _dbus_string_init_const (&tmp, "sha-1/byte-hashes.sha1");
779   if (!_dbus_concat_dir_and_file (&results_file, &tmp))
780     _dbus_assert_not_reached ("no memory");
781
782   if (!_dbus_file_get_contents (&tests, &tests_file, &error))
783     {
784       fprintf (stderr, "could not load test data file %s: %s\n",
785                _dbus_string_get_const_data (&tests_file),
786                error.message);
787       dbus_error_free (&error);
788       goto out;
789     }
790
791   if (!_dbus_file_get_contents (&results, &results_file, &error))
792     {
793       fprintf (stderr, "could not load results data file %s: %s\n",
794                _dbus_string_get_const_data (&results_file), error.message);
795       dbus_error_free (&error);
796       goto out;
797     }
798
799   success_count = 0;
800   line_no = 0;
801  next_iteration:
802   while (_dbus_string_pop_line (&tests, &line))
803     {
804       line_no += 1;
805
806       _dbus_string_delete_leading_blanks (&line);
807
808       if (_dbus_string_get_length (&line) == 0)
809         goto next_iteration;
810       else if (_dbus_string_starts_with_c_str (&line, "#"))
811         goto next_iteration;
812       else if (_dbus_string_starts_with_c_str (&line, "H>"))
813         {
814           printf ("SHA-1: %s\n", _dbus_string_get_const_data (&line));
815
816           if (_dbus_string_find (&line, 0, "Type 3", NULL))
817             {
818               /* See sha-1/Readme.txt - the "Type 3" tests are
819                * random seeds, rather than data to be hashed.
820                * we'd have to do a little bit more implementation
821                * to use those tests.
822                */
823               
824               printf (" (ending tests due to Type 3 tests seen - this is normal)\n");
825               break;
826             }
827         }
828       else if (_dbus_string_starts_with_c_str (&line, "D>") ||
829                _dbus_string_starts_with_c_str (&line, "<D"))
830         goto next_iteration;
831       else
832         {
833           DBusString test;
834           DBusString result;
835           DBusString next_line;
836           DBusString expected;
837           dbus_bool_t success;
838
839           success = FALSE;
840           
841           if (!_dbus_string_init (&next_line))
842             _dbus_assert_not_reached ("no memory");
843
844           if (!_dbus_string_init (&expected))
845             _dbus_assert_not_reached ("no memory");
846           
847           if (!_dbus_string_init (&test))
848             _dbus_assert_not_reached ("no memory");
849
850           if (!_dbus_string_init (&result))
851             _dbus_assert_not_reached ("no memory");
852
853           /* the "compact strings" are "^"-terminated not
854            * newline-terminated so readahead to find the
855            * "^"
856            */
857           while (!_dbus_string_find (&line, 0, "^", NULL) &&
858                  _dbus_string_pop_line (&tests, &next_line))
859             {
860               if (!_dbus_string_append_byte (&line, ' ') ||
861                   !_dbus_string_move (&next_line, 0, &line,
862                                       _dbus_string_get_length (&line)))
863                 _dbus_assert_not_reached ("no memory");
864             }
865           
866           if (!decode_compact_string (&line, &test))
867             {
868               fprintf (stderr, "Failed to decode line %d as a compact string\n",
869                        line_no);
870               goto failure;
871             }
872           
873           if (!_dbus_sha_compute (&test, &result))
874             _dbus_assert_not_reached ("no memory for SHA-1 result");
875
876           if (!get_next_expected_result (&results, &expected))
877             {
878               fprintf (stderr, "Failed to read an expected result\n");
879               goto failure;
880             }
881           
882           if (!_dbus_string_equal (&result, &expected))
883             {              
884               fprintf (stderr, " for line %d got hash %s expected %s\n",
885                        line_no,
886                        _dbus_string_get_const_data (&result),
887                        _dbus_string_get_const_data (&expected));
888               goto failure;
889             }
890           else
891             {
892               success_count += 1;
893             }
894
895           success = TRUE;
896
897         failure:
898           _dbus_string_free (&test);
899           _dbus_string_free (&result);
900           _dbus_string_free (&next_line);
901           _dbus_string_free (&expected);
902
903           if (!success)
904             goto out;
905         }
906     }
907
908   retval = TRUE;
909
910   printf ("Passed the %d SHA-1 tests in the test file\n",
911           success_count);
912   
913  out:
914   _dbus_string_free (&tests_file);
915   _dbus_string_free (&results_file);
916   _dbus_string_free (&tests);
917   _dbus_string_free (&results);
918   _dbus_string_free (&line);
919
920   return retval;
921 }
922
923 /**
924  * @ingroup DBusSHAInternals
925  * Unit test for SHA computation.
926  *
927  * @returns #TRUE on success.
928  */
929 dbus_bool_t
930 _dbus_sha_test (const char *test_data_dir)
931 {
932   unsigned char all_bytes[256];
933   int i;
934
935   if (test_data_dir != NULL)
936     {
937       if (!process_test_data (test_data_dir))
938         return FALSE;
939     }
940   else
941     printf ("No test data dir\n");
942   
943   i = 0;
944   while (i < 256)
945     {
946       all_bytes[i] = i;
947       ++i;
948     }
949
950   if (!check_sha_binary (all_bytes, 256,
951                          "4916d6bdb7f78e6803698cab32d1586ea457dfc8"))
952     return FALSE;
953
954 #define CHECK(input,expected) if (!check_sha_str (input, expected)) return FALSE
955
956   CHECK ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
957   CHECK ("a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
958   CHECK ("abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
959   CHECK ("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3");
960   CHECK ("abcdefghijklmnopqrstuvwxyz", "32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
961   CHECK ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
962          "761c457bf73b14d27e9e9265c46f4b4dda11f940");
963   CHECK ("12345678901234567890123456789012345678901234567890123456789012345678901234567890",
964          "50abf5706a150990a08b2c5ea40fa0e585554732");
965
966   return TRUE;
967 }
968
969 #endif /* DBUS_BUILD_TESTS */