Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: zlib - New zlib crypto module, using pcomp

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Cc: James Morris <jmorris@namei.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Geert Uytterhoeven and committed by
Herbert Xu
bf68e65e 8064efb8

+408
+9
crypto/Kconfig
··· 748 748 749 749 You will most probably want this if using IPSec. 750 750 751 + config CRYPTO_ZLIB 752 + tristate "Zlib compression algorithm" 753 + select CRYPTO_PCOMP 754 + select ZLIB_INFLATE 755 + select ZLIB_DEFLATE 756 + select NLATTR 757 + help 758 + This is the zlib algorithm. 759 + 751 760 config CRYPTO_LZO 752 761 tristate "LZO compression algorithm" 753 762 select CRYPTO_ALGAPI
+1
crypto/Makefile
··· 74 74 obj-$(CONFIG_CRYPTO_SEED) += seed.o 75 75 obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o 76 76 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o 77 + obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o 77 78 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o 78 79 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o 79 80 obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
+378
crypto/zlib.c
··· 1 + /* 2 + * Cryptographic API. 3 + * 4 + * Zlib algorithm 5 + * 6 + * Copyright 2008 Sony Corporation 7 + * 8 + * Based on deflate.c, which is 9 + * Copyright (c) 2003 James Morris <jmorris@intercode.com.au> 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms of the GNU General Public License as published by the Free 13 + * Software Foundation; either version 2 of the License, or (at your option) 14 + * any later version. 15 + * 16 + * FIXME: deflate transforms will require up to a total of about 436k of kernel 17 + * memory on i386 (390k for compression, the rest for decompression), as the 18 + * current zlib kernel code uses a worst case pre-allocation system by default. 19 + * This needs to be fixed so that the amount of memory required is properly 20 + * related to the winbits and memlevel parameters. 21 + */ 22 + 23 + #define pr_fmt(fmt) "%s: " fmt, __func__ 24 + 25 + #include <linux/init.h> 26 + #include <linux/module.h> 27 + #include <linux/zlib.h> 28 + #include <linux/vmalloc.h> 29 + #include <linux/interrupt.h> 30 + #include <linux/mm.h> 31 + #include <linux/net.h> 32 + #include <linux/slab.h> 33 + 34 + #include <crypto/internal/compress.h> 35 + 36 + #include <net/netlink.h> 37 + 38 + 39 + struct zlib_ctx { 40 + struct z_stream_s comp_stream; 41 + struct z_stream_s decomp_stream; 42 + int decomp_windowBits; 43 + }; 44 + 45 + 46 + static void zlib_comp_exit(struct zlib_ctx *ctx) 47 + { 48 + struct z_stream_s *stream = &ctx->comp_stream; 49 + 50 + if (stream->workspace) { 51 + zlib_deflateEnd(stream); 52 + vfree(stream->workspace); 53 + stream->workspace = NULL; 54 + } 55 + } 56 + 57 + static void zlib_decomp_exit(struct zlib_ctx *ctx) 58 + { 59 + struct z_stream_s *stream = &ctx->decomp_stream; 60 + 61 + if (stream->workspace) { 62 + zlib_inflateEnd(stream); 63 + kfree(stream->workspace); 64 + stream->workspace = NULL; 65 + } 66 + } 67 + 68 + static int zlib_init(struct crypto_tfm *tfm) 69 + { 70 + return 0; 71 + } 72 + 73 + static void zlib_exit(struct crypto_tfm *tfm) 74 + { 75 + struct zlib_ctx *ctx = crypto_tfm_ctx(tfm); 76 + 77 + zlib_comp_exit(ctx); 78 + zlib_decomp_exit(ctx); 79 + } 80 + 81 + 82 + static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params, 83 + unsigned int len) 84 + { 85 + struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 86 + struct z_stream_s *stream = &ctx->comp_stream; 87 + struct nlattr *tb[ZLIB_COMP_MAX + 1]; 88 + size_t workspacesize; 89 + int ret; 90 + 91 + ret = nla_parse(tb, ZLIB_COMP_MAX, params, len, NULL); 92 + if (ret) 93 + return ret; 94 + 95 + zlib_comp_exit(ctx); 96 + 97 + workspacesize = zlib_deflate_workspacesize(); 98 + stream->workspace = vmalloc(workspacesize); 99 + if (!stream->workspace) 100 + return -ENOMEM; 101 + 102 + memset(stream->workspace, 0, workspacesize); 103 + ret = zlib_deflateInit2(stream, 104 + tb[ZLIB_COMP_LEVEL] 105 + ? nla_get_u32(tb[ZLIB_COMP_LEVEL]) 106 + : Z_DEFAULT_COMPRESSION, 107 + tb[ZLIB_COMP_METHOD] 108 + ? nla_get_u32(tb[ZLIB_COMP_METHOD]) 109 + : Z_DEFLATED, 110 + tb[ZLIB_COMP_WINDOWBITS] 111 + ? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS]) 112 + : MAX_WBITS, 113 + tb[ZLIB_COMP_MEMLEVEL] 114 + ? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL]) 115 + : DEF_MEM_LEVEL, 116 + tb[ZLIB_COMP_STRATEGY] 117 + ? nla_get_u32(tb[ZLIB_COMP_STRATEGY]) 118 + : Z_DEFAULT_STRATEGY); 119 + if (ret != Z_OK) { 120 + vfree(stream->workspace); 121 + stream->workspace = NULL; 122 + return -EINVAL; 123 + } 124 + 125 + return 0; 126 + } 127 + 128 + static int zlib_compress_init(struct crypto_pcomp *tfm) 129 + { 130 + int ret; 131 + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 132 + struct z_stream_s *stream = &dctx->comp_stream; 133 + 134 + ret = zlib_deflateReset(stream); 135 + if (ret != Z_OK) 136 + return -EINVAL; 137 + 138 + return 0; 139 + } 140 + 141 + static int zlib_compress_update(struct crypto_pcomp *tfm, 142 + struct comp_request *req) 143 + { 144 + int ret; 145 + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 146 + struct z_stream_s *stream = &dctx->comp_stream; 147 + 148 + pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); 149 + stream->next_in = req->next_in; 150 + stream->avail_in = req->avail_in; 151 + stream->next_out = req->next_out; 152 + stream->avail_out = req->avail_out; 153 + 154 + ret = zlib_deflate(stream, Z_NO_FLUSH); 155 + switch (ret) { 156 + case Z_OK: 157 + break; 158 + 159 + case Z_BUF_ERROR: 160 + pr_debug("zlib_deflate could not make progress\n"); 161 + return -EAGAIN; 162 + 163 + default: 164 + pr_debug("zlib_deflate failed %d\n", ret); 165 + return -EINVAL; 166 + } 167 + 168 + pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", 169 + stream->avail_in, stream->avail_out, 170 + req->avail_in - stream->avail_in, 171 + req->avail_out - stream->avail_out); 172 + req->next_in = stream->next_in; 173 + req->avail_in = stream->avail_in; 174 + req->next_out = stream->next_out; 175 + req->avail_out = stream->avail_out; 176 + return 0; 177 + } 178 + 179 + static int zlib_compress_final(struct crypto_pcomp *tfm, 180 + struct comp_request *req) 181 + { 182 + int ret; 183 + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 184 + struct z_stream_s *stream = &dctx->comp_stream; 185 + 186 + pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); 187 + stream->next_in = req->next_in; 188 + stream->avail_in = req->avail_in; 189 + stream->next_out = req->next_out; 190 + stream->avail_out = req->avail_out; 191 + 192 + ret = zlib_deflate(stream, Z_FINISH); 193 + if (ret != Z_STREAM_END) { 194 + pr_debug("zlib_deflate failed %d\n", ret); 195 + return -EINVAL; 196 + } 197 + 198 + pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", 199 + stream->avail_in, stream->avail_out, 200 + req->avail_in - stream->avail_in, 201 + req->avail_out - stream->avail_out); 202 + req->next_in = stream->next_in; 203 + req->avail_in = stream->avail_in; 204 + req->next_out = stream->next_out; 205 + req->avail_out = stream->avail_out; 206 + return 0; 207 + } 208 + 209 + 210 + static int zlib_decompress_setup(struct crypto_pcomp *tfm, void *params, 211 + unsigned int len) 212 + { 213 + struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 214 + struct z_stream_s *stream = &ctx->decomp_stream; 215 + struct nlattr *tb[ZLIB_DECOMP_MAX + 1]; 216 + int ret = 0; 217 + 218 + ret = nla_parse(tb, ZLIB_DECOMP_MAX, params, len, NULL); 219 + if (ret) 220 + return ret; 221 + 222 + zlib_decomp_exit(ctx); 223 + 224 + ctx->decomp_windowBits = tb[ZLIB_DECOMP_WINDOWBITS] 225 + ? nla_get_u32(tb[ZLIB_DECOMP_WINDOWBITS]) 226 + : DEF_WBITS; 227 + 228 + stream->workspace = kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL); 229 + if (!stream->workspace) 230 + return -ENOMEM; 231 + 232 + ret = zlib_inflateInit2(stream, ctx->decomp_windowBits); 233 + if (ret != Z_OK) { 234 + kfree(stream->workspace); 235 + stream->workspace = NULL; 236 + return -EINVAL; 237 + } 238 + 239 + return 0; 240 + } 241 + 242 + static int zlib_decompress_init(struct crypto_pcomp *tfm) 243 + { 244 + int ret; 245 + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 246 + struct z_stream_s *stream = &dctx->decomp_stream; 247 + 248 + ret = zlib_inflateReset(stream); 249 + if (ret != Z_OK) 250 + return -EINVAL; 251 + 252 + return 0; 253 + } 254 + 255 + static int zlib_decompress_update(struct crypto_pcomp *tfm, 256 + struct comp_request *req) 257 + { 258 + int ret; 259 + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 260 + struct z_stream_s *stream = &dctx->decomp_stream; 261 + 262 + pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); 263 + stream->next_in = req->next_in; 264 + stream->avail_in = req->avail_in; 265 + stream->next_out = req->next_out; 266 + stream->avail_out = req->avail_out; 267 + 268 + ret = zlib_inflate(stream, Z_SYNC_FLUSH); 269 + switch (ret) { 270 + case Z_OK: 271 + case Z_STREAM_END: 272 + break; 273 + 274 + case Z_BUF_ERROR: 275 + pr_debug("zlib_inflate could not make progress\n"); 276 + return -EAGAIN; 277 + 278 + default: 279 + pr_debug("zlib_inflate failed %d\n", ret); 280 + return -EINVAL; 281 + } 282 + 283 + pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", 284 + stream->avail_in, stream->avail_out, 285 + req->avail_in - stream->avail_in, 286 + req->avail_out - stream->avail_out); 287 + req->next_in = stream->next_in; 288 + req->avail_in = stream->avail_in; 289 + req->next_out = stream->next_out; 290 + req->avail_out = stream->avail_out; 291 + return 0; 292 + } 293 + 294 + static int zlib_decompress_final(struct crypto_pcomp *tfm, 295 + struct comp_request *req) 296 + { 297 + int ret; 298 + struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); 299 + struct z_stream_s *stream = &dctx->decomp_stream; 300 + 301 + pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); 302 + stream->next_in = req->next_in; 303 + stream->avail_in = req->avail_in; 304 + stream->next_out = req->next_out; 305 + stream->avail_out = req->avail_out; 306 + 307 + if (dctx->decomp_windowBits < 0) { 308 + ret = zlib_inflate(stream, Z_SYNC_FLUSH); 309 + /* 310 + * Work around a bug in zlib, which sometimes wants to taste an 311 + * extra byte when being used in the (undocumented) raw deflate 312 + * mode. (From USAGI). 313 + */ 314 + if (ret == Z_OK && !stream->avail_in && stream->avail_out) { 315 + const void *saved_next_in = stream->next_in; 316 + u8 zerostuff = 0; 317 + 318 + stream->next_in = &zerostuff; 319 + stream->avail_in = 1; 320 + ret = zlib_inflate(stream, Z_FINISH); 321 + stream->next_in = saved_next_in; 322 + stream->avail_in = 0; 323 + } 324 + } else 325 + ret = zlib_inflate(stream, Z_FINISH); 326 + if (ret != Z_STREAM_END) { 327 + pr_debug("zlib_inflate failed %d\n", ret); 328 + return -EINVAL; 329 + } 330 + 331 + pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", 332 + stream->avail_in, stream->avail_out, 333 + req->avail_in - stream->avail_in, 334 + req->avail_out - stream->avail_out); 335 + req->next_in = stream->next_in; 336 + req->avail_in = stream->avail_in; 337 + req->next_out = stream->next_out; 338 + req->avail_out = stream->avail_out; 339 + return 0; 340 + } 341 + 342 + 343 + static struct pcomp_alg zlib_alg = { 344 + .compress_setup = zlib_compress_setup, 345 + .compress_init = zlib_compress_init, 346 + .compress_update = zlib_compress_update, 347 + .compress_final = zlib_compress_final, 348 + .decompress_setup = zlib_decompress_setup, 349 + .decompress_init = zlib_decompress_init, 350 + .decompress_update = zlib_decompress_update, 351 + .decompress_final = zlib_decompress_final, 352 + 353 + .base = { 354 + .cra_name = "zlib", 355 + .cra_flags = CRYPTO_ALG_TYPE_PCOMPRESS, 356 + .cra_ctxsize = sizeof(struct zlib_ctx), 357 + .cra_module = THIS_MODULE, 358 + .cra_init = zlib_init, 359 + .cra_exit = zlib_exit, 360 + } 361 + }; 362 + 363 + static int __init zlib_mod_init(void) 364 + { 365 + return crypto_register_pcomp(&zlib_alg); 366 + } 367 + 368 + static void __exit zlib_mod_fini(void) 369 + { 370 + crypto_unregister_pcomp(&zlib_alg); 371 + } 372 + 373 + module_init(zlib_mod_init); 374 + module_exit(zlib_mod_fini); 375 + 376 + MODULE_LICENSE("GPL"); 377 + MODULE_DESCRIPTION("Zlib Compression Algorithm"); 378 + MODULE_AUTHOR("Sony Corporation");
+20
include/crypto/compress.h
··· 30 30 unsigned int avail_out; /* bytes available at next_out */ 31 31 }; 32 32 33 + enum zlib_comp_params { 34 + ZLIB_COMP_LEVEL = 1, /* e.g. Z_DEFAULT_COMPRESSION */ 35 + ZLIB_COMP_METHOD, /* e.g. Z_DEFLATED */ 36 + ZLIB_COMP_WINDOWBITS, /* e.g. MAX_WBITS */ 37 + ZLIB_COMP_MEMLEVEL, /* e.g. DEF_MEM_LEVEL */ 38 + ZLIB_COMP_STRATEGY, /* e.g. Z_DEFAULT_STRATEGY */ 39 + __ZLIB_COMP_MAX, 40 + }; 41 + 42 + #define ZLIB_COMP_MAX (__ZLIB_COMP_MAX - 1) 43 + 44 + 45 + enum zlib_decomp_params { 46 + ZLIB_DECOMP_WINDOWBITS = 1, /* e.g. DEF_WBITS */ 47 + __ZLIB_DECOMP_MAX, 48 + }; 49 + 50 + #define ZLIB_DECOMP_MAX (__ZLIB_DECOMP_MAX - 1) 51 + 52 + 33 53 struct crypto_pcomp { 34 54 struct crypto_tfm base; 35 55 };