zlib-streams 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,91 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025-2026, Gildas Lormeau
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ ---
31
+
32
+ This software includes zlib (src/zlib) and altered versions of zlib sources
33
+ (src/deflate.c, src/deflate.h, src/inflate.c, src/inflate.h, src/inftrees.c,
34
+ src/inffast.h, src/trees.c, with deflate64 support added), which are
35
+ distributed under the zlib license:
36
+
37
+ Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
38
+
39
+ This software is provided 'as-is', without any express or implied
40
+ warranty. In no event will the authors be held liable for any damages
41
+ arising from the use of this software.
42
+
43
+ Permission is granted to anyone to use this software for any purpose,
44
+ including commercial applications, and to alter it and redistribute it
45
+ freely, subject to the following restrictions:
46
+
47
+ 1. The origin of this software must not be misrepresented; you must not
48
+ claim that you wrote the original software. If you use this software
49
+ in a product, an acknowledgment in the product documentation would be
50
+ appreciated but is not required.
51
+ 2. Altered source versions must be plainly marked as such, and must not be
52
+ misrepresented as being the original software.
53
+ 3. This notice may not be removed or altered from any source distribution.
54
+
55
+ Jean-loup Gailly Mark Adler
56
+ jloup@gzip.org madler@alumni.caltech.edu
57
+
58
+ ---
59
+
60
+ src/chunkcopy.h, src/compare256.h, src/cpu_features.h, src/inffast_chunk.c,
61
+ src/inffast_chunk.h and src/insert_string.h come from the zlib fork of the
62
+ Chromium project (Copyright 2017 ARM, Inc. for the chunk copy code), and are
63
+ distributed under the Chromium license:
64
+
65
+ Copyright 2015 The Chromium Authors
66
+
67
+ Redistribution and use in source and binary forms, with or without
68
+ modification, are permitted provided that the following conditions are
69
+ met:
70
+
71
+ * Redistributions of source code must retain the above copyright
72
+ notice, this list of conditions and the following disclaimer.
73
+ * Redistributions in binary form must reproduce the above
74
+ copyright notice, this list of conditions and the following disclaimer
75
+ in the documentation and/or other materials provided with the
76
+ distribution.
77
+ * Neither the name of Google LLC nor the names of its
78
+ contributors may be used to endorse or promote products derived from
79
+ this software without specific prior written permission.
80
+
81
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
82
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
83
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
84
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
85
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
86
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
87
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
88
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
89
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
90
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
91
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/Makefile CHANGED
@@ -152,7 +152,8 @@ WASM_EXPORTED_FUNCTIONS = "_inflate9_new","_inflate9_init","_inflate9_init_raw",
152
152
  WASM_CFLAGS = -Isrc -Isrc/zlib -Isrc/zlib/contrib/infback9 -O2 -flto -DDYNAMIC_CRC_TABLE -DBUILDFIXED -DZ_SOLO $(WASM_CRC_CFLAGS) $(WASM_DEFLATE_CFLAGS) $(INFLATE_CHUNK_CFLAGS)
153
153
 
154
154
  .PHONY: wasm
155
- wasm: dist/zlib-streams-dev.wasm
155
+ wasm:
156
+ @$(MAKE) -B dist/zlib-streams-dev.wasm
156
157
 
157
158
  .PHONY: wasm_traced
158
159
  wasm_traced: dist/zlib-streams_traced.wasm
@@ -307,7 +308,8 @@ dist/zlib-streams-dev.wasm: $(WASM_SRCS)
307
308
 
308
309
  # Production-optimized wasm: smaller build with -Oz and no extra runtime methods.
309
310
  .PHONY: wasm_prod
310
- wasm_prod: dist/zlib-streams.wasm
311
+ wasm_prod:
312
+ @$(MAKE) -B dist/zlib-streams.wasm
311
313
 
312
314
  dist/zlib-streams.wasm: $(WASM_SRCS)
313
315
  @echo "Building production wasm $@ using $(EMCC)"
@@ -328,7 +330,8 @@ ZIP_MODULE_SRCS = src/wasm/aes_hmac_wasm.c
328
330
  ZIP_MODULE_EXPORTED_FUNCTIONS = $(WASM_EXPORTED_FUNCTIONS),"_aes_hmac_new","_aes_hmac_init","_aes_hmac_process","_aes_hmac_end"
329
331
 
330
332
  .PHONY: zip_module
331
- zip_module: dist/zip-module.wasm
333
+ zip_module:
334
+ @$(MAKE) -B dist/zip-module.wasm
332
335
 
333
336
  dist/zip-module.wasm: $(WASM_SRCS) $(ZIP_MODULE_SRCS)
334
337
  @echo "Building zip.js module $@ using $(EMCC)"
package/README.md CHANGED
@@ -19,24 +19,28 @@ git submodule update --init --recursive
19
19
  ```
20
20
 
21
21
  ### 2. Build WASM module
22
- - Developmeent
22
+ The build needs the Emscripten SDK. The Makefile looks for it in `emsdk/` at the repository root (ignored by git) and can be pointed elsewhere with `make EMCC=... WASM_OPT=...`.
23
+
24
+ - Development: `-O2`, used by the test targets. Do not benchmark or ship this file.
23
25
  ```sh
24
26
  make wasm
25
27
  ```
26
28
  Output: `dist/zlib-streams-dev.wasm` and `dist/zlib-streams.js`
27
29
 
28
- - Production
30
+ - Production: `-Oz` plus `wasm-opt`. This is the published module.
29
31
  ```sh
30
32
  make wasm_prod
31
33
  ```
32
34
  Output: `dist/zlib-streams.wasm` and `dist/zlib-streams.js`
33
35
 
34
- - zip.js module: the codecs plus the AES-CTR/HMAC-SHA1 engine behind the encrypted entries of zip.js
36
+ - zip.js module: the codecs plus the AES-CTR/HMAC-SHA1 engine behind the encrypted entries of zip.js, vendored by zip.js as `lib/core/streams/zlib-wasm/zlib-streams.wasm`.
35
37
  ```sh
36
38
  make zip_module
37
39
  make test_zip_module
38
40
  ```
39
41
  Output: `dist/zip-module.wasm`
40
42
 
43
+ The files in `dist/` are tracked, so a checkout leaves them with the same timestamp as the sources and `make dist/<file>` reports them up to date even when the sources changed. The three targets above always rebuild their file; the test targets depend on the file rules and rebuild only when a source is newer. Rebuild and commit `dist/` in the same commit as a change to `src/`.
44
+
41
45
  ## License
42
46
  See LICENSE for details.
Binary file
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "WASM-based Compression Streams API implementation using zlib, with support for deflate64 decompression.",
4
4
  "author": "Gildas Lormeau",
5
5
  "license": "BSD-3-Clause",
6
- "version": "1.2.0",
6
+ "version": "1.2.1",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "deflate",
@@ -2,7 +2,8 @@
2
2
  little-endian integer starting at 1, and HMAC-SHA1 over the ciphertext. Forward-only T-table
3
3
  AES, the aes_core.c layout. One context per stream: init() takes the cipher key and the
4
4
  authentication key, process() works in place and takes whole 16-byte blocks except for the last
5
- call, end() writes the 20-byte MAC when given an output pointer and frees the context. */
5
+ call, end() writes the 20-byte MAC when given an output pointer, clears sensitive state, and
6
+ frees the context. */
6
7
  #include <stdlib.h>
7
8
  #include <string.h>
8
9
  #include <stdint.h>
@@ -15,11 +16,11 @@
15
16
  struct aes_hmac_ctx {
16
17
  uint32_t round_keys[ROUND_KEYS_LENGTH];
17
18
  int rounds;
18
- uint8_t counter[BLOCK_LENGTH];
19
- uint32_t h[5];
20
- uint8_t block[SHA1_BLOCK_LENGTH];
21
- unsigned block_length;
22
- uint64_t total_length;
19
+ /* 64-bit WinZip counter followed by eight zero bytes; wasm32 is little-endian. */
20
+ uint64_t counter[2];
21
+ uint32_t sha1_state[5];
22
+ uint64_t sha1_count;
23
+ uint8_t sha1_buffer[SHA1_BLOCK_LENGTH];
23
24
  uint8_t opad[SHA1_BLOCK_LENGTH];
24
25
  };
25
26
 
@@ -40,6 +41,15 @@ static void store_be32(uint8_t *p, uint32_t v) {
40
41
  p[3] = (uint8_t)v;
41
42
  }
42
43
 
44
+ /* Volatile stores keep LTO from removing the wipe before free(). */
45
+ __attribute__((noinline, minsize))
46
+ static void secure_clear(void *ptr, size_t length) {
47
+ volatile uint8_t *p = (volatile uint8_t *)ptr;
48
+ while (length--) {
49
+ *p++ = 0;
50
+ }
51
+ }
52
+
43
53
  static void init_tables(void) {
44
54
  uint8_t p = 1, q = 1;
45
55
  do {
@@ -93,122 +103,185 @@ static void encrypt_block(const struct aes_hmac_ctx *c, const uint8_t in[BLOCK_L
93
103
  uint32_t s0 = load_be32(in) ^ rk[0], s1 = load_be32(in + 4) ^ rk[1];
94
104
  uint32_t s2 = load_be32(in + 8) ^ rk[2], s3 = load_be32(in + 12) ^ rk[3];
95
105
  uint32_t t0, t1, t2, t3;
96
- rk += 4;
97
- for (int r = 1; r < c->rounds; r++) {
98
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 255] ^ Te2[(s2 >> 8) & 255] ^ Te3[s3 & 255] ^ rk[0];
99
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 255] ^ Te2[(s3 >> 8) & 255] ^ Te3[s0 & 255] ^ rk[1];
100
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 255] ^ Te2[(s0 >> 8) & 255] ^ Te3[s1 & 255] ^ rk[2];
101
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 255] ^ Te2[(s1 >> 8) & 255] ^ Te3[s2 & 255] ^ rk[3];
102
- s0 = t0;
103
- s1 = t1;
104
- s2 = t2;
105
- s3 = t3;
106
- rk += 4;
106
+ #define AES_ROUND(O0, O1, O2, O3, I0, I1, I2, I3, K) do { \
107
+ (O0) = Te0[(I0) >> 24] ^ Te1[((I1) >> 16) & 255] ^ Te2[((I2) >> 8) & 255] ^ Te3[(I3) & 255] ^ (K)[0]; \
108
+ (O1) = Te0[(I1) >> 24] ^ Te1[((I2) >> 16) & 255] ^ Te2[((I3) >> 8) & 255] ^ Te3[(I0) & 255] ^ (K)[1]; \
109
+ (O2) = Te0[(I2) >> 24] ^ Te1[((I3) >> 16) & 255] ^ Te2[((I0) >> 8) & 255] ^ Te3[(I1) & 255] ^ (K)[2]; \
110
+ (O3) = Te0[(I3) >> 24] ^ Te1[((I0) >> 16) & 255] ^ Te2[((I1) >> 8) & 255] ^ Te3[(I2) & 255] ^ (K)[3]; \
111
+ } while (0)
112
+ AES_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, rk + 4);
113
+ AES_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, rk + 8);
114
+ AES_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, rk + 12);
115
+ AES_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, rk + 16);
116
+ AES_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, rk + 20);
117
+ AES_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, rk + 24);
118
+ AES_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, rk + 28);
119
+ AES_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, rk + 32);
120
+ AES_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, rk + 36);
121
+ rk += 40;
122
+ if (c->rounds > 10) {
123
+ AES_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, rk);
124
+ AES_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, rk + 4);
125
+ rk += 8;
107
126
  }
108
- store_be32(out, (((uint32_t)sbox[s0 >> 24] << 24) | ((uint32_t)sbox[(s1 >> 16) & 255] << 16) | ((uint32_t)sbox[(s2 >> 8) & 255] << 8) | sbox[s3 & 255]) ^ rk[0]);
109
- store_be32(out + 4, (((uint32_t)sbox[s1 >> 24] << 24) | ((uint32_t)sbox[(s2 >> 16) & 255] << 16) | ((uint32_t)sbox[(s3 >> 8) & 255] << 8) | sbox[s0 & 255]) ^ rk[1]);
110
- store_be32(out + 8, (((uint32_t)sbox[s2 >> 24] << 24) | ((uint32_t)sbox[(s3 >> 16) & 255] << 16) | ((uint32_t)sbox[(s0 >> 8) & 255] << 8) | sbox[s1 & 255]) ^ rk[2]);
111
- store_be32(out + 12, (((uint32_t)sbox[s3 >> 24] << 24) | ((uint32_t)sbox[(s0 >> 16) & 255] << 16) | ((uint32_t)sbox[(s1 >> 8) & 255] << 8) | sbox[s2 & 255]) ^ rk[3]);
127
+ if (c->rounds > 12) {
128
+ AES_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, rk);
129
+ AES_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, rk + 4);
130
+ rk += 8;
131
+ }
132
+ #undef AES_ROUND
133
+ store_be32(out, (Te2[t0 >> 24] & 0xff000000) ^ (Te3[(t1 >> 16) & 255] & 0x00ff0000) ^
134
+ (Te0[(t2 >> 8) & 255] & 0x0000ff00) ^ (Te1[t3 & 255] & 0x000000ff) ^ rk[0]);
135
+ store_be32(out + 4, (Te2[t1 >> 24] & 0xff000000) ^ (Te3[(t2 >> 16) & 255] & 0x00ff0000) ^
136
+ (Te0[(t3 >> 8) & 255] & 0x0000ff00) ^ (Te1[t0 & 255] & 0x000000ff) ^ rk[1]);
137
+ store_be32(out + 8, (Te2[t2 >> 24] & 0xff000000) ^ (Te3[(t3 >> 16) & 255] & 0x00ff0000) ^
138
+ (Te0[(t0 >> 8) & 255] & 0x0000ff00) ^ (Te1[t1 & 255] & 0x000000ff) ^ rk[2]);
139
+ store_be32(out + 12, (Te2[t3 >> 24] & 0xff000000) ^ (Te3[(t0 >> 16) & 255] & 0x00ff0000) ^
140
+ (Te0[(t1 >> 8) & 255] & 0x0000ff00) ^ (Te1[t2 & 255] & 0x000000ff) ^ rk[3]);
112
141
  }
113
142
 
114
- static void sha1_block(struct aes_hmac_ctx *c, const uint8_t *p) {
115
- uint32_t w[80];
116
- for (int i = 0; i < 16; i++) {
117
- w[i] = load_be32(p + 4 * i);
118
- }
119
- for (int i = 16; i < 80; i++) {
120
- w[i] = rotl(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
121
- }
122
- uint32_t a = c->h[0], b = c->h[1], cc = c->h[2], d = c->h[3], e = c->h[4], t;
123
- for (int i = 0; i < 20; i++) {
124
- t = rotl(a, 5) + ((b & cc) | (~b & d)) + e + 0x5A827999 + w[i];
125
- e = d;
126
- d = cc;
127
- cc = rotl(b, 30);
128
- b = a;
129
- a = t;
130
- }
131
- for (int i = 20; i < 40; i++) {
132
- t = rotl(a, 5) + (b ^ cc ^ d) + e + 0x6ED9EBA1 + w[i];
133
- e = d;
134
- d = cc;
135
- cc = rotl(b, 30);
136
- b = a;
137
- a = t;
138
- }
139
- for (int i = 40; i < 60; i++) {
140
- t = rotl(a, 5) + ((b & cc) | (b & d) | (cc & d)) + e + 0x8F1BBCDC + w[i];
141
- e = d;
142
- d = cc;
143
- cc = rotl(b, 30);
144
- b = a;
145
- a = t;
146
- }
147
- for (int i = 60; i < 80; i++) {
148
- t = rotl(a, 5) + (b ^ cc ^ d) + e + 0xCA62C1D6 + w[i];
149
- e = d;
150
- d = cc;
151
- cc = rotl(b, 30);
152
- b = a;
153
- a = t;
154
- }
155
- c->h[0] += a;
156
- c->h[1] += b;
157
- c->h[2] += cc;
158
- c->h[3] += d;
159
- c->h[4] += e;
143
+ /*
144
+ * SHA-1 in C
145
+ * By Steve Reid <steve@edmweb.com>
146
+ * 100% Public Domain
147
+ *
148
+ * Adapted from OpenSSH portable's openbsd-compat/sha1.c for this combined
149
+ * AES/HMAC context and the little-endian wasm32 target.
150
+ */
151
+ typedef union {
152
+ uint8_t c[SHA1_BLOCK_LENGTH];
153
+ uint32_t l[SHA1_BLOCK_LENGTH / sizeof(uint32_t)];
154
+ } sha1_block;
155
+
156
+ #define SHA1_ROL(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
157
+ /* wasm32 is little-endian, so the first 16 words need byte swapping. */
158
+ #define SHA1_BLK0(block, i) ((block).l[i] = \
159
+ (SHA1_ROL((block).l[i], 24) & 0xFF00FF00) | \
160
+ (SHA1_ROL((block).l[i], 8) & 0x00FF00FF))
161
+ #define SHA1_BLK(block, i) ((block).l[(i) & 15] = SHA1_ROL( \
162
+ (block).l[((i) + 13) & 15] ^ (block).l[((i) + 8) & 15] ^ \
163
+ (block).l[((i) + 2) & 15] ^ (block).l[(i) & 15], 1))
164
+ #define SHA1_R0(block, v, w, x, y, z, i) do { \
165
+ (z) += (((w) & ((x) ^ (y))) ^ (y)) + SHA1_BLK0((block), (i)) + \
166
+ 0x5A827999 + SHA1_ROL((v), 5); \
167
+ (w) = SHA1_ROL((w), 30); \
168
+ } while (0)
169
+ #define SHA1_R1(block, v, w, x, y, z, i) do { \
170
+ (z) += (((w) & ((x) ^ (y))) ^ (y)) + SHA1_BLK((block), (i)) + \
171
+ 0x5A827999 + SHA1_ROL((v), 5); \
172
+ (w) = SHA1_ROL((w), 30); \
173
+ } while (0)
174
+ #define SHA1_R2(block, v, w, x, y, z, i) do { \
175
+ (z) += ((w) ^ (x) ^ (y)) + SHA1_BLK((block), (i)) + \
176
+ 0x6ED9EBA1 + SHA1_ROL((v), 5); \
177
+ (w) = SHA1_ROL((w), 30); \
178
+ } while (0)
179
+ #define SHA1_R3(block, v, w, x, y, z, i) do { \
180
+ (z) += ((((w) | (x)) & (y)) | ((w) & (x))) + SHA1_BLK((block), (i)) + \
181
+ 0x8F1BBCDC + SHA1_ROL((v), 5); \
182
+ (w) = SHA1_ROL((w), 30); \
183
+ } while (0)
184
+ #define SHA1_R4(block, v, w, x, y, z, i) do { \
185
+ (z) += ((w) ^ (x) ^ (y)) + SHA1_BLK((block), (i)) + \
186
+ 0xCA62C1D6 + SHA1_ROL((v), 5); \
187
+ (w) = SHA1_ROL((w), 30); \
188
+ } while (0)
189
+
190
+ static void sha1_transform(uint32_t state[5], const uint8_t buffer[SHA1_BLOCK_LENGTH]) {
191
+ uint32_t a, b, c, d, e;
192
+ sha1_block block;
193
+
194
+ memcpy(&block, buffer, sizeof(block));
195
+ a = state[0];
196
+ b = state[1];
197
+ c = state[2];
198
+ d = state[3];
199
+ e = state[4];
200
+
201
+ SHA1_R0(block,a,b,c,d,e, 0); SHA1_R0(block,e,a,b,c,d, 1); SHA1_R0(block,d,e,a,b,c, 2); SHA1_R0(block,c,d,e,a,b, 3);
202
+ SHA1_R0(block,b,c,d,e,a, 4); SHA1_R0(block,a,b,c,d,e, 5); SHA1_R0(block,e,a,b,c,d, 6); SHA1_R0(block,d,e,a,b,c, 7);
203
+ SHA1_R0(block,c,d,e,a,b, 8); SHA1_R0(block,b,c,d,e,a, 9); SHA1_R0(block,a,b,c,d,e,10); SHA1_R0(block,e,a,b,c,d,11);
204
+ SHA1_R0(block,d,e,a,b,c,12); SHA1_R0(block,c,d,e,a,b,13); SHA1_R0(block,b,c,d,e,a,14); SHA1_R0(block,a,b,c,d,e,15);
205
+ SHA1_R1(block,e,a,b,c,d,16); SHA1_R1(block,d,e,a,b,c,17); SHA1_R1(block,c,d,e,a,b,18); SHA1_R1(block,b,c,d,e,a,19);
206
+ SHA1_R2(block,a,b,c,d,e,20); SHA1_R2(block,e,a,b,c,d,21); SHA1_R2(block,d,e,a,b,c,22); SHA1_R2(block,c,d,e,a,b,23);
207
+ SHA1_R2(block,b,c,d,e,a,24); SHA1_R2(block,a,b,c,d,e,25); SHA1_R2(block,e,a,b,c,d,26); SHA1_R2(block,d,e,a,b,c,27);
208
+ SHA1_R2(block,c,d,e,a,b,28); SHA1_R2(block,b,c,d,e,a,29); SHA1_R2(block,a,b,c,d,e,30); SHA1_R2(block,e,a,b,c,d,31);
209
+ SHA1_R2(block,d,e,a,b,c,32); SHA1_R2(block,c,d,e,a,b,33); SHA1_R2(block,b,c,d,e,a,34); SHA1_R2(block,a,b,c,d,e,35);
210
+ SHA1_R2(block,e,a,b,c,d,36); SHA1_R2(block,d,e,a,b,c,37); SHA1_R2(block,c,d,e,a,b,38); SHA1_R2(block,b,c,d,e,a,39);
211
+ SHA1_R3(block,a,b,c,d,e,40); SHA1_R3(block,e,a,b,c,d,41); SHA1_R3(block,d,e,a,b,c,42); SHA1_R3(block,c,d,e,a,b,43);
212
+ SHA1_R3(block,b,c,d,e,a,44); SHA1_R3(block,a,b,c,d,e,45); SHA1_R3(block,e,a,b,c,d,46); SHA1_R3(block,d,e,a,b,c,47);
213
+ SHA1_R3(block,c,d,e,a,b,48); SHA1_R3(block,b,c,d,e,a,49); SHA1_R3(block,a,b,c,d,e,50); SHA1_R3(block,e,a,b,c,d,51);
214
+ SHA1_R3(block,d,e,a,b,c,52); SHA1_R3(block,c,d,e,a,b,53); SHA1_R3(block,b,c,d,e,a,54); SHA1_R3(block,a,b,c,d,e,55);
215
+ SHA1_R3(block,e,a,b,c,d,56); SHA1_R3(block,d,e,a,b,c,57); SHA1_R3(block,c,d,e,a,b,58); SHA1_R3(block,b,c,d,e,a,59);
216
+ SHA1_R4(block,a,b,c,d,e,60); SHA1_R4(block,e,a,b,c,d,61); SHA1_R4(block,d,e,a,b,c,62); SHA1_R4(block,c,d,e,a,b,63);
217
+ SHA1_R4(block,b,c,d,e,a,64); SHA1_R4(block,a,b,c,d,e,65); SHA1_R4(block,e,a,b,c,d,66); SHA1_R4(block,d,e,a,b,c,67);
218
+ SHA1_R4(block,c,d,e,a,b,68); SHA1_R4(block,b,c,d,e,a,69); SHA1_R4(block,a,b,c,d,e,70); SHA1_R4(block,e,a,b,c,d,71);
219
+ SHA1_R4(block,d,e,a,b,c,72); SHA1_R4(block,c,d,e,a,b,73); SHA1_R4(block,b,c,d,e,a,74); SHA1_R4(block,a,b,c,d,e,75);
220
+ SHA1_R4(block,e,a,b,c,d,76); SHA1_R4(block,d,e,a,b,c,77); SHA1_R4(block,c,d,e,a,b,78); SHA1_R4(block,b,c,d,e,a,79);
221
+
222
+ state[0] += a;
223
+ state[1] += b;
224
+ state[2] += c;
225
+ state[3] += d;
226
+ state[4] += e;
227
+ a = b = c = d = e = 0;
160
228
  }
161
229
 
162
230
  static void sha1_init(struct aes_hmac_ctx *c) {
163
- c->h[0] = 0x67452301;
164
- c->h[1] = 0xEFCDAB89;
165
- c->h[2] = 0x98BADCFE;
166
- c->h[3] = 0x10325476;
167
- c->h[4] = 0xC3D2E1F0;
168
- c->block_length = 0;
169
- c->total_length = 0;
231
+ c->sha1_count = 0;
232
+ c->sha1_state[0] = 0x67452301;
233
+ c->sha1_state[1] = 0xEFCDAB89;
234
+ c->sha1_state[2] = 0x98BADCFE;
235
+ c->sha1_state[3] = 0x10325476;
236
+ c->sha1_state[4] = 0xC3D2E1F0;
170
237
  }
171
238
 
172
- static void sha1_update(struct aes_hmac_ctx *c, const uint8_t *p, unsigned length) {
173
- c->total_length += length;
174
- if (c->block_length) {
175
- unsigned n = SHA1_BLOCK_LENGTH - c->block_length;
176
- if (n > length) {
177
- n = length;
178
- }
179
- memcpy(c->block + c->block_length, p, n);
180
- c->block_length += n;
181
- p += n;
182
- length -= n;
183
- if (c->block_length == SHA1_BLOCK_LENGTH) {
184
- sha1_block(c, c->block);
185
- c->block_length = 0;
239
+ static void sha1_update(struct aes_hmac_ctx *c, const uint8_t *data, size_t length) {
240
+ size_t i, j;
241
+
242
+ j = (size_t)((c->sha1_count >> 3) & 63);
243
+ c->sha1_count += ((uint64_t)length << 3);
244
+ if (j + length > 63) {
245
+ memcpy(&c->sha1_buffer[j], data, (i = SHA1_BLOCK_LENGTH - j));
246
+ sha1_transform(c->sha1_state, c->sha1_buffer);
247
+ for (; i + 63 < length; i += SHA1_BLOCK_LENGTH) {
248
+ sha1_transform(c->sha1_state, &data[i]);
186
249
  }
250
+ j = 0;
251
+ } else {
252
+ i = 0;
187
253
  }
188
- while (length >= SHA1_BLOCK_LENGTH) {
189
- sha1_block(c, p);
190
- p += SHA1_BLOCK_LENGTH;
191
- length -= SHA1_BLOCK_LENGTH;
192
- }
193
- if (length) {
194
- memcpy(c->block, p, length);
195
- c->block_length = length;
196
- }
254
+ memcpy(&c->sha1_buffer[j], &data[i], length - i);
197
255
  }
198
256
 
199
257
  static void sha1_final(struct aes_hmac_ctx *c, uint8_t out[SHA1_DIGEST_LENGTH]) {
200
- uint64_t bits = c->total_length * 8;
201
- uint8_t padding[SHA1_BLOCK_LENGTH + 8] = { 0x80 };
202
- unsigned padding_length = (c->block_length < 56 ? 56 : 120) - c->block_length;
203
- for (int i = 0; i < 8; i++) {
204
- padding[padding_length + i] = (uint8_t)(bits >> (56 - 8 * i));
258
+ uint8_t final_count[8];
259
+
260
+ for (unsigned i = 0; i < 8; i++) {
261
+ final_count[i] = (uint8_t)((c->sha1_count >> ((7 - i) * 8)) & 255);
262
+ }
263
+ sha1_update(c, (const uint8_t *)"\200", 1);
264
+ while ((c->sha1_count & 504) != 448) {
265
+ sha1_update(c, (const uint8_t *)"\0", 1);
205
266
  }
206
- sha1_update(c, padding, padding_length + 8);
207
- for (int i = 0; i < 5; i++) {
208
- store_be32(out + 4 * i, c->h[i]);
267
+ sha1_update(c, final_count, sizeof(final_count));
268
+ for (unsigned i = 0; i < SHA1_DIGEST_LENGTH; i++) {
269
+ out[i] = (uint8_t)((c->sha1_state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
209
270
  }
271
+ secure_clear(c->sha1_state, sizeof(c->sha1_state));
272
+ secure_clear(c->sha1_buffer, sizeof(c->sha1_buffer));
273
+ c->sha1_count = 0;
210
274
  }
211
275
 
276
+ #undef SHA1_R4
277
+ #undef SHA1_R3
278
+ #undef SHA1_R2
279
+ #undef SHA1_R1
280
+ #undef SHA1_R0
281
+ #undef SHA1_BLK
282
+ #undef SHA1_BLK0
283
+ #undef SHA1_ROL
284
+
212
285
  static void hmac_init(struct aes_hmac_ctx *c, const uint8_t *key, unsigned length) {
213
286
  uint8_t ipad[SHA1_BLOCK_LENGTH], hashed_key[SHA1_DIGEST_LENGTH];
214
287
  if (length > SHA1_BLOCK_LENGTH) {
@@ -254,7 +327,7 @@ int aes_hmac_init(unsigned ctx, unsigned key_ptr, unsigned key_length, unsigned
254
327
  init_tables();
255
328
  }
256
329
  expand_key(c, (const uint8_t *)(uintptr_t)key_ptr, key_length);
257
- memset(c->counter, 0, BLOCK_LENGTH);
330
+ memset(c->counter, 0, sizeof(c->counter));
258
331
  hmac_init(c, (const uint8_t *)(uintptr_t)auth_ptr, auth_length);
259
332
  return 0;
260
333
  }
@@ -270,12 +343,8 @@ void aes_hmac_process(unsigned ctx, unsigned ptr, unsigned length, int decrypt)
270
343
  sha1_update(c, p, length);
271
344
  }
272
345
  for (unsigned i = 0; i < length; i += BLOCK_LENGTH) {
273
- for (int j = 0; j < BLOCK_LENGTH; j++) {
274
- if (++c->counter[j]) {
275
- break;
276
- }
277
- }
278
- encrypt_block(c, c->counter, (uint8_t *)keystream);
346
+ ++c->counter[0];
347
+ encrypt_block(c, (const uint8_t *)c->counter, (uint8_t *)keystream);
279
348
  if (length - i >= BLOCK_LENGTH) {
280
349
  memcpy(words, p + i, BLOCK_LENGTH);
281
350
  words[0] ^= keystream[0];
@@ -303,5 +372,6 @@ void aes_hmac_end(unsigned ctx, unsigned out_ptr) {
303
372
  if (out_ptr) {
304
373
  hmac_final(c, (uint8_t *)(uintptr_t)out_ptr);
305
374
  }
375
+ secure_clear(c, sizeof(*c));
306
376
  free(c);
307
377
  }