zlib-streams 1.1.0 → 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 +30 -3
- package/README.md +7 -0
- package/dist/zip-module.wasm +0 -0
- package/dist/zlib-streams-dev.wasm +0 -0
- package/dist/zlib-streams.js +10 -13
- package/dist/zlib-streams.wasm +0 -0
- package/package.json +3 -2
- package/src/wasm/aes_hmac_wasm.c +307 -0
- package/src/wasm/api/zlib-streams.js +10 -13
- package/src/wasm/wasm_stream_common.c +8 -4
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='[
|
|
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
|
|
@@ -292,13 +293,15 @@ run_all_tests: dist/zlib-streams-dev.wasm
|
|
|
292
293
|
# Output buffer filling before any input is consumed, including a deflate64
|
|
293
294
|
# match longer than the buffer, which no encoder we have can produce
|
|
294
295
|
@node src/wasm/tests/test_output_buffer_boundary.js dist/zlib-streams-dev.wasm
|
|
296
|
+
# Error codes packed the same way as a success, on both directions
|
|
297
|
+
@node src/wasm/tests/test_process_error_encoding.js dist/zlib-streams-dev.wasm
|
|
295
298
|
@echo "Completed run_all_tests"
|
|
296
299
|
|
|
297
300
|
dist/zlib-streams-dev.wasm: $(WASM_SRCS)
|
|
298
301
|
@echo "Building $@ using $(EMCC)"
|
|
299
302
|
@mkdir -p dist
|
|
300
303
|
$(EMCC) $(WASM_SRCS) $(WASM_CFLAGS) -s WASM=1 -s STANDALONE_WASM=1 --no-entry \
|
|
301
|
-
-s EXPORTED_FUNCTIONS='[
|
|
304
|
+
-s EXPORTED_FUNCTIONS='[$(WASM_EXPORTED_FUNCTIONS)]' \
|
|
302
305
|
-o $@
|
|
303
306
|
cp src/wasm/api/zlib-streams.js dist/zlib-streams.js
|
|
304
307
|
|
|
@@ -311,11 +314,35 @@ dist/zlib-streams.wasm: $(WASM_SRCS)
|
|
|
311
314
|
@mkdir -p dist
|
|
312
315
|
$(EMCC) $(WASM_SRCS) $(WASM_CFLAGS) -Oz -flto -s WASM=1 -s STANDALONE_WASM=1 --no-entry \
|
|
313
316
|
-s FILESYSTEM=0 -s DISABLE_EXCEPTION_CATCHING=1 \
|
|
314
|
-
-s EXPORTED_FUNCTIONS='[
|
|
317
|
+
-s EXPORTED_FUNCTIONS='[$(WASM_EXPORTED_FUNCTIONS)]' \
|
|
315
318
|
-o $@
|
|
316
319
|
cp src/wasm/api/zlib-streams.js dist/zlib-streams.js
|
|
317
320
|
@test -x $(WASM_OPT) && { echo "Running wasm-opt -Oz --enable-bulk-memory-opt"; $(WASM_OPT) -Oz --enable-bulk-memory-opt -o $@ $@ || true; } || true
|
|
318
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
|
+
|
|
319
346
|
# -----------------------------------------------------------------------------
|
|
320
347
|
# Optional generator: build a C++ tool that creates Deflate64 ZIPs using the
|
|
321
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
|
|
Binary file
|
package/dist/zlib-streams.js
CHANGED
|
@@ -138,18 +138,17 @@ function _make(isCompress, type, options = {}) {
|
|
|
138
138
|
}
|
|
139
139
|
heap.set(buffer.subarray(offset, offset + toRead), this.in);
|
|
140
140
|
const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
|
|
141
|
+
// checked before the byte count is used, so a status code can never be read as one
|
|
142
|
+
const code = (result >> 24) & 0xff;
|
|
143
|
+
const signedCode = (code & 0x80) ? code - 256 : code;
|
|
144
|
+
if (signedCode < 0) {
|
|
145
|
+
throw new Error("process error:" + signedCode);
|
|
146
|
+
}
|
|
141
147
|
const prod = result & 0x00ffffff;
|
|
142
148
|
if (prod) {
|
|
143
149
|
scratch.set(heap.subarray(out, out + prod), 0);
|
|
144
150
|
controller.enqueue(scratch.slice(0, prod));
|
|
145
151
|
}
|
|
146
|
-
if (!isCompress) {
|
|
147
|
-
const code = (result >> 24) & 0xff;
|
|
148
|
-
const signedCode = (code & 0x80) ? code - 256 : code;
|
|
149
|
-
if (signedCode < 0) {
|
|
150
|
-
throw new Error("process error:" + signedCode);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
152
|
const consumed = last_consumed(this.streamHandle);
|
|
154
153
|
if (consumed === 0 && prod === 0) {
|
|
155
154
|
break;
|
|
@@ -169,14 +168,12 @@ function _make(isCompress, type, options = {}) {
|
|
|
169
168
|
const scratch = this._scratch;
|
|
170
169
|
while (true) {
|
|
171
170
|
const result = process(this.streamHandle, 0, 0, out, outBufferSize, 4);
|
|
172
|
-
const produced = result & 0x00ffffff;
|
|
173
171
|
const code = (result >> 24) & 0xff;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
throw new Error("process error:" + signedCode);
|
|
178
|
-
}
|
|
172
|
+
const signedCode = (code & 0x80) ? code - 256 : code;
|
|
173
|
+
if (signedCode < 0) {
|
|
174
|
+
throw new Error("process error:" + signedCode);
|
|
179
175
|
}
|
|
176
|
+
const produced = result & 0x00ffffff;
|
|
180
177
|
if (produced) {
|
|
181
178
|
scratch.set(heap.subarray(out, out + produced), 0);
|
|
182
179
|
controller.enqueue(scratch.slice(0, produced));
|
package/dist/zlib-streams.wasm
CHANGED
|
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.
|
|
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
|
+
}
|
|
@@ -138,18 +138,17 @@ function _make(isCompress, type, options = {}) {
|
|
|
138
138
|
}
|
|
139
139
|
heap.set(buffer.subarray(offset, offset + toRead), this.in);
|
|
140
140
|
const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
|
|
141
|
+
// checked before the byte count is used, so a status code can never be read as one
|
|
142
|
+
const code = (result >> 24) & 0xff;
|
|
143
|
+
const signedCode = (code & 0x80) ? code - 256 : code;
|
|
144
|
+
if (signedCode < 0) {
|
|
145
|
+
throw new Error("process error:" + signedCode);
|
|
146
|
+
}
|
|
141
147
|
const prod = result & 0x00ffffff;
|
|
142
148
|
if (prod) {
|
|
143
149
|
scratch.set(heap.subarray(out, out + prod), 0);
|
|
144
150
|
controller.enqueue(scratch.slice(0, prod));
|
|
145
151
|
}
|
|
146
|
-
if (!isCompress) {
|
|
147
|
-
const code = (result >> 24) & 0xff;
|
|
148
|
-
const signedCode = (code & 0x80) ? code - 256 : code;
|
|
149
|
-
if (signedCode < 0) {
|
|
150
|
-
throw new Error("process error:" + signedCode);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
152
|
const consumed = last_consumed(this.streamHandle);
|
|
154
153
|
if (consumed === 0 && prod === 0) {
|
|
155
154
|
break;
|
|
@@ -169,14 +168,12 @@ function _make(isCompress, type, options = {}) {
|
|
|
169
168
|
const scratch = this._scratch;
|
|
170
169
|
while (true) {
|
|
171
170
|
const result = process(this.streamHandle, 0, 0, out, outBufferSize, 4);
|
|
172
|
-
const produced = result & 0x00ffffff;
|
|
173
171
|
const code = (result >> 24) & 0xff;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
throw new Error("process error:" + signedCode);
|
|
178
|
-
}
|
|
172
|
+
const signedCode = (code & 0x80) ? code - 256 : code;
|
|
173
|
+
if (signedCode < 0) {
|
|
174
|
+
throw new Error("process error:" + signedCode);
|
|
179
175
|
}
|
|
176
|
+
const produced = result & 0x00ffffff;
|
|
180
177
|
if (produced) {
|
|
181
178
|
scratch.set(heap.subarray(out, out + produced), 0);
|
|
182
179
|
controller.enqueue(scratch.slice(0, produced));
|
|
@@ -34,17 +34,22 @@ unsigned wasm_stream_last_consumed(unsigned zptr) {
|
|
|
34
34
|
return c->last_consumed;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/* the process functions pack the produced byte count and the zlib status code into one int, so
|
|
38
|
+
every return path has to use this shape: a bare negative code decodes as a huge byte count */
|
|
39
|
+
#define WASM_STREAM_RESULT(produced, code) \
|
|
40
|
+
(((produced) & 0x00ffffff) | (((code) & 0xff) << 24))
|
|
41
|
+
|
|
37
42
|
int wasm_stream_process_common(unsigned zptr, unsigned in_ptr, unsigned in_len,
|
|
38
43
|
unsigned out_ptr, unsigned out_len, int flush,
|
|
39
44
|
int (*process_func)(z_streamp, int)) {
|
|
40
45
|
struct wasm_stream_ctx *c = (struct wasm_stream_ctx *)(uintptr_t)zptr;
|
|
41
46
|
if (!c)
|
|
42
|
-
return Z_STREAM_ERROR;
|
|
47
|
+
return WASM_STREAM_RESULT(0, Z_STREAM_ERROR);
|
|
43
48
|
|
|
44
49
|
if (in_len > c->inbuf_sz) {
|
|
45
50
|
unsigned char *nb = (unsigned char *)realloc(c->inbuf, in_len);
|
|
46
51
|
if (!nb)
|
|
47
|
-
return Z_MEM_ERROR;
|
|
52
|
+
return WASM_STREAM_RESULT(0, Z_MEM_ERROR);
|
|
48
53
|
c->inbuf = nb;
|
|
49
54
|
c->inbuf_sz = in_len;
|
|
50
55
|
}
|
|
@@ -58,6 +63,5 @@ int wasm_stream_process_common(unsigned zptr, unsigned in_ptr, unsigned in_len,
|
|
|
58
63
|
int ret = process_func(&c->strm, flush);
|
|
59
64
|
int produced = (int)(out_len - c->strm.avail_out);
|
|
60
65
|
c->last_consumed = (unsigned)(in_len - c->strm.avail_in);
|
|
61
|
-
|
|
62
|
-
return (produced & 0x00ffffff) | ((code & 0xff) << 24);
|
|
66
|
+
return WASM_STREAM_RESULT(produced, ret);
|
|
63
67
|
}
|