/src/wget/lib/sha1-stream.c
Line | Count | Source |
1 | | /* sha1.c - Functions to compute SHA1 message digest of files or |
2 | | memory blocks according to the NIST specification FIPS-180-1. |
3 | | |
4 | | Copyright (C) 2000-2001, 2003-2006, 2008-2026 Free Software Foundation, Inc. |
5 | | |
6 | | This file is free software: you can redistribute it and/or modify |
7 | | it under the terms of the GNU Lesser General Public License as |
8 | | published by the Free Software Foundation; either version 2.1 of the |
9 | | License, or (at your option) any later version. |
10 | | |
11 | | This file is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | GNU Lesser General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU Lesser General Public License |
17 | | along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
18 | | |
19 | | /* Written by Scott G. Miller |
20 | | Credits: |
21 | | Robert Klep <robert@ilse.nl> -- Expansion function fix |
22 | | */ |
23 | | |
24 | | #include <config.h> |
25 | | |
26 | | /* Specification. */ |
27 | | #include "sha1.h" |
28 | | |
29 | | #include <stdlib.h> |
30 | | |
31 | | #if USE_UNLOCKED_IO |
32 | | # include "unlocked-io.h" |
33 | | #endif |
34 | | |
35 | | #include "af_alg.h" |
36 | | |
37 | 0 | #define BLOCKSIZE 32768 |
38 | | #if BLOCKSIZE % 64 != 0 |
39 | | # error "invalid BLOCKSIZE" |
40 | | #endif |
41 | | |
42 | | /* Compute SHA1 message digest for bytes read from STREAM. The |
43 | | resulting message digest number will be written into the 20 bytes |
44 | | beginning at RESBLOCK. */ |
45 | | int |
46 | | sha1_stream (FILE *stream, void *resblock) |
47 | 0 | { |
48 | 0 | switch (afalg_stream (stream, "sha1", resblock, SHA1_DIGEST_SIZE)) |
49 | 0 | { |
50 | 0 | case 0: return 0; |
51 | 0 | case -EIO: return 1; |
52 | 0 | } |
53 | | |
54 | 0 | char *buffer = malloc (BLOCKSIZE + 72); |
55 | 0 | if (!buffer) |
56 | 0 | return 1; |
57 | | |
58 | 0 | struct sha1_ctx ctx; |
59 | 0 | sha1_init_ctx (&ctx); |
60 | 0 | size_t sum; |
61 | | |
62 | | /* Iterate over full file contents. */ |
63 | 0 | while (1) |
64 | 0 | { |
65 | | /* We read the file in blocks of BLOCKSIZE bytes. One call of the |
66 | | computation function processes the whole buffer so that with the |
67 | | next round of the loop another block can be read. */ |
68 | 0 | sum = 0; |
69 | | |
70 | | /* Read block. Take care for partial reads. */ |
71 | 0 | while (1) |
72 | 0 | { |
73 | | /* Either process a partial fread() from this loop, |
74 | | or the fread() in afalg_stream may have gotten EOF. |
75 | | We need to avoid a subsequent fread() as EOF may |
76 | | not be sticky. For details of such systems, see: |
77 | | https://sourceware.org/PR1190 */ |
78 | 0 | if (feof (stream)) |
79 | 0 | goto process_partial_block; |
80 | | |
81 | 0 | size_t n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); |
82 | |
|
83 | 0 | sum += n; |
84 | |
|
85 | 0 | if (sum == BLOCKSIZE) |
86 | 0 | break; |
87 | | |
88 | 0 | if (n == 0) |
89 | 0 | { |
90 | | /* Check for the error flag IFF N == 0, so that we don't |
91 | | exit the loop after a partial read due to e.g., EAGAIN |
92 | | or EWOULDBLOCK. */ |
93 | 0 | if (ferror (stream)) |
94 | 0 | { |
95 | 0 | free (buffer); |
96 | 0 | return 1; |
97 | 0 | } |
98 | 0 | goto process_partial_block; |
99 | 0 | } |
100 | 0 | } |
101 | | |
102 | | /* Process buffer with BLOCKSIZE bytes. Note that |
103 | | BLOCKSIZE % 64 == 0 |
104 | | */ |
105 | 0 | sha1_process_block (buffer, BLOCKSIZE, &ctx); |
106 | 0 | } |
107 | | |
108 | 0 | process_partial_block:; |
109 | | |
110 | | /* Process any remaining bytes. */ |
111 | 0 | if (sum > 0) |
112 | 0 | sha1_process_bytes (buffer, sum, &ctx); |
113 | | |
114 | | /* Construct result in desired memory. */ |
115 | 0 | sha1_finish_ctx (&ctx, resblock); |
116 | 0 | free (buffer); |
117 | 0 | return 0; |
118 | 0 | } |