zlib-streams 1.1.1 → 1.2.0

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/Makefile CHANGED
@@ -148,6 +148,7 @@ WASM_CRC_CFLAGS = -DZ_U4=unsigned -DZ_U8='unsigned long long' -DZ_TESTW=8
148
148
  # USE_ZLIB_RABIN_KARP_ROLLING_HASH turns Chromium's own hash OFF so the deflate stream
149
149
  # stays bit-for-bit what madler's deflate.c produces.
150
150
  WASM_DEFLATE_CFLAGS = -DDEFLATE_COMPARE256_64LE -DUSE_ZLIB_RABIN_KARP_ROLLING_HASH
151
+ WASM_EXPORTED_FUNCTIONS = "_inflate9_new","_inflate9_init","_inflate9_init_raw","_inflate9_process","_inflate9_end","_inflate9_last_consumed","_inflate_new","_inflate_init","_inflate_init_raw","_inflate_init_gzip","_inflate_process","_inflate_end","_inflate_last_consumed","_deflate_new","_deflate_init","_deflate_init_raw","_deflate_init_gzip","_deflate_process","_deflate_end","_deflate_last_consumed","_malloc","_free"
151
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)
152
153
 
153
154
  .PHONY: wasm
@@ -160,7 +161,7 @@ dist/zlib-streams_traced.wasm: $(WASM_SRCS)
160
161
  @echo "Building traced $@ using $(EMCC)"
161
162
  @mkdir -p dist
162
163
  $(EMCC) $(WASM_SRCS) $(WASM_CFLAGS) $(DEBUG_DEFINES_TRACED) -s WASM=1 -s STANDALONE_WASM=1 --no-entry \
163
- -s EXPORTED_FUNCTIONS='["_inflate9_new","_inflate9_init","_inflate9_init_raw","_inflate9_process","_inflate9_end","_inflate9_last_consumed","_inflate_new","_inflate_init","_inflate_init_raw","_inflate_init_gzip","_inflate_process","_inflate_end","_inflate_last_consumed","_deflate_new","_deflate_init","_deflate_init_raw","_deflate_init_gzip","_deflate_process","_deflate_end","_deflate_last_consumed","_malloc","_free"]' \
164
+ -s EXPORTED_FUNCTIONS='[$(WASM_EXPORTED_FUNCTIONS)]' \
164
165
  -o $@
165
166
 
166
167
  # Run reference C and WASM test suites over payloads in test/ref-data
@@ -300,7 +301,7 @@ dist/zlib-streams-dev.wasm: $(WASM_SRCS)
300
301
  @echo "Building $@ using $(EMCC)"
301
302
  @mkdir -p dist
302
303
  $(EMCC) $(WASM_SRCS) $(WASM_CFLAGS) -s WASM=1 -s STANDALONE_WASM=1 --no-entry \
303
- -s EXPORTED_FUNCTIONS='["_inflate9_new","_inflate9_init","_inflate9_init_raw","_inflate9_process","_inflate9_end","_inflate9_last_consumed","_inflate_new","_inflate_init","_inflate_init_raw","_inflate_init_gzip","_inflate_process","_inflate_end","_inflate_last_consumed","_deflate_new","_deflate_init","_deflate_init_raw","_deflate_init_gzip","_deflate_process","_deflate_end","_deflate_last_consumed","_malloc","_free"]' \
304
+ -s EXPORTED_FUNCTIONS='[$(WASM_EXPORTED_FUNCTIONS)]' \
304
305
  -o $@
305
306
  cp src/wasm/api/zlib-streams.js dist/zlib-streams.js
306
307
 
@@ -313,11 +314,35 @@ dist/zlib-streams.wasm: $(WASM_SRCS)
313
314
  @mkdir -p dist
314
315
  $(EMCC) $(WASM_SRCS) $(WASM_CFLAGS) -Oz -flto -s WASM=1 -s STANDALONE_WASM=1 --no-entry \
315
316
  -s FILESYSTEM=0 -s DISABLE_EXCEPTION_CATCHING=1 \
316
- -s EXPORTED_FUNCTIONS='["_inflate9_new","_inflate9_init","_inflate9_init_raw","_inflate9_process","_inflate9_end","_inflate9_last_consumed","_inflate_new","_inflate_init","_inflate_init_raw","_inflate_init_gzip","_inflate_process","_inflate_end","_inflate_last_consumed","_deflate_new","_deflate_init","_deflate_init_raw","_deflate_init_gzip","_deflate_process","_deflate_end","_deflate_last_consumed","_malloc","_free"]' \
317
+ -s EXPORTED_FUNCTIONS='[$(WASM_EXPORTED_FUNCTIONS)]' \
317
318
  -o $@
318
319
  cp src/wasm/api/zlib-streams.js dist/zlib-streams.js
319
320
  @test -x $(WASM_OPT) && { echo "Running wasm-opt -Oz --enable-bulk-memory-opt"; $(WASM_OPT) -Oz --enable-bulk-memory-opt -o $@ $@ || true; } || true
320
321
 
322
+ # -----------------------------------------------------------------------------
323
+ # zip.js module: the zlib codecs plus the AES-CTR/HMAC-SHA1 engine behind its
324
+ # encrypted entries (src/wasm/aes_hmac_wasm.c), vendored by zip.js as
325
+ # lib/core/streams/zlib-wasm/zlib-streams.wasm
326
+ # -----------------------------------------------------------------------------
327
+ ZIP_MODULE_SRCS = src/wasm/aes_hmac_wasm.c
328
+ ZIP_MODULE_EXPORTED_FUNCTIONS = $(WASM_EXPORTED_FUNCTIONS),"_aes_hmac_new","_aes_hmac_init","_aes_hmac_process","_aes_hmac_end"
329
+
330
+ .PHONY: zip_module
331
+ zip_module: dist/zip-module.wasm
332
+
333
+ dist/zip-module.wasm: $(WASM_SRCS) $(ZIP_MODULE_SRCS)
334
+ @echo "Building zip.js module $@ using $(EMCC)"
335
+ @mkdir -p dist
336
+ $(EMCC) $(WASM_SRCS) $(ZIP_MODULE_SRCS) $(WASM_CFLAGS) -Oz -flto -s WASM=1 -s STANDALONE_WASM=1 --no-entry \
337
+ -s FILESYSTEM=0 -s DISABLE_EXCEPTION_CATCHING=1 \
338
+ -s EXPORTED_FUNCTIONS='[$(ZIP_MODULE_EXPORTED_FUNCTIONS)]' \
339
+ -o $@
340
+ @test -x $(WASM_OPT) && { echo "Running wasm-opt -Oz --enable-bulk-memory-opt"; $(WASM_OPT) -Oz --enable-bulk-memory-opt -o $@ $@ || true; } || true
341
+
342
+ .PHONY: test_zip_module
343
+ test_zip_module: dist/zip-module.wasm
344
+ @node src/wasm/tests/test_aes_hmac.js dist/zip-module.wasm
345
+
321
346
  # -----------------------------------------------------------------------------
322
347
  # Optional generator: build a C++ tool that creates Deflate64 ZIPs using the
323
348
  # 7-Zip SDK. This target is guarded: it only compiles when the SDK is present
package/README.md CHANGED
@@ -31,5 +31,12 @@ make wasm_prod
31
31
  ```
32
32
  Output: `dist/zlib-streams.wasm` and `dist/zlib-streams.js`
33
33
 
34
+ - zip.js module: the codecs plus the AES-CTR/HMAC-SHA1 engine behind the encrypted entries of zip.js
35
+ ```sh
36
+ make zip_module
37
+ make test_zip_module
38
+ ```
39
+ Output: `dist/zip-module.wasm`
40
+
34
41
  ## License
35
42
  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.1.1",
6
+ "version": "1.2.0",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "deflate",
@@ -15,7 +15,8 @@
15
15
  "exports": {
16
16
  "./package.json": "./package.json",
17
17
  "./zlib-streams.js": "./dist/zlib-streams.js",
18
- "./zlib-streams.wasm": "./dist/zlib-streams.wasm"
18
+ "./zlib-streams.wasm": "./dist/zlib-streams.wasm",
19
+ "./zip-module.wasm": "./dist/zip-module.wasm"
19
20
  },
20
21
  "repository": {
21
22
  "type": "git",
@@ -0,0 +1,307 @@
1
+ /* The engine behind the AES entries of zip.js: AES-CTR with the WinZip counter, a 16-byte
2
+ little-endian integer starting at 1, and HMAC-SHA1 over the ciphertext. Forward-only T-table
3
+ AES, the aes_core.c layout. One context per stream: init() takes the cipher key and the
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. */
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <stdint.h>
9
+
10
+ #define BLOCK_LENGTH 16
11
+ #define SHA1_BLOCK_LENGTH 64
12
+ #define SHA1_DIGEST_LENGTH 20
13
+ #define ROUND_KEYS_LENGTH 60
14
+
15
+ struct aes_hmac_ctx {
16
+ uint32_t round_keys[ROUND_KEYS_LENGTH];
17
+ 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;
23
+ uint8_t opad[SHA1_BLOCK_LENGTH];
24
+ };
25
+
26
+ static uint32_t Te0[256], Te1[256], Te2[256], Te3[256];
27
+ static uint8_t sbox[256];
28
+ static int tables_ready;
29
+
30
+ static uint8_t xtime(uint8_t x) { return (uint8_t)((x << 1) ^ ((x >> 7) * 0x1b)); }
31
+ static uint32_t rotr(uint32_t x, int n) { return (x >> n) | (x << (32 - n)); }
32
+ static uint32_t rotl(uint32_t x, int n) { return (x << n) | (x >> (32 - n)); }
33
+ static uint32_t load_be32(const uint8_t *p) {
34
+ return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | p[3];
35
+ }
36
+ static void store_be32(uint8_t *p, uint32_t v) {
37
+ p[0] = (uint8_t)(v >> 24);
38
+ p[1] = (uint8_t)(v >> 16);
39
+ p[2] = (uint8_t)(v >> 8);
40
+ p[3] = (uint8_t)v;
41
+ }
42
+
43
+ static void init_tables(void) {
44
+ uint8_t p = 1, q = 1;
45
+ do {
46
+ p = (uint8_t)(p ^ (p << 1) ^ ((p & 0x80) ? 0x1b : 0));
47
+ q ^= (uint8_t)(q << 1);
48
+ q ^= (uint8_t)(q << 2);
49
+ q ^= (uint8_t)(q << 4);
50
+ q ^= (q & 0x80) ? 0x09 : 0;
51
+ uint8_t x = (uint8_t)(q ^ ((q << 1) | (q >> 7)) ^ ((q << 2) | (q >> 6)) ^ ((q << 3) | (q >> 5)) ^ ((q << 4) | (q >> 4)));
52
+ sbox[p] = (uint8_t)(x ^ 0x63);
53
+ } while (p != 1);
54
+ sbox[0] = 0x63;
55
+ for (int i = 0; i < 256; i++) {
56
+ uint8_t s = sbox[i], s2 = xtime(s), s3 = (uint8_t)(s2 ^ s);
57
+ uint32_t t = ((uint32_t)s2 << 24) | ((uint32_t)s << 16) | ((uint32_t)s << 8) | s3;
58
+ Te0[i] = t;
59
+ Te1[i] = rotr(t, 8);
60
+ Te2[i] = rotr(t, 16);
61
+ Te3[i] = rotr(t, 24);
62
+ }
63
+ tables_ready = 1;
64
+ }
65
+
66
+ static uint32_t sub_word(uint32_t w) {
67
+ return ((uint32_t)sbox[w >> 24] << 24) | ((uint32_t)sbox[(w >> 16) & 255] << 16) |
68
+ ((uint32_t)sbox[(w >> 8) & 255] << 8) | sbox[w & 255];
69
+ }
70
+
71
+ static void expand_key(struct aes_hmac_ctx *c, const uint8_t *key, unsigned key_length) {
72
+ int nk = (int)key_length / 4;
73
+ c->rounds = nk + 6;
74
+ int total = 4 * (c->rounds + 1);
75
+ uint8_t rcon = 1;
76
+ for (int i = 0; i < nk; i++) {
77
+ c->round_keys[i] = load_be32(key + 4 * i);
78
+ }
79
+ for (int i = nk; i < total; i++) {
80
+ uint32_t t = c->round_keys[i - 1];
81
+ if (i % nk == 0) {
82
+ t = sub_word(rotl(t, 8)) ^ ((uint32_t)rcon << 24);
83
+ rcon = xtime(rcon);
84
+ } else if (nk > 6 && i % nk == 4) {
85
+ t = sub_word(t);
86
+ }
87
+ c->round_keys[i] = c->round_keys[i - nk] ^ t;
88
+ }
89
+ }
90
+
91
+ static void encrypt_block(const struct aes_hmac_ctx *c, const uint8_t in[BLOCK_LENGTH], uint8_t out[BLOCK_LENGTH]) {
92
+ const uint32_t *rk = c->round_keys;
93
+ uint32_t s0 = load_be32(in) ^ rk[0], s1 = load_be32(in + 4) ^ rk[1];
94
+ uint32_t s2 = load_be32(in + 8) ^ rk[2], s3 = load_be32(in + 12) ^ rk[3];
95
+ 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;
107
+ }
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]);
112
+ }
113
+
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;
160
+ }
161
+
162
+ 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;
170
+ }
171
+
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;
186
+ }
187
+ }
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
+ }
197
+ }
198
+
199
+ 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));
205
+ }
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]);
209
+ }
210
+ }
211
+
212
+ static void hmac_init(struct aes_hmac_ctx *c, const uint8_t *key, unsigned length) {
213
+ uint8_t ipad[SHA1_BLOCK_LENGTH], hashed_key[SHA1_DIGEST_LENGTH];
214
+ if (length > SHA1_BLOCK_LENGTH) {
215
+ sha1_init(c);
216
+ sha1_update(c, key, length);
217
+ sha1_final(c, hashed_key);
218
+ key = hashed_key;
219
+ length = SHA1_DIGEST_LENGTH;
220
+ }
221
+ for (unsigned i = 0; i < SHA1_BLOCK_LENGTH; i++) {
222
+ uint8_t k = i < length ? key[i] : 0;
223
+ ipad[i] = (uint8_t)(k ^ 0x36);
224
+ c->opad[i] = (uint8_t)(k ^ 0x5c);
225
+ }
226
+ sha1_init(c);
227
+ sha1_update(c, ipad, SHA1_BLOCK_LENGTH);
228
+ }
229
+
230
+ static void hmac_final(struct aes_hmac_ctx *c, uint8_t out[SHA1_DIGEST_LENGTH]) {
231
+ uint8_t inner[SHA1_DIGEST_LENGTH];
232
+ sha1_final(c, inner);
233
+ sha1_init(c);
234
+ sha1_update(c, c->opad, SHA1_BLOCK_LENGTH);
235
+ sha1_update(c, inner, SHA1_DIGEST_LENGTH);
236
+ sha1_final(c, out);
237
+ }
238
+
239
+ unsigned aes_hmac_new(void) {
240
+ struct aes_hmac_ctx *c = (struct aes_hmac_ctx *)malloc(sizeof(*c));
241
+ if (!c) {
242
+ return 0;
243
+ }
244
+ memset(c, 0, sizeof(*c));
245
+ return (unsigned)(uintptr_t)c;
246
+ }
247
+
248
+ int aes_hmac_init(unsigned ctx, unsigned key_ptr, unsigned key_length, unsigned auth_ptr, unsigned auth_length) {
249
+ struct aes_hmac_ctx *c = (struct aes_hmac_ctx *)(uintptr_t)ctx;
250
+ if (!c || (key_length != 16 && key_length != 24 && key_length != 32)) {
251
+ return -1;
252
+ }
253
+ if (!tables_ready) {
254
+ init_tables();
255
+ }
256
+ expand_key(c, (const uint8_t *)(uintptr_t)key_ptr, key_length);
257
+ memset(c->counter, 0, BLOCK_LENGTH);
258
+ hmac_init(c, (const uint8_t *)(uintptr_t)auth_ptr, auth_length);
259
+ return 0;
260
+ }
261
+
262
+ void aes_hmac_process(unsigned ctx, unsigned ptr, unsigned length, int decrypt) {
263
+ struct aes_hmac_ctx *c = (struct aes_hmac_ctx *)(uintptr_t)ctx;
264
+ uint8_t *p = (uint8_t *)(uintptr_t)ptr;
265
+ uint32_t keystream[4], words[4];
266
+ if (!c) {
267
+ return;
268
+ }
269
+ if (decrypt) {
270
+ sha1_update(c, p, length);
271
+ }
272
+ 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);
279
+ if (length - i >= BLOCK_LENGTH) {
280
+ memcpy(words, p + i, BLOCK_LENGTH);
281
+ words[0] ^= keystream[0];
282
+ words[1] ^= keystream[1];
283
+ words[2] ^= keystream[2];
284
+ words[3] ^= keystream[3];
285
+ memcpy(p + i, words, BLOCK_LENGTH);
286
+ } else {
287
+ const uint8_t *k = (const uint8_t *)keystream;
288
+ for (unsigned j = 0; j < length - i; j++) {
289
+ p[i + j] ^= k[j];
290
+ }
291
+ }
292
+ }
293
+ if (!decrypt) {
294
+ sha1_update(c, p, length);
295
+ }
296
+ }
297
+
298
+ void aes_hmac_end(unsigned ctx, unsigned out_ptr) {
299
+ struct aes_hmac_ctx *c = (struct aes_hmac_ctx *)(uintptr_t)ctx;
300
+ if (!c) {
301
+ return;
302
+ }
303
+ if (out_ptr) {
304
+ hmac_final(c, (uint8_t *)(uintptr_t)out_ptr);
305
+ }
306
+ free(c);
307
+ }