18c2ecf20Sopenharmony_ci/***********************license start************************************ 28c2ecf20Sopenharmony_ci * Copyright (c) 2003-2017 Cavium, Inc. 38c2ecf20Sopenharmony_ci * All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * License: one of 'Cavium License' or 'GNU General Public License Version 2' 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This file is provided under the terms of the Cavium License (see below) 88c2ecf20Sopenharmony_ci * or under the terms of GNU General Public License, Version 2, as 98c2ecf20Sopenharmony_ci * published by the Free Software Foundation. When using or redistributing 108c2ecf20Sopenharmony_ci * this file, you may do so under either license. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Cavium License: Redistribution and use in source and binary forms, with 138c2ecf20Sopenharmony_ci * or without modification, are permitted provided that the following 148c2ecf20Sopenharmony_ci * conditions are met: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * * Redistributions of source code must retain the above copyright 178c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * * Redistributions in binary form must reproduce the above 208c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 218c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials provided 228c2ecf20Sopenharmony_ci * with the distribution. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * * Neither the name of Cavium Inc. nor the names of its contributors may be 258c2ecf20Sopenharmony_ci * used to endorse or promote products derived from this software without 268c2ecf20Sopenharmony_ci * specific prior written permission. 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * This Software, including technical data, may be subject to U.S. export 298c2ecf20Sopenharmony_ci * control laws, including the U.S. Export Administration Act and its 308c2ecf20Sopenharmony_ci * associated regulations, and may be subject to export or import 318c2ecf20Sopenharmony_ci * regulations in other countries. 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 348c2ecf20Sopenharmony_ci * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS 358c2ecf20Sopenharmony_ci * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 368c2ecf20Sopenharmony_ci * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 378c2ecf20Sopenharmony_ci * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 388c2ecf20Sopenharmony_ci * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) 398c2ecf20Sopenharmony_ci * WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A 408c2ecf20Sopenharmony_ci * PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET 418c2ecf20Sopenharmony_ci * ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE 428c2ecf20Sopenharmony_ci * ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES 438c2ecf20Sopenharmony_ci * WITH YOU. 448c2ecf20Sopenharmony_ci ***********************license end**************************************/ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include "zip_crypto.h" 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic void zip_static_init_zip_ops(struct zip_operation *zip_ops, 498c2ecf20Sopenharmony_ci int lzs_flag) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci zip_ops->flush = ZIP_FLUSH_FINISH; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* equivalent to level 6 of opensource zlib */ 548c2ecf20Sopenharmony_ci zip_ops->speed = 1; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci if (!lzs_flag) { 578c2ecf20Sopenharmony_ci zip_ops->ccode = 0; /* Auto Huffman */ 588c2ecf20Sopenharmony_ci zip_ops->lzs_flag = 0; 598c2ecf20Sopenharmony_ci zip_ops->format = ZLIB_FORMAT; 608c2ecf20Sopenharmony_ci } else { 618c2ecf20Sopenharmony_ci zip_ops->ccode = 3; /* LZS Encoding */ 628c2ecf20Sopenharmony_ci zip_ops->lzs_flag = 1; 638c2ecf20Sopenharmony_ci zip_ops->format = LZS_FORMAT; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci zip_ops->begin_file = 1; 668c2ecf20Sopenharmony_ci zip_ops->history_len = 0; 678c2ecf20Sopenharmony_ci zip_ops->end_file = 1; 688c2ecf20Sopenharmony_ci zip_ops->compcode = 0; 698c2ecf20Sopenharmony_ci zip_ops->csum = 1; /* Adler checksum desired */ 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic int zip_ctx_init(struct zip_kernel_ctx *zip_ctx, int lzs_flag) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci struct zip_operation *comp_ctx = &zip_ctx->zip_comp; 758c2ecf20Sopenharmony_ci struct zip_operation *decomp_ctx = &zip_ctx->zip_decomp; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci zip_static_init_zip_ops(comp_ctx, lzs_flag); 788c2ecf20Sopenharmony_ci zip_static_init_zip_ops(decomp_ctx, lzs_flag); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci comp_ctx->input = zip_data_buf_alloc(MAX_INPUT_BUFFER_SIZE); 818c2ecf20Sopenharmony_ci if (!comp_ctx->input) 828c2ecf20Sopenharmony_ci return -ENOMEM; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci comp_ctx->output = zip_data_buf_alloc(MAX_OUTPUT_BUFFER_SIZE); 858c2ecf20Sopenharmony_ci if (!comp_ctx->output) 868c2ecf20Sopenharmony_ci goto err_comp_input; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci decomp_ctx->input = zip_data_buf_alloc(MAX_INPUT_BUFFER_SIZE); 898c2ecf20Sopenharmony_ci if (!decomp_ctx->input) 908c2ecf20Sopenharmony_ci goto err_comp_output; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci decomp_ctx->output = zip_data_buf_alloc(MAX_OUTPUT_BUFFER_SIZE); 938c2ecf20Sopenharmony_ci if (!decomp_ctx->output) 948c2ecf20Sopenharmony_ci goto err_decomp_input; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci return 0; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cierr_decomp_input: 998c2ecf20Sopenharmony_ci zip_data_buf_free(decomp_ctx->input, MAX_INPUT_BUFFER_SIZE); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cierr_comp_output: 1028c2ecf20Sopenharmony_ci zip_data_buf_free(comp_ctx->output, MAX_OUTPUT_BUFFER_SIZE); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cierr_comp_input: 1058c2ecf20Sopenharmony_ci zip_data_buf_free(comp_ctx->input, MAX_INPUT_BUFFER_SIZE); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci return -ENOMEM; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic void zip_ctx_exit(struct zip_kernel_ctx *zip_ctx) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci struct zip_operation *comp_ctx = &zip_ctx->zip_comp; 1138c2ecf20Sopenharmony_ci struct zip_operation *dec_ctx = &zip_ctx->zip_decomp; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci zip_data_buf_free(comp_ctx->input, MAX_INPUT_BUFFER_SIZE); 1168c2ecf20Sopenharmony_ci zip_data_buf_free(comp_ctx->output, MAX_OUTPUT_BUFFER_SIZE); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci zip_data_buf_free(dec_ctx->input, MAX_INPUT_BUFFER_SIZE); 1198c2ecf20Sopenharmony_ci zip_data_buf_free(dec_ctx->output, MAX_OUTPUT_BUFFER_SIZE); 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic int zip_compress(const u8 *src, unsigned int slen, 1238c2ecf20Sopenharmony_ci u8 *dst, unsigned int *dlen, 1248c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci struct zip_operation *zip_ops = NULL; 1278c2ecf20Sopenharmony_ci struct zip_state *zip_state; 1288c2ecf20Sopenharmony_ci struct zip_device *zip = NULL; 1298c2ecf20Sopenharmony_ci int ret; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (!zip_ctx || !src || !dst || !dlen) 1328c2ecf20Sopenharmony_ci return -ENOMEM; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci zip = zip_get_device(zip_get_node_id()); 1358c2ecf20Sopenharmony_ci if (!zip) 1368c2ecf20Sopenharmony_ci return -ENODEV; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC); 1398c2ecf20Sopenharmony_ci if (!zip_state) 1408c2ecf20Sopenharmony_ci return -ENOMEM; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci zip_ops = &zip_ctx->zip_comp; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci zip_ops->input_len = slen; 1458c2ecf20Sopenharmony_ci zip_ops->output_len = *dlen; 1468c2ecf20Sopenharmony_ci memcpy(zip_ops->input, src, slen); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci ret = zip_deflate(zip_ops, zip_state, zip); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci if (!ret) { 1518c2ecf20Sopenharmony_ci *dlen = zip_ops->output_len; 1528c2ecf20Sopenharmony_ci memcpy(dst, zip_ops->output, *dlen); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci kfree(zip_state); 1558c2ecf20Sopenharmony_ci return ret; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic int zip_decompress(const u8 *src, unsigned int slen, 1598c2ecf20Sopenharmony_ci u8 *dst, unsigned int *dlen, 1608c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci struct zip_operation *zip_ops = NULL; 1638c2ecf20Sopenharmony_ci struct zip_state *zip_state; 1648c2ecf20Sopenharmony_ci struct zip_device *zip = NULL; 1658c2ecf20Sopenharmony_ci int ret; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci if (!zip_ctx || !src || !dst || !dlen) 1688c2ecf20Sopenharmony_ci return -ENOMEM; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci zip = zip_get_device(zip_get_node_id()); 1718c2ecf20Sopenharmony_ci if (!zip) 1728c2ecf20Sopenharmony_ci return -ENODEV; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci zip_state = kzalloc(sizeof(*zip_state), GFP_ATOMIC); 1758c2ecf20Sopenharmony_ci if (!zip_state) 1768c2ecf20Sopenharmony_ci return -ENOMEM; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci zip_ops = &zip_ctx->zip_decomp; 1798c2ecf20Sopenharmony_ci memcpy(zip_ops->input, src, slen); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci /* Work around for a bug in zlib which needs an extra bytes sometimes */ 1828c2ecf20Sopenharmony_ci if (zip_ops->ccode != 3) /* Not LZS Encoding */ 1838c2ecf20Sopenharmony_ci zip_ops->input[slen++] = 0; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci zip_ops->input_len = slen; 1868c2ecf20Sopenharmony_ci zip_ops->output_len = *dlen; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci ret = zip_inflate(zip_ops, zip_state, zip); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if (!ret) { 1918c2ecf20Sopenharmony_ci *dlen = zip_ops->output_len; 1928c2ecf20Sopenharmony_ci memcpy(dst, zip_ops->output, *dlen); 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci kfree(zip_state); 1958c2ecf20Sopenharmony_ci return ret; 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci/* Legacy Compress framework start */ 1998c2ecf20Sopenharmony_ciint zip_alloc_comp_ctx_deflate(struct crypto_tfm *tfm) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci int ret; 2028c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = crypto_tfm_ctx(tfm); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci ret = zip_ctx_init(zip_ctx, 0); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci return ret; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ciint zip_alloc_comp_ctx_lzs(struct crypto_tfm *tfm) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci int ret; 2128c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = crypto_tfm_ctx(tfm); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci ret = zip_ctx_init(zip_ctx, 1); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci return ret; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_civoid zip_free_comp_ctx(struct crypto_tfm *tfm) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = crypto_tfm_ctx(tfm); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci zip_ctx_exit(zip_ctx); 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ciint zip_comp_compress(struct crypto_tfm *tfm, 2278c2ecf20Sopenharmony_ci const u8 *src, unsigned int slen, 2288c2ecf20Sopenharmony_ci u8 *dst, unsigned int *dlen) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci int ret; 2318c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = crypto_tfm_ctx(tfm); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci ret = zip_compress(src, slen, dst, dlen, zip_ctx); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci return ret; 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ciint zip_comp_decompress(struct crypto_tfm *tfm, 2398c2ecf20Sopenharmony_ci const u8 *src, unsigned int slen, 2408c2ecf20Sopenharmony_ci u8 *dst, unsigned int *dlen) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci int ret; 2438c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = crypto_tfm_ctx(tfm); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci ret = zip_decompress(src, slen, dst, dlen, zip_ctx); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci return ret; 2488c2ecf20Sopenharmony_ci} /* Legacy compress framework end */ 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci/* SCOMP framework start */ 2518c2ecf20Sopenharmony_civoid *zip_alloc_scomp_ctx_deflate(struct crypto_scomp *tfm) 2528c2ecf20Sopenharmony_ci{ 2538c2ecf20Sopenharmony_ci int ret; 2548c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci zip_ctx = kzalloc(sizeof(*zip_ctx), GFP_KERNEL); 2578c2ecf20Sopenharmony_ci if (!zip_ctx) 2588c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci ret = zip_ctx_init(zip_ctx, 0); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci if (ret) { 2638c2ecf20Sopenharmony_ci kfree_sensitive(zip_ctx); 2648c2ecf20Sopenharmony_ci return ERR_PTR(ret); 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci return zip_ctx; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_civoid *zip_alloc_scomp_ctx_lzs(struct crypto_scomp *tfm) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci int ret; 2738c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci zip_ctx = kzalloc(sizeof(*zip_ctx), GFP_KERNEL); 2768c2ecf20Sopenharmony_ci if (!zip_ctx) 2778c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci ret = zip_ctx_init(zip_ctx, 1); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (ret) { 2828c2ecf20Sopenharmony_ci kfree_sensitive(zip_ctx); 2838c2ecf20Sopenharmony_ci return ERR_PTR(ret); 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci return zip_ctx; 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_civoid zip_free_scomp_ctx(struct crypto_scomp *tfm, void *ctx) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = ctx; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci zip_ctx_exit(zip_ctx); 2948c2ecf20Sopenharmony_ci kfree_sensitive(zip_ctx); 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ciint zip_scomp_compress(struct crypto_scomp *tfm, 2988c2ecf20Sopenharmony_ci const u8 *src, unsigned int slen, 2998c2ecf20Sopenharmony_ci u8 *dst, unsigned int *dlen, void *ctx) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci int ret; 3028c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = ctx; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci ret = zip_compress(src, slen, dst, dlen, zip_ctx); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci return ret; 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ciint zip_scomp_decompress(struct crypto_scomp *tfm, 3108c2ecf20Sopenharmony_ci const u8 *src, unsigned int slen, 3118c2ecf20Sopenharmony_ci u8 *dst, unsigned int *dlen, void *ctx) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci int ret; 3148c2ecf20Sopenharmony_ci struct zip_kernel_ctx *zip_ctx = ctx; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci ret = zip_decompress(src, slen, dst, dlen, zip_ctx); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci return ret; 3198c2ecf20Sopenharmony_ci} /* SCOMP framework end */ 320