Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/opencrypto/cryptodeflate.c
39478 views
1
/* $OpenBSD: deflate.c,v 1.3 2001/08/20 02:45:22 hugh Exp $ */
2
3
/*-
4
* Copyright (c) 2001 Jean-Jacques Bernard-Gundol ([email protected])
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
*
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
* 3. The name of the author may not be used to endorse or promote products
16
* derived from this software without specific prior written permission.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
/*
31
* This file contains a wrapper around the deflate algo compression
32
* functions using the zlib library (see sys/contrib/zlib)
33
*/
34
35
#include <sys/types.h>
36
#include <sys/param.h>
37
#include <sys/malloc.h>
38
#include <sys/param.h>
39
#include <sys/kernel.h>
40
#include <sys/sdt.h>
41
#include <sys/systm.h>
42
#include <contrib/zlib/zlib.h>
43
44
#include <opencrypto/cryptodev.h>
45
#include <opencrypto/deflate.h>
46
47
SDT_PROVIDER_DECLARE(opencrypto);
48
SDT_PROBE_DEFINE2(opencrypto, deflate, deflate_global, entry,
49
"int", "uint32_t");
50
SDT_PROBE_DEFINE6(opencrypto, deflate, deflate_global, bad,
51
"int", "int", "int", "int", "int", "int");
52
SDT_PROBE_DEFINE6(opencrypto, deflate, deflate_global, iter,
53
"int", "int", "int", "int", "int", "int");
54
SDT_PROBE_DEFINE2(opencrypto, deflate, deflate_global, return,
55
"int", "uint32_t");
56
57
int window_inflate = -1 * MAX_WBITS;
58
int window_deflate = -12;
59
60
static void *
61
crypto_zalloc(void *nil, u_int type, u_int size)
62
{
63
void *ptr;
64
65
ptr = malloc(type *size, M_CRYPTO_DATA, M_NOWAIT);
66
return ptr;
67
}
68
69
static void
70
crypto_zfree(void *nil, void *ptr)
71
{
72
73
free(ptr, M_CRYPTO_DATA);
74
}
75
76
/*
77
* This function takes a block of data and (de)compress it using the deflate
78
* algorithm
79
*/
80
81
uint32_t
82
deflate_global(uint8_t *data, uint32_t size, int decomp, uint8_t **out)
83
{
84
/* decomp indicates whether we compress (0) or decompress (1) */
85
86
z_stream zbuf;
87
uint8_t *output;
88
uint32_t count, result;
89
int error, i;
90
struct deflate_buf *bufh, *bufp;
91
92
SDT_PROBE2(opencrypto, deflate, deflate_global, entry, decomp, size);
93
94
bufh = bufp = NULL;
95
if (!decomp) {
96
i = 1;
97
} else {
98
/*
99
* Choose a buffer with 4x the size of the input buffer
100
* for the size of the output buffer in the case of
101
* decompression. If it's not sufficient, it will need to be
102
* updated while the decompression is going on.
103
*/
104
i = 4;
105
}
106
/*
107
* Make sure we do have enough output space. Repeated calls to
108
* deflate need at least 6 bytes of output buffer space to avoid
109
* repeated markers. We will always provide at least 16 bytes.
110
*/
111
while ((size * i) < 16)
112
i++;
113
114
bufh = bufp = malloc(sizeof(*bufp) + (size_t)(size * i),
115
M_CRYPTO_DATA, M_NOWAIT);
116
if (bufp == NULL) {
117
SDT_PROBE6(opencrypto, deflate, deflate_global, bad,
118
decomp, 0, __LINE__, 0, 0, 0);
119
goto bad2;
120
}
121
bufp->next = NULL;
122
bufp->size = size * i;
123
124
bzero(&zbuf, sizeof(z_stream));
125
zbuf.zalloc = crypto_zalloc;
126
zbuf.zfree = crypto_zfree;
127
zbuf.opaque = Z_NULL;
128
zbuf.next_in = data; /* Data that is going to be processed. */
129
zbuf.avail_in = size; /* Total length of data to be processed. */
130
zbuf.next_out = bufp->data;
131
zbuf.avail_out = bufp->size;
132
133
error = decomp ? inflateInit2(&zbuf, window_inflate) :
134
deflateInit2(&zbuf, Z_DEFAULT_COMPRESSION, Z_METHOD,
135
window_deflate, Z_MEMLEVEL, Z_DEFAULT_STRATEGY);
136
if (error != Z_OK) {
137
SDT_PROBE6(opencrypto, deflate, deflate_global, bad,
138
decomp, error, __LINE__, 0, 0, 0);
139
goto bad;
140
}
141
142
for (;;) {
143
error = decomp ? inflate(&zbuf, Z_SYNC_FLUSH) :
144
deflate(&zbuf, Z_FINISH);
145
if (error != Z_OK && error != Z_STREAM_END) {
146
SDT_PROBE6(opencrypto, deflate, deflate_global, bad,
147
decomp, error, __LINE__,
148
zbuf.avail_in, zbuf.avail_out, zbuf.total_out);
149
goto bad;
150
}
151
SDT_PROBE6(opencrypto, deflate, deflate_global, iter,
152
decomp, error, __LINE__,
153
zbuf.avail_in, zbuf.avail_out, zbuf.total_out);
154
if (decomp && zbuf.avail_in == 0 && error == Z_STREAM_END) {
155
/* Done. */
156
break;
157
} else if (!decomp && error == Z_STREAM_END) {
158
/* Done. */
159
break;
160
} else if (zbuf.avail_out == 0) {
161
struct deflate_buf *p;
162
163
/* We need more output space for another iteration. */
164
p = malloc(sizeof(*p) + (size_t)(size * i),
165
M_CRYPTO_DATA, M_NOWAIT);
166
if (p == NULL) {
167
SDT_PROBE6(opencrypto, deflate, deflate_global,
168
bad, decomp, 0, __LINE__, 0, 0, 0);
169
goto bad;
170
}
171
p->next = NULL;
172
p->size = size * i;
173
bufp->next = p;
174
bufp = p;
175
zbuf.next_out = bufp->data;
176
zbuf.avail_out = bufp->size;
177
} else {
178
/* Unexpect result. */
179
SDT_PROBE6(opencrypto, deflate, deflate_global,
180
bad, decomp, error, __LINE__,
181
zbuf.avail_in, zbuf.avail_out, zbuf.total_out);
182
goto bad;
183
}
184
}
185
186
result = count = zbuf.total_out;
187
188
*out = malloc(result, M_CRYPTO_DATA, M_NOWAIT);
189
if (*out == NULL) {
190
SDT_PROBE6(opencrypto, deflate, deflate_global, bad,
191
decomp, 0, __LINE__, 0, 0, 0);
192
goto bad;
193
}
194
if (decomp)
195
inflateEnd(&zbuf);
196
else
197
deflateEnd(&zbuf);
198
output = *out;
199
for (bufp = bufh; bufp != NULL; ) {
200
if (count > bufp->size) {
201
struct deflate_buf *p;
202
203
bcopy(bufp->data, *out, bufp->size);
204
*out += bufp->size;
205
count -= bufp->size;
206
p = bufp;
207
bufp = bufp->next;
208
free(p, M_CRYPTO_DATA);
209
} else {
210
/* It should be the last buffer. */
211
bcopy(bufp->data, *out, count);
212
*out += count;
213
free(bufp, M_CRYPTO_DATA);
214
bufp = NULL;
215
count = 0;
216
}
217
}
218
*out = output;
219
SDT_PROBE2(opencrypto, deflate, deflate_global, return, decomp, result);
220
return result;
221
222
bad:
223
if (decomp)
224
inflateEnd(&zbuf);
225
else
226
deflateEnd(&zbuf);
227
for (bufp = bufh; bufp != NULL; ) {
228
struct deflate_buf *p;
229
230
p = bufp;
231
bufp = bufp->next;
232
free(p, M_CRYPTO_DATA);
233
}
234
bad2:
235
*out = NULL;
236
return 0;
237
}
238
239