2 * shsfile - old Secure Hash Standard
4 * @(#) $Revision: 13.3 $
5 * @(#) $Id: shsio.c,v 13.3 2006/08/14 11:25:24 chongo Exp $
6 * @(#) $Source: /usr/local/src/cmd/hash/RCS/shsio.c,v $
8 **************************************************************************
9 * This version implements the old Secure Hash Algorithm specified by *
10 * (FIPS Pub 180). This version is kept for backward compatibility with *
11 * shs version 2.10.1. See the shs utility for the new standard. *
12 **************************************************************************
14 * This file was written by Landon Curt Noll.
16 * This code has been placed in the public domain. Please do not
17 * copyright this code.
19 * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO
20 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MER-
21 * CHANTABILITY AND FITNESS. IN NO EVENT SHALL LANDON CURT
22 * NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
23 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
24 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
25 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 * chongo (was here) /\oo/\
29 * http://www.isthe.com/chongo/index.html
31 * Share and enjoy! :-)
33 * See shsdrvr.c for version and modification history.
41 #include <sys/resource.h>
45 /* global variables */
46 ULONG shs_zero
[SHS_CHUNKWORDS
]; /* block of zeros */
50 * shsStream - digest a open file stream
53 * pre_str data prefix or NULL
54 * pre_len length of pre_str
55 * stream the stream to process
59 shsStream(BYTE
*pre_str
, UINT pre_len
, FILE *stream
, SHS_INFO
*dig
)
61 BYTE data
[SHS_READSIZE
]; /* our read buffer */
62 unsigned int bytes
; /* bytes last read */
63 int ret
; /* partial fread return value */
66 * pre-process prefix if needed
68 if (pre_str
!= NULL
&& pre_len
> 0) {
69 shsUpdate(dig
, pre_str
, pre_len
);
73 * Try to read as much as we can (up to SHS_READSIZE bytes). If there
74 * is data in the hash buffer already, try to read so that we can
75 * perform as many full hash operations as possible.
81 /* determine what we have so far */
84 /* try to read what we need to fill the chunk */
85 while (!feof(stream
) && bytes
< SHS_READSIZE
) {
87 /* try to read what we need */
90 fprintf(stderr
, "DEBUG: have: %u will try to read: %u\n",
91 bytes
, SHS_READSIZE
-bytes
);
94 ret
= fread(data
+bytes
, 1, SHS_READSIZE
-bytes
, stream
);
97 fprintf(stderr
, "DEBUG: fread returrned: %d\n", ret
);
101 /* look read for errors */
102 if (ret
< 0 || ferror(stream
)) {
103 /* error processing */
104 fprintf(stderr
, "%s: ", program
);
105 perror("shs read error");
109 /* note that we have more bytes */
113 /* process whatever new data we have in the buffer */
114 if (bytes
> dig
->datalen
) {
115 shsUpdate(dig
, data
+dig
->datalen
, bytes
-dig
->datalen
);
117 } while (ret
> 0 && !feof(stream
));
123 * shsFile - digest a file
126 * pre_str string prefix or NULL
127 * pre_len length of pre_str
128 * filename the filename to process
129 * inode 1 => process inode & filename
133 shsFile(BYTE
*pre_str
, UINT pre_len
, char *filename
,
134 int inode
, SHS_INFO
*dig
)
136 FILE *inFile
; /* the open file stream */
137 struct stat buf
; /* stat or lstat of file */
138 struct shs_stat hashbuf
; /* stat data to digest */
139 struct shs_stat hashlbuf
; /* lstat data to digest */
140 ULONG filename_len
; /* length of the filename */
145 inFile
= fopen(filename
, "rb");
146 if (inFile
== NULL
) {
147 fprintf(stderr
, "%s: cannot open %s: ", program
, filename
);
153 * pre-process prefix if needed
155 if (pre_str
== NULL
) {
157 filename_len
= strlen(filename
);
158 shsUpdate(dig
, (BYTE
*)filename
, filename_len
);
162 "DEBUG: filename_len:%lu octets:%llu\n",
163 (unsigned long)filename_len
, dig
->octets
);
169 shsUpdate(dig
, pre_str
, pre_len
);
170 filename_len
= strlen(filename
);
171 shsUpdate(dig
, (BYTE
*)filename
, filename_len
);
175 "DEBUG: pre_len:%lu filename_len:%lu octets:%lld\n",
176 (unsigned long)pre_len
,
177 (unsigned long)filename_len
, dig
->octets
);
181 shsUpdate(dig
, pre_str
, pre_len
);
186 * digest file stat and lstat
189 if (fstat(fileno(inFile
), &buf
) < 0) {
190 printf("%s can't be stated.\n", filename
);
193 hashbuf
.stat_dev
= buf
.st_dev
;
194 hashbuf
.stat_ino
= buf
.st_ino
;
195 hashbuf
.stat_mode
= buf
.st_mode
;
196 hashbuf
.stat_nlink
= buf
.st_nlink
;
197 hashbuf
.stat_uid
= buf
.st_uid
;
198 hashbuf
.stat_gid
= buf
.st_gid
;
199 hashbuf
.stat_size
= buf
.st_size
;
200 hashbuf
.stat_mtime
= buf
.st_mtime
;
201 hashbuf
.stat_ctime
= buf
.st_ctime
;
205 "DEBUG: dev:%ld ino:%ld mode:%o nlink:%d uid:%d gid:%d\n",
206 (unsigned long)hashbuf
.stat_dev
,
207 (unsigned long)hashbuf
.stat_ino
,
208 hashbuf
.stat_mode
, hashbuf
.stat_nlink
,
209 hashbuf
.stat_uid
, hashbuf
.stat_gid
);
211 "DEBUG: size:%llu mtime:%llu ctime:%llu\n",
212 (unsigned long long)hashbuf
.stat_size
,
213 (unsigned long long)hashbuf
.stat_mtime
,
214 (unsigned long long)hashbuf
.stat_ctime
);
217 shsUpdate(dig
, (BYTE
*)&hashbuf
, sizeof(hashbuf
));
218 if (lstat(filename
, &buf
) < 0) {
219 printf("%s can't be lstated.\n", filename
);
222 hashlbuf
.stat_dev
= buf
.st_dev
;
223 hashlbuf
.stat_ino
= buf
.st_ino
;
224 hashlbuf
.stat_mode
= buf
.st_mode
;
225 hashlbuf
.stat_nlink
= buf
.st_nlink
;
226 hashlbuf
.stat_uid
= buf
.st_uid
;
227 hashlbuf
.stat_gid
= buf
.st_gid
;
228 hashlbuf
.stat_size
= buf
.st_size
;
229 hashlbuf
.stat_mtime
= buf
.st_mtime
;
230 hashlbuf
.stat_ctime
= buf
.st_ctime
;
234 "DEBUG: ldev:%ld lino:%ld mode:%o lnlink:%d luid:%d lgid:%d\n",
235 (unsigned long)hashbuf
.stat_dev
,
236 (unsigned long)hashbuf
.stat_ino
,
237 hashlbuf
.stat_mode
, hashlbuf
.stat_nlink
,
238 hashlbuf
.stat_uid
, hashlbuf
.stat_gid
);
240 "DEBUG: lsize:%llu lmtime:%llu lctime:%llu\n",
241 (unsigned long long)hashlbuf
.stat_size
,
242 (unsigned long long)hashlbuf
.stat_mtime
,
243 (unsigned long long)hashbuf
.stat_ctime
);
246 shsUpdate(dig
, (BYTE
*)&hashlbuf
, sizeof(hashlbuf
));
249 * pad with zeros to process file data faster
251 if (dig
->datalen
> 0) {
255 "DEBUG: pad_len:%lu\n",
256 (unsigned long)(SHS_CHUNKSIZE
- dig
->datalen
));
259 shsUpdate(dig
, (BYTE
*)shs_zero
, SHS_CHUNKSIZE
- dig
->datalen
);
263 fprintf(stderr
, "DEBUG: datalen:%lu count:%llu\n",
264 (unsigned long)dig
->datalen
, dig
->octets
);
270 * process the data stream
272 shsStream(NULL
, 0, inFile
, dig
);