D-Bus 1.2.24
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-sha.c SHA-1 implementation 00003 * 00004 * Copyright (C) 2003 Red Hat Inc. 00005 * Copyright (C) 1995 A. M. Kuchling 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 */ 00024 00025 #include "dbus-internals.h" 00026 #include "dbus-sha.h" 00027 #include "dbus-marshal-basic.h" /* for byteswap routines */ 00028 #include <string.h> 00029 00030 /* The following comments have the history of where this code 00031 * comes from. I actually copied it from GNet in GNOME CVS. 00032 * - hp@redhat.com 00033 */ 00034 00035 /* 00036 * sha.h : Implementation of the Secure Hash Algorithm 00037 * 00038 * Part of the Python Cryptography Toolkit, version 1.0.0 00039 * 00040 * Copyright (C) 1995, A.M. Kuchling 00041 * 00042 * Distribute and use freely; there are no restrictions on further 00043 * dissemination and usage except those imposed by the laws of your 00044 * country of residence. 00045 * 00046 */ 00047 00048 /* SHA: NIST's Secure Hash Algorithm */ 00049 00050 /* Based on SHA code originally posted to sci.crypt by Peter Gutmann 00051 in message <30ajo5$oe8@ccu2.auckland.ac.nz>. 00052 Modified to test for endianness on creation of SHA objects by AMK. 00053 Also, the original specification of SHA was found to have a weakness 00054 by NSA/NIST. This code implements the fixed version of SHA. 00055 */ 00056 00057 /* Here's the first paragraph of Peter Gutmann's posting: 00058 00059 The following is my SHA (FIPS 180) code updated to allow use of the "fixed" 00060 SHA, thanks to Jim Gillogly and an anonymous contributor for the information on 00061 what's changed in the new version. The fix is a simple change which involves 00062 adding a single rotate in the initial expansion function. It is unknown 00063 whether this is an optimal solution to the problem which was discovered in the 00064 SHA or whether it's simply a bandaid which fixes the problem with a minimum of 00065 effort (for example the reengineering of a great many Capstone chips). 00066 */ 00067 00087 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00088 00089 /* The SHA block size and message digest sizes, in bytes */ 00090 00091 #define SHA_DATASIZE 64 00092 #define SHA_DIGESTSIZE 20 00093 00094 /* The SHA f()-functions. The f1 and f3 functions can be optimized to 00095 save one boolean operation each - thanks to Rich Schroeppel, 00096 rcs@cs.arizona.edu for discovering this */ 00097 00098 /*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) // Rounds 0-19 */ 00099 #define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ 00100 #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ 00101 /*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) // Rounds 40-59 */ 00102 #define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ 00103 #define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ 00104 00105 /* The SHA Mysterious Constants */ 00106 00107 #define K1 0x5A827999L /* Rounds 0-19 */ 00108 #define K2 0x6ED9EBA1L /* Rounds 20-39 */ 00109 #define K3 0x8F1BBCDCL /* Rounds 40-59 */ 00110 #define K4 0xCA62C1D6L /* Rounds 60-79 */ 00111 00112 /* SHA initial values */ 00113 00114 #define h0init 0x67452301L 00115 #define h1init 0xEFCDAB89L 00116 #define h2init 0x98BADCFEL 00117 #define h3init 0x10325476L 00118 #define h4init 0xC3D2E1F0L 00119 00120 /* Note that it may be necessary to add parentheses to these macros if they 00121 are to be called with expressions as arguments */ 00122 /* 32-bit rotate left - kludged with shifts */ 00123 00124 #define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) ) 00125 00126 /* The initial expanding function. The hash function is defined over an 00127 80-word expanded input array W, where the first 16 are copies of the input 00128 data, and the remaining 64 are defined by 00129 00130 W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ] 00131 00132 This implementation generates these values on the fly in a circular 00133 buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this 00134 optimization. 00135 00136 The updated SHA changes the expanding function by adding a rotate of 1 00137 bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor 00138 for this information */ 00139 00140 #define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ 00141 W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) ) 00142 00143 00144 /* The prototype SHA sub-round. The fundamental sub-round is: 00145 00146 a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; 00147 b' = a; 00148 c' = ROTL( 30, b ); 00149 d' = c; 00150 e' = d; 00151 00152 but this is implemented by unrolling the loop 5 times and renaming the 00153 variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. 00154 This code is then replicated 20 times for each of the 4 functions, using 00155 the next 20 values from the W[] array each time */ 00156 00157 #define subRound(a, b, c, d, e, f, k, data) \ 00158 ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) 00159 00160 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ 00161 00162 /* Perform the SHA transformation. Note that this code, like MD5, seems to 00163 break some optimizing compilers due to the complexity of the expressions 00164 and the size of the basic block. It may be necessary to split it into 00165 sections, e.g. based on the four subrounds 00166 00167 Note that this corrupts the context->data area */ 00168 00169 static void 00170 SHATransform(dbus_uint32_t *digest, dbus_uint32_t *data) 00171 { 00172 dbus_uint32_t A, B, C, D, E; /* Local vars */ 00173 dbus_uint32_t eData[16]; /* Expanded data */ 00174 00175 /* Set up first buffer and local data buffer */ 00176 A = digest[0]; 00177 B = digest[1]; 00178 C = digest[2]; 00179 D = digest[3]; 00180 E = digest[4]; 00181 memmove (eData, data, SHA_DATASIZE); 00182 00183 /* Heavy mangling, in 4 sub-rounds of 20 interations each. */ 00184 subRound (A, B, C, D, E, f1, K1, eData[0]); 00185 subRound (E, A, B, C, D, f1, K1, eData[1]); 00186 subRound (D, E, A, B, C, f1, K1, eData[2]); 00187 subRound (C, D, E, A, B, f1, K1, eData[3]); 00188 subRound (B, C, D, E, A, f1, K1, eData[4]); 00189 subRound (A, B, C, D, E, f1, K1, eData[5]); 00190 subRound (E, A, B, C, D, f1, K1, eData[6]); 00191 subRound (D, E, A, B, C, f1, K1, eData[7]); 00192 subRound (C, D, E, A, B, f1, K1, eData[8]); 00193 subRound (B, C, D, E, A, f1, K1, eData[9]); 00194 subRound (A, B, C, D, E, f1, K1, eData[10]); 00195 subRound (E, A, B, C, D, f1, K1, eData[11]); 00196 subRound (D, E, A, B, C, f1, K1, eData[12]); 00197 subRound (C, D, E, A, B, f1, K1, eData[13]); 00198 subRound (B, C, D, E, A, f1, K1, eData[14]); 00199 subRound (A, B, C, D, E, f1, K1, eData[15]); 00200 subRound (E, A, B, C, D, f1, K1, expand ( eData, 16) ); 00201 subRound (D, E, A, B, C, f1, K1, expand ( eData, 17) ); 00202 subRound (C, D, E, A, B, f1, K1, expand ( eData, 18) ); 00203 subRound (B, C, D, E, A, f1, K1, expand ( eData, 19) ); 00204 00205 subRound (A, B, C, D, E, f2, K2, expand ( eData, 20) ); 00206 subRound (E, A, B, C, D, f2, K2, expand ( eData, 21) ); 00207 subRound (D, E, A, B, C, f2, K2, expand ( eData, 22) ); 00208 subRound (C, D, E, A, B, f2, K2, expand ( eData, 23) ); 00209 subRound (B, C, D, E, A, f2, K2, expand ( eData, 24) ); 00210 subRound (A, B, C, D, E, f2, K2, expand ( eData, 25) ); 00211 subRound (E, A, B, C, D, f2, K2, expand ( eData, 26) ); 00212 subRound (D, E, A, B, C, f2, K2, expand ( eData, 27) ); 00213 subRound (C, D, E, A, B, f2, K2, expand ( eData, 28) ); 00214 subRound (B, C, D, E, A, f2, K2, expand ( eData, 29) ); 00215 subRound (A, B, C, D, E, f2, K2, expand ( eData, 30) ); 00216 subRound (E, A, B, C, D, f2, K2, expand ( eData, 31) ); 00217 subRound (D, E, A, B, C, f2, K2, expand ( eData, 32) ); 00218 subRound (C, D, E, A, B, f2, K2, expand ( eData, 33) ); 00219 subRound (B, C, D, E, A, f2, K2, expand ( eData, 34) ); 00220 subRound (A, B, C, D, E, f2, K2, expand ( eData, 35) ); 00221 subRound (E, A, B, C, D, f2, K2, expand ( eData, 36) ); 00222 subRound (D, E, A, B, C, f2, K2, expand ( eData, 37) ); 00223 subRound (C, D, E, A, B, f2, K2, expand ( eData, 38) ); 00224 subRound (B, C, D, E, A, f2, K2, expand ( eData, 39) ); 00225 00226 subRound (A, B, C, D, E, f3, K3, expand ( eData, 40) ); 00227 subRound (E, A, B, C, D, f3, K3, expand ( eData, 41) ); 00228 subRound (D, E, A, B, C, f3, K3, expand ( eData, 42) ); 00229 subRound (C, D, E, A, B, f3, K3, expand ( eData, 43) ); 00230 subRound (B, C, D, E, A, f3, K3, expand ( eData, 44) ); 00231 subRound (A, B, C, D, E, f3, K3, expand ( eData, 45) ); 00232 subRound (E, A, B, C, D, f3, K3, expand ( eData, 46) ); 00233 subRound (D, E, A, B, C, f3, K3, expand ( eData, 47) ); 00234 subRound (C, D, E, A, B, f3, K3, expand ( eData, 48) ); 00235 subRound (B, C, D, E, A, f3, K3, expand ( eData, 49) ); 00236 subRound (A, B, C, D, E, f3, K3, expand ( eData, 50) ); 00237 subRound (E, A, B, C, D, f3, K3, expand ( eData, 51) ); 00238 subRound (D, E, A, B, C, f3, K3, expand ( eData, 52) ); 00239 subRound (C, D, E, A, B, f3, K3, expand ( eData, 53) ); 00240 subRound (B, C, D, E, A, f3, K3, expand ( eData, 54) ); 00241 subRound (A, B, C, D, E, f3, K3, expand ( eData, 55) ); 00242 subRound (E, A, B, C, D, f3, K3, expand ( eData, 56) ); 00243 subRound (D, E, A, B, C, f3, K3, expand ( eData, 57) ); 00244 subRound (C, D, E, A, B, f3, K3, expand ( eData, 58) ); 00245 subRound (B, C, D, E, A, f3, K3, expand ( eData, 59) ); 00246 00247 subRound (A, B, C, D, E, f4, K4, expand ( eData, 60) ); 00248 subRound (E, A, B, C, D, f4, K4, expand ( eData, 61) ); 00249 subRound (D, E, A, B, C, f4, K4, expand ( eData, 62) ); 00250 subRound (C, D, E, A, B, f4, K4, expand ( eData, 63) ); 00251 subRound (B, C, D, E, A, f4, K4, expand ( eData, 64) ); 00252 subRound (A, B, C, D, E, f4, K4, expand ( eData, 65) ); 00253 subRound (E, A, B, C, D, f4, K4, expand ( eData, 66) ); 00254 subRound (D, E, A, B, C, f4, K4, expand ( eData, 67) ); 00255 subRound (C, D, E, A, B, f4, K4, expand ( eData, 68) ); 00256 subRound (B, C, D, E, A, f4, K4, expand ( eData, 69) ); 00257 subRound (A, B, C, D, E, f4, K4, expand ( eData, 70) ); 00258 subRound (E, A, B, C, D, f4, K4, expand ( eData, 71) ); 00259 subRound (D, E, A, B, C, f4, K4, expand ( eData, 72) ); 00260 subRound (C, D, E, A, B, f4, K4, expand ( eData, 73) ); 00261 subRound (B, C, D, E, A, f4, K4, expand ( eData, 74) ); 00262 subRound (A, B, C, D, E, f4, K4, expand ( eData, 75) ); 00263 subRound (E, A, B, C, D, f4, K4, expand ( eData, 76) ); 00264 subRound (D, E, A, B, C, f4, K4, expand ( eData, 77) ); 00265 subRound (C, D, E, A, B, f4, K4, expand ( eData, 78) ); 00266 subRound (B, C, D, E, A, f4, K4, expand ( eData, 79) ); 00267 00268 /* Build message digest */ 00269 digest[0] += A; 00270 digest[1] += B; 00271 digest[2] += C; 00272 digest[3] += D; 00273 digest[4] += E; 00274 } 00275 00276 /* When run on a little-endian CPU we need to perform byte reversal on an 00277 array of longwords. */ 00278 00279 #ifdef WORDS_BIGENDIAN 00280 #define swap_words(buffer, byte_count) 00281 #else 00282 static void 00283 swap_words (dbus_uint32_t *buffer, 00284 int byte_count) 00285 { 00286 byte_count /= sizeof (dbus_uint32_t); 00287 while (byte_count--) 00288 { 00289 *buffer = DBUS_UINT32_SWAP_LE_BE (*buffer); 00290 ++buffer; 00291 } 00292 } 00293 #endif 00294 00295 static void 00296 sha_init (DBusSHAContext *context) 00297 { 00298 /* Set the h-vars to their initial values */ 00299 context->digest[0] = h0init; 00300 context->digest[1] = h1init; 00301 context->digest[2] = h2init; 00302 context->digest[3] = h3init; 00303 context->digest[4] = h4init; 00304 00305 /* Initialise bit count */ 00306 context->count_lo = context->count_hi = 0; 00307 } 00308 00309 static void 00310 sha_append (DBusSHAContext *context, 00311 const unsigned char *buffer, 00312 unsigned int count) 00313 { 00314 dbus_uint32_t tmp; 00315 unsigned int dataCount; 00316 00317 /* Update bitcount */ 00318 tmp = context->count_lo; 00319 if (( context->count_lo = tmp + ( ( dbus_uint32_t) count << 3) ) < tmp) 00320 context->count_hi++; /* Carry from low to high */ 00321 context->count_hi += count >> 29; 00322 00323 /* Get count of bytes already in data */ 00324 dataCount = (int) (tmp >> 3) & 0x3F; 00325 00326 /* Handle any leading odd-sized chunks */ 00327 if (dataCount) 00328 { 00329 unsigned char *p = (unsigned char *) context->data + dataCount; 00330 00331 dataCount = SHA_DATASIZE - dataCount; 00332 if (count < dataCount) 00333 { 00334 memmove (p, buffer, count); 00335 return; 00336 } 00337 memmove (p, buffer, dataCount); 00338 swap_words (context->data, SHA_DATASIZE); 00339 SHATransform (context->digest, context->data); 00340 buffer += dataCount; 00341 count -= dataCount; 00342 } 00343 00344 /* Process data in SHA_DATASIZE chunks */ 00345 while (count >= SHA_DATASIZE) 00346 { 00347 memmove (context->data, buffer, SHA_DATASIZE); 00348 swap_words (context->data, SHA_DATASIZE); 00349 SHATransform (context->digest, context->data); 00350 buffer += SHA_DATASIZE; 00351 count -= SHA_DATASIZE; 00352 } 00353 00354 /* Handle any remaining bytes of data. */ 00355 memmove (context->data, buffer, count); 00356 } 00357 00358 00359 /* Final wrapup - pad to SHA_DATASIZE-byte boundary with the bit pattern 00360 1 0* (64-bit count of bits processed, MSB-first) */ 00361 00362 static void 00363 sha_finish (DBusSHAContext *context, unsigned char digest[20]) 00364 { 00365 int count; 00366 unsigned char *data_p; 00367 00368 /* Compute number of bytes mod 64 */ 00369 count = (int) context->count_lo; 00370 count = (count >> 3) & 0x3F; 00371 00372 /* Set the first char of padding to 0x80. This is safe since there is 00373 always at least one byte free */ 00374 data_p = (unsigned char *) context->data + count; 00375 *data_p++ = 0x80; 00376 00377 /* Bytes of padding needed to make 64 bytes */ 00378 count = SHA_DATASIZE - 1 - count; 00379 00380 /* Pad out to 56 mod 64 */ 00381 if (count < 8) 00382 { 00383 /* Two lots of padding: Pad the first block to 64 bytes */ 00384 memset (data_p, 0, count); 00385 swap_words (context->data, SHA_DATASIZE); 00386 SHATransform (context->digest, context->data); 00387 00388 /* Now fill the next block with 56 bytes */ 00389 memset (context->data, 0, SHA_DATASIZE - 8); 00390 } 00391 else 00392 /* Pad block to 56 bytes */ 00393 memset (data_p, 0, count - 8); 00394 00395 /* Append length in bits and transform */ 00396 context->data[14] = context->count_hi; 00397 context->data[15] = context->count_lo; 00398 00399 swap_words (context->data, SHA_DATASIZE - 8); 00400 SHATransform (context->digest, context->data); 00401 swap_words (context->digest, SHA_DIGESTSIZE); 00402 memmove (digest, context->digest, SHA_DIGESTSIZE); 00403 } 00404 /* End of internals */ 00406 00418 void 00419 _dbus_sha_init (DBusSHAContext *context) 00420 { 00421 sha_init (context); 00422 } 00423 00430 void 00431 _dbus_sha_update (DBusSHAContext *context, 00432 const DBusString *data) 00433 { 00434 unsigned int inputLen; 00435 const unsigned char *input; 00436 00437 input = (const unsigned char*) _dbus_string_get_const_data (data); 00438 inputLen = _dbus_string_get_length (data); 00439 00440 sha_append (context, input, inputLen); 00441 } 00442 00454 dbus_bool_t 00455 _dbus_sha_final (DBusSHAContext *context, 00456 DBusString *results) 00457 { 00458 unsigned char digest[20]; 00459 00460 sha_finish (context, digest); 00461 00462 if (!_dbus_string_append_len (results, digest, 20)) 00463 return FALSE; 00464 00465 /* some kind of security paranoia, though it seems pointless 00466 * to me given the nonzeroed stuff flying around 00467 */ 00468 memset ((void*)context, '\0', sizeof (DBusSHAContext)); 00469 00470 return TRUE; 00471 } 00472 00481 dbus_bool_t 00482 _dbus_sha_compute (const DBusString *data, 00483 DBusString *ascii_output) 00484 { 00485 DBusSHAContext context; 00486 DBusString digest; 00487 00488 _dbus_sha_init (&context); 00489 00490 _dbus_sha_update (&context, data); 00491 00492 if (!_dbus_string_init (&digest)) 00493 return FALSE; 00494 00495 if (!_dbus_sha_final (&context, &digest)) 00496 goto error; 00497 00498 if (!_dbus_string_hex_encode (&digest, 0, ascii_output, 00499 _dbus_string_get_length (ascii_output))) 00500 goto error; 00501 00502 _dbus_string_free (&digest); 00503 00504 return TRUE; 00505 00506 error: 00507 _dbus_string_free (&digest); 00508 return FALSE; 00509 } 00510 /* end of exported functions */ 00512 00513 #ifdef DBUS_BUILD_TESTS 00514 #include "dbus-test.h" 00515 #include <stdio.h> 00516 00517 static dbus_bool_t 00518 check_sha_binary (const unsigned char *input, 00519 int input_len, 00520 const char *expected) 00521 { 00522 DBusString input_str; 00523 DBusString expected_str; 00524 DBusString results; 00525 00526 _dbus_string_init_const_len (&input_str, input, input_len); 00527 _dbus_string_init_const (&expected_str, expected); 00528 00529 if (!_dbus_string_init (&results)) 00530 _dbus_assert_not_reached ("no memory for SHA-1 results"); 00531 00532 if (!_dbus_sha_compute (&input_str, &results)) 00533 _dbus_assert_not_reached ("no memory for SHA-1 results"); 00534 00535 if (!_dbus_string_equal (&expected_str, &results)) 00536 { 00537 _dbus_warn ("Expected hash %s got %s for SHA-1 sum\n", 00538 expected, 00539 _dbus_string_get_const_data (&results)); 00540 _dbus_string_free (&results); 00541 return FALSE; 00542 } 00543 00544 _dbus_string_free (&results); 00545 return TRUE; 00546 } 00547 00548 static dbus_bool_t 00549 check_sha_str (const char *input, 00550 const char *expected) 00551 { 00552 return check_sha_binary (input, strlen (input), expected); 00553 } 00554 00555 static dbus_bool_t 00556 decode_compact_string (const DBusString *line, 00557 DBusString *decoded) 00558 { 00559 int n_bits; 00560 dbus_bool_t current_b; 00561 int offset; 00562 int next; 00563 long val; 00564 int length_bytes; 00565 00566 offset = 0; 00567 next = 0; 00568 00569 if (!_dbus_string_parse_int (line, offset, &val, &next)) 00570 { 00571 fprintf (stderr, "could not parse length at start of compact string: %s\n", 00572 _dbus_string_get_const_data (line)); 00573 return FALSE; 00574 } 00575 00576 _dbus_string_skip_blank (line, next, &next); 00577 00578 offset = next; 00579 if (!_dbus_string_parse_int (line, offset, &val, &next)) 00580 { 00581 fprintf (stderr, "could not parse start bit 'b' in compact string: %s\n", 00582 _dbus_string_get_const_data (line)); 00583 return FALSE; 00584 } 00585 00586 if (!(val == 0 || val == 1)) 00587 { 00588 fprintf (stderr, "the value 'b' must be 0 or 1, see sha-1/Readme.txt\n"); 00589 return FALSE; 00590 } 00591 00592 _dbus_string_skip_blank (line, next, &next); 00593 00594 current_b = val; 00595 n_bits = 0; 00596 00597 while (next < _dbus_string_get_length (line)) 00598 { 00599 int total_bits; 00600 00601 offset = next; 00602 00603 if (_dbus_string_get_byte (line, offset) == '^') 00604 break; 00605 00606 if (!_dbus_string_parse_int (line, offset, &val, &next)) 00607 { 00608 fprintf (stderr, "could not parse bit count in compact string\n"); 00609 return FALSE; 00610 } 00611 00612 /* We now append "val" copies of "current_b" bits to the string */ 00613 total_bits = n_bits + val; 00614 while (n_bits < total_bits) 00615 { 00616 int byte_containing_next_bit = n_bits / 8; 00617 int bit_containing_next_bit = 7 - (n_bits % 8); 00618 unsigned char old_byte; 00619 00620 if (byte_containing_next_bit >= _dbus_string_get_length (decoded)) 00621 { 00622 if (!_dbus_string_set_length (decoded, byte_containing_next_bit + 1)) 00623 _dbus_assert_not_reached ("no memory to extend to next byte"); 00624 } 00625 00626 old_byte = _dbus_string_get_byte (decoded, byte_containing_next_bit); 00627 old_byte |= current_b << bit_containing_next_bit; 00628 00629 #if 0 00630 printf ("Appending bit %d to byte %d at bit %d resulting in byte 0x%x\n", 00631 current_b, byte_containing_next_bit, 00632 bit_containing_next_bit, old_byte); 00633 #endif 00634 00635 _dbus_string_set_byte (decoded, byte_containing_next_bit, old_byte); 00636 00637 ++n_bits; 00638 } 00639 00640 _dbus_string_skip_blank (line, next, &next); 00641 00642 current_b = !current_b; 00643 } 00644 00645 length_bytes = (n_bits / 8 + ((n_bits % 8) ? 1 : 0)); 00646 00647 if (_dbus_string_get_length (decoded) != length_bytes) 00648 { 00649 fprintf (stderr, "Expected length %d bytes %d bits for compact string, got %d bytes\n", 00650 length_bytes, n_bits, _dbus_string_get_length (decoded)); 00651 return FALSE; 00652 } 00653 else 00654 return TRUE; 00655 } 00656 00657 static dbus_bool_t 00658 get_next_expected_result (DBusString *results, 00659 DBusString *result) 00660 { 00661 DBusString line; 00662 dbus_bool_t retval; 00663 00664 retval = FALSE; 00665 00666 if (!_dbus_string_init (&line)) 00667 _dbus_assert_not_reached ("no memory"); 00668 00669 next_iteration: 00670 while (_dbus_string_pop_line (results, &line)) 00671 { 00672 _dbus_string_delete_leading_blanks (&line); 00673 00674 if (_dbus_string_get_length (&line) == 0) 00675 goto next_iteration; 00676 else if (_dbus_string_starts_with_c_str (&line, "#")) 00677 goto next_iteration; 00678 else if (_dbus_string_starts_with_c_str (&line, "H>")) 00679 { 00680 /* don't print */ 00681 } 00682 else if (_dbus_string_starts_with_c_str (&line, "D>") || 00683 _dbus_string_starts_with_c_str (&line, "<D")) 00684 goto next_iteration; 00685 else 00686 { 00687 int i; 00688 00689 if (!_dbus_string_move (&line, 0, result, 0)) 00690 _dbus_assert_not_reached ("no memory"); 00691 00692 i = 0; 00693 while (i < _dbus_string_get_length (result)) 00694 { 00695 switch (_dbus_string_get_byte (result, i)) 00696 { 00697 case 'A': 00698 _dbus_string_set_byte (result, i, 'a'); 00699 break; 00700 case 'B': 00701 _dbus_string_set_byte (result, i, 'b'); 00702 break; 00703 case 'C': 00704 _dbus_string_set_byte (result, i, 'c'); 00705 break; 00706 case 'D': 00707 _dbus_string_set_byte (result, i, 'd'); 00708 break; 00709 case 'E': 00710 _dbus_string_set_byte (result, i, 'e'); 00711 break; 00712 case 'F': 00713 _dbus_string_set_byte (result, i, 'f'); 00714 break; 00715 case '^': 00716 case ' ': 00717 _dbus_string_delete (result, i, 1); 00718 --i; /* to offset ++i below */ 00719 break; 00720 } 00721 00722 ++i; 00723 } 00724 00725 break; 00726 } 00727 } 00728 00729 retval = TRUE; 00730 00731 /* out: */ 00732 _dbus_string_free (&line); 00733 return retval; 00734 } 00735 00736 static dbus_bool_t 00737 process_test_data (const char *test_data_dir) 00738 { 00739 DBusString tests_file; 00740 DBusString results_file; 00741 DBusString tests; 00742 DBusString results; 00743 DBusString line; 00744 DBusString tmp; 00745 int line_no; 00746 dbus_bool_t retval; 00747 int success_count; 00748 DBusError error = DBUS_ERROR_INIT; 00749 00750 retval = FALSE; 00751 00752 if (!_dbus_string_init (&tests_file)) 00753 _dbus_assert_not_reached ("no memory"); 00754 00755 if (!_dbus_string_init (&results_file)) 00756 _dbus_assert_not_reached ("no memory"); 00757 00758 if (!_dbus_string_init (&tests)) 00759 _dbus_assert_not_reached ("no memory"); 00760 00761 if (!_dbus_string_init (&results)) 00762 _dbus_assert_not_reached ("no memory"); 00763 00764 if (!_dbus_string_init (&line)) 00765 _dbus_assert_not_reached ("no memory"); 00766 00767 if (!_dbus_string_append (&tests_file, test_data_dir)) 00768 _dbus_assert_not_reached ("no memory"); 00769 00770 if (!_dbus_string_append (&results_file, test_data_dir)) 00771 _dbus_assert_not_reached ("no memory"); 00772 00773 _dbus_string_init_const (&tmp, "sha-1/byte-messages.sha1"); 00774 if (!_dbus_concat_dir_and_file (&tests_file, &tmp)) 00775 _dbus_assert_not_reached ("no memory"); 00776 00777 _dbus_string_init_const (&tmp, "sha-1/byte-hashes.sha1"); 00778 if (!_dbus_concat_dir_and_file (&results_file, &tmp)) 00779 _dbus_assert_not_reached ("no memory"); 00780 00781 if (!_dbus_file_get_contents (&tests, &tests_file, &error)) 00782 { 00783 fprintf (stderr, "could not load test data file %s: %s\n", 00784 _dbus_string_get_const_data (&tests_file), 00785 error.message); 00786 dbus_error_free (&error); 00787 goto out; 00788 } 00789 00790 if (!_dbus_file_get_contents (&results, &results_file, &error)) 00791 { 00792 fprintf (stderr, "could not load results data file %s: %s\n", 00793 _dbus_string_get_const_data (&results_file), error.message); 00794 dbus_error_free (&error); 00795 goto out; 00796 } 00797 00798 success_count = 0; 00799 line_no = 0; 00800 next_iteration: 00801 while (_dbus_string_pop_line (&tests, &line)) 00802 { 00803 line_no += 1; 00804 00805 _dbus_string_delete_leading_blanks (&line); 00806 00807 if (_dbus_string_get_length (&line) == 0) 00808 goto next_iteration; 00809 else if (_dbus_string_starts_with_c_str (&line, "#")) 00810 goto next_iteration; 00811 else if (_dbus_string_starts_with_c_str (&line, "H>")) 00812 { 00813 printf ("SHA-1: %s\n", _dbus_string_get_const_data (&line)); 00814 00815 if (_dbus_string_find (&line, 0, "Type 3", NULL)) 00816 { 00817 /* See sha-1/Readme.txt - the "Type 3" tests are 00818 * random seeds, rather than data to be hashed. 00819 * we'd have to do a little bit more implementation 00820 * to use those tests. 00821 */ 00822 00823 printf (" (ending tests due to Type 3 tests seen - this is normal)\n"); 00824 break; 00825 } 00826 } 00827 else if (_dbus_string_starts_with_c_str (&line, "D>") || 00828 _dbus_string_starts_with_c_str (&line, "<D")) 00829 goto next_iteration; 00830 else 00831 { 00832 DBusString test; 00833 DBusString result; 00834 DBusString next_line; 00835 DBusString expected; 00836 dbus_bool_t success; 00837 00838 success = FALSE; 00839 00840 if (!_dbus_string_init (&next_line)) 00841 _dbus_assert_not_reached ("no memory"); 00842 00843 if (!_dbus_string_init (&expected)) 00844 _dbus_assert_not_reached ("no memory"); 00845 00846 if (!_dbus_string_init (&test)) 00847 _dbus_assert_not_reached ("no memory"); 00848 00849 if (!_dbus_string_init (&result)) 00850 _dbus_assert_not_reached ("no memory"); 00851 00852 /* the "compact strings" are "^"-terminated not 00853 * newline-terminated so readahead to find the 00854 * "^" 00855 */ 00856 while (!_dbus_string_find (&line, 0, "^", NULL) && 00857 _dbus_string_pop_line (&tests, &next_line)) 00858 { 00859 if (!_dbus_string_append_byte (&line, ' ') || 00860 !_dbus_string_move (&next_line, 0, &line, 00861 _dbus_string_get_length (&line))) 00862 _dbus_assert_not_reached ("no memory"); 00863 } 00864 00865 if (!decode_compact_string (&line, &test)) 00866 { 00867 fprintf (stderr, "Failed to decode line %d as a compact string\n", 00868 line_no); 00869 goto failure; 00870 } 00871 00872 if (!_dbus_sha_compute (&test, &result)) 00873 _dbus_assert_not_reached ("no memory for SHA-1 result"); 00874 00875 if (!get_next_expected_result (&results, &expected)) 00876 { 00877 fprintf (stderr, "Failed to read an expected result\n"); 00878 goto failure; 00879 } 00880 00881 if (!_dbus_string_equal (&result, &expected)) 00882 { 00883 fprintf (stderr, " for line %d got hash %s expected %s\n", 00884 line_no, 00885 _dbus_string_get_const_data (&result), 00886 _dbus_string_get_const_data (&expected)); 00887 goto failure; 00888 } 00889 else 00890 { 00891 success_count += 1; 00892 } 00893 00894 success = TRUE; 00895 00896 failure: 00897 _dbus_string_free (&test); 00898 _dbus_string_free (&result); 00899 _dbus_string_free (&next_line); 00900 _dbus_string_free (&expected); 00901 00902 if (!success) 00903 goto out; 00904 } 00905 } 00906 00907 retval = TRUE; 00908 00909 printf ("Passed the %d SHA-1 tests in the test file\n", 00910 success_count); 00911 00912 out: 00913 _dbus_string_free (&tests_file); 00914 _dbus_string_free (&results_file); 00915 _dbus_string_free (&tests); 00916 _dbus_string_free (&results); 00917 _dbus_string_free (&line); 00918 00919 return retval; 00920 } 00921 00928 dbus_bool_t 00929 _dbus_sha_test (const char *test_data_dir) 00930 { 00931 unsigned char all_bytes[256]; 00932 int i; 00933 00934 if (test_data_dir != NULL) 00935 { 00936 if (!process_test_data (test_data_dir)) 00937 return FALSE; 00938 } 00939 else 00940 printf ("No test data dir\n"); 00941 00942 i = 0; 00943 while (i < 256) 00944 { 00945 all_bytes[i] = i; 00946 ++i; 00947 } 00948 00949 if (!check_sha_binary (all_bytes, 256, 00950 "4916d6bdb7f78e6803698cab32d1586ea457dfc8")) 00951 return FALSE; 00952 00953 #define CHECK(input,expected) if (!check_sha_str (input, expected)) return FALSE 00954 00955 CHECK ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"); 00956 CHECK ("a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8"); 00957 CHECK ("abc", "a9993e364706816aba3e25717850c26c9cd0d89d"); 00958 CHECK ("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3"); 00959 CHECK ("abcdefghijklmnopqrstuvwxyz", "32d10c7b8cf96570ca04ce37f2a19d84240d3a89"); 00960 CHECK ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 00961 "761c457bf73b14d27e9e9265c46f4b4dda11f940"); 00962 CHECK ("12345678901234567890123456789012345678901234567890123456789012345678901234567890", 00963 "50abf5706a150990a08b2c5ea40fa0e585554732"); 00964 00965 return TRUE; 00966 } 00967 00968 #endif /* DBUS_BUILD_TESTS */