162306a36Sopenharmony_ci/***********************license start************************************ 262306a36Sopenharmony_ci * Copyright (c) 2003-2017 Cavium, Inc. 362306a36Sopenharmony_ci * All rights reserved. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * License: one of 'Cavium License' or 'GNU General Public License Version 2' 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This file is provided under the terms of the Cavium License (see below) 862306a36Sopenharmony_ci * or under the terms of GNU General Public License, Version 2, as 962306a36Sopenharmony_ci * published by the Free Software Foundation. When using or redistributing 1062306a36Sopenharmony_ci * this file, you may do so under either license. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Cavium License: Redistribution and use in source and binary forms, with 1362306a36Sopenharmony_ci * or without modification, are permitted provided that the following 1462306a36Sopenharmony_ci * conditions are met: 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * * Redistributions of source code must retain the above copyright 1762306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * * Redistributions in binary form must reproduce the above 2062306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 2162306a36Sopenharmony_ci * disclaimer in the documentation and/or other materials provided 2262306a36Sopenharmony_ci * with the distribution. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * * Neither the name of Cavium Inc. nor the names of its contributors may be 2562306a36Sopenharmony_ci * used to endorse or promote products derived from this software without 2662306a36Sopenharmony_ci * specific prior written permission. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * This Software, including technical data, may be subject to U.S. export 2962306a36Sopenharmony_ci * control laws, including the U.S. Export Administration Act and its 3062306a36Sopenharmony_ci * associated regulations, and may be subject to export or import 3162306a36Sopenharmony_ci * regulations in other countries. 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 3462306a36Sopenharmony_ci * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS 3562306a36Sopenharmony_ci * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 3662306a36Sopenharmony_ci * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 3762306a36Sopenharmony_ci * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 3862306a36Sopenharmony_ci * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) 3962306a36Sopenharmony_ci * WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A 4062306a36Sopenharmony_ci * PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET 4162306a36Sopenharmony_ci * ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE 4262306a36Sopenharmony_ci * ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES 4362306a36Sopenharmony_ci * WITH YOU. 4462306a36Sopenharmony_ci ***********************license end**************************************/ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#include "zip_crypto.h" 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic void zip_static_init_zip_ops(struct zip_operation *zip_ops, 4962306a36Sopenharmony_ci int lzs_flag) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci zip_ops->flush = ZIP_FLUSH_FINISH; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /* equivalent to level 6 of opensource zlib */ 5462306a36Sopenharmony_ci zip_ops->speed = 1; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (!lzs_flag) { 5762306a36Sopenharmony_ci zip_ops->ccode = 0; /* Auto Huffman */ 5862306a36Sopenharmony_ci zip_ops->lzs_flag = 0; 5962306a36Sopenharmony_ci zip_ops->format = ZLIB_FORMAT; 6062306a36Sopenharmony_ci } else { 6162306a36Sopenharmony_ci zip_ops->ccode = 3; /* LZS Encoding */ 6262306a36Sopenharmony_ci zip_ops->lzs_flag = 1; 6362306a36Sopenharmony_ci zip_ops->format = LZS_FORMAT; 6462306a36Sopenharmony_ci } 6562306a36Sopenharmony_ci zip_ops->begin_file = 1; 6662306a36Sopenharmony_ci zip_ops->history_len = 0; 6762306a36Sopenharmony_ci zip_ops->end_file = 1; 6862306a36Sopenharmony_ci zip_ops->compcode = 0; 6962306a36Sopenharmony_ci zip_ops->csum = 1; /* Adler checksum desired */ 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic int zip_ctx_init(struct zip_kernel_ctx *zip_ctx, int lzs_flag) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct zip_operation *comp_ctx = &zip_ctx->zip_comp; 7562306a36Sopenharmony_ci struct zip_operation *decomp_ctx = &zip_ctx->zip_decomp; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci zip_static_init_zip_ops(comp_ctx, lzs_flag); 7862306a36Sopenharmony_ci zip_static_init_zip_ops(decomp_ctx, lzs_flag); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci comp_ctx->input = zip_data_buf_alloc(MAX_INPUT_BUFFER_SIZE); 8162306a36Sopenharmony_ci if (!comp_ctx->input) 8262306a36Sopenharmony_ci return -ENOMEM; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci comp_ctx->output = zip_data_buf_alloc(MAX_OUTPUT_BUFFER_SIZE); 8562306a36Sopenharmony_ci if (!comp_ctx->output) 8662306a36Sopenharmony_ci goto err_comp_input; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci decomp_ctx->input = zip_data_buf_alloc(MAX_INPUT_BUFFER_SIZE); 8962306a36Sopenharmony_ci if (!decomp_ctx->input) 9062306a36Sopenharmony_ci goto err_comp_output; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci decomp_ctx->output = zip_data_buf_alloc(MAX_OUTPUT_BUFFER_SIZE); 9362306a36Sopenharmony_ci if (!decomp_ctx->output) 9462306a36Sopenharmony_ci goto err_decomp_input; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci return 0; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cierr_decomp_input: 9962306a36Sopenharmony_ci zip_data_buf_free(decomp_ctx->input, MAX_INPUT_BUFFER_SIZE); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cierr_comp_output: 10262306a36Sopenharmony_ci zip_data_buf_free(comp_ctx->output, MAX_OUTPUT_BUFFER_SIZE); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cierr_comp_input: 10562306a36Sopenharmony_ci zip_data_buf_free(comp_ctx->input, MAX_INPUT_BUFFER_SIZE); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci return -ENOMEM; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic void zip_ctx_exit(struct zip_kernel_ctx *zip_ctx) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci struct zip_operation *comp_ctx = &zip_ctx->zip_comp; 11362306a36Sopenharmony_ci struct zip_operation *dec_ctx = &zip_ctx->zip_decomp; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci zip_data_buf_free(comp_ctx->input, MAX_INPUT_BUFFER_SIZE); 11662306a36Sopenharmony_ci zip_data_buf_free(comp_ctx->output, MAX_OUTPUT_BUFFER_SIZE); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci zip_data_buf_free(dec_ctx->input, MAX_INPUT_BUFFER_SIZE); 11962306a36Sopenharmony_ci zip_data_buf_free(dec_ctx->output, MAX_OUTPUT_BUFFER_SIZE); 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic int zip_compress(const u8 *src, unsigned int slen, 12362306a36Sopenharmony_ci u8 *dst, unsigned int *dlen, 12462306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct zip_operation *zip_ops = NULL; 12762306a36Sopenharmony_ci struct zip_state *zip_state; 12862306a36Sopenharmony_ci struct zip_device *zip = NULL; 12962306a36Sopenharmony_ci int ret; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci if (!zip_ctx || !src || !dst || !dlen) 13262306a36Sopenharmony_ci return -ENOMEM; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci zip = zip_get_device(zip_get_node_id()); 13562306a36Sopenharmony_ci if (!zip) 13662306a36Sopenharmony_ci return -ENODEV; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC); 13962306a36Sopenharmony_ci if (!zip_state) 14062306a36Sopenharmony_ci return -ENOMEM; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci zip_ops = &zip_ctx->zip_comp; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci zip_ops->input_len = slen; 14562306a36Sopenharmony_ci zip_ops->output_len = *dlen; 14662306a36Sopenharmony_ci memcpy(zip_ops->input, src, slen); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci ret = zip_deflate(zip_ops, zip_state, zip); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (!ret) { 15162306a36Sopenharmony_ci *dlen = zip_ops->output_len; 15262306a36Sopenharmony_ci memcpy(dst, zip_ops->output, *dlen); 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci kfree(zip_state); 15562306a36Sopenharmony_ci return ret; 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic int zip_decompress(const u8 *src, unsigned int slen, 15962306a36Sopenharmony_ci u8 *dst, unsigned int *dlen, 16062306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci struct zip_operation *zip_ops = NULL; 16362306a36Sopenharmony_ci struct zip_state *zip_state; 16462306a36Sopenharmony_ci struct zip_device *zip = NULL; 16562306a36Sopenharmony_ci int ret; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (!zip_ctx || !src || !dst || !dlen) 16862306a36Sopenharmony_ci return -ENOMEM; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci zip = zip_get_device(zip_get_node_id()); 17162306a36Sopenharmony_ci if (!zip) 17262306a36Sopenharmony_ci return -ENODEV; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC); 17562306a36Sopenharmony_ci if (!zip_state) 17662306a36Sopenharmony_ci return -ENOMEM; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci zip_ops = &zip_ctx->zip_decomp; 17962306a36Sopenharmony_ci memcpy(zip_ops->input, src, slen); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci /* Work around for a bug in zlib which needs an extra bytes sometimes */ 18262306a36Sopenharmony_ci if (zip_ops->ccode != 3) /* Not LZS Encoding */ 18362306a36Sopenharmony_ci zip_ops->input[slen++] = 0; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci zip_ops->input_len = slen; 18662306a36Sopenharmony_ci zip_ops->output_len = *dlen; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci ret = zip_inflate(zip_ops, zip_state, zip); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (!ret) { 19162306a36Sopenharmony_ci *dlen = zip_ops->output_len; 19262306a36Sopenharmony_ci memcpy(dst, zip_ops->output, *dlen); 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci kfree(zip_state); 19562306a36Sopenharmony_ci return ret; 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci/* Legacy Compress framework start */ 19962306a36Sopenharmony_ciint zip_alloc_comp_ctx_deflate(struct crypto_tfm *tfm) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = crypto_tfm_ctx(tfm); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci return zip_ctx_init(zip_ctx, 0); 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ciint zip_alloc_comp_ctx_lzs(struct crypto_tfm *tfm) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = crypto_tfm_ctx(tfm); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci return zip_ctx_init(zip_ctx, 1); 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_civoid zip_free_comp_ctx(struct crypto_tfm *tfm) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = crypto_tfm_ctx(tfm); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci zip_ctx_exit(zip_ctx); 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ciint zip_comp_compress(struct crypto_tfm *tfm, 22162306a36Sopenharmony_ci const u8 *src, unsigned int slen, 22262306a36Sopenharmony_ci u8 *dst, unsigned int *dlen) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = crypto_tfm_ctx(tfm); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci return zip_compress(src, slen, dst, dlen, zip_ctx); 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ciint zip_comp_decompress(struct crypto_tfm *tfm, 23062306a36Sopenharmony_ci const u8 *src, unsigned int slen, 23162306a36Sopenharmony_ci u8 *dst, unsigned int *dlen) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = crypto_tfm_ctx(tfm); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return zip_decompress(src, slen, dst, dlen, zip_ctx); 23662306a36Sopenharmony_ci} /* Legacy compress framework end */ 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci/* SCOMP framework start */ 23962306a36Sopenharmony_civoid *zip_alloc_scomp_ctx_deflate(struct crypto_scomp *tfm) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci int ret; 24262306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci zip_ctx = kzalloc(sizeof(*zip_ctx), GFP_KERNEL); 24562306a36Sopenharmony_ci if (!zip_ctx) 24662306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci ret = zip_ctx_init(zip_ctx, 0); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (ret) { 25162306a36Sopenharmony_ci kfree_sensitive(zip_ctx); 25262306a36Sopenharmony_ci return ERR_PTR(ret); 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci return zip_ctx; 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_civoid *zip_alloc_scomp_ctx_lzs(struct crypto_scomp *tfm) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci int ret; 26162306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci zip_ctx = kzalloc(sizeof(*zip_ctx), GFP_KERNEL); 26462306a36Sopenharmony_ci if (!zip_ctx) 26562306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci ret = zip_ctx_init(zip_ctx, 1); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci if (ret) { 27062306a36Sopenharmony_ci kfree_sensitive(zip_ctx); 27162306a36Sopenharmony_ci return ERR_PTR(ret); 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci return zip_ctx; 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_civoid zip_free_scomp_ctx(struct crypto_scomp *tfm, void *ctx) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = ctx; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci zip_ctx_exit(zip_ctx); 28262306a36Sopenharmony_ci kfree_sensitive(zip_ctx); 28362306a36Sopenharmony_ci} 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ciint zip_scomp_compress(struct crypto_scomp *tfm, 28662306a36Sopenharmony_ci const u8 *src, unsigned int slen, 28762306a36Sopenharmony_ci u8 *dst, unsigned int *dlen, void *ctx) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = ctx; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci return zip_compress(src, slen, dst, dlen, zip_ctx); 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ciint zip_scomp_decompress(struct crypto_scomp *tfm, 29562306a36Sopenharmony_ci const u8 *src, unsigned int slen, 29662306a36Sopenharmony_ci u8 *dst, unsigned int *dlen, void *ctx) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = ctx; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci return zip_decompress(src, slen, dst, dlen, zip_ctx); 30162306a36Sopenharmony_ci} /* SCOMP framework end */ 302