home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume41 / mdigest / part01 next >
Internet Message Format  |  1994-03-24  |  53KB

  1. From: M.Gream@uts.edu.au (Matthew Gream)
  2. Newsgroups: comp.sources.misc
  3. Subject: v41i137: mdigest - message digest library, Part01/03
  4. Date: 28 Feb 1994 18:25:53 -0000
  5. Sender: aem@aber.ac.uk
  6. Approved: aem@aber.ac.uk
  7. Message-ID: <csm-v41i137=mdigest.182540@aber.ac.uk>
  8. X-Md4-Signature: 4c7b954030c2a62cf28c6787c57af528
  9.  
  10. Submitted-by: M.Gream@uts.edu.au (Matthew Gream)
  11. Posting-number: Volume 41, Issue 137
  12. Archive-name: mdigest/part01
  13. Environment: C
  14.  
  15. #! /bin/sh
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  19. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  20. # Contents:  README MANIFEST EXPORT haval.c mtest.c
  21. # Wrapped by alecm@uk-usenet on Thu Feb 24 09:36:44 1994
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 1 (of 3)."'
  25. if test -f 'README' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'README'\"
  27. else
  28.   echo shar: Extracting \"'README'\" \(10157 characters\)
  29.   sed "s/^X//" >'README' <<'END_OF_FILE'
  30. X
  31. XMESSAGE DIGEST LIBRARY
  32. X
  33. XCopyright,
  34. XMatthew Gream <M.Gream@uts.edu.au>,
  35. XFebruary 1994.
  36. X
  37. X
  38. X-- License
  39. X
  40. XPlease read 'license.txt', it is written for my larger project, but
  41. Xapplies to this as well (it doesn't cover the items of sofware that
  42. Xare not under my control, ie. the message digests themselves).
  43. X
  44. X
  45. X-- Acknowledgements
  46. X
  47. XI acknowledge the use and inclusion of the following items of software
  48. Xwithin the library:
  49. X
  50. X    MD4, MD5  -- RSA Laboratories Inc.
  51. X    SHS       -- Peter C. Gutmann, Colin Plumb.
  52. X    HAVAL      -- Y. Zheng, J. Pieprzyk and J. Seberry.
  53. X
  54. X
  55. X-- Overview
  56. X
  57. XIn working on a larger project, I've had to construct some generic
  58. Xmodular handlers for message digest, encryption and compression methods.
  59. XThe idea is that the one generic interface handler allows selection and
  60. Xuse of any of the particular methods by a common set of interface
  61. Xfunctions, thereby removing the idiosyncrasies of each particular
  62. Xmethod.
  63. X
  64. XSome of the goals when writing this are to ensure it is flexible enough
  65. Xto allow addition of new methods even external to this library, ie so an
  66. Xapplication could selectively add or remove methods due to some other
  67. Xinfluence. At the same, it must be easy to determine what methods are
  68. Xcurrently available, and select them. Therefore, each method is known by
  69. Xa string, ie "md5" for RSAs message-digest #5.
  70. X
  71. XAccess to the module is, similar to how most message digests are
  72. Xstructure at the moment, via a context structure which keeps all the per
  73. Xassociation static data within it. This allows concurrency.
  74. X
  75. XAnyway, the reason for release of this is that I gave it to a friend to
  76. Xuse on something he was working on, he expressed delight at the
  77. X'niftyness' of it, and suggested I make it available. Writing this
  78. Xdocumentation and packaging it up for posting has already taken longer
  79. Xthan writing the thing in the first place :-)
  80. X
  81. X
  82. X-- Startup
  83. X
  84. XMost, just about all actually, functions have an enumerated return type
  85. Xof 'err_code' which are defined in the header file (note: I had to hack
  86. Xaround to move a few things into this header file, because in the larger
  87. Xproject, it is more distributed). To be honest, err_code is a bit of a
  88. Xmisnomer, it should really be ret_code, but anyway ... these give
  89. Xinformation about function execution problems.
  90. X
  91. XBefore you use the module in anyway whatsoever, you want to call the
  92. Xmodule initialisation function, this sets up internal tables and
  93. Xregisters a few common message digests (md4,md5,shs,haval). The syntax
  94. Xfor this is:
  95. X
  96. X                md_mod_open ();
  97. X
  98. XEven though it does return an err_code, it is currently redundant. By
  99. Xthe same token, after you've finished with the module, you're expected
  100. Xto call:
  101. X
  102. X                md_mod_close ();
  103. X
  104. Xwhich closes down and clears any used internal info. Naturally, a call
  105. Xto /md_mod_open()/ will re-initialise it again.
  106. X
  107. X
  108. X-- Lookup
  109. X
  110. XTo look at what methods are already registered, two functions so you can
  111. X'walk the list' so to speak. To initialise the walk, call:
  112. X
  113. X                md_list_init (word* state_var);
  114. X
  115. X/state_var/ is used as an index and used in the subsequent procedure of
  116. Xreturning each registered identifier in turn, the syntax for this is:
  117. X
  118. X                md_list_next (word* state_var, string ident);
  119. X
  120. XWhere string is a char array of minimum size /ident_sz/ (defined in the
  121. Xheader -- currently 16). At each iteration, /state_var/ is updated and
  122. Xthe next identifier is copied into /ident/. The return code here will be
  123. X/err_ok/ until the end of list is reached (or you pass an incorrect
  124. X/state_var/). For example, the following bit of code would list all the
  125. Xcurrently registered methods:
  126. X
  127. X        void list_methods ()
  128. X          {
  129. X            word        s;
  130. X            char        ident[ident_sz+1];
  131. X
  132. X            md_list_init (&s);
  133. X            while (md_list_next (&s, ident) == err_ok)
  134. X              printf ("-> %s\n", ident);
  135. X          }
  136. X
  137. X-- Registration/Deregistration
  138. X
  139. XIf you wish to add a custom digest to the module, you need to call the
  140. Xregistration process. First, your message digest needs to provide the
  141. Xfollowing functions (examine, say, md4-if.c to see how this works):
  142. X
  143. X  create() :            this takes as argument the message digest
  144. X                        context and allocates/initialises the internal
  145. X                        private data store.
  146. X
  147. X  destroy() :           takes a context as argument and deallocates the
  148. X                        the internal private data store.
  149. X
  150. X  register() :          takes and info structure as it's argument and
  151. X                        fills out all the function call handlers to
  152. X                        those just described above.
  153. X
  154. X  deregister() :        can be NULL, if not this is called when the
  155. X                        module is deregistered and takes an info struct
  156. X                        as it's argument.
  157. X
  158. X  [the user called functions that actually do work:]
  159. X
  160. X  init() :              called with the private data structure as
  161. X                        argument and expected to initialise state
  162. X                        information ready to start calculating a digest.
  163. X
  164. X  update () :           takes private data structure, data and it's
  165. X                        length to be used to update the digest.
  166. X
  167. X  final () :            takes private data structure and a storage area
  168. X                        to copy the digest too when all update()s have
  169. X                        been finished.
  170. X
  171. XTo register, you call the registration function with the ASCII string
  172. Xname of the method and the above registration function, the syntax for
  173. Xthis is:
  174. X
  175. X                md_register (string ident, function register);
  176. X
  177. X/md_register()/ will then check that an identifier of the same name
  178. Xdoesn't exist, and if so, allocate new storage for an info structure on
  179. Xthe list and call the register function so it can fill in the details.
  180. XAgain, a much better explanation can be had if you read the source code
  181. X:-).
  182. X
  183. XDeregistration is even easier, just call the deregistration function
  184. Xwith the identifier to remove, the syntax for this is:
  185. X
  186. X                md_deregister (string ident);
  187. X
  188. XAs a practical example, say you wanted to register a crc32 message
  189. Xdigest, you'd have code something to the effect of:
  190. X
  191. X                extern          err_code crc32_register ();
  192. X
  193. X                if (md_register ("crc32", crc32_register) != err_ok)
  194. X                  {
  195. X                    ...
  196. X                  }
  197. X
  198. Xand for deregistration:
  199. X
  200. X                (void)md_deregister ("crc32");
  201. X
  202. X
  203. X-- Operation
  204. X
  205. XPutting aside the administrative details of initialisation and
  206. Xregistration, using the module from an application is exceeding simple.
  207. XYou first need to call /md_open()/ with an empty context structure, and
  208. Xthe requested digest to use. From then on, you can use successive
  209. Xiterations of /md_init()/ to initialise the digest, /md_update()/ to
  210. Xupdate the digest with new data, and /md_final()/ to return the digest.
  211. XAgain, a practical example is the easiest. Consider the following
  212. Xfunction to take a files as input and determine the digest using md4.
  213. X
  214. X
  215. X        /* returns size of digest if ok, or -1 if error occured
  216. X         */
  217. X        int md_of_file (filename, digest, digest_sz)
  218. X                char*           filename;  /* filename to work on */
  219. X                char*           digest;    /* where to place the digest */
  220. X                int             digest_sz; /* how much space is avail */
  221. X          {
  222. X                int             f;
  223. X                int             i, j, k;
  224. X                char            buf[8192];
  225. X                md_ctx          ctx;
  226. X
  227. X                if (md_mod_open () != err_ok)
  228. X                  return -1;            /* something failed at init */
  229. X
  230. X                if (md_open (&ctx, "md4") != err_ok)
  231. X                  return -1;            /* md4 isn't registered */
  232. X
  233. X                if (digest_sz < md_hash_sz (&ctx))
  234. X                  return -1;            /* not enough space for the digest */
  235. X
  236. X                if ((f = open (filename, O_RDONLY)) < 0)
  237. X                  return -1;            /* can't open file */
  238. X
  239. X                md_init (&ctx);         /* initialisation */
  240. X
  241. X                do                      /* read and update */
  242. X                  {
  243. X                    j = read (f, buf, 8192);
  244. X                    if (j > 0)
  245. X                      md_update (&ctx, buf, j);
  246. X                  }
  247. X                while (j == 8192);      /* until exhausted input */
  248. X
  249. X                close (f);
  250. X
  251. X                md_final (&ctx, digest); /* compute and place in buffer */
  252. X                j = md_hash_sz (&ctx);   /* store size of hash before close */
  253. X
  254. X                md_close (&ctx);        /* close the context */
  255. X
  256. X                md_mod_close ();        /* shutdown the module */
  257. X
  258. X                return j;               /* return size of hash */
  259. X          }
  260. X
  261. X
  262. X-- Building
  263. X
  264. XType make. Should work on most architectures as there is little, if no,
  265. Xarchitecture dependent code. I've tested it on linux under gcc and SunOS
  266. Xunder both gcc and cc, no problems at all. I haven't tried it on MSDOS
  267. Xyet though.
  268. X
  269. XIf you want to modify which digests are included and/or which are loaded
  270. Xat module open, the add or remove the object files from the makefile,
  271. Xand edit the lines in mdigest.c in /md_mod_open()/ add or subtract
  272. X/md_register()/s.
  273. X
  274. X
  275. X-- Testing
  276. X
  277. XI've not done exhaustive testing on it, but running test suites and
  278. Xcomparing against vanilla digests, all seems ok. Anyway, it's so damn
  279. Xsmall there isn't really much that can go wrong :-) [famous last
  280. Xwords ...].
  281. X
  282. X
  283. X-- Included software
  284. X
  285. X > mfile.
  286. X
  287. X program which takes as arguments a number of files to calculate message
  288. X digests of. Each digest can be explicitly requested, or if none are,
  289. X then the default is to calculate all of them. This is used to make the
  290. X CHECKSUMS file.
  291. X
  292. X > mtest.
  293. X
  294. X runs test suites relevant to particular message digests.
  295. X
  296. X-- Bugs
  297. X
  298. XNone (so far).
  299. X
  300. X-- Finally
  301. X
  302. XI had to reverse the arguments to some of the message digests. Theres a
  303. Xbit of inconsistency because the init() and update() functions take a
  304. Xcontext as first parameter, but the final() doesn't. I guess it's just
  305. Xmy pedantic genericism that does it, but hey.
  306. X
  307. Xps. I hate writing documentation, so excuse the above if it seems too
  308. Xcryptic.
  309. X
  310. X
  311. END_OF_FILE
  312.   if test 10157 -ne `wc -c <'README'`; then
  313.     echo shar: \"'README'\" unpacked with wrong size!
  314.   fi
  315.   # end of 'README'
  316. fi
  317. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  318.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  319. else
  320.   echo shar: Extracting \"'MANIFEST'\" \(785 characters\)
  321.   sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  322. X   File Name        Archive #    Description
  323. X----------------------------------------------------------
  324. XREADME                     1    
  325. XMANIFEST                   1    
  326. XCHECKSUMS                  3    
  327. XEXPORT                     1    
  328. XMakefile                   3    
  329. Xhaval-if.c                 3    
  330. Xhaval.c                    1    
  331. Xhaval.h                    3    
  332. Xlicense.txt                3    
  333. Xmd4-if.c                   3    
  334. Xmd4.c                      2    
  335. Xmd4.h                      3    
  336. Xmd5-if.c                   3    
  337. Xmd5.c                      2    
  338. Xmd5.h                      3    
  339. Xmdigest.c                  2    
  340. Xmdigest.h                  3    
  341. Xmfile.c                    2    
  342. Xmtest.c                    1    
  343. Xshs-if.c                   3    
  344. Xshs.c                      2    
  345. Xshs.h                      3    
  346. Xutility.c                  3    
  347. END_OF_FILE
  348.   if test 785 -ne `wc -c <'MANIFEST'`; then
  349.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  350.   fi
  351.   # end of 'MANIFEST'
  352. fi
  353. if test -f 'EXPORT' -a "${1}" != "-c" ; then 
  354.   echo shar: Will not clobber existing file \"'EXPORT'\"
  355. else
  356.   echo shar: Extracting \"'EXPORT'\" \(97 characters\)
  357.   sed "s/^X//" >'EXPORT' <<'END_OF_FILE'
  358. X
  359. XMessage digests are not covered by ITAR. Hence, export of this
  360. Xproduct from the USA is legal. 
  361. X
  362. END_OF_FILE
  363.   if test 97 -ne `wc -c <'EXPORT'`; then
  364.     echo shar: \"'EXPORT'\" unpacked with wrong size!
  365.   fi
  366.   # end of 'EXPORT'
  367. fi
  368. if test -f 'haval.c' -a "${1}" != "-c" ; then 
  369.   echo shar: Will not clobber existing file \"'haval.c'\"
  370. else
  371.   echo shar: Extracting \"'haval.c'\" \(26139 characters\)
  372.   sed "s/^X//" >'haval.c' <<'END_OF_FILE'
  373. X
  374. X/*  -- derived from original haval.c, changes are:
  375. X *  -- mgream: added run time endian checks, instead of precompiled
  376. X *  -- mgream: changed function args from ansi (for compat)
  377. X *
  378. X *  haval.c:  specifies the routines in the HAVAL (V.1) hashing library.
  379. X *
  380. X *      HAVAL is a one-way hashing algorithm with the following
  381. X *      collision-resistant property:
  382. X *             It is computationally infeasible to find two or more
  383. X *             messages that are hashed into the same fingerprint.
  384. X *      
  385. X *  Reference:
  386. X *       Y. Zheng, J. Pieprzyk and J. Seberry:
  387. X *       ``HAVAL --- a one-way hashing algorithm with variable
  388. X *       length of output'', Advances in Cryptology --- AUSCRYPT'92,
  389. X *       Lecture Notes in Computer Science, Springer-Verlag, 1993.
  390. X *
  391. X *  Descriptions:
  392. X *      -  haval_string:      hash a string
  393. X *      -  haval_file:        hash a file
  394. X *      -  haval_stdin:       filter -- hash input from the stdin device
  395. X *      -  haval_hash:        hash a string of specified length
  396. X *                            (Haval_hash is used in conjunction with
  397. X *                             haval_start & haval_end.)
  398. X *      -  haval_hash_block:  hash a 32-word block
  399. X *      -  haval_start:       initialization
  400. X *      -  haval_end:         finalization
  401. X *
  402. X *  Author:     Yuliang Zheng
  403. X *              Department of Computer Science
  404. X *              University of Wollongong
  405. X *              Wollongong, NSW 2522, Australia
  406. X *              Email: yuliang@cs.uow.edu.au
  407. X *              Voice: +61 42 21 4331 (office)
  408. X *
  409. X *  Date:       June 1993
  410. X *
  411. X *      Copyright (C) 1993 by C^3SR. All rights reserved. 
  412. X *      This program may not be sold or used as inducement to
  413. X *      buy a product without the written permission of C^3SR.
  414. X */
  415. X
  416. X#include <stdio.h>
  417. X#include <memory.h>
  418. X#include "haval.h"
  419. X
  420. Xstatic   int        endian = 0;          /* 0  = little, 1 = big */
  421. X
  422. X#define VERSION    1                         /* current version number */
  423. X
  424. Xvoid haval_start ();            /* initialization */
  425. Xvoid haval_hash ();      /* updating routine */
  426. Xvoid haval_end (); /* finalization */
  427. Xvoid haval_hash_block ();       /* hash a 32-word block */
  428. Xstatic void haval_tailor ();    /* folding the last output */
  429. X
  430. Xstatic unsigned char padding[128] = {        /* constants for padding */
  431. X0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  432. X   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  433. X   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  434. X   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  435. X   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  436. X   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  437. X   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  438. X   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  439. X};
  440. X
  441. X#define f_1(x6, x5, x4, x3, x2, x1, x0)          \
  442. X           ((x1) & ((x0) ^ (x4)) ^ (x2) & (x5) ^ \
  443. X            (x3) & (x6) ^ (x0))
  444. X
  445. X#define f_2(x6, x5, x4, x3, x2, x1, x0)                         \
  446. X           ((x2) & ((x1) & ~(x3) ^ (x4) & (x5) ^ (x6) ^ (x0)) ^ \
  447. X            (x4) & ((x1) ^ (x5)) ^ (x3) & (x5) ^ (x0)) 
  448. X
  449. X#define f_3(x6, x5, x4, x3, x2, x1, x0)          \
  450. X           ((x3) & ((x1) & (x2) ^ (x6) ^ (x0)) ^ \
  451. X            (x1) & (x4) ^ (x2) & (x5) ^ (x0))
  452. X
  453. X#define f_4(x6, x5, x4, x3, x2, x1, x0)                                 \
  454. X           ((x4) & ((x5) & ~(x2) ^ (x3) & ~(x6) ^ (x1) ^ (x6) ^ (x0)) ^ \
  455. X            (x3) & ((x1) & (x2) ^ (x5) ^ (x6)) ^                        \
  456. X            (x2) & (x6) ^ (x0))
  457. X
  458. X#define f_5(x6, x5, x4, x3, x2, x1, x0)             \
  459. X           ((x0) & ((x1) & (x2) & (x3) ^ ~(x5)) ^   \
  460. X            (x1) & (x4) ^ (x2) & (x5) ^ (x3) & (x6))
  461. X
  462. X/*
  463. X * Permutations phi_{i,j}, i=3,4,5, j=1,...,i.
  464. X *
  465. X * PASS = 3:
  466. X *               6 5 4 3 2 1 0
  467. X *               | | | | | | | (replaced by)
  468. X *  phi_{3,1}:   1 0 3 5 6 2 4
  469. X *  phi_{3,2}:   4 2 1 0 5 3 6
  470. X *  phi_{3,3}:   6 1 2 3 4 5 0
  471. X *
  472. X * PASS = 4:
  473. X *               6 5 4 3 2 1 0
  474. X *               | | | | | | | (replaced by)
  475. X *  phi_{4,1}:   2 6 1 4 5 3 0
  476. X *  phi_{4,2}:   3 5 2 0 1 6 4
  477. X *  phi_{4,3}:   1 4 3 6 0 2 5
  478. X *  phi_{4,4}:   6 4 0 5 2 1 3
  479. X *
  480. X * PASS = 5:
  481. X *               6 5 4 3 2 1 0
  482. X *               | | | | | | | (replaced by)
  483. X *  phi_{5,1}:   3 4 1 0 5 2 6
  484. X *  phi_{5,2}:   6 2 1 0 3 4 5
  485. X *  phi_{5,3}:   2 6 0 4 3 1 5
  486. X *  phi_{5,4}:   1 5 3 2 0 4 6
  487. X *  phi_{5,5}:   2 5 0 6 4 3 1
  488. X */
  489. X
  490. X#if   PASS == 3
  491. X#define Fphi_1(x6, x5, x4, x3, x2, x1, x0) \
  492. X           f_1(x1, x0, x3, x5, x6, x2, x4)
  493. X#elif PASS == 4
  494. X#define Fphi_1(x6, x5, x4, x3, x2, x1, x0) \
  495. X           f_1(x2, x6, x1, x4, x5, x3, x0)
  496. X#else 
  497. X#define Fphi_1(x6, x5, x4, x3, x2, x1, x0) \
  498. X           f_1(x3, x4, x1, x0, x5, x2, x6)
  499. X#endif
  500. X
  501. X#if   PASS == 3
  502. X#define Fphi_2(x6, x5, x4, x3, x2, x1, x0) \
  503. X           f_2(x4, x2, x1, x0, x5, x3, x6)
  504. X#elif PASS == 4
  505. X#define Fphi_2(x6, x5, x4, x3, x2, x1, x0) \
  506. X           f_2(x3, x5, x2, x0, x1, x6, x4)
  507. X#else 
  508. X#define Fphi_2(x6, x5, x4, x3, x2, x1, x0) \
  509. X           f_2(x6, x2, x1, x0, x3, x4, x5)
  510. X#endif
  511. X
  512. X#if   PASS == 3
  513. X#define Fphi_3(x6, x5, x4, x3, x2, x1, x0) \
  514. X           f_3(x6, x1, x2, x3, x4, x5, x0)
  515. X#elif PASS == 4
  516. X#define Fphi_3(x6, x5, x4, x3, x2, x1, x0) \
  517. X           f_3(x1, x4, x3, x6, x0, x2, x5)
  518. X#else 
  519. X#define Fphi_3(x6, x5, x4, x3, x2, x1, x0) \
  520. X           f_3(x2, x6, x0, x4, x3, x1, x5)
  521. X#endif
  522. X
  523. X#if   PASS == 4
  524. X#define Fphi_4(x6, x5, x4, x3, x2, x1, x0) \
  525. X           f_4(x6, x4, x0, x5, x2, x1, x3)
  526. X#else 
  527. X#define Fphi_4(x6, x5, x4, x3, x2, x1, x0) \
  528. X            f_4(x1, x5, x3, x2, x0, x4, x6)
  529. X#endif
  530. X
  531. X#define Fphi_5(x6, x5, x4, x3, x2, x1, x0) \
  532. X           f_5(x2, x5, x0, x6, x4, x3, x1)
  533. X
  534. X#define rotate_right(x, n) (((x) >> (n)) | ((x) << (32-(n))))
  535. X
  536. X#define FF_1(x7, x6, x5, x4, x3, x2, x1, x0, w) {                        \
  537. X      register haval_word temp = Fphi_1(x6, x5, x4, x3, x2, x1, x0);     \
  538. X      (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w);       \
  539. X      }
  540. X
  541. X#define FF_2(x7, x6, x5, x4, x3, x2, x1, x0, w, c) {                      \
  542. X      register haval_word temp = Fphi_2(x6, x5, x4, x3, x2, x1, x0);      \
  543. X      (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c);  \
  544. X      }
  545. X
  546. X#define FF_3(x7, x6, x5, x4, x3, x2, x1, x0, w, c) {                      \
  547. X      register haval_word temp = Fphi_3(x6, x5, x4, x3, x2, x1, x0);      \
  548. X      (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c);  \
  549. X      }
  550. X
  551. X#define FF_4(x7, x6, x5, x4, x3, x2, x1, x0, w, c) {                      \
  552. X      register haval_word temp = Fphi_4(x6, x5, x4, x3, x2, x1, x0);      \
  553. X      (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c);  \
  554. X      }
  555. X
  556. X#define FF_5(x7, x6, x5, x4, x3, x2, x1, x0, w, c) {                      \
  557. X      register haval_word temp = Fphi_5(x6, x5, x4, x3, x2, x1, x0);      \
  558. X      (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c);  \
  559. X      }
  560. X
  561. X/*
  562. X * translate every four characters into a word.
  563. X * assume the number of characters is a multiple of four.
  564. X */
  565. X#define ch2uint(string, word, slen) {      \
  566. X  unsigned char *sp = string;              \
  567. X  haval_word    *wp = word;                \
  568. X  while (sp < (string) + (slen)) {         \
  569. X    *wp++ =  (haval_word)*sp            |  \
  570. X            ((haval_word)*(sp+1) <<  8) |  \
  571. X            ((haval_word)*(sp+2) << 16) |  \
  572. X            ((haval_word)*(sp+3) << 24);   \
  573. X    sp += 4;                               \
  574. X  }                                        \
  575. X}
  576. X
  577. X/* translate each word into four characters */
  578. X#define uint2ch(word, string, wlen) {              \
  579. X  haval_word    *wp = word;                        \
  580. X  unsigned char *sp = string;                      \
  581. X  while (wp < (word) + (wlen)) {                   \
  582. X    *(sp++) = (unsigned char)( *wp        & 0xFF); \
  583. X    *(sp++) = (unsigned char)((*wp >>  8) & 0xFF); \
  584. X    *(sp++) = (unsigned char)((*wp >> 16) & 0xFF); \
  585. X    *(sp++) = (unsigned char)((*wp >> 24) & 0xFF); \
  586. X    wp++;                                          \
  587. X  }                                                \
  588. X}
  589. X
  590. X/* initialization */
  591. Xvoid haval_start (state)
  592. X    haval_state *state;
  593. X{
  594. X    state->count[0]       = state->count[1] = 0;   /* clear count */
  595. X    state->fingerprint[0] = 0x243F6A88;            /* initial fingerprint */
  596. X    state->fingerprint[1] = 0x85A308D3;
  597. X    state->fingerprint[2] = 0x13198A2E;
  598. X    state->fingerprint[3] = 0x03707344;
  599. X    state->fingerprint[4] = 0xA4093822;
  600. X    state->fingerprint[5] = 0x299F31D0;
  601. X    state->fingerprint[6] = 0x082EFA98;
  602. X    state->fingerprint[7] = 0xEC4E6C89;
  603. X
  604. X    /* from shs.c
  605. X     *
  606. X     * Find out what the byte order is on this machine.
  607. X     * Big endian is for machines that place the most significant byte
  608. X     * first (eg. Sun SPARC). Little endian is for machines that place
  609. X     * the least significant byte first (eg. VAX).
  610. X     *
  611. X     * We figure out the byte order by stuffing a 2 byte string into a
  612. X     * short and examining the left byte. '@' = 0x40  and  'P' = 0x50
  613. X     * If the left byte is the 'high' byte, then it is 'big endian'.
  614. X     * If the left byte is the 'low' byte, then the machine is 'little
  615. X     * endian'.
  616. X     *
  617. X     *                          -- Shawn A. Clifford (sac@eng.ufl.edu)
  618. X     */
  619. X
  620. X    if ((*(unsigned short *) ("@P") >> 8) == '@')
  621. X        endian = 1;
  622. X    else
  623. X        endian = 0;
  624. X
  625. X}
  626. X
  627. X/*
  628. X * hash a string of specified length.
  629. X * to be used in conjunction with haval_start and haval_end.
  630. X */
  631. Xvoid haval_hash (state, str, str_len)
  632. X  haval_state* state;
  633. X  unsigned char *str;
  634. X  unsigned int str_len;
  635. X{
  636. X  unsigned int i,
  637. X           rmd_len,
  638. X           fill_len;
  639. X
  640. X  /* calculate the number of bytes in the remainder */
  641. X  rmd_len  = (unsigned int)((state->count[0] >> 3) & 0x7F);
  642. X  fill_len = 128 - rmd_len;
  643. X
  644. X  /* update the number of bits */
  645. X  if ((state->count[0] +=  (haval_word)str_len << 3)
  646. X                        < ((haval_word)str_len << 3)) {
  647. X     state->count[1]++;
  648. X  }
  649. X  state->count[1] += (haval_word)str_len >> 29;
  650. X
  651. X/*#ifdef LITTLE_ENDIAN*/
  652. X  if (endian == 0) {
  653. X
  654. X  /* hash as many blocks as possible */
  655. X  if (rmd_len + str_len >= 128) {
  656. X    memcpy (((unsigned char *)state->block)+rmd_len, str, fill_len);
  657. X    haval_hash_block (state);
  658. X    for (i = fill_len; i + 127 < str_len; i += 128){
  659. X      memcpy ((unsigned char *)state->block, str+i, 128);
  660. X      haval_hash_block (state);
  661. X    }
  662. X    rmd_len = 0;
  663. X  } else {
  664. X    i = 0;
  665. X  }
  666. X  memcpy (((unsigned char *)state->block)+rmd_len, str+i, str_len-i);
  667. X
  668. X/*#else*/
  669. X  } else {
  670. X
  671. X  /* hash as many blocks as possible */
  672. X  if (rmd_len + str_len >= 128) {
  673. X    memcpy (&state->remainder[rmd_len], str, fill_len);
  674. X    ch2uint(state->remainder, state->block, 128);
  675. X    haval_hash_block (state);
  676. X    for (i = fill_len; i + 127 < str_len; i += 128){
  677. X      memcpy (state->remainder, str+i, 128);
  678. X      ch2uint(state->remainder, state->block, 128);
  679. X      haval_hash_block (state);
  680. X    }
  681. X    rmd_len = 0;
  682. X  } else {
  683. X    i = 0;
  684. X  }
  685. X  /* save the remaining input chars */
  686. X  memcpy (&state->remainder[rmd_len], str+i, str_len-i);
  687. X
  688. X/*#endif*/
  689. X  }
  690. X
  691. X}
  692. X
  693. X/* finalization */
  694. Xvoid haval_end (state, final_fpt)
  695. X  haval_state * state;
  696. X  unsigned char final_fpt[FPTLEN >> 3];
  697. X{
  698. X  unsigned char tail[10];
  699. X  unsigned int  rmd_len, pad_len;
  700. X
  701. X  /*
  702. X   * save the version number, the number of passes, the fingerprint 
  703. X   * length and the number of bits in the unpadded message.
  704. X   */
  705. X  tail[0] = (unsigned char)(((FPTLEN  & 0x3) << 6) |
  706. X                            ((PASS    & 0x7) << 3) |
  707. X                             (VERSION & 0x7));
  708. X  tail[1] = (unsigned char)((FPTLEN >> 2) & 0xFF);
  709. X  uint2ch (state->count, &tail[2], 2);
  710. X
  711. X  /* pad out to 118 mod 128 */
  712. X  rmd_len = (unsigned int)((state->count[0] >> 3) & 0x7f);
  713. X  pad_len = (rmd_len < 118) ? (118 - rmd_len) : (246 - rmd_len);
  714. X  haval_hash (state, padding, pad_len);
  715. X
  716. X  /*
  717. X   * append the version number, the number of passes,
  718. X   * the fingerprint length and the number of bits
  719. X   */
  720. X  haval_hash (state, tail, 10);
  721. X
  722. X  /* tailor the last output */
  723. X  haval_tailor(state);
  724. X
  725. X  /* translate and save the final fingerprint */
  726. X  uint2ch (state->fingerprint, final_fpt, FPTLEN >> 5);
  727. X
  728. X  /* clear the state information */
  729. X  memset ((unsigned char *)state, 0, sizeof (*state));
  730. X}
  731. X
  732. X/* hash a 32-word block */
  733. Xvoid haval_hash_block (state)
  734. X  haval_state* state;
  735. X{
  736. X  register haval_word t0 = state->fingerprint[0],    /* make use of */
  737. X                      t1 = state->fingerprint[1],    /* internal registers */
  738. X                      t2 = state->fingerprint[2],
  739. X                      t3 = state->fingerprint[3],
  740. X                      t4 = state->fingerprint[4],
  741. X                      t5 = state->fingerprint[5],
  742. X                      t6 = state->fingerprint[6],
  743. X                      t7 = state->fingerprint[7],
  744. X                      *w = state->block;
  745. X
  746. X  /* Pass 1 */
  747. X  FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w   ));
  748. X  FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 1));
  749. X  FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 2));
  750. X  FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 3));
  751. X  FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 4));
  752. X  FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 5));
  753. X  FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 6));
  754. X  FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 7));
  755. X
  756. X  FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 8));
  757. X  FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 9));
  758. X  FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+10));
  759. X  FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+11));
  760. X  FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+12));
  761. X  FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+13));
  762. X  FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+14));
  763. X  FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+15));
  764. X
  765. X  FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w+16));
  766. X  FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+17));
  767. X  FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+18));
  768. X  FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+19));
  769. X  FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+20));
  770. X  FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+21));
  771. X  FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+22));
  772. X  FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+23));
  773. X
  774. X  FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w+24));
  775. X  FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+25));
  776. X  FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+26));
  777. X  FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+27));
  778. X  FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+28));
  779. X  FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+29));
  780. X  FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+30));
  781. X  FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+31));
  782. X
  783. X  /* Pass 2 */
  784. X  FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 5), 0x452821E6);
  785. X  FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+14), 0x38D01377);
  786. X  FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+26), 0xBE5466CF);
  787. X  FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+18), 0x34E90C6C);
  788. X  FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+11), 0xC0AC29B7);
  789. X  FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+28), 0xC97C50DD);
  790. X  FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 7), 0x3F84D5B5);
  791. X  FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+16), 0xB5470917);
  792. X
  793. X  FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w   ), 0x9216D5D9);
  794. X  FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+23), 0x8979FB1B);
  795. X  FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+20), 0xD1310BA6);
  796. X  FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+22), 0x98DFB5AC);
  797. X  FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 1), 0x2FFD72DB);
  798. X  FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+10), 0xD01ADFB7);
  799. X  FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 4), 0xB8E1AFED);
  800. X  FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 8), 0x6A267E96);
  801. X
  802. X  FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w+30), 0xBA7C9045);
  803. X  FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 3), 0xF12C7F99);
  804. X  FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+21), 0x24A19947);
  805. X  FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 9), 0xB3916CF7);
  806. X  FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+17), 0x0801F2E2);
  807. X  FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+24), 0x858EFC16);
  808. X  FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+29), 0x636920D8);
  809. X  FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 6), 0x71574E69);
  810. X
  811. X  FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w+19), 0xA458FEA3);
  812. X  FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+12), 0xF4933D7E);
  813. X  FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+15), 0x0D95748F);
  814. X  FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+13), 0x728EB658);
  815. X  FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 2), 0x718BCD58);
  816. X  FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+25), 0x82154AEE);
  817. X  FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+31), 0x7B54A41D);
  818. X  FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+27), 0xC25A59B5);
  819. X
  820. X  /* Pass 3 */
  821. X  FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+19), 0x9C30D539);
  822. X  FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 9), 0x2AF26013);
  823. X  FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 4), 0xC5D1B023);
  824. X  FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+20), 0x286085F0);
  825. X  FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+28), 0xCA417918);
  826. X  FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w+17), 0xB8DB38EF);
  827. X  FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 8), 0x8E79DCB0);
  828. X  FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+22), 0x603A180E);
  829. X
  830. X  FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+29), 0x6C9E0E8B);
  831. X  FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+14), 0xB01E8A3E);
  832. X  FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+25), 0xD71577C1);
  833. X  FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+12), 0xBD314B27);
  834. X  FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+24), 0x78AF2FDA);
  835. X  FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w+30), 0x55605C60);
  836. X  FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+16), 0xE65525F3);
  837. X  FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+26), 0xAA55AB94);
  838. X
  839. X  FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+31), 0x57489862);
  840. X  FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+15), 0x63E81440);
  841. X  FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 7), 0x55CA396A);
  842. X  FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 3), 0x2AAB10B6);
  843. X  FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 1), 0xB4CC5C34);
  844. X  FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w   ), 0x1141E8CE);
  845. X  FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+18), 0xA15486AF);
  846. X  FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+27), 0x7C72E993);
  847. X
  848. X  FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+13), 0xB3EE1411);
  849. X  FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 6), 0x636FBC2A);
  850. X  FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+21), 0x2BA9C55D);
  851. X  FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+10), 0x741831F6);
  852. X  FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+23), 0xCE5C3E16);
  853. X  FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w+11), 0x9B87931E);
  854. X  FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 5), 0xAFD6BA33);
  855. X  FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 2), 0x6C24CF5C);
  856. X
  857. X#if PASS >= 4
  858. X  /* Pass 4. executed only when PASS =4 or 5 */
  859. X  FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+24), 0x7A325381);
  860. X  FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 4), 0x28958677);
  861. X  FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w   ), 0x3B8F4898);
  862. X  FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+14), 0x6B4BB9AF);
  863. X  FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 2), 0xC4BFE81B);
  864. X  FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 7), 0x66282193);
  865. X  FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+28), 0x61D809CC);
  866. X  FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+23), 0xFB21A991);
  867. X
  868. X  FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+26), 0x487CAC60);
  869. X  FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 6), 0x5DEC8032);
  870. X  FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w+30), 0xEF845D5D);
  871. X  FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+20), 0xE98575B1);
  872. X  FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+18), 0xDC262302);
  873. X  FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+25), 0xEB651B88);
  874. X  FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+19), 0x23893E81);
  875. X  FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 3), 0xD396ACC5);
  876. X
  877. X  FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+22), 0x0F6D6FF3);
  878. X  FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+11), 0x83F44239);
  879. X  FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w+31), 0x2E0B4482);
  880. X  FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+21), 0xA4842004);
  881. X  FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 8), 0x69C8F04A);
  882. X  FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+27), 0x9E1F9B5E);
  883. X  FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+12), 0x21C66842);
  884. X  FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 9), 0xF6E96C9A);
  885. X
  886. X  FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 1), 0x670C9C61);
  887. X  FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+29), 0xABD388F0);
  888. X  FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 5), 0x6A51A0D2);
  889. X  FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+15), 0xD8542F68);
  890. X  FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+17), 0x960FA728);
  891. X  FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+10), 0xAB5133A3);
  892. X  FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+16), 0x6EEF0B6C);
  893. X  FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+13), 0x137A3BE4);
  894. X#endif
  895. X
  896. X#if PASS == 5
  897. X  /* Pass 5. executed only when PASS = 5 */
  898. X  FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+27), 0xBA3BF050);
  899. X  FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 3), 0x7EFB2A98);
  900. X  FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+21), 0xA1F1651D);
  901. X  FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+26), 0x39AF0176);
  902. X  FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+17), 0x66CA593E);
  903. X  FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+11), 0x82430E88);
  904. X  FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+20), 0x8CEE8619);
  905. X  FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+29), 0x456F9FB4);
  906. X
  907. X  FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+19), 0x7D84A5C3);
  908. X  FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w   ), 0x3B8B5EBE);
  909. X  FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+12), 0xE06F75D8);
  910. X  FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 7), 0x85C12073);
  911. X  FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+13), 0x401A449F);
  912. X  FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 8), 0x56C16AA6);
  913. X  FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+31), 0x4ED3AA62);
  914. X  FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+10), 0x363F7706);
  915. X
  916. X  FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 5), 0x1BFEDF72);
  917. X  FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 9), 0x429B023D);
  918. X  FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+14), 0x37D0D724);
  919. X  FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+30), 0xD00A1248);
  920. X  FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+18), 0xDB0FEAD3);
  921. X  FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 6), 0x49F1C09B);
  922. X  FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+28), 0x075372C9);
  923. X  FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+24), 0x80991B7B);
  924. X
  925. X  FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 2), 0x25D479D8);
  926. X  FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w+23), 0xF6E8DEF7);
  927. X  FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+16), 0xE3FE501A);
  928. X  FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+22), 0xB6794C3B);
  929. X  FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 4), 0x976CE0BD);
  930. X  FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 1), 0x04C006BA);
  931. X  FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+25), 0xC1A94FB6);
  932. X  FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+15), 0x409F60C4);
  933. X#endif
  934. X
  935. X  state->fingerprint[0] += t0;
  936. X  state->fingerprint[1] += t1;
  937. X  state->fingerprint[2] += t2;
  938. X  state->fingerprint[3] += t3;
  939. X  state->fingerprint[4] += t4;
  940. X  state->fingerprint[5] += t5;
  941. X  state->fingerprint[6] += t6;
  942. X  state->fingerprint[7] += t7;
  943. X}
  944. X
  945. X/* tailor the last output */
  946. Xstatic void haval_tailor (state)
  947. X  haval_state * state;
  948. X{
  949. X  haval_word temp;
  950. X
  951. X#if FPTLEN == 128
  952. X  temp = (state->fingerprint[7] & 0x000000FF) | 
  953. X         (state->fingerprint[6] & 0xFF000000) | 
  954. X         (state->fingerprint[5] & 0x00FF0000) | 
  955. X         (state->fingerprint[4] & 0x0000FF00);
  956. X  state->fingerprint[0] += rotate_right(temp,  8);
  957. X
  958. X  temp = (state->fingerprint[7] & 0x0000FF00) | 
  959. X         (state->fingerprint[6] & 0x000000FF) | 
  960. X         (state->fingerprint[5] & 0xFF000000) | 
  961. X         (state->fingerprint[4] & 0x00FF0000);
  962. X  state->fingerprint[1] += rotate_right(temp, 16);
  963. X
  964. X  temp  = (state->fingerprint[7] & 0x00FF0000) | 
  965. X          (state->fingerprint[6] & 0x0000FF00) | 
  966. X          (state->fingerprint[5] & 0x000000FF) | 
  967. X          (state->fingerprint[4] & 0xFF000000);
  968. X  state->fingerprint[2] += rotate_right(temp, 24);
  969. X
  970. X  temp = (state->fingerprint[7] & 0xFF000000) | 
  971. X         (state->fingerprint[6] & 0x00FF0000) | 
  972. X         (state->fingerprint[5] & 0x0000FF00) | 
  973. X         (state->fingerprint[4] & 0x000000FF);
  974. X  state->fingerprint[3] += temp;
  975. X
  976. X#elif FPTLEN == 160
  977. X  temp = (state->fingerprint[7] &  (haval_word)0x3F) | 
  978. X         (state->fingerprint[6] & ((haval_word)0x7F << 25)) |  
  979. X         (state->fingerprint[5] & ((haval_word)0x3F << 19));
  980. X  state->fingerprint[0] += rotate_right(temp, 19);
  981. X
  982. X  temp = (state->fingerprint[7] & ((haval_word)0x3F <<  6)) | 
  983. X         (state->fingerprint[6] &  (haval_word)0x3F) |  
  984. X         (state->fingerprint[5] & ((haval_word)0x7F << 25));
  985. X  state->fingerprint[1] += rotate_right(temp, 25);
  986. X
  987. X  temp = (state->fingerprint[7] & ((haval_word)0x7F << 12)) | 
  988. X         (state->fingerprint[6] & ((haval_word)0x3F <<  6)) |  
  989. X         (state->fingerprint[5] &  (haval_word)0x3F);
  990. X  state->fingerprint[2] += temp;
  991. X
  992. X  temp = (state->fingerprint[7] & ((haval_word)0x3F << 19)) | 
  993. X         (state->fingerprint[6] & ((haval_word)0x7F << 12)) |  
  994. X         (state->fingerprint[5] & ((haval_word)0x3F <<  6));
  995. X  state->fingerprint[3] += temp >> 6; 
  996. X
  997. X  temp = (state->fingerprint[7] & ((haval_word)0x7F << 25)) | 
  998. X         (state->fingerprint[6] & ((haval_word)0x3F << 19)) |  
  999. X         (state->fingerprint[5] & ((haval_word)0x7F << 12));
  1000. X  state->fingerprint[4] += temp >> 12;
  1001. X
  1002. X#elif FPTLEN == 192
  1003. X  temp = (state->fingerprint[7] &  (haval_word)0x1F) | 
  1004. X         (state->fingerprint[6] & ((haval_word)0x3F << 26));
  1005. X  state->fingerprint[0] += rotate_right(temp, 26);
  1006. X
  1007. X  temp = (state->fingerprint[7] & ((haval_word)0x1F <<  5)) | 
  1008. X         (state->fingerprint[6] &  (haval_word)0x1F);
  1009. X  state->fingerprint[1] += temp;
  1010. X
  1011. X  temp = (state->fingerprint[7] & ((haval_word)0x3F << 10)) | 
  1012. X         (state->fingerprint[6] & ((haval_word)0x1F <<  5));
  1013. X  state->fingerprint[2] += temp >> 5;
  1014. X
  1015. X  temp = (state->fingerprint[7] & ((haval_word)0x1F << 16)) | 
  1016. X         (state->fingerprint[6] & ((haval_word)0x3F << 10));
  1017. X  state->fingerprint[3] += temp >> 10;
  1018. X
  1019. X  temp = (state->fingerprint[7] & ((haval_word)0x1F << 21)) | 
  1020. X         (state->fingerprint[6] & ((haval_word)0x1F << 16));
  1021. X  state->fingerprint[4] += temp >> 16;
  1022. X
  1023. X  temp = (state->fingerprint[7] & ((haval_word)0x3F << 26)) | 
  1024. X         (state->fingerprint[6] & ((haval_word)0x1F << 21));
  1025. X  state->fingerprint[5] += temp >> 21;
  1026. X
  1027. X#elif FPTLEN == 224
  1028. X  state->fingerprint[0] += (state->fingerprint[7] >> 27) & 0x1F;
  1029. X  state->fingerprint[1] += (state->fingerprint[7] >> 22) & 0x1F;
  1030. X  state->fingerprint[2] += (state->fingerprint[7] >> 18) & 0x0F;
  1031. X  state->fingerprint[3] += (state->fingerprint[7] >> 13) & 0x1F;
  1032. X  state->fingerprint[4] += (state->fingerprint[7] >>  9) & 0x0F;
  1033. X  state->fingerprint[5] += (state->fingerprint[7] >>  4) & 0x1F;
  1034. X  state->fingerprint[6] +=  state->fingerprint[7]        & 0x0F;
  1035. X#endif
  1036. X}
  1037. X
  1038. X
  1039. END_OF_FILE
  1040.   if test 26139 -ne `wc -c <'haval.c'`; then
  1041.     echo shar: \"'haval.c'\" unpacked with wrong size!
  1042.   fi
  1043.   # end of 'haval.c'
  1044. fi
  1045. if test -f 'mtest.c' -a "${1}" != "-c" ; then 
  1046.   echo shar: Will not clobber existing file \"'mtest.c'\"
  1047. else
  1048.   echo shar: Extracting \"'mtest.c'\" \(11052 characters\)
  1049.   sed "s/^X//" >'mtest.c' <<'END_OF_FILE'
  1050. X
  1051. X/* -------------------------------------------------------------------- */
  1052. X/*                                                                      */
  1053. X/*  Secure Asyncronous Communications Subsystem (SACS)                  */
  1054. X/*  (C) 1994 Matthew Gream <M.Gream@uts.edu.au>                         */
  1055. X/*                                                                      */
  1056. X/*  You have been given a limited license to use and distribute this    */
  1057. X/*  library. You should have received this license with the original    */
  1058. X/*  release package of this library, named "license.txt" and entitled   */
  1059. X/*  "SACS SOFTWARE LICENSE". In the event that you have not read or     */
  1060. X/*  understood this license, regardless of reason, you may do nothing   */
  1061. X/*  with this library other than read it for self-awareness.            */
  1062. X/*                                                                      */
  1063. X/* -------------------------------------------------------------------- */
  1064. X
  1065. X/* $Id: mfile.c%v 0.90 1994/02/22 20:51:46 matt Exp $
  1066. X */
  1067. X
  1068. X/*
  1069. X *  File:         mtest.c
  1070. X *  Description:  test md4, md5, shs and (if added) other digests
  1071. X */
  1072. X
  1073. X#include <stdio.h>
  1074. X#include <stdlib.h>
  1075. X#include <unistd.h>
  1076. X#include <fcntl.h>
  1077. X
  1078. X#include <mdigest.h>
  1079. X
  1080. X/* -------------------------------------------------------------------- */
  1081. X
  1082. Xstatic string           digest_to_hex ();
  1083. Xstatic word             test_md4 ();
  1084. Xstatic word             test_md5 ();
  1085. Xstatic word             test_shs ();
  1086. Xstatic word             test_haval ();
  1087. X
  1088. X/* -------------------------------------------------------------------- */
  1089. X
  1090. Xtypedef struct
  1091. X  {
  1092. X    string              ident;
  1093. X    word                (*test)();
  1094. X  } test_func;
  1095. X
  1096. Xtest_func               testable_mds[] =
  1097. X  {
  1098. X    { "md4",            test_md4 },
  1099. X    { "md5",            test_md5 },
  1100. X    { "shs",            test_shs },
  1101. X    { "haval",          test_haval },
  1102. X    { NULL,             NULL     },
  1103. X  };
  1104. X
  1105. X/* -------------------------------------------------------------------- */
  1106. X/* function    : main                                                   */
  1107. X/* -------------------------------------------------------------------- */
  1108. Xvoid
  1109. Xmain (argc, argv)
  1110. X    int             argc;
  1111. X    char**          argv;
  1112. X{
  1113. X    word            c;
  1114. X    word            s;
  1115. X    md_ctx          ctx;
  1116. X    char            ident[ident_sz+1];
  1117. X
  1118. X    /* ---------------------------------------------------------------- */
  1119. X    /* open the module and try to test whatever is available            */
  1120. X    /* ---------------------------------------------------------------- */
  1121. X
  1122. X    md_mod_open ();
  1123. X
  1124. X    md_list_init (&s);
  1125. X    while (md_list_next (&s, ident) == err_ok)
  1126. X      {
  1127. X        printf ("%-8s : ", ident);
  1128. X
  1129. X        for (c = 0; testable_mds[c].ident != NULL &&
  1130. X                    strcasecmp(ident, testable_mds[c].ident) != 0; c++)
  1131. X          ;
  1132. X
  1133. X        if (testable_mds[c].ident == NULL)
  1134. X          {
  1135. X            printf ("no test suite exists.\n");
  1136. X            continue;
  1137. X          }
  1138. X
  1139. X        /* ------------------------------------------------------------ */
  1140. X        /* create an association for that particular message digest     */
  1141. X        /* ------------------------------------------------------------ */
  1142. X
  1143. X        if (md_open (&ctx, ident) != err_ok)
  1144. X          {
  1145. X            printf ("internal error.\n");
  1146. X            exit (1);
  1147. X          }
  1148. X
  1149. X        /* ------------------------------------------------------------ */
  1150. X        /* call it, and then close the association                      */
  1151. X        /* ------------------------------------------------------------ */
  1152. X
  1153. X        c = (*(testable_mds[c].test))(&ctx);
  1154. X
  1155. X        if (c == -1)
  1156. X          printf ("test(s) failed !\n");
  1157. X        else
  1158. X          printf ("%d test%s, all successfull.\n", c, (c == 1) ?"":"s");
  1159. X
  1160. X        md_close (&ctx);
  1161. X
  1162. X      }
  1163. X
  1164. X    exit (0);
  1165. X}
  1166. X
  1167. X
  1168. X/* -------------------------------------------------------------------- */
  1169. X/* function    : digest_to_hex                                          */
  1170. X/* description : format a digest into a hex string                      */
  1171. X/* -------------------------------------------------------------------- */
  1172. Xstatic string
  1173. Xdigest_to_hex (digest, sz)
  1174. X    opaque          digest;         /* bytes of digest                  */
  1175. X    word            sz;             /* # bytes in digest                */
  1176. X{
  1177. X    static char     hex_str[81];
  1178. X    word            c;
  1179. X
  1180. X    for (c = 0; c < sz; c++)
  1181. X      sprintf (&hex_str[c<<1], "%02x", (digest[c] & 0xff));
  1182. X
  1183. X    hex_str[c<<1] = '\0';
  1184. X    return (hex_str);
  1185. X}
  1186. X
  1187. X/* -------------------------------------------------------------------- */
  1188. X/* -------------------------------------------------------------------- */
  1189. X/* place test routines/structures/info from here onwards ...            */
  1190. X/* -------------------------------------------------------------------- */
  1191. X/* -------------------------------------------------------------------- */
  1192. X
  1193. Xtypedef struct
  1194. X  {
  1195. X    string              test;
  1196. X    string              result;
  1197. X  } test_set;
  1198. X
  1199. Xchar                    digest[64];
  1200. Xstring                  hdigest;
  1201. X
  1202. X/* -------------------------------------------------------------------- */
  1203. X/* function    : check_test_set                                         */
  1204. X/* description : check all items in a test_set                          */
  1205. X/* -------------------------------------------------------------------- */
  1206. XSTATIC word
  1207. Xcheck_test_set (ctx, tset)
  1208. X    md_ctx*         ctx;
  1209. X    test_set        tset[];
  1210. X{
  1211. X    word            c;
  1212. X
  1213. X    for (c = 0; tset[c].test != NULL; c++)
  1214. X      {
  1215. X        md_init (ctx);
  1216. X        md_update (ctx, tset[c].test, strlen(tset[c].test));
  1217. X        md_final (ctx, digest);
  1218. X
  1219. X        hdigest = digest_to_hex (digest, md_hash_sz (ctx));
  1220. X
  1221. X        if (strcmp (hdigest, tset[c].result) != 0)
  1222. X          return -1;
  1223. X      }
  1224. X
  1225. X    return c;
  1226. X}
  1227. X
  1228. X
  1229. X/* -------------------------------------------------------------------- */
  1230. X/* message-digest 4 test suite from RFC-1186                            */
  1231. X/* -------------------------------------------------------------------- */
  1232. X
  1233. Xstatic test_set         md4_tests[] =
  1234. X  {
  1235. X    { "",
  1236. X      "31d6cfe0d16ae931b73c59d7e0c089c0" },
  1237. X    { "a",
  1238. X      "bde52cb31de33e46245e05fbdbd6fb24" },
  1239. X    { "abc",
  1240. X      "a448017aaf21d8525fc10ae87aa6729d" },
  1241. X    { "message digest",
  1242. X      "d9130a8164549fe818874806e1c7014b" },
  1243. X    { "abcdefghijklmnopqrstuvwxyz",
  1244. X      "d79e1c308aa5bbcdeea8ed63df412da9" },
  1245. X    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
  1246. X      "043f8582f241db351ce627e153e7f0e4" },
  1247. X    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
  1248. X      "e33b4ddc9c38f2199c3e7b164fcc0536" },
  1249. X    { NULL,
  1250. X      NULL },
  1251. X  };
  1252. X
  1253. X/* -------------------------------------------------------------------- */
  1254. X/* function    : test_md4                                               */
  1255. X/* description : run through the md4 test suite                         */
  1256. X/* -------------------------------------------------------------------- */
  1257. XSTATIC word
  1258. Xtest_md4 (ctx)
  1259. X    md_ctx*         ctx;
  1260. X{
  1261. X    return  check_test_set (ctx, md4_tests);
  1262. X}
  1263. X
  1264. X
  1265. X/* -------------------------------------------------------------------- */
  1266. X/* message-digest 5 test suite from RFC-1321                            */
  1267. X/* -------------------------------------------------------------------- */
  1268. X
  1269. Xstatic test_set         md5_tests[] =
  1270. X  {
  1271. X    { "",
  1272. X      "d41d8cd98f00b204e9800998ecf8427e" },
  1273. X    { "a",
  1274. X      "0cc175b9c0f1b6a831c399e269772661" },
  1275. X    { "abc",
  1276. X      "900150983cd24fb0d6963f7d28e17f72" },
  1277. X    { "message digest",
  1278. X      "f96b697d7cb7938d525a2f31aaf161d0" },
  1279. X    { "abcdefghijklmnopqrstuvwxyz",
  1280. X      "c3fcd3d76192e4007dfb496cca67e13b" },
  1281. X    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
  1282. X      "d174ab98d277d9f5a5611c2c9f419d9f" },
  1283. X    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
  1284. X      "57edf4a22be3c955ac49da2e2107b67a" },
  1285. X    { NULL,
  1286. X      NULL },
  1287. X  };
  1288. X
  1289. X/* -------------------------------------------------------------------- */
  1290. X/* function    : test_md5                                               */
  1291. X/* description : run through the md5 test suite                         */
  1292. X/* -------------------------------------------------------------------- */
  1293. XSTATIC word
  1294. Xtest_md5 (ctx)
  1295. X    md_ctx*         ctx;
  1296. X{
  1297. X   return  check_test_set (ctx, md5_tests);
  1298. X}
  1299. X
  1300. X
  1301. X/* -------------------------------------------------------------------- */
  1302. X/* NIST shs test                                                        */
  1303. X/* -------------------------------------------------------------------- */
  1304. X
  1305. Xstatic test_set         shs_tests[] =
  1306. X  {
  1307. X    { "abc",
  1308. X      "0164b8a914cd2a5e74c4f7ff082c4d97f1edf880" },
  1309. X    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
  1310. X      "d2516ee1acfa5baf33dfc1c471e438449ef134c8" },
  1311. X    { NULL,
  1312. X      NULL },
  1313. X  };
  1314. X
  1315. X/* -------------------------------------------------------------------- */
  1316. X/* function    : test_shs                                               */
  1317. X/* description : go through NIST shs tests                              */
  1318. X/* -------------------------------------------------------------------- */
  1319. XSTATIC word
  1320. Xtest_shs (ctx)
  1321. X    md_ctx*         ctx;
  1322. X{
  1323. X    word            c;
  1324. X    word            i;
  1325. X    char            buf[1000];
  1326. X
  1327. X    c = check_test_set (ctx, shs_tests);
  1328. X
  1329. X    if (c == -1)
  1330. X      return -1;
  1331. X
  1332. X    /* ---------------------------------------------------------------- */
  1333. X    /* do 1million 'a's.                                                */
  1334. X    /* ---------------------------------------------------------------- */
  1335. X
  1336. X    memset (buf, 'a', 1000);
  1337. X
  1338. X    md_init (ctx);
  1339. X    for (i = 0; i < 1000; i++)
  1340. X      md_update (ctx, buf, 1000);
  1341. X    md_final (ctx, digest);
  1342. X
  1343. X    hdigest = digest_to_hex (digest, md_hash_sz (ctx));
  1344. X
  1345. X    if (strcmp (hdigest, "3232affa48628a26653b5aaa44541fd90d690603") != 0)
  1346. X      return -1;
  1347. X
  1348. X    return ++c;
  1349. X}
  1350. X
  1351. X
  1352. X/* -------------------------------------------------------------------- */
  1353. X/* function    : test_haval                                             */
  1354. X/* description : do haval test                                          */
  1355. X/* -- NOTE --  : this assumes the default pass3=,fptlen=128/160 setup!  */
  1356. X/* -------------------------------------------------------------------- */
  1357. XSTATIC word
  1358. Xtest_haval (ctx)
  1359. X    md_ctx*         ctx;
  1360. X{
  1361. X    string          test_f128 = "";
  1362. X    string          result_f128 = "1bdc556b29ad02ec09af8c66477f2a87";
  1363. X    string          test_f160 = "a";
  1364. X    string          result_f160 = "5e1610fced1d3adb0bb18e92ac2b11f0bd99d8ed";
  1365. X    string          t, r;
  1366. X
  1367. X
  1368. X    if (md_hash_sz (ctx) == (128>>3))
  1369. X      {
  1370. X        t = test_f128;
  1371. X        r = result_f128;
  1372. X      }
  1373. X    else if (md_hash_sz (ctx) == (160>>3))
  1374. X      {
  1375. X        t = test_f160;
  1376. X        r = result_f160;
  1377. X      }
  1378. X    else
  1379. X      return -1;
  1380. X      
  1381. X    md_init (ctx);
  1382. X    md_update (ctx, t, strlen (t));
  1383. X    md_final (ctx, digest);
  1384. X
  1385. X    hdigest = digest_to_hex (digest, md_hash_sz (ctx));
  1386. X
  1387. X    if (strcmp (hdigest, r) != 0)
  1388. X      return -1;
  1389. X
  1390. X    return 1;
  1391. X}
  1392. X
  1393. X/* -------------------------------------------------------------------- */
  1394. X
  1395. X
  1396. END_OF_FILE
  1397.   if test 11052 -ne `wc -c <'mtest.c'`; then
  1398.     echo shar: \"'mtest.c'\" unpacked with wrong size!
  1399.   fi
  1400.   # end of 'mtest.c'
  1401. fi
  1402. echo shar: End of archive 1 \(of 3\).
  1403. cp /dev/null ark1isdone
  1404. MISSING=""
  1405. for I in 1 2 3 ; do
  1406.     if test ! -f ark${I}isdone ; then
  1407.     MISSING="${MISSING} ${I}"
  1408.     fi
  1409. done
  1410. if test "${MISSING}" = "" ; then
  1411.     echo You have unpacked all 3 archives.
  1412.     rm -f ark[1-9]isdone
  1413. else
  1414.     echo You still must unpack the following archives:
  1415.     echo "        " ${MISSING}
  1416. fi
  1417. exit 0
  1418. exit 0 # Just in case...
  1419.