Path: blob/master/tools/testing/crypto/chacha20-s390/test-cipher.c
26288 views
/* SPDX-License-Identifier: GPL-2.01*2* Copyright (C) 2022 Red Hat, Inc.3* Author: Vladis Dronov <[email protected]>4*/56#include <asm/elf.h>7#include <asm/uaccess.h>8#include <asm/smp.h>9#include <crypto/skcipher.h>10#include <crypto/akcipher.h>11#include <crypto/acompress.h>12#include <crypto/rng.h>13#include <crypto/drbg.h>14#include <crypto/kpp.h>15#include <crypto/internal/simd.h>16#include <crypto/chacha.h>17#include <crypto/aead.h>18#include <crypto/hash.h>19#include <linux/crypto.h>20#include <linux/debugfs.h>21#include <linux/delay.h>22#include <linux/err.h>23#include <linux/fs.h>24#include <linux/fips.h>25#include <linux/kernel.h>26#include <linux/kthread.h>27#include <linux/module.h>28#include <linux/sched.h>29#include <linux/scatterlist.h>30#include <linux/time.h>31#include <linux/vmalloc.h>32#include <linux/zlib.h>33#include <linux/once.h>34#include <linux/random.h>35#include <linux/slab.h>36#include <linux/string.h>3738static unsigned int data_size __read_mostly = 256;39static unsigned int debug __read_mostly = 0;4041/* tie all skcipher structures together */42struct skcipher_def {43struct scatterlist sginp, sgout;44struct crypto_skcipher *tfm;45struct skcipher_request *req;46struct crypto_wait wait;47};4849/* Perform cipher operations with the chacha lib */50static int test_lib_chacha(u8 *revert, u8 *cipher, u8 *plain)51{52struct chacha_state chacha_state;53u8 iv[16], key[32];54u64 start, end;5556memset(key, 'X', sizeof(key));57memset(iv, 'I', sizeof(iv));5859if (debug) {60print_hex_dump(KERN_INFO, "key: ", DUMP_PREFIX_OFFSET,6116, 1, key, 32, 1);6263print_hex_dump(KERN_INFO, "iv: ", DUMP_PREFIX_OFFSET,6416, 1, iv, 16, 1);65}6667/* Encrypt */68chacha_init(&chacha_state, (u32 *)key, iv);6970start = ktime_get_ns();71chacha_crypt_arch(&chacha_state, cipher, plain, data_size, 20);72end = ktime_get_ns();737475if (debug)76print_hex_dump(KERN_INFO, "encr:", DUMP_PREFIX_OFFSET,7716, 1, cipher,78(data_size > 64 ? 64 : data_size), 1);7980pr_info("lib encryption took: %lld nsec", end - start);8182/* Decrypt */83chacha_init(&chacha_state, (u32 *)key, iv);8485start = ktime_get_ns();86chacha_crypt_arch(&chacha_state, revert, cipher, data_size, 20);87end = ktime_get_ns();8889if (debug)90print_hex_dump(KERN_INFO, "decr:", DUMP_PREFIX_OFFSET,9116, 1, revert,92(data_size > 64 ? 64 : data_size), 1);9394pr_info("lib decryption took: %lld nsec", end - start);9596return 0;97}9899/* Perform cipher operations with skcipher */100static unsigned int test_skcipher_encdec(struct skcipher_def *sk,101int enc)102{103int rc;104105if (enc) {106rc = crypto_wait_req(crypto_skcipher_encrypt(sk->req),107&sk->wait);108if (rc)109pr_info("skcipher encrypt returned with result"110"%d\n", rc);111}112else113{114rc = crypto_wait_req(crypto_skcipher_decrypt(sk->req),115&sk->wait);116if (rc)117pr_info("skcipher decrypt returned with result"118"%d\n", rc);119}120121return rc;122}123124/* Initialize and trigger cipher operations */125static int test_skcipher(char *name, u8 *revert, u8 *cipher, u8 *plain)126{127struct skcipher_def sk;128struct crypto_skcipher *skcipher = NULL;129struct skcipher_request *req = NULL;130u8 iv[16], key[32];131u64 start, end;132int ret = -EFAULT;133134skcipher = crypto_alloc_skcipher(name, 0, 0);135if (IS_ERR(skcipher)) {136pr_info("could not allocate skcipher %s handle\n", name);137return PTR_ERR(skcipher);138}139140req = skcipher_request_alloc(skcipher, GFP_KERNEL);141if (!req) {142pr_info("could not allocate skcipher request\n");143ret = -ENOMEM;144goto out;145}146147skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,148crypto_req_done,149&sk.wait);150151memset(key, 'X', sizeof(key));152memset(iv, 'I', sizeof(iv));153154if (crypto_skcipher_setkey(skcipher, key, 32)) {155pr_info("key could not be set\n");156ret = -EAGAIN;157goto out;158}159160if (debug) {161print_hex_dump(KERN_INFO, "key: ", DUMP_PREFIX_OFFSET,16216, 1, key, 32, 1);163164print_hex_dump(KERN_INFO, "iv: ", DUMP_PREFIX_OFFSET,16516, 1, iv, 16, 1);166}167168sk.tfm = skcipher;169sk.req = req;170171/* Encrypt in one pass */172sg_init_one(&sk.sginp, plain, data_size);173sg_init_one(&sk.sgout, cipher, data_size);174skcipher_request_set_crypt(req, &sk.sginp, &sk.sgout,175data_size, iv);176crypto_init_wait(&sk.wait);177178/* Encrypt data */179start = ktime_get_ns();180ret = test_skcipher_encdec(&sk, 1);181end = ktime_get_ns();182183if (ret)184goto out;185186pr_info("%s tfm encryption successful, took %lld nsec\n", name, end - start);187188if (debug)189print_hex_dump(KERN_INFO, "encr:", DUMP_PREFIX_OFFSET,19016, 1, cipher,191(data_size > 64 ? 64 : data_size), 1);192193/* Prepare for decryption */194memset(iv, 'I', sizeof(iv));195196sg_init_one(&sk.sginp, cipher, data_size);197sg_init_one(&sk.sgout, revert, data_size);198skcipher_request_set_crypt(req, &sk.sginp, &sk.sgout,199data_size, iv);200crypto_init_wait(&sk.wait);201202/* Decrypt data */203start = ktime_get_ns();204ret = test_skcipher_encdec(&sk, 0);205end = ktime_get_ns();206207if (ret)208goto out;209210pr_info("%s tfm decryption successful, took %lld nsec\n", name, end - start);211212if (debug)213print_hex_dump(KERN_INFO, "decr:", DUMP_PREFIX_OFFSET,21416, 1, revert,215(data_size > 64 ? 64 : data_size), 1);216217/* Dump some internal skcipher data */218if (debug)219pr_info("skcipher %s: cryptlen %d blksize %d stride %d "220"ivsize %d alignmask 0x%x\n",221name, sk.req->cryptlen,222crypto_skcipher_blocksize(sk.tfm),223crypto_skcipher_alg(sk.tfm)->walksize,224crypto_skcipher_ivsize(sk.tfm),225crypto_skcipher_alignmask(sk.tfm));226227out:228if (skcipher)229crypto_free_skcipher(skcipher);230if (req)231skcipher_request_free(req);232return ret;233}234235static int __init chacha_s390_test_init(void)236{237u8 *plain = NULL, *revert = NULL;238u8 *cipher_generic = NULL, *cipher_s390 = NULL;239int ret = -1;240241pr_info("s390 ChaCha20 test module: size=%d debug=%d\n",242data_size, debug);243244/* Allocate and fill buffers */245plain = vmalloc(data_size);246if (!plain) {247pr_info("could not allocate plain buffer\n");248ret = -2;249goto out;250}251memset(plain, 'a', data_size);252get_random_bytes(plain, (data_size > 256 ? 256 : data_size));253254cipher_generic = vzalloc(data_size);255if (!cipher_generic) {256pr_info("could not allocate cipher_generic buffer\n");257ret = -2;258goto out;259}260261cipher_s390 = vzalloc(data_size);262if (!cipher_s390) {263pr_info("could not allocate cipher_s390 buffer\n");264ret = -2;265goto out;266}267268revert = vzalloc(data_size);269if (!revert) {270pr_info("could not allocate revert buffer\n");271ret = -2;272goto out;273}274275if (debug)276print_hex_dump(KERN_INFO, "src: ", DUMP_PREFIX_OFFSET,27716, 1, plain,278(data_size > 64 ? 64 : data_size), 1);279280/* Use chacha20 generic */281ret = test_skcipher("chacha20-generic", revert, cipher_generic, plain);282if (ret)283goto out;284285if (memcmp(plain, revert, data_size)) {286pr_info("generic en/decryption check FAILED\n");287ret = -2;288goto out;289}290else291pr_info("generic en/decryption check OK\n");292293memset(revert, 0, data_size);294295/* Use chacha20 s390 */296ret = test_skcipher("chacha20-s390", revert, cipher_s390, plain);297if (ret)298goto out;299300if (memcmp(plain, revert, data_size)) {301pr_info("s390 en/decryption check FAILED\n");302ret = -2;303goto out;304}305else306pr_info("s390 en/decryption check OK\n");307308if (memcmp(cipher_generic, cipher_s390, data_size)) {309pr_info("s390 vs generic check FAILED\n");310ret = -2;311goto out;312}313else314pr_info("s390 vs generic check OK\n");315316memset(cipher_s390, 0, data_size);317memset(revert, 0, data_size);318319/* Use chacha20 lib */320test_lib_chacha(revert, cipher_s390, plain);321322if (memcmp(plain, revert, data_size)) {323pr_info("lib en/decryption check FAILED\n");324ret = -2;325goto out;326}327else328pr_info("lib en/decryption check OK\n");329330if (memcmp(cipher_generic, cipher_s390, data_size)) {331pr_info("lib vs generic check FAILED\n");332ret = -2;333goto out;334}335else336pr_info("lib vs generic check OK\n");337338pr_info("--- chacha20 s390 test end ---\n");339340out:341if (plain)342vfree(plain);343if (cipher_generic)344vfree(cipher_generic);345if (cipher_s390)346vfree(cipher_s390);347if (revert)348vfree(revert);349350return -1;351}352353static void __exit chacha_s390_test_exit(void)354{355pr_info("s390 ChaCha20 test module exit\n");356}357358module_param_named(size, data_size, uint, 0660);359module_param(debug, int, 0660);360MODULE_PARM_DESC(size, "Size of a plaintext");361MODULE_PARM_DESC(debug, "Debug level (0=off,1=on)");362363module_init(chacha_s390_test_init);364module_exit(chacha_s390_test_exit);365366MODULE_DESCRIPTION("s390 ChaCha20 self-test");367MODULE_AUTHOR("Vladis Dronov <[email protected]>");368MODULE_LICENSE("GPL v2");369370371