1From 308795a7713ca6fcd468b60fba9a2fca99cee6a0 Mon Sep 17 00:00:00 2001 2From: Nick Terrell <terrelln@fb.com> 3Date: Wed, 2 Aug 2017 18:02:13 -0700 4Subject: [PATCH v5 5/5] crypto: Add zstd support 5 6Adds zstd support to crypto and scompress. Only supports the default 7level. 8 9Signed-off-by: Nick Terrell <terrelln@fb.com> 10--- 11 crypto/Kconfig | 9 ++ 12 crypto/Makefile | 1 + 13 crypto/testmgr.c | 10 +++ 14 crypto/testmgr.h | 71 +++++++++++++++ 15 crypto/zstd.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 16 5 files changed, 356 insertions(+) 17 create mode 100644 crypto/zstd.c 18 19diff --git a/crypto/Kconfig b/crypto/Kconfig 20index caa770e..4fc3936 100644 21--- a/crypto/Kconfig 22+++ b/crypto/Kconfig 23@@ -1662,6 +1662,15 @@ config CRYPTO_LZ4HC 24 help 25 This is the LZ4 high compression mode algorithm. 26 27+config CRYPTO_ZSTD 28+ tristate "Zstd compression algorithm" 29+ select CRYPTO_ALGAPI 30+ select CRYPTO_ACOMP2 31+ select ZSTD_COMPRESS 32+ select ZSTD_DECOMPRESS 33+ help 34+ This is the zstd algorithm. 35+ 36 comment "Random Number Generation" 37 38 config CRYPTO_ANSI_CPRNG 39diff --git a/crypto/Makefile b/crypto/Makefile 40index d41f033..b22e1e8 100644 41--- a/crypto/Makefile 42+++ b/crypto/Makefile 43@@ -133,6 +133,7 @@ obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o 44 obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o 45 obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o 46 obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o 47+obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o 48 49 ecdh_generic-y := ecc.o 50 ecdh_generic-y += ecdh.o 51diff --git a/crypto/testmgr.c b/crypto/testmgr.c 52index 7125ba3..8a124d3 100644 53--- a/crypto/testmgr.c 54+++ b/crypto/testmgr.c 55@@ -3603,6 +3603,16 @@ static const struct alg_test_desc alg_test_descs[] = { 56 .decomp = __VECS(zlib_deflate_decomp_tv_template) 57 } 58 } 59+ }, { 60+ .alg = "zstd", 61+ .test = alg_test_comp, 62+ .fips_allowed = 1, 63+ .suite = { 64+ .comp = { 65+ .comp = __VECS(zstd_comp_tv_template), 66+ .decomp = __VECS(zstd_decomp_tv_template) 67+ } 68+ } 69 } 70 }; 71 72diff --git a/crypto/testmgr.h b/crypto/testmgr.h 73index 6ceb0e2..e6b5920 100644 74--- a/crypto/testmgr.h 75+++ b/crypto/testmgr.h 76@@ -34631,4 +34631,75 @@ static const struct comp_testvec lz4hc_decomp_tv_template[] = { 77 }, 78 }; 79 80+static const struct comp_testvec zstd_comp_tv_template[] = { 81+ { 82+ .inlen = 68, 83+ .outlen = 39, 84+ .input = "The algorithm is zstd. " 85+ "The algorithm is zstd. " 86+ "The algorithm is zstd.", 87+ .output = "\x28\xb5\x2f\xfd\x00\x50\xf5\x00\x00\xb8\x54\x68\x65" 88+ "\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x20\x69\x73" 89+ "\x20\x7a\x73\x74\x64\x2e\x20\x01\x00\x55\x73\x36\x01" 90+ , 91+ }, 92+ { 93+ .inlen = 244, 94+ .outlen = 151, 95+ .input = "zstd, short for Zstandard, is a fast lossless " 96+ "compression algorithm, targeting real-time " 97+ "compression scenarios at zlib-level and better " 98+ "compression ratios. The zstd compression library " 99+ "provides in-memory compression and decompression " 100+ "functions.", 101+ .output = "\x28\xb5\x2f\xfd\x00\x50\x75\x04\x00\x42\x4b\x1e\x17" 102+ "\x90\x81\x31\x00\xf2\x2f\xe4\x36\xc9\xef\x92\x88\x32" 103+ "\xc9\xf2\x24\x94\xd8\x68\x9a\x0f\x00\x0c\xc4\x31\x6f" 104+ "\x0d\x0c\x38\xac\x5c\x48\x03\xcd\x63\x67\xc0\xf3\xad" 105+ "\x4e\x90\xaa\x78\xa0\xa4\xc5\x99\xda\x2f\xb6\x24\x60" 106+ "\xe2\x79\x4b\xaa\xb6\x6b\x85\x0b\xc9\xc6\x04\x66\x86" 107+ "\xe2\xcc\xe2\x25\x3f\x4f\x09\xcd\xb8\x9d\xdb\xc1\x90" 108+ "\xa9\x11\xbc\x35\x44\x69\x2d\x9c\x64\x4f\x13\x31\x64" 109+ "\xcc\xfb\x4d\x95\x93\x86\x7f\x33\x7f\x1a\xef\xe9\x30" 110+ "\xf9\x67\xa1\x94\x0a\x69\x0f\x60\xcd\xc3\xab\x99\xdc" 111+ "\x42\xed\x97\x05\x00\x33\xc3\x15\x95\x3a\x06\xa0\x0e" 112+ "\x20\xa9\x0e\x82\xb9\x43\x45\x01", 113+ }, 114+}; 115+ 116+static const struct comp_testvec zstd_decomp_tv_template[] = { 117+ { 118+ .inlen = 43, 119+ .outlen = 68, 120+ .input = "\x28\xb5\x2f\xfd\x04\x50\xf5\x00\x00\xb8\x54\x68\x65" 121+ "\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x20\x69\x73" 122+ "\x20\x7a\x73\x74\x64\x2e\x20\x01\x00\x55\x73\x36\x01" 123+ "\x6b\xf4\x13\x35", 124+ .output = "The algorithm is zstd. " 125+ "The algorithm is zstd. " 126+ "The algorithm is zstd.", 127+ }, 128+ { 129+ .inlen = 155, 130+ .outlen = 244, 131+ .input = "\x28\xb5\x2f\xfd\x04\x50\x75\x04\x00\x42\x4b\x1e\x17" 132+ "\x90\x81\x31\x00\xf2\x2f\xe4\x36\xc9\xef\x92\x88\x32" 133+ "\xc9\xf2\x24\x94\xd8\x68\x9a\x0f\x00\x0c\xc4\x31\x6f" 134+ "\x0d\x0c\x38\xac\x5c\x48\x03\xcd\x63\x67\xc0\xf3\xad" 135+ "\x4e\x90\xaa\x78\xa0\xa4\xc5\x99\xda\x2f\xb6\x24\x60" 136+ "\xe2\x79\x4b\xaa\xb6\x6b\x85\x0b\xc9\xc6\x04\x66\x86" 137+ "\xe2\xcc\xe2\x25\x3f\x4f\x09\xcd\xb8\x9d\xdb\xc1\x90" 138+ "\xa9\x11\xbc\x35\x44\x69\x2d\x9c\x64\x4f\x13\x31\x64" 139+ "\xcc\xfb\x4d\x95\x93\x86\x7f\x33\x7f\x1a\xef\xe9\x30" 140+ "\xf9\x67\xa1\x94\x0a\x69\x0f\x60\xcd\xc3\xab\x99\xdc" 141+ "\x42\xed\x97\x05\x00\x33\xc3\x15\x95\x3a\x06\xa0\x0e" 142+ "\x20\xa9\x0e\x82\xb9\x43\x45\x01\xaa\x6d\xda\x0d", 143+ .output = "zstd, short for Zstandard, is a fast lossless " 144+ "compression algorithm, targeting real-time " 145+ "compression scenarios at zlib-level and better " 146+ "compression ratios. The zstd compression library " 147+ "provides in-memory compression and decompression " 148+ "functions.", 149+ }, 150+}; 151 #endif /* _CRYPTO_TESTMGR_H */ 152diff --git a/crypto/zstd.c b/crypto/zstd.c 153new file mode 100644 154index 0000000..9a76b3e 155--- /dev/null 156+++ b/crypto/zstd.c 157@@ -0,0 +1,265 @@ 158+/* 159+ * Cryptographic API. 160+ * 161+ * Copyright (c) 2017-present, Facebook, Inc. 162+ * 163+ * This program is free software; you can redistribute it and/or modify it 164+ * under the terms of the GNU General Public License version 2 as published by 165+ * the Free Software Foundation. 166+ * 167+ * This program is distributed in the hope that it will be useful, but WITHOUT 168+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 169+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 170+ * more details. 171+ */ 172+#include <linux/crypto.h> 173+#include <linux/init.h> 174+#include <linux/interrupt.h> 175+#include <linux/mm.h> 176+#include <linux/module.h> 177+#include <linux/net.h> 178+#include <linux/vmalloc.h> 179+#include <linux/zstd.h> 180+#include <crypto/internal/scompress.h> 181+ 182+ 183+#define ZSTD_DEF_LEVEL 3 184+ 185+struct zstd_ctx { 186+ ZSTD_CCtx *cctx; 187+ ZSTD_DCtx *dctx; 188+ void *cwksp; 189+ void *dwksp; 190+}; 191+ 192+static ZSTD_parameters zstd_params(void) 193+{ 194+ return ZSTD_getParams(ZSTD_DEF_LEVEL, 0, 0); 195+} 196+ 197+static int zstd_comp_init(struct zstd_ctx *ctx) 198+{ 199+ int ret = 0; 200+ const ZSTD_parameters params = zstd_params(); 201+ const size_t wksp_size = ZSTD_CCtxWorkspaceBound(params.cParams); 202+ 203+ ctx->cwksp = vzalloc(wksp_size); 204+ if (!ctx->cwksp) { 205+ ret = -ENOMEM; 206+ goto out; 207+ } 208+ 209+ ctx->cctx = ZSTD_initCCtx(ctx->cwksp, wksp_size); 210+ if (!ctx->cctx) { 211+ ret = -EINVAL; 212+ goto out_free; 213+ } 214+out: 215+ return ret; 216+out_free: 217+ vfree(ctx->cwksp); 218+ goto out; 219+} 220+ 221+static int zstd_decomp_init(struct zstd_ctx *ctx) 222+{ 223+ int ret = 0; 224+ const size_t wksp_size = ZSTD_DCtxWorkspaceBound(); 225+ 226+ ctx->dwksp = vzalloc(wksp_size); 227+ if (!ctx->dwksp) { 228+ ret = -ENOMEM; 229+ goto out; 230+ } 231+ 232+ ctx->dctx = ZSTD_initDCtx(ctx->dwksp, wksp_size); 233+ if (!ctx->dctx) { 234+ ret = -EINVAL; 235+ goto out_free; 236+ } 237+out: 238+ return ret; 239+out_free: 240+ vfree(ctx->dwksp); 241+ goto out; 242+} 243+ 244+static void zstd_comp_exit(struct zstd_ctx *ctx) 245+{ 246+ vfree(ctx->cwksp); 247+ ctx->cwksp = NULL; 248+ ctx->cctx = NULL; 249+} 250+ 251+static void zstd_decomp_exit(struct zstd_ctx *ctx) 252+{ 253+ vfree(ctx->dwksp); 254+ ctx->dwksp = NULL; 255+ ctx->dctx = NULL; 256+} 257+ 258+static int __zstd_init(void *ctx) 259+{ 260+ int ret; 261+ 262+ ret = zstd_comp_init(ctx); 263+ if (ret) 264+ return ret; 265+ ret = zstd_decomp_init(ctx); 266+ if (ret) 267+ zstd_comp_exit(ctx); 268+ return ret; 269+} 270+ 271+static void *zstd_alloc_ctx(struct crypto_scomp *tfm) 272+{ 273+ int ret; 274+ struct zstd_ctx *ctx; 275+ 276+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 277+ if (!ctx) 278+ return ERR_PTR(-ENOMEM); 279+ 280+ ret = __zstd_init(ctx); 281+ if (ret) { 282+ kfree(ctx); 283+ return ERR_PTR(ret); 284+ } 285+ 286+ return ctx; 287+} 288+ 289+static int zstd_init(struct crypto_tfm *tfm) 290+{ 291+ struct zstd_ctx *ctx = crypto_tfm_ctx(tfm); 292+ 293+ return __zstd_init(ctx); 294+} 295+ 296+static void __zstd_exit(void *ctx) 297+{ 298+ zstd_comp_exit(ctx); 299+ zstd_decomp_exit(ctx); 300+} 301+ 302+static void zstd_free_ctx(struct crypto_scomp *tfm, void *ctx) 303+{ 304+ __zstd_exit(ctx); 305+ kzfree(ctx); 306+} 307+ 308+static void zstd_exit(struct crypto_tfm *tfm) 309+{ 310+ struct zstd_ctx *ctx = crypto_tfm_ctx(tfm); 311+ 312+ __zstd_exit(ctx); 313+} 314+ 315+static int __zstd_compress(const u8 *src, unsigned int slen, 316+ u8 *dst, unsigned int *dlen, void *ctx) 317+{ 318+ size_t out_len; 319+ struct zstd_ctx *zctx = ctx; 320+ const ZSTD_parameters params = zstd_params(); 321+ 322+ out_len = ZSTD_compressCCtx(zctx->cctx, dst, *dlen, src, slen, params); 323+ if (ZSTD_isError(out_len)) 324+ return -EINVAL; 325+ *dlen = out_len; 326+ return 0; 327+} 328+ 329+static int zstd_compress(struct crypto_tfm *tfm, const u8 *src, 330+ unsigned int slen, u8 *dst, unsigned int *dlen) 331+{ 332+ struct zstd_ctx *ctx = crypto_tfm_ctx(tfm); 333+ 334+ return __zstd_compress(src, slen, dst, dlen, ctx); 335+} 336+ 337+static int zstd_scompress(struct crypto_scomp *tfm, const u8 *src, 338+ unsigned int slen, u8 *dst, unsigned int *dlen, 339+ void *ctx) 340+{ 341+ return __zstd_compress(src, slen, dst, dlen, ctx); 342+} 343+ 344+static int __zstd_decompress(const u8 *src, unsigned int slen, 345+ u8 *dst, unsigned int *dlen, void *ctx) 346+{ 347+ size_t out_len; 348+ struct zstd_ctx *zctx = ctx; 349+ 350+ out_len = ZSTD_decompressDCtx(zctx->dctx, dst, *dlen, src, slen); 351+ if (ZSTD_isError(out_len)) 352+ return -EINVAL; 353+ *dlen = out_len; 354+ return 0; 355+} 356+ 357+static int zstd_decompress(struct crypto_tfm *tfm, const u8 *src, 358+ unsigned int slen, u8 *dst, unsigned int *dlen) 359+{ 360+ struct zstd_ctx *ctx = crypto_tfm_ctx(tfm); 361+ 362+ return __zstd_decompress(src, slen, dst, dlen, ctx); 363+} 364+ 365+static int zstd_sdecompress(struct crypto_scomp *tfm, const u8 *src, 366+ unsigned int slen, u8 *dst, unsigned int *dlen, 367+ void *ctx) 368+{ 369+ return __zstd_decompress(src, slen, dst, dlen, ctx); 370+} 371+ 372+static struct crypto_alg alg = { 373+ .cra_name = "zstd", 374+ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, 375+ .cra_ctxsize = sizeof(struct zstd_ctx), 376+ .cra_module = THIS_MODULE, 377+ .cra_init = zstd_init, 378+ .cra_exit = zstd_exit, 379+ .cra_u = { .compress = { 380+ .coa_compress = zstd_compress, 381+ .coa_decompress = zstd_decompress } } 382+}; 383+ 384+static struct scomp_alg scomp = { 385+ .alloc_ctx = zstd_alloc_ctx, 386+ .free_ctx = zstd_free_ctx, 387+ .compress = zstd_scompress, 388+ .decompress = zstd_sdecompress, 389+ .base = { 390+ .cra_name = "zstd", 391+ .cra_driver_name = "zstd-scomp", 392+ .cra_module = THIS_MODULE, 393+ } 394+}; 395+ 396+static int __init zstd_mod_init(void) 397+{ 398+ int ret; 399+ 400+ ret = crypto_register_alg(&alg); 401+ if (ret) 402+ return ret; 403+ 404+ ret = crypto_register_scomp(&scomp); 405+ if (ret) 406+ crypto_unregister_alg(&alg); 407+ 408+ return ret; 409+} 410+ 411+static void __exit zstd_mod_fini(void) 412+{ 413+ crypto_unregister_alg(&alg); 414+ crypto_unregister_scomp(&scomp); 415+} 416+ 417+module_init(zstd_mod_init); 418+module_exit(zstd_mod_fini); 419+ 420+MODULE_LICENSE("GPL"); 421+MODULE_DESCRIPTION("Zstd Compression Algorithm"); 422+MODULE_ALIAS_CRYPTO("zstd"); 423-- 4242.9.3 425