*** BLURB HERE ***
Hao Fang (1): uadk/test: move main function to testsuit.c and rm test_sva_perf.c
Longfang Liu (1): uadk: fix some code bugs
Qi Tao (1): uadk: add null pointer check
Wenkai Lin (3): uadk: fix for sec software compute check uadk: fix for cipher update iv uadk/v1: fix for cipher update iv
Yang Shen (1): uadk/cipher - add length check of CBC_CTS mode
drv/hash_mb/hash_mb.c | 6 +- drv/hisi_comp.c | 10 +- drv/hisi_dae.c | 6 +- drv/hisi_hpre.c | 8 +- drv/hisi_sec.c | 61 ++-- drv/isa_ce_sm3.c | 6 +- drv/isa_ce_sm4.c | 6 +- test/hisi_zip_test/Makefile.am | 2 +- test/hisi_zip_test/test_sva_perf.c | 524 ----------------------------- test/hisi_zip_test/testsuit.c | 474 +++++++++++++++++++++++++- v1/drv/hisi_sec_udrv.c | 80 ++++- wd_cipher.c | 36 +- wd_ecc.c | 6 +- wd_util.c | 11 +- 14 files changed, 639 insertions(+), 597 deletions(-) delete mode 100644 test/hisi_zip_test/test_sva_perf.c
Add null pointer check to avoid segment errors.
Signed-off-by: Qi Tao taoqi10@huawei.com --- drv/hash_mb/hash_mb.c | 6 +++--- drv/hisi_comp.c | 8 +++----- drv/hisi_dae.c | 6 +++--- drv/hisi_hpre.c | 8 +++----- drv/hisi_sec.c | 8 +++----- drv/isa_ce_sm3.c | 6 +++--- drv/isa_ce_sm4.c | 6 +++--- 7 files changed, 21 insertions(+), 27 deletions(-)
diff --git a/drv/hash_mb/hash_mb.c b/drv/hash_mb/hash_mb.c index e4a9564f..9ad36b81 100644 --- a/drv/hash_mb/hash_mb.c +++ b/drv/hash_mb/hash_mb.c @@ -217,11 +217,11 @@ static int hash_mb_init(struct wd_alg_driver *drv, void *conf)
static void hash_mb_exit(struct wd_alg_driver *drv) { - struct hash_mb_ctx *priv = (struct hash_mb_ctx *)drv->priv; - - if (!priv) + if(!drv || !drv->priv) return;
+ struct hash_mb_ctx *priv = (struct hash_mb_ctx *)drv->priv; + hash_mb_queue_uninit(&priv->config, priv->config.ctx_num); free(priv); drv->priv = NULL; diff --git a/drv/hisi_comp.c b/drv/hisi_comp.c index 4c8e18b2..c5569986 100644 --- a/drv/hisi_comp.c +++ b/drv/hisi_comp.c @@ -835,16 +835,14 @@ out:
static void hisi_zip_exit(struct wd_alg_driver *drv) { + if(!drv || !drv->priv) + return; + struct hisi_zip_ctx *priv = (struct hisi_zip_ctx *)drv->priv; struct wd_ctx_config_internal *config; handle_t h_qp; __u32 i;
- if (!priv) { - /* return if already exit */ - return; - } - config = &priv->config; for (i = 0; i < config->ctx_num; i++) { h_qp = (handle_t)wd_ctx_get_priv(config->ctxs[i].ctx); diff --git a/drv/hisi_dae.c b/drv/hisi_dae.c index 09d23874..864d21ba 100644 --- a/drv/hisi_dae.c +++ b/drv/hisi_dae.c @@ -1604,14 +1604,14 @@ out:
static void dae_exit(struct wd_alg_driver *drv) { + if(!drv || !drv->priv) + return; + struct hisi_dae_ctx *priv = (struct hisi_dae_ctx *)drv->priv; struct wd_ctx_config_internal *config; handle_t h_qp; __u32 i;
- if (!priv) - return; - config = &priv->config; for (i = 0; i < config->ctx_num; i++) { h_qp = (handle_t)wd_ctx_get_priv(config->ctxs[i].ctx); diff --git a/drv/hisi_hpre.c b/drv/hisi_hpre.c index 37bb5ee1..313cdcc8 100644 --- a/drv/hisi_hpre.c +++ b/drv/hisi_hpre.c @@ -583,16 +583,14 @@ static int hpre_ecc_init(struct wd_alg_driver *drv, void *conf)
static void hpre_exit(struct wd_alg_driver *drv) { + if(!drv || !drv->priv) + return; + struct hisi_hpre_ctx *priv = (struct hisi_hpre_ctx *)drv->priv; struct wd_ctx_config_internal *config; handle_t h_qp; __u32 i;
- if (!priv) { - /* return if already exit */ - return; - } - config = &priv->config; for (i = 0; i < config->ctx_num; i++) { h_qp = (handle_t)wd_ctx_get_priv(config->ctxs[i].ctx); diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index 0a1bcc1e..63775869 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -3102,16 +3102,14 @@ out:
static void hisi_sec_exit(struct wd_alg_driver *drv) { + if(!drv || !drv->priv) + return; + struct hisi_sec_ctx *priv = (struct hisi_sec_ctx *)drv->priv; struct wd_ctx_config_internal *config; handle_t h_qp; __u32 i;
- if (!priv) { - /* return if already exit */ - return; - } - config = &priv->config; for (i = 0; i < config->ctx_num; i++) { h_qp = (handle_t)wd_ctx_get_priv(config->ctxs[i].ctx); diff --git a/drv/isa_ce_sm3.c b/drv/isa_ce_sm3.c index 99cd6404..54c2a9e7 100644 --- a/drv/isa_ce_sm3.c +++ b/drv/isa_ce_sm3.c @@ -392,11 +392,11 @@ static int sm3_ce_drv_init(struct wd_alg_driver *drv, void *conf)
static void sm3_ce_drv_exit(struct wd_alg_driver *drv) { - struct sm3_ce_drv_ctx *sctx = (struct sm3_ce_drv_ctx *)drv->priv; - - if (!sctx) + if(!drv || !drv->priv) return;
+ struct sm3_ce_drv_ctx *sctx = (struct sm3_ce_drv_ctx *)drv->priv; + free(sctx); drv->priv = NULL; } diff --git a/drv/isa_ce_sm4.c b/drv/isa_ce_sm4.c index 3404465b..5e448fa0 100644 --- a/drv/isa_ce_sm4.c +++ b/drv/isa_ce_sm4.c @@ -53,11 +53,11 @@ static int isa_ce_init(struct wd_alg_driver *drv, void *conf)
static void isa_ce_exit(struct wd_alg_driver *drv) { - struct sm4_ce_drv_ctx *sctx = (struct sm4_ce_drv_ctx *)drv->priv; - - if (!sctx) + if(!drv || !drv->priv) return;
+ struct sm4_ce_drv_ctx *sctx = (struct sm4_ce_drv_ctx *)drv->priv; + free(sctx); drv->priv = NULL; }
From: Hao Fang fanghao11@huawei.com
test_suit.c should be the main function file, and these two files have the duplicate code.
Signed-off-by: Hao Fang fanghao11@huawei.com --- test/hisi_zip_test/Makefile.am | 2 +- test/hisi_zip_test/test_sva_perf.c | 524 ----------------------------- test/hisi_zip_test/testsuit.c | 474 +++++++++++++++++++++++++- 3 files changed, 474 insertions(+), 526 deletions(-) delete mode 100644 test/hisi_zip_test/test_sva_perf.c
diff --git a/test/hisi_zip_test/Makefile.am b/test/hisi_zip_test/Makefile.am index f6715820..8b464f58 100644 --- a/test/hisi_zip_test/Makefile.am +++ b/test/hisi_zip_test/Makefile.am @@ -3,7 +3,7 @@ AUTOMAKE_OPTIONS = subdir-objects
bin_PROGRAMS=zip_sva_perf
-zip_sva_perf_SOURCES=test_sva_perf.c test_lib.c testsuit.c +zip_sva_perf_SOURCES=testsuit.c test_lib.c
if WD_STATIC_DRV zip_sva_perf_LDADD=../../.libs/libwd.a ../../.libs/libwd_comp.a \ diff --git a/test/hisi_zip_test/test_sva_perf.c b/test/hisi_zip_test/test_sva_perf.c deleted file mode 100644 index 98670a5b..00000000 --- a/test/hisi_zip_test/test_sva_perf.c +++ /dev/null @@ -1,524 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -/* - * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. - * Copyright 2020-2021 Linaro ltd. - */ - -/* - * Test performance of the SVA API - */ -#include <asm/unistd.h> /* For __NR_perf_event_open */ -#include <fenv.h> -#include <getopt.h> -#include <inttypes.h> -#include <math.h> -#include <signal.h> -#include <time.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> - -#include <linux/perf_event.h> - -#include "test_lib.h" -#include "wd_sched.h" - -enum hizip_stats_variable { - ST_SETUP_TIME, - ST_RUN_TIME, - ST_CPU_TIME, - - /* CPU usage */ - ST_USER_TIME, - ST_SYSTEM_TIME, - - /* Faults */ - ST_MINFLT, - ST_MAJFLT, - - /* Context switches */ - ST_INVCTX, - ST_VCTX, - - /* Signals */ - ST_SIGNALS, - - /* Aggregated */ - ST_SPEED, - ST_TOTAL_SPEED, - ST_CPU_IDLE, - ST_FAULTS, - ST_IOPF, - - ST_COMPRESSION_RATIO, - - NUM_STATS -}; - -struct hizip_stats { - double v[NUM_STATS]; -}; - -int perf_event_open(struct perf_event_attr *attr, - pid_t pid, int cpu, int group_fd, - unsigned long flags) -{ - return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); -} - -unsigned long long perf_event_put(int *perf_fds, int nr_fds); - -int perf_event_get(const char *event_name, int **perf_fds, int *nr_fds) -{ - int ret; - int cpu; - FILE *fd; - int nr_cpus; - unsigned int event_id; - char event_id_file[256]; - struct perf_event_attr event = { - .type = PERF_TYPE_TRACEPOINT, - .size = sizeof(event), - .disabled = true, - }; - - *perf_fds = NULL; - *nr_fds = 0; - - nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); - if (nr_cpus <= 0) { - WD_ERR("invalid number of CPUs\n"); - return nr_cpus; - } - - ret = snprintf(event_id_file, sizeof(event_id_file), - "/sys/kernel/debug/tracing/events/%s/id", event_name); - if (ret >= sizeof(event_id_file)) { - WD_ERR("event_id buffer overflow\n"); - return -EOVERFLOW; - } - fd = fopen(event_id_file, "r"); - if (fd == NULL) { - ret = -errno; - WD_ERR("Couldn't open file %s\n", event_id_file); - return ret; - } - - if (fscanf(fd, "%d", &event_id) != 1) { - WD_ERR("Couldn't parse file %s\n", event_id_file); - return -EINVAL; - } - fclose(fd); - event.config = event_id; - - *perf_fds = calloc(nr_cpus, sizeof(int)); - if (!*perf_fds) - return -ENOMEM; - *nr_fds = nr_cpus; - - /* - * An event is bound to either a CPU or a PID. If we want both, we need - * to open the event on all CPUs. Note that we can't use a perf group - * since they have to be on the same CPU. - */ - for (cpu = 0; cpu < nr_cpus; cpu++) { - int fd = perf_event_open(&event, -1, cpu, -1, 0); - - if (fd < 0) { - WD_ERR("Couldn't get perf event %s on CPU%d: %d\n", - event_name, cpu, errno); - perf_event_put(*perf_fds, cpu); - return fd; - } - - ioctl(fd, PERF_EVENT_IOC_RESET, 0); - ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); - (*perf_fds)[cpu] = fd; - } - - return 0; -} - -/* - * Closes the perf fd and return the sample count. If it wasn't open, return 0. - */ -unsigned long long perf_event_put(int *perf_fds, int nr_fds) -{ - int ret; - int cpu; - uint64_t count, total = 0; - - if (!perf_fds) - return 0; - - for (cpu = 0; cpu < nr_fds; cpu++) { - int fd = perf_fds[cpu]; - - if (fd <= 0) { - WD_ERR("Invalid perf fd %d\n", cpu); - continue; - } - - ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); - - ret = read(fd, &count, sizeof(count)); - if (ret < sizeof(count)) - WD_ERR("Couldn't read perf event for CPU%d\n", cpu); - - total += count; - close(fd); - - } - - free(perf_fds); - return total; -} - -static void set_thp(struct test_options *opts) -{ - char *p; - char s[14]; - FILE *file; - - file = fopen("/sys/kernel/mm/transparent_hugepage/enabled", "r"); - if (!file) - goto out_err; - p = fgets(s, 14, file); - fclose(file); - if (!p) - goto out_err; - - if (strcmp(s, "never") == 0) { - printf("Cannot test THP with enable=never\n"); - return; - } - - file = fopen("/sys/kernel/mm/transparent_hugepage/defrag", "r"); - if (!file) - goto out_err; - p = fgets(s, 14, file); - fclose(file); - if (!p) - goto out_err; - - if (strcmp(s, "defer") == 0 || strcmp(s, "never") == 0) { - printf("Cannot test THP with defrag=%s\n", s); - return; - } - - return; -out_err: - printf("THP unsupported?\n"); -} - -void stat_setup(struct hizip_test_info *info) -{ - clock_gettime(CLOCK_MONOTONIC_RAW, &info->tv.setup_time); - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &info->tv.setup_cputime); - getrusage(RUSAGE_SELF, &info->tv.setup_rusage); -} - -void stat_start(struct hizip_test_info *info) -{ - clock_gettime(CLOCK_MONOTONIC_RAW, &info->tv.start_time); - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &info->tv.start_cputime); - getrusage(RUSAGE_SELF, &info->tv.start_rusage); -} - -void stat_end(struct hizip_test_info *info) -{ - struct test_options *opts = info->opts; - struct hizip_stats *stats = info->stats; - double v; - size_t total_out; - unsigned long total_len; - - total_out = __atomic_load_n(&info->total_out, __ATOMIC_ACQUIRE); - clock_gettime(CLOCK_MONOTONIC_RAW, &info->tv.end_time); - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &info->tv.end_cputime); - getrusage(RUSAGE_SELF, &info->tv.end_rusage); - - stats->v[ST_SETUP_TIME] = (info->tv.start_time.tv_sec - - info->tv.setup_time.tv_sec) * 1000000000 + - info->tv.start_time.tv_nsec - - info->tv.setup_time.tv_nsec; - stats->v[ST_RUN_TIME] = (info->tv.end_time.tv_sec - - info->tv.start_time.tv_sec) * 1000000000 + - info->tv.end_time.tv_nsec - - info->tv.start_time.tv_nsec; - - stats->v[ST_CPU_TIME] = (info->tv.end_cputime.tv_sec - - info->tv.setup_cputime.tv_sec) * 1000000000 + - info->tv.end_cputime.tv_nsec - - info->tv.setup_cputime.tv_nsec; - stats->v[ST_USER_TIME] = (info->tv.end_rusage.ru_utime.tv_sec - - info->tv.setup_rusage.ru_utime.tv_sec) * - 1000000 + - info->tv.end_rusage.ru_utime.tv_usec - - info->tv.setup_rusage.ru_utime.tv_usec; - stats->v[ST_SYSTEM_TIME] = (info->tv.end_rusage.ru_stime.tv_sec - - info->tv.setup_rusage.ru_stime.tv_sec) * - 1000000 + - info->tv.end_rusage.ru_stime.tv_usec - - info->tv.setup_rusage.ru_stime.tv_usec; - - stats->v[ST_MINFLT] = info->tv.end_rusage.ru_minflt - - info->tv.setup_rusage.ru_minflt; - stats->v[ST_MAJFLT] = info->tv.end_rusage.ru_majflt - - info->tv.setup_rusage.ru_majflt; - - stats->v[ST_VCTX] = info->tv.end_rusage.ru_nvcsw - - info->tv.setup_rusage.ru_nvcsw; - stats->v[ST_INVCTX] = info->tv.end_rusage.ru_nivcsw - - info->tv.setup_rusage.ru_nivcsw; - - stats->v[ST_SIGNALS] = info->tv.end_rusage.ru_nsignals - - info->tv.setup_rusage.ru_nsignals; - - /* check last loop is enough, same as below hizip_verify_output */ - stats->v[ST_COMPRESSION_RATIO] = (double)opts->total_len / - total_out * 100; - - total_len = opts->total_len * opts->compact_run_num; - /* ST_RUN_TIME records nanoseconds */ - stats->v[ST_SPEED] = (total_len * opts->thread_num * 1000) / - (1.024 * 1.024 * stats->v[ST_RUN_TIME]); - - stats->v[ST_TOTAL_SPEED] = (total_len * opts->thread_num * 1000) / - ((stats->v[ST_RUN_TIME] + - stats->v[ST_SETUP_TIME]) * 1.024 * 1.024); - - v = stats->v[ST_RUN_TIME] + stats->v[ST_SETUP_TIME]; - stats->v[ST_CPU_IDLE] = (v - stats->v[ST_CPU_TIME]) / v * 100; - stats->v[ST_FAULTS] = stats->v[ST_MAJFLT] + stats->v[ST_MINFLT]; -} - -static void handle_sigbus(int sig) -{ - printf("SIGBUS!\n"); - _exit(0); -} - -int main(int argc, char **argv) -{ - struct test_options opts = { - .alg_type = WD_GZIP, - .op_type = WD_DIR_COMPRESS, - .q_num = 1, - .run_num = 1, - .compact_run_num = 1, - .thread_num = 1, - .sync_mode = 0, - .block_size = 512000, - .total_len = opts.block_size * 10, - .verify = false, - .verbose = false, - .is_decomp = false, - .is_stream = false, - .is_file = false, - .display_stats = STATS_PRETTY, - .children = 0, - .faults = 0, - .data_fmt = 0, - }; - struct option long_options[] = { - {"self", no_argument, 0, 0 }, - {"in", required_argument, 0, 0 }, - {"out", required_argument, 0, 0 }, - {"ilist", required_argument, 0, 0 }, - {"olist", required_argument, 0, 0 }, - {"env", no_argument, 0, 0 }, - {0, 0, 0, 0 }, - }; - int show_help = 0; - int opt, option_idx; - int self = 0; - - opts.fd_in = -1; - opts.fd_out = -1; - opts.fd_ilist = -1; - opts.fd_olist = -1; - opts.alg_type = WD_COMP_ALG_MAX; - while ((opt = getopt_long(argc, argv, COMMON_OPTSTRING "f:o:w:k:r:", - long_options, &option_idx)) != -1) { - switch (opt) { - case 0: - switch (option_idx) { - case 0: /* self */ - self = 1; - break; - case 1: /* in */ - if (optarg) { - opts.fd_in = open(optarg, O_RDONLY); - if (opts.fd_in < 0) { - printf("Fail to open %s\n", - optarg); - show_help = 1; - } else - opts.is_file = true; - } else { - printf("Input file is missing!\n"); - show_help = 1; - } - if (lseek(opts.fd_in, 0, SEEK_SET) < 0) { - printf("Fail on lseek()!\n"); - show_help = 1; - } - break; - case 2: /* out */ - if (optarg) { - opts.fd_out = open(optarg, - O_CREAT | O_WRONLY, - S_IWUSR | S_IRGRP | - S_IROTH); - if (opts.fd_out < 0) { - printf("Fail to open %s\n", - optarg); - show_help = 1; - } else - opts.is_file = true; - } else { - printf("Output file is missing!\n"); - show_help = 1; - } - if (lseek(opts.fd_out, 0, SEEK_SET) < 0) { - printf("Fail on lseek()!\n"); - show_help = 1; - } - break; - case 3: /* ilist */ - if (!optarg) { - printf("IN list file is missing!\n"); - show_help = 1; - break; - } - opts.fd_ilist = open(optarg, O_RDONLY); - if (opts.fd_ilist < 0) { - printf("Fail to open %s\n", optarg); - show_help = 1; - break; - } - opts.is_file = true; - if (lseek(opts.fd_ilist, 0, SEEK_SET) < 0) { - printf("Fail on lseek()!\n"); - show_help = 1; - break; - } - break; - case 4: /* olist */ - if (!optarg) { - printf("OUT list file is missing!\n"); - show_help = 1; - break; - } - opts.fd_olist = open(optarg, - O_CREAT | O_WRONLY, - S_IWUSR | S_IRGRP | - S_IROTH); - if (opts.fd_olist < 0) { - printf("Fail to open %s\n", optarg); - show_help = 1; - break; - } - opts.is_file = true; - if (lseek(opts.fd_olist, 0, SEEK_SET) < 0) { - printf("Fail on lseek()!\n"); - show_help = 1; - break; - } - break; - case 5: /* env */ - opts.use_env = true; - break; - default: - show_help = 1; - break; - } - break; - case 'f': - if (strcmp(optarg, "none") == 0) { - opts.display_stats = STATS_NONE; - } else if (strcmp(optarg, "csv") == 0) { - opts.display_stats = STATS_CSV; - } else if (strcmp(optarg, "pretty") == 0) { - opts.display_stats = STATS_PRETTY; - } else { - SYS_ERR_COND(1, "invalid argument to -f: '%s'\n", optarg); - break; - } - break; - case 'o': - switch (optarg[0]) { - case 'p': - opts.option |= PERFORMANCE; - break; - case 't': - opts.option |= TEST_THP; - set_thp(&opts); - break; - default: - SYS_ERR_COND(1, "invalid argument to -o: '%s'\n", optarg); - break; - } - break; - case 'c': - opts.option |= TEST_ZLIB; - break; - case 'r': - opts.children = strtol(optarg, NULL, 0); - if (opts.children < 0) - show_help = 1; - break; - case 'k': - switch (optarg[0]) { - case 'b': - opts.faults |= INJECT_SIG_BIND; - break; - case 't': - opts.faults |= INJECT_TLB_FAULT; - break; - case 'w': - opts.faults |= INJECT_SIG_WORK; - break; - default: - SYS_ERR_COND(1, "invalid argument to -k: '%s'\n", optarg); - break; - } - break; - default: - show_help = parse_common_option(opt, optarg, &opts); - break; - } - } - - signal(SIGBUS, handle_sigbus); - - if (!show_help) { - if (self) - return run_self_test(&opts); - return run_cmd(&opts); - } - - hizip_test_adjust_len(&opts); - - SYS_ERR_COND(show_help || optind > argc, - COMMON_HELP - " -f <format> output format for the statistics\n" - " 'none' do not output statistics\n" - " 'pretty' human readable format\n" - " 'csv' raw, machine readable\n" - " -o <mode> options\n" - " 'perf' prefaults the output pages\n" - " 'thp' try to enable transparent huge pages\n" - " 'zlib' use zlib instead of the device\n" - " -r <children> number of children to create\n" - " -k <mode> kill thread\n" - " 'bind' kills the process after bind\n" - " 'tlb' tries to access an unmapped buffer\n" - " 'work' kills the process while the queue is working\n", - argv[0] - ); - return 0; -} diff --git a/test/hisi_zip_test/testsuit.c b/test/hisi_zip_test/testsuit.c index ac1a5f68..e1b157a7 100644 --- a/test/hisi_zip_test/testsuit.c +++ b/test/hisi_zip_test/testsuit.c @@ -3,12 +3,22 @@ * Copyright 2020-2021 Huawei Technologies Co.,Ltd. All rights reserved. * Copyright 2020-2021 Linaro ltd. */ - #include <linux/perf_event.h> +#include <asm/unistd.h> /* For __NR_perf_event_open */ +#include <fenv.h> +#include <getopt.h> +#include <inttypes.h> +#include <math.h> #include <signal.h> +#include <time.h> +#include <sys/ioctl.h> +#include <sys/mman.h> #include <sys/types.h> #include <sys/wait.h> +#include <unistd.h> + #include "test_lib.h" +#include "wd_sched.h"
#define POLL_STRING_LEN 128
@@ -1370,3 +1380,465 @@ int run_cmd(struct test_options *opts) ret = run_one_cmd(opts); return ret; } + +int perf_event_open(struct perf_event_attr *attr, + pid_t pid, int cpu, int group_fd, + unsigned long flags) +{ + return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); +} + +unsigned long long perf_event_put(int *perf_fds, int nr_fds); + +int perf_event_get(const char *event_name, int **perf_fds, int *nr_fds) +{ + int ret; + int cpu; + FILE *fd; + int nr_cpus; + unsigned int event_id; + char event_id_file[256]; + struct perf_event_attr event = { + .type = PERF_TYPE_TRACEPOINT, + .size = sizeof(event), + .disabled = true, + }; + + *perf_fds = NULL; + *nr_fds = 0; + + nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); + if (nr_cpus <= 0) { + WD_ERR("invalid number of CPUs\n"); + return nr_cpus; + } + + ret = snprintf(event_id_file, sizeof(event_id_file), + "/sys/kernel/debug/tracing/events/%s/id", event_name); + if (ret >= sizeof(event_id_file)) { + WD_ERR("event_id buffer overflow\n"); + return -EOVERFLOW; + } + fd = fopen(event_id_file, "r"); + if (fd == NULL) { + ret = -errno; + WD_ERR("Couldn't open file %s\n", event_id_file); + return ret; + } + + if (fscanf(fd, "%d", &event_id) != 1) { + WD_ERR("Couldn't parse file %s\n", event_id_file); + return -EINVAL; + } + fclose(fd); + event.config = event_id; + + *perf_fds = calloc(nr_cpus, sizeof(int)); + if (!*perf_fds) + return -ENOMEM; + *nr_fds = nr_cpus; + + /* + * An event is bound to either a CPU or a PID. If we want both, we need + * to open the event on all CPUs. Note that we can't use a perf group + * since they have to be on the same CPU. + */ + for (cpu = 0; cpu < nr_cpus; cpu++) { + int fd = perf_event_open(&event, -1, cpu, -1, 0); + + if (fd < 0) { + WD_ERR("Couldn't get perf event %s on CPU%d: %d\n", + event_name, cpu, errno); + perf_event_put(*perf_fds, cpu); + return fd; + } + + ioctl(fd, PERF_EVENT_IOC_RESET, 0); + ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); + (*perf_fds)[cpu] = fd; + } + + return 0; +} + +/* + * Closes the perf fd and return the sample count. If it wasn't open, return 0. + */ +unsigned long long perf_event_put(int *perf_fds, int nr_fds) +{ + int ret; + int cpu; + uint64_t count, total = 0; + + if (!perf_fds) + return 0; + + for (cpu = 0; cpu < nr_fds; cpu++) { + int fd = perf_fds[cpu]; + + if (fd <= 0) { + WD_ERR("Invalid perf fd %d\n", cpu); + continue; + } + + ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); + + ret = read(fd, &count, sizeof(count)); + if (ret < sizeof(count)) + WD_ERR("Couldn't read perf event for CPU%d\n", cpu); + + total += count; + close(fd); + + } + + free(perf_fds); + return total; +} + +static void set_thp(struct test_options *opts) +{ + char *p; + char s[14]; + FILE *file; + + file = fopen("/sys/kernel/mm/transparent_hugepage/enabled", "r"); + if (!file) + goto out_err; + p = fgets(s, 14, file); + fclose(file); + if (!p) + goto out_err; + + if (strcmp(s, "never") == 0) { + printf("Cannot test THP with enable=never\n"); + return; + } + + file = fopen("/sys/kernel/mm/transparent_hugepage/defrag", "r"); + if (!file) + goto out_err; + p = fgets(s, 14, file); + fclose(file); + if (!p) + goto out_err; + + if (strcmp(s, "defer") == 0 || strcmp(s, "never") == 0) { + printf("Cannot test THP with defrag=%s\n", s); + return; + } + + return; +out_err: + printf("THP unsupported?\n"); +} + +void stat_setup(struct hizip_test_info *info) +{ + clock_gettime(CLOCK_MONOTONIC_RAW, &info->tv.setup_time); + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &info->tv.setup_cputime); + getrusage(RUSAGE_SELF, &info->tv.setup_rusage); +} + +void stat_start(struct hizip_test_info *info) +{ + clock_gettime(CLOCK_MONOTONIC_RAW, &info->tv.start_time); + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &info->tv.start_cputime); + getrusage(RUSAGE_SELF, &info->tv.start_rusage); +} + +void stat_end(struct hizip_test_info *info) +{ + struct test_options *opts = info->opts; + struct hizip_stats *stats = info->stats; + double v; + size_t total_out; + unsigned long total_len; + + total_out = __atomic_load_n(&info->total_out, __ATOMIC_ACQUIRE); + clock_gettime(CLOCK_MONOTONIC_RAW, &info->tv.end_time); + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &info->tv.end_cputime); + getrusage(RUSAGE_SELF, &info->tv.end_rusage); + + stats->v[ST_SETUP_TIME] = (info->tv.start_time.tv_sec - + info->tv.setup_time.tv_sec) * 1000000000 + + info->tv.start_time.tv_nsec - + info->tv.setup_time.tv_nsec; + stats->v[ST_RUN_TIME] = (info->tv.end_time.tv_sec - + info->tv.start_time.tv_sec) * 1000000000 + + info->tv.end_time.tv_nsec - + info->tv.start_time.tv_nsec; + + stats->v[ST_CPU_TIME] = (info->tv.end_cputime.tv_sec - + info->tv.setup_cputime.tv_sec) * 1000000000 + + info->tv.end_cputime.tv_nsec - + info->tv.setup_cputime.tv_nsec; + stats->v[ST_USER_TIME] = (info->tv.end_rusage.ru_utime.tv_sec - + info->tv.setup_rusage.ru_utime.tv_sec) * + 1000000 + + info->tv.end_rusage.ru_utime.tv_usec - + info->tv.setup_rusage.ru_utime.tv_usec; + stats->v[ST_SYSTEM_TIME] = (info->tv.end_rusage.ru_stime.tv_sec - + info->tv.setup_rusage.ru_stime.tv_sec) * + 1000000 + + info->tv.end_rusage.ru_stime.tv_usec - + info->tv.setup_rusage.ru_stime.tv_usec; + + stats->v[ST_MINFLT] = info->tv.end_rusage.ru_minflt - + info->tv.setup_rusage.ru_minflt; + stats->v[ST_MAJFLT] = info->tv.end_rusage.ru_majflt - + info->tv.setup_rusage.ru_majflt; + + stats->v[ST_VCTX] = info->tv.end_rusage.ru_nvcsw - + info->tv.setup_rusage.ru_nvcsw; + stats->v[ST_INVCTX] = info->tv.end_rusage.ru_nivcsw - + info->tv.setup_rusage.ru_nivcsw; + + stats->v[ST_SIGNALS] = info->tv.end_rusage.ru_nsignals - + info->tv.setup_rusage.ru_nsignals; + + /* check last loop is enough, same as below hizip_verify_output */ + stats->v[ST_COMPRESSION_RATIO] = (double)opts->total_len / + total_out * 100; + + total_len = opts->total_len * opts->compact_run_num; + /* ST_RUN_TIME records nanoseconds */ + stats->v[ST_SPEED] = (total_len * opts->thread_num * 1000) / + (1.024 * 1.024 * stats->v[ST_RUN_TIME]); + + stats->v[ST_TOTAL_SPEED] = (total_len * opts->thread_num * 1000) / + ((stats->v[ST_RUN_TIME] + + stats->v[ST_SETUP_TIME]) * 1.024 * 1.024); + + v = stats->v[ST_RUN_TIME] + stats->v[ST_SETUP_TIME]; + stats->v[ST_CPU_IDLE] = (v - stats->v[ST_CPU_TIME]) / v * 100; + stats->v[ST_FAULTS] = stats->v[ST_MAJFLT] + stats->v[ST_MINFLT]; +} + +static void handle_sigbus(int sig) +{ + printf("SIGBUS!\n"); + _exit(0); +} + +int main(int argc, char **argv) +{ + struct test_options opts = { + .alg_type = WD_GZIP, + .op_type = WD_DIR_COMPRESS, + .q_num = 1, + .run_num = 1, + .compact_run_num = 1, + .thread_num = 1, + .sync_mode = 0, + .block_size = 512000, + .total_len = opts.block_size * 10, + .verify = false, + .verbose = false, + .is_decomp = false, + .is_stream = false, + .is_file = false, + .display_stats = STATS_PRETTY, + .children = 0, + .faults = 0, + .data_fmt = 0, + }; + struct option long_options[] = { + {"self", no_argument, 0, 0 }, + {"in", required_argument, 0, 0 }, + {"out", required_argument, 0, 0 }, + {"ilist", required_argument, 0, 0 }, + {"olist", required_argument, 0, 0 }, + {"env", no_argument, 0, 0 }, + {0, 0, 0, 0 }, + }; + int show_help = 0; + int opt, option_idx; + int self = 0; + + opts.fd_in = -1; + opts.fd_out = -1; + opts.fd_ilist = -1; + opts.fd_olist = -1; + opts.alg_type = WD_COMP_ALG_MAX; + while ((opt = getopt_long(argc, argv, COMMON_OPTSTRING "f:o:w:k:r:", + long_options, &option_idx)) != -1) { + switch (opt) { + case 0: + switch (option_idx) { + case 0: /* self */ + self = 1; + break; + case 1: /* in */ + if (optarg) { + opts.fd_in = open(optarg, O_RDONLY); + if (opts.fd_in < 0) { + printf("Fail to open %s\n", + optarg); + show_help = 1; + } else + opts.is_file = true; + } else { + printf("Input file is missing!\n"); + show_help = 1; + } + if (lseek(opts.fd_in, 0, SEEK_SET) < 0) { + printf("Fail on lseek()!\n"); + show_help = 1; + } + break; + case 2: /* out */ + if (optarg) { + opts.fd_out = open(optarg, + O_CREAT | O_WRONLY, + S_IWUSR | S_IRGRP | + S_IROTH); + if (opts.fd_out < 0) { + printf("Fail to open %s\n", + optarg); + show_help = 1; + } else + opts.is_file = true; + } else { + printf("Output file is missing!\n"); + show_help = 1; + } + if (lseek(opts.fd_out, 0, SEEK_SET) < 0) { + printf("Fail on lseek()!\n"); + show_help = 1; + } + break; + case 3: /* ilist */ + if (!optarg) { + printf("IN list file is missing!\n"); + show_help = 1; + break; + } + opts.fd_ilist = open(optarg, O_RDONLY); + if (opts.fd_ilist < 0) { + printf("Fail to open %s\n", optarg); + show_help = 1; + break; + } + opts.is_file = true; + if (lseek(opts.fd_ilist, 0, SEEK_SET) < 0) { + printf("Fail on lseek()!\n"); + show_help = 1; + break; + } + break; + case 4: /* olist */ + if (!optarg) { + printf("OUT list file is missing!\n"); + show_help = 1; + break; + } + opts.fd_olist = open(optarg, + O_CREAT | O_WRONLY, + S_IWUSR | S_IRGRP | + S_IROTH); + if (opts.fd_olist < 0) { + printf("Fail to open %s\n", optarg); + show_help = 1; + break; + } + opts.is_file = true; + if (lseek(opts.fd_olist, 0, SEEK_SET) < 0) { + printf("Fail on lseek()!\n"); + show_help = 1; + break; + } + break; + case 5: /* env */ + opts.use_env = true; + break; + default: + show_help = 1; + break; + } + break; + case 'f': + if (strcmp(optarg, "none") == 0) { + opts.display_stats = STATS_NONE; + } else if (strcmp(optarg, "csv") == 0) { + opts.display_stats = STATS_CSV; + } else if (strcmp(optarg, "pretty") == 0) { + opts.display_stats = STATS_PRETTY; + } else { + SYS_ERR_COND(1, "invalid argument to -f: '%s'\n", optarg); + break; + } + break; + case 'o': + switch (optarg[0]) { + case 'p': + opts.option |= PERFORMANCE; + break; + case 't': + opts.option |= TEST_THP; + set_thp(&opts); + break; + default: + SYS_ERR_COND(1, "invalid argument to -o: '%s'\n", optarg); + break; + } + break; + case 'c': + opts.option |= TEST_ZLIB; + break; + case 'r': + opts.children = strtol(optarg, NULL, 0); + if (opts.children < 0) + show_help = 1; + break; + case 'k': + switch (optarg[0]) { + case 'b': + opts.faults |= INJECT_SIG_BIND; + break; + case 't': + opts.faults |= INJECT_TLB_FAULT; + break; + case 'w': + opts.faults |= INJECT_SIG_WORK; + break; + default: + SYS_ERR_COND(1, "invalid argument to -k: '%s'\n", optarg); + break; + } + break; + default: + show_help = parse_common_option(opt, optarg, &opts); + break; + } + } + + signal(SIGBUS, handle_sigbus); + + if (!show_help) { + if (self) + return run_self_test(&opts); + return run_cmd(&opts); + } + + hizip_test_adjust_len(&opts); + + SYS_ERR_COND(show_help || optind > argc, + COMMON_HELP + " -f <format> output format for the statistics\n" + " 'none' do not output statistics\n" + " 'pretty' human readable format\n" + " 'csv' raw, machine readable\n" + " -o <mode> options\n" + " 'perf' prefaults the output pages\n" + " 'thp' try to enable transparent huge pages\n" + " 'zlib' use zlib instead of the device\n" + " -r <children> number of children to create\n" + " -k <mode> kill thread\n" + " 'bind' kills the process after bind\n" + " 'tlb' tries to access an unmapped buffer\n" + " 'work' kills the process while the queue is working\n", + argv[0] + ); + return 0; +} \ No newline at end of file
From: Wenkai Lin linwenkai6@hisilicon.com
For aead stream mode, the final message is not sent to hardware when the qm V3 version is used or when the length of the message is 0, so software compute check should return true to stop qm_recv process.
Signed-off-by: Wenkai Lin linwenkai6@hisilicon.com --- drv/hisi_sec.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index 63775869..9d698316 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -2647,8 +2647,17 @@ static void parse_aead_bd2(struct hisi_qp *qp, struct hisi_sec_sqe *sqe, static bool soft_compute_check(struct hisi_qp *qp, struct wd_aead_msg *msg) { /* Asynchronous mode does not use the sent message, so ignores it */ - if (msg->cmode == WD_CIPHER_GCM) - return (msg->msg_state == AEAD_MSG_END) && qp->q_info.qp_mode == CTX_MODE_SYNC; + if (qp->q_info.qp_mode == CTX_MODE_ASYNC) + return false; + /* + * For aead gcm stream mode, due to some hardware limitations, + * the final message was not sent to hardware if the qm is + * not higher than v3 version or the input length of the + * message is 0, the software calculation has been executed. + */ + if (msg->msg_state == AEAD_MSG_END && msg->cmode == WD_CIPHER_GCM && + (qp->q_info.hw_type <= HISI_QM_API_VER3_BASE || !msg->in_bytes)) + return true;
return false; }
From: Longfang Liu liulongfang@huawei.com
Upstream: Yes Bugfix or Feature: Bugfix DTS:DTS2024073110036
There are some previously undiscovered issues in these code files. These issues include: 1. Unchecked function return value 2. Unverified external input parameters 3. Illegal assignment operation
Therefore, it needs to be fixed.
Signed-off-by: Longfang Liu liulongfang@huawei.com --- drv/hisi_comp.c | 2 ++ wd_ecc.c | 6 +++--- wd_util.c | 11 +++++++++-- 3 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/drv/hisi_comp.c b/drv/hisi_comp.c index c5569986..b4c216fa 100644 --- a/drv/hisi_comp.c +++ b/drv/hisi_comp.c @@ -510,6 +510,8 @@ static int fill_buf_lz77_zstd_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe, fill_buf_type_sgl(sqe);
seq_start = get_seq_start_list(req); + if (unlikely(!seq_start)) + return -WD_EINVAL;
data->literals_start = req->list_dst; data->sequences_start = seq_start; diff --git a/wd_ecc.c b/wd_ecc.c index b1712c50..292338a6 100644 --- a/wd_ecc.c +++ b/wd_ecc.c @@ -1504,7 +1504,7 @@ static int fill_ecc_msg(struct wd_ecc_msg *msg, struct wd_ecc_req *req, void *key = NULL;
memcpy(&msg->req, req, sizeof(msg->req)); - msg->hash = sess->setup.hash; + memcpy(&msg->hash, &sess->setup.hash, sizeof(msg->hash)); msg->key_bytes = sess->key_size; msg->curve_id = sess->setup.cv.cfg.id; msg->result = WD_EINVAL; @@ -1655,10 +1655,10 @@ static int set_sign_in_param(struct wd_ecc_sign_in *sin,
static int generate_random(struct wd_ecc_sess *sess, struct wd_dtb *k) { - struct wd_rand_mt rand_t = sess->setup.rand; + struct wd_rand_mt *rand_t = &sess->setup.rand; int ret;
- ret = rand_t.cb(k->data, k->dsize, rand_t.usr); + ret = rand_t->cb(k->data, k->dsize, rand_t->usr); if (ret) WD_ERR("failed to do rand cb, ret = %d!\n", ret);
diff --git a/wd_util.c b/wd_util.c index d58e8b85..e908dcb4 100644 --- a/wd_util.c +++ b/wd_util.c @@ -421,8 +421,15 @@ void wd_uninit_async_request_pool(struct wd_async_msg_pool *pool) void *wd_find_msg_in_pool(struct wd_async_msg_pool *pool, int ctx_idx, __u32 tag) { - struct msg_pool *p = &pool->pools[ctx_idx]; - __u32 msg_num = p->msg_num; + struct msg_pool *p; + __u32 msg_num; + + if ((__u32)ctx_idx > pool->pool_num) { + WD_ERR("invalid: message ctx id index is %d!\n", ctx_idx); + return NULL; + } + p = &pool->pools[ctx_idx]; + msg_num = p->msg_num;
/* tag value start from 1 */ if (tag == 0 || tag > msg_num) {
From: Yang Shen shenyang39@huawei.com
Add length check of CBC_CTS mode.
Signed-off-by: Yang Shen shenyang39@huawei.com --- wd_cipher.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/wd_cipher.c b/wd_cipher.c index f6b035a5..ec6fb156 100644 --- a/wd_cipher.c +++ b/wd_cipher.c @@ -588,9 +588,10 @@ static int cipher_iv_len_check(struct wd_cipher_req *req, return ret; }
-static int cipher_len_check(handle_t h_sess, struct wd_cipher_req *req) +static int cipher_in_len_check(handle_t h_sess, struct wd_cipher_req *req) { struct wd_cipher_sess *sess = (struct wd_cipher_sess *)h_sess; + int ret = 0;
if (!req->in_bytes) { WD_ERR("invalid: cipher input length is zero!\n"); @@ -600,14 +601,27 @@ static int cipher_len_check(handle_t h_sess, struct wd_cipher_req *req) if (sess->alg != WD_CIPHER_AES && sess->alg != WD_CIPHER_SM4) return 0;
- if ((req->in_bytes & (AES_BLOCK_SIZE - 1)) && - (sess->mode == WD_CIPHER_CBC || sess->mode == WD_CIPHER_ECB)) { - WD_ERR("failed to check input bytes of AES or SM4, size = %u\n", - req->in_bytes); - return -WD_EINVAL; + switch (sess->mode) { + case WD_CIPHER_ECB: + case WD_CIPHER_CBC: + if (req->in_bytes & (AES_BLOCK_SIZE - 1)) + ret = -WD_EINVAL; + break; + case WD_CIPHER_CBC_CS1: + case WD_CIPHER_CBC_CS2: + case WD_CIPHER_CBC_CS3: + if (req->in_bytes < AES_BLOCK_SIZE) + ret = -WD_EINVAL; + break; + default: + break; }
- return 0; + if (ret) + WD_ERR("invalid: %s input bytes is %u!\n", + wd_cipher_alg_name[sess->alg][sess->mode], req->in_bytes); + + return ret; }
static int wd_cipher_check_params(handle_t h_sess, @@ -632,7 +646,7 @@ static int wd_cipher_check_params(handle_t h_sess, return -WD_EINVAL; }
- ret = cipher_len_check(h_sess, req); + ret = cipher_in_len_check(h_sess, req); if (unlikely(ret)) return ret;
From: Wenkai Lin linwenkai6@hisilicon.com
The cipher iv is incorrectly updated, as a result, the uadk fails to encrypt data. The CFB, OFB, and CTR mode are modified according to the algorithm protocol.
Signed-off-by: Wenkai Lin linwenkai6@hisilicon.com --- drv/hisi_sec.c | 40 ++++++++++++++++++++++++++++------------ wd_cipher.c | 6 ++++++ 2 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index 9d698316..bdde39fc 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -733,11 +733,14 @@ static void ctr_iv_inc(__u8 *counter, __u32 len)
static void update_iv(struct wd_cipher_msg *msg) { + __u8 i; + switch (msg->mode) { case WD_CIPHER_CBC: case WD_CIPHER_CBC_CS1: case WD_CIPHER_CBC_CS2: case WD_CIPHER_CBC_CS3: + case WD_CIPHER_CFB: if (msg->op_type == WD_CIPHER_ENCRYPTION && msg->out_bytes >= msg->iv_bytes) memcpy(msg->iv, msg->out + msg->out_bytes - @@ -748,14 +751,15 @@ static void update_iv(struct wd_cipher_msg *msg) msg->iv_bytes, msg->iv_bytes); break; case WD_CIPHER_OFB: - case WD_CIPHER_CFB: - if (msg->out_bytes >= msg->iv_bytes) - memcpy(msg->iv, msg->out + msg->out_bytes - - msg->iv_bytes, msg->iv_bytes); + if (msg->in_bytes < msg->iv_bytes) + break; + /* The iv_bytes has been checked and it is not greater than AES_BLOCK_SIZE. */ + for (i = 0; i < msg->iv_bytes; i++) + msg->iv[i] = *((__u8 *)msg->in + msg->in_bytes - msg->iv_bytes + i) ^ + *((__u8 *)msg->out + msg->out_bytes - msg->iv_bytes + i); break; case WD_CIPHER_CTR: - ctr_iv_inc(msg->iv, msg->iv_bytes >> - CTR_MODE_LEN_SHIFT); + ctr_iv_inc(msg->iv, msg->in_bytes >> CTR_MODE_LEN_SHIFT); break; default: break; @@ -764,8 +768,16 @@ static void update_iv(struct wd_cipher_msg *msg)
static void update_iv_sgl(struct wd_cipher_msg *msg) { + __u8 out[AES_BLOCK_SIZE] = {0}; + __u8 in[AES_BLOCK_SIZE] = {0}; + __u8 i; + switch (msg->mode) { case WD_CIPHER_CBC: + case WD_CIPHER_CBC_CS1: + case WD_CIPHER_CBC_CS2: + case WD_CIPHER_CBC_CS3: + case WD_CIPHER_CFB: if (msg->op_type == WD_CIPHER_ENCRYPTION && msg->out_bytes >= msg->iv_bytes) hisi_qm_sgl_copy(msg->iv, msg->out, @@ -780,16 +792,20 @@ static void update_iv_sgl(struct wd_cipher_msg *msg)
break; case WD_CIPHER_OFB: - case WD_CIPHER_CFB: - if (msg->out_bytes >= msg->iv_bytes) - hisi_qm_sgl_copy(msg->iv, msg->out, + /* The iv_bytes has been checked and it is not greater than AES_BLOCK_SIZE. */ + if (msg->in_bytes >= msg->iv_bytes) { + hisi_qm_sgl_copy(in, msg->in, + msg->in_bytes - msg->iv_bytes, + msg->iv_bytes, COPY_SGL_TO_PBUFF); + hisi_qm_sgl_copy(out, msg->out, msg->out_bytes - msg->iv_bytes, msg->iv_bytes, COPY_SGL_TO_PBUFF); - + for (i = 0; i < msg->iv_bytes; i++) + msg->iv[i] = *(in + i) ^ *(out + i); + } break; case WD_CIPHER_CTR: - ctr_iv_inc(msg->iv, msg->iv_bytes >> - CTR_MODE_LEN_SHIFT); + ctr_iv_inc(msg->iv, msg->in_bytes >> CTR_MODE_LEN_SHIFT); break; default: break; diff --git a/wd_cipher.c b/wd_cipher.c index ec6fb156..0e5de25c 100644 --- a/wd_cipher.c +++ b/wd_cipher.c @@ -646,6 +646,12 @@ static int wd_cipher_check_params(handle_t h_sess, return -WD_EINVAL; }
+ if (unlikely(req->in_bytes != req->out_bytes)) { + WD_ERR("cipher set out_bytes is error, size = %u\n", + req->out_bytes); + return -WD_EINVAL; + } + ret = cipher_in_len_check(h_sess, req); if (unlikely(ret)) return ret;
From: Wenkai Lin linwenkai6@hisilicon.com
The cipher iv is incorrectly updated, as a result, the uadk fails to encrypt data. The CFB, OFB mode are modified according to the algorithm protocol. BD2 does not support the ofb mode, it works with cipher_ofb_data_handle, so it still uses the old way to update iv.
Signed-off-by: Wenkai Lin linwenkai6@hisilicon.com --- v1/drv/hisi_sec_udrv.c | 80 +++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 17 deletions(-)
diff --git a/v1/drv/hisi_sec_udrv.c b/v1/drv/hisi_sec_udrv.c index ac6df5f9..2c7ca201 100644 --- a/v1/drv/hisi_sec_udrv.c +++ b/v1/drv/hisi_sec_udrv.c @@ -253,30 +253,76 @@ static void update_iv_from_res(__u8 *dst, __u8 *src, size_t offset, __u16 bytes, } }
-static void update_iv(struct wcrypto_cipher_msg *msg) +static int update_iv_ofb(struct wcrypto_cipher_msg *msg, size_t offset) { + __u8 out[AES_BLOCK_SIZE] = {0}; + __u8 in[AES_BLOCK_SIZE] = {0}; + __u8 iv[AES_BLOCK_SIZE] = {0}; + int ret; + __u8 i; + + /* The iv_bytes is not greater than AES_BLOCK_SIZE. */ + if (msg->data_fmt == WD_SGL_BUF) { + ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)msg->out, offset, + (void *)out, msg->iv_bytes); + if (unlikely(ret)) + return ret; + ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)msg->in, offset, + (void *)in, msg->iv_bytes); + if (unlikely(ret)) + return ret; + for (i = 0; i < msg->iv_bytes; i++) + iv[i] = in[i] ^ out[i]; + + return wd_sgl_cp_from_pbuf((struct wd_sgl *)msg->iv, 0, + (void *)iv, msg->iv_bytes); + } + + for (i = 0; i < msg->iv_bytes; i++) + msg->iv[i] = *((__u8 *)msg->in + offset + i) ^ + *((__u8 *)msg->out + offset + i); + + return 0; +} + +static void update_iv(struct wcrypto_cipher_msg *msg, int bd_type) +{ + size_t offset; + int ret; + switch (msg->mode) { case WCRYPTO_CIPHER_CBC: case WCRYPTO_CIPHER_CBC_CS1: case WCRYPTO_CIPHER_CBC_CS2: case WCRYPTO_CIPHER_CBC_CS3: - if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION && - msg->out_bytes >= msg->iv_bytes) - update_iv_from_res(msg->iv, msg->out, - msg->out_bytes - msg->iv_bytes, + case WCRYPTO_CIPHER_CFB: + /* The out_bytes is equal to the in_bytes. */ + if (msg->out_bytes < msg->iv_bytes) + break; + + offset = msg->out_bytes - msg->iv_bytes; + if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION) + update_iv_from_res(msg->iv, msg->out, offset, msg->iv_bytes, msg->data_fmt); - if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION && - msg->in_bytes >= msg->iv_bytes) - update_iv_from_res(msg->iv, msg->in, - msg->in_bytes - msg->iv_bytes, + else + update_iv_from_res(msg->iv, msg->in, offset, msg->iv_bytes, msg->data_fmt); break; case WCRYPTO_CIPHER_OFB: - case WCRYPTO_CIPHER_CFB: - if (msg->out_bytes >= msg->iv_bytes) - update_iv_from_res(msg->iv, msg->out, - msg->out_bytes - msg->iv_bytes, + /* The out_bytes is equal to the in_bytes. */ + if (msg->out_bytes < msg->iv_bytes) + break; + + offset = msg->out_bytes - msg->iv_bytes; + /* BD2 does not support the ofb mode, it works with cipher_ofb_data_handle. */ + if (bd_type == BD_TYPE2) { + update_iv_from_res(msg->iv, msg->out, offset, msg->iv_bytes, msg->data_fmt); + } else if (bd_type == BD_TYPE3) { + ret = update_iv_ofb(msg, offset); + if (unlikely(ret)) + WD_ERR("failed to update ofb iv!\n"); + } break; case WCRYPTO_CIPHER_CTR: ctr_iv_inc(msg->iv, msg->in_bytes >> CTR_MODE_LEN_SHIFT, @@ -680,8 +726,8 @@ static int cipher_param_check(struct wcrypto_cipher_msg *msg) int ret;
if (unlikely(msg->in_bytes > MAX_CIPHER_LENGTH || - !msg->in_bytes)) { - WD_ERR("input cipher len is too large!\n"); + !msg->in_bytes || msg->in_bytes != msg->out_bytes)) { + WD_ERR("failed to check input cipher len(%u)!\n", msg->in_bytes); return -WD_EINVAL; }
@@ -1849,7 +1895,7 @@ static void parse_cipher_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, sqe->type2.c_ivin_addr_l, sqe->type2.c_ivin_addr_h, cipher_msg->data_fmt);
- update_iv(cipher_msg); + update_iv(cipher_msg, BD_TYPE2);
if (cipher_msg->mode == WCRYPTO_CIPHER_OFB) cipher_ofb_data_handle(cipher_msg); @@ -1883,7 +1929,7 @@ static void parse_cipher_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, sqe->ipsec_scene.c_ivin_addr_h, cipher_msg->data_fmt);
- update_iv(cipher_msg); + update_iv(cipher_msg, BD_TYPE3); }
/*