1 /* 2 * Cryptographic API. 3 * 4 * Deflate algorithm (RFC 1951), implemented here primarily for use 5 * by IPCOMP (RFC 3173 & RFC 2394). 6 * 7 * Copyright (c) 2003 James Morris <jmorris@intercode.com.au> 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 * 14 * FIXME: deflate transforms will require up to a total of about 436k of kernel 15 * memory on i386 (390k for compression, the rest for decompression), as the 16 * current zlib kernel code uses a worst case pre-allocation system by default. 17 * This needs to be fixed so that the amount of memory required is properly 18 * related to the winbits and memlevel parameters. 19 * 20 * The default winbits of 11 should suit most packets, and it may be something 21 * to configure on a per-tfm basis in the future. 22 * 23 * Currently, compression history is not maintained between tfm calls, as 24 * it is not needed for IPCOMP and keeps the code simpler. It can be 25 * implemented if someone wants it. 26 */ 27 #include <linux/init.h> 28 #include <linux/module.h> 29 #include <linux/crypto.h> 30 #include <linux/zlib.h> 31 #include <linux/vmalloc.h> 32 #include <linux/interrupt.h> 33 #include <linux/mm.h> 34 #include <linux/net.h> 35 #include <crypto/internal/scompress.h> 36 37 #define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION 38 #define DEFLATE_DEF_WINBITS 11 39 #define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL 40 41 struct deflate_ctx { 42 struct z_stream_s comp_stream; 43 struct z_stream_s decomp_stream; 44 }; 45 46 static int deflate_comp_init(struct deflate_ctx *ctx) 47 { 48 int ret = 0; 49 struct z_stream_s *stream = &ctx->comp_stream; 50 51 stream->workspace = vzalloc(zlib_deflate_workspacesize( 52 -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL)); 53 if (!stream->workspace) { 54 ret = -ENOMEM; 55 goto out; 56 } 57 ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED, 58 -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL, 59 Z_DEFAULT_STRATEGY); 60 if (ret != Z_OK) { 61 ret = -EINVAL; 62 goto out_free; 63 } 64 out: 65 return ret; 66 out_free: 67 vfree(stream->workspace); 68 goto out; 69 } 70 71 static int deflate_decomp_init(struct deflate_ctx *ctx) 72 { 73 int ret = 0; 74 struct z_stream_s *stream = &ctx->decomp_stream; 75 76 stream->workspace = vzalloc(zlib_inflate_workspacesize()); 77 if (!stream->workspace) { 78 ret = -ENOMEM; 79 goto out; 80 } 81 ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS); 82 if (ret != Z_OK) { 83 ret = -EINVAL; 84 goto out_free; 85 } 86 out: 87 return ret; 88 out_free: 89 vfree(stream->workspace); 90 goto out; 91 } 92 93 static void deflate_comp_exit(struct deflate_ctx *ctx) 94 { 95 zlib_deflateEnd(&ctx->comp_stream); 96 vfree(ctx->comp_stream.workspace); 97 } 98 99 static void deflate_decomp_exit(struct deflate_ctx *ctx) 100 { 101 zlib_inflateEnd(&ctx->decomp_stream); 102 vfree(ctx->decomp_stream.workspace); 103 } 104 105 static int __deflate_init(void *ctx) 106 { 107 int ret; 108 109 ret = deflate_comp_init(ctx); 110 if (ret) 111 goto out; 112 ret = deflate_decomp_init(ctx); 113 if (ret) 114 deflate_comp_exit(ctx); 115 out: 116 return ret; 117 } 118 119 static void *deflate_alloc_ctx(struct crypto_scomp *tfm) 120 { 121 struct deflate_ctx *ctx; 122 int ret; 123 124 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 125 if (!ctx) 126 return ERR_PTR(-ENOMEM); 127 128 ret = __deflate_init(ctx); 129 if (ret) { 130 kfree(ctx); 131 return ERR_PTR(ret); 132 } 133 134 return ctx; 135 } 136 137 static int deflate_init(struct crypto_tfm *tfm) 138 { 139 struct deflate_ctx *ctx = crypto_tfm_ctx(tfm); 140 141 return __deflate_init(ctx); 142 } 143 144 static void __deflate_exit(void *ctx) 145 { 146 deflate_comp_exit(ctx); 147 deflate_decomp_exit(ctx); 148 } 149 150 static void deflate_free_ctx(struct crypto_scomp *tfm, void *ctx) 151 { 152 __deflate_exit(ctx); 153 kzfree(ctx); 154 } 155 156 static void deflate_exit(struct crypto_tfm *tfm) 157 { 158 struct deflate_ctx *ctx = crypto_tfm_ctx(tfm); 159 160 __deflate_exit(ctx); 161 } 162 163 static int __deflate_compress(const u8 *src, unsigned int slen, 164 u8 *dst, unsigned int *dlen, void *ctx) 165 { 166 int ret = 0; 167 struct deflate_ctx *dctx = ctx; 168 struct z_stream_s *stream = &dctx->comp_stream; 169 170 ret = zlib_deflateReset(stream); 171 if (ret != Z_OK) { 172 ret = -EINVAL; 173 goto out; 174 } 175 176 stream->next_in = (u8 *)src; 177 stream->avail_in = slen; 178 stream->next_out = (u8 *)dst; 179 stream->avail_out = *dlen; 180 181 ret = zlib_deflate(stream, Z_FINISH); 182 if (ret != Z_STREAM_END) { 183 ret = -EINVAL; 184 goto out; 185 } 186 ret = 0; 187 *dlen = stream->total_out; 188 out: 189 return ret; 190 } 191 192 static int deflate_compress(struct crypto_tfm *tfm, const u8 *src, 193 unsigned int slen, u8 *dst, unsigned int *dlen) 194 { 195 struct deflate_ctx *dctx = crypto_tfm_ctx(tfm); 196 197 return __deflate_compress(src, slen, dst, dlen, dctx); 198 } 199 200 static int deflate_scompress(struct crypto_scomp *tfm, const u8 *src, 201 unsigned int slen, u8 *dst, unsigned int *dlen, 202 void *ctx) 203 { 204 return __deflate_compress(src, slen, dst, dlen, ctx); 205 } 206 207 static int __deflate_decompress(const u8 *src, unsigned int slen, 208 u8 *dst, unsigned int *dlen, void *ctx) 209 { 210 211 int ret = 0; 212 struct deflate_ctx *dctx = ctx; 213 struct z_stream_s *stream = &dctx->decomp_stream; 214 215 ret = zlib_inflateReset(stream); 216 if (ret != Z_OK) { 217 ret = -EINVAL; 218 goto out; 219 } 220 221 stream->next_in = (u8 *)src; 222 stream->avail_in = slen; 223 stream->next_out = (u8 *)dst; 224 stream->avail_out = *dlen; 225 226 ret = zlib_inflate(stream, Z_SYNC_FLUSH); 227 /* 228 * Work around a bug in zlib, which sometimes wants to taste an extra 229 * byte when being used in the (undocumented) raw deflate mode. 230 * (From USAGI). 231 */ 232 if (ret == Z_OK && !stream->avail_in && stream->avail_out) { 233 u8 zerostuff = 0; 234 stream->next_in = &zerostuff; 235 stream->avail_in = 1; 236 ret = zlib_inflate(stream, Z_FINISH); 237 } 238 if (ret != Z_STREAM_END) { 239 ret = -EINVAL; 240 goto out; 241 } 242 ret = 0; 243 *dlen = stream->total_out; 244 out: 245 return ret; 246 } 247 248 static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src, 249 unsigned int slen, u8 *dst, unsigned int *dlen) 250 { 251 struct deflate_ctx *dctx = crypto_tfm_ctx(tfm); 252 253 return __deflate_decompress(src, slen, dst, dlen, dctx); 254 } 255 256 static int deflate_sdecompress(struct crypto_scomp *tfm, const u8 *src, 257 unsigned int slen, u8 *dst, unsigned int *dlen, 258 void *ctx) 259 { 260 return __deflate_decompress(src, slen, dst, dlen, ctx); 261 } 262 263 static struct crypto_alg alg = { 264 .cra_name = "deflate", 265 .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, 266 .cra_ctxsize = sizeof(struct deflate_ctx), 267 .cra_module = THIS_MODULE, 268 .cra_init = deflate_init, 269 .cra_exit = deflate_exit, 270 .cra_u = { .compress = { 271 .coa_compress = deflate_compress, 272 .coa_decompress = deflate_decompress } } 273 }; 274 275 static struct scomp_alg scomp = { 276 .alloc_ctx = deflate_alloc_ctx, 277 .free_ctx = deflate_free_ctx, 278 .compress = deflate_scompress, 279 .decompress = deflate_sdecompress, 280 .base = { 281 .cra_name = "deflate", 282 .cra_driver_name = "deflate-scomp", 283 .cra_module = THIS_MODULE, 284 } 285 }; 286 287 static int __init deflate_mod_init(void) 288 { 289 int ret; 290 291 ret = crypto_register_alg(&alg); 292 if (ret) 293 return ret; 294 295 ret = crypto_register_scomp(&scomp); 296 if (ret) { 297 crypto_unregister_alg(&alg); 298 return ret; 299 } 300 301 return ret; 302 } 303 304 static void __exit deflate_mod_fini(void) 305 { 306 crypto_unregister_alg(&alg); 307 crypto_unregister_scomp(&scomp); 308 } 309 310 module_init(deflate_mod_init); 311 module_exit(deflate_mod_fini); 312 313 MODULE_LICENSE("GPL"); 314 MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP"); 315 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); 316 MODULE_ALIAS_CRYPTO("deflate"); 317