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