Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/crypto/chacha20-s390/test-cipher.c
26288 views
1
/* SPDX-License-Identifier: GPL-2.0
2
*
3
* Copyright (C) 2022 Red Hat, Inc.
4
* Author: Vladis Dronov <[email protected]>
5
*/
6
7
#include <asm/elf.h>
8
#include <asm/uaccess.h>
9
#include <asm/smp.h>
10
#include <crypto/skcipher.h>
11
#include <crypto/akcipher.h>
12
#include <crypto/acompress.h>
13
#include <crypto/rng.h>
14
#include <crypto/drbg.h>
15
#include <crypto/kpp.h>
16
#include <crypto/internal/simd.h>
17
#include <crypto/chacha.h>
18
#include <crypto/aead.h>
19
#include <crypto/hash.h>
20
#include <linux/crypto.h>
21
#include <linux/debugfs.h>
22
#include <linux/delay.h>
23
#include <linux/err.h>
24
#include <linux/fs.h>
25
#include <linux/fips.h>
26
#include <linux/kernel.h>
27
#include <linux/kthread.h>
28
#include <linux/module.h>
29
#include <linux/sched.h>
30
#include <linux/scatterlist.h>
31
#include <linux/time.h>
32
#include <linux/vmalloc.h>
33
#include <linux/zlib.h>
34
#include <linux/once.h>
35
#include <linux/random.h>
36
#include <linux/slab.h>
37
#include <linux/string.h>
38
39
static unsigned int data_size __read_mostly = 256;
40
static unsigned int debug __read_mostly = 0;
41
42
/* tie all skcipher structures together */
43
struct skcipher_def {
44
struct scatterlist sginp, sgout;
45
struct crypto_skcipher *tfm;
46
struct skcipher_request *req;
47
struct crypto_wait wait;
48
};
49
50
/* Perform cipher operations with the chacha lib */
51
static int test_lib_chacha(u8 *revert, u8 *cipher, u8 *plain)
52
{
53
struct chacha_state chacha_state;
54
u8 iv[16], key[32];
55
u64 start, end;
56
57
memset(key, 'X', sizeof(key));
58
memset(iv, 'I', sizeof(iv));
59
60
if (debug) {
61
print_hex_dump(KERN_INFO, "key: ", DUMP_PREFIX_OFFSET,
62
16, 1, key, 32, 1);
63
64
print_hex_dump(KERN_INFO, "iv: ", DUMP_PREFIX_OFFSET,
65
16, 1, iv, 16, 1);
66
}
67
68
/* Encrypt */
69
chacha_init(&chacha_state, (u32 *)key, iv);
70
71
start = ktime_get_ns();
72
chacha_crypt_arch(&chacha_state, cipher, plain, data_size, 20);
73
end = ktime_get_ns();
74
75
76
if (debug)
77
print_hex_dump(KERN_INFO, "encr:", DUMP_PREFIX_OFFSET,
78
16, 1, cipher,
79
(data_size > 64 ? 64 : data_size), 1);
80
81
pr_info("lib encryption took: %lld nsec", end - start);
82
83
/* Decrypt */
84
chacha_init(&chacha_state, (u32 *)key, iv);
85
86
start = ktime_get_ns();
87
chacha_crypt_arch(&chacha_state, revert, cipher, data_size, 20);
88
end = ktime_get_ns();
89
90
if (debug)
91
print_hex_dump(KERN_INFO, "decr:", DUMP_PREFIX_OFFSET,
92
16, 1, revert,
93
(data_size > 64 ? 64 : data_size), 1);
94
95
pr_info("lib decryption took: %lld nsec", end - start);
96
97
return 0;
98
}
99
100
/* Perform cipher operations with skcipher */
101
static unsigned int test_skcipher_encdec(struct skcipher_def *sk,
102
int enc)
103
{
104
int rc;
105
106
if (enc) {
107
rc = crypto_wait_req(crypto_skcipher_encrypt(sk->req),
108
&sk->wait);
109
if (rc)
110
pr_info("skcipher encrypt returned with result"
111
"%d\n", rc);
112
}
113
else
114
{
115
rc = crypto_wait_req(crypto_skcipher_decrypt(sk->req),
116
&sk->wait);
117
if (rc)
118
pr_info("skcipher decrypt returned with result"
119
"%d\n", rc);
120
}
121
122
return rc;
123
}
124
125
/* Initialize and trigger cipher operations */
126
static int test_skcipher(char *name, u8 *revert, u8 *cipher, u8 *plain)
127
{
128
struct skcipher_def sk;
129
struct crypto_skcipher *skcipher = NULL;
130
struct skcipher_request *req = NULL;
131
u8 iv[16], key[32];
132
u64 start, end;
133
int ret = -EFAULT;
134
135
skcipher = crypto_alloc_skcipher(name, 0, 0);
136
if (IS_ERR(skcipher)) {
137
pr_info("could not allocate skcipher %s handle\n", name);
138
return PTR_ERR(skcipher);
139
}
140
141
req = skcipher_request_alloc(skcipher, GFP_KERNEL);
142
if (!req) {
143
pr_info("could not allocate skcipher request\n");
144
ret = -ENOMEM;
145
goto out;
146
}
147
148
skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
149
crypto_req_done,
150
&sk.wait);
151
152
memset(key, 'X', sizeof(key));
153
memset(iv, 'I', sizeof(iv));
154
155
if (crypto_skcipher_setkey(skcipher, key, 32)) {
156
pr_info("key could not be set\n");
157
ret = -EAGAIN;
158
goto out;
159
}
160
161
if (debug) {
162
print_hex_dump(KERN_INFO, "key: ", DUMP_PREFIX_OFFSET,
163
16, 1, key, 32, 1);
164
165
print_hex_dump(KERN_INFO, "iv: ", DUMP_PREFIX_OFFSET,
166
16, 1, iv, 16, 1);
167
}
168
169
sk.tfm = skcipher;
170
sk.req = req;
171
172
/* Encrypt in one pass */
173
sg_init_one(&sk.sginp, plain, data_size);
174
sg_init_one(&sk.sgout, cipher, data_size);
175
skcipher_request_set_crypt(req, &sk.sginp, &sk.sgout,
176
data_size, iv);
177
crypto_init_wait(&sk.wait);
178
179
/* Encrypt data */
180
start = ktime_get_ns();
181
ret = test_skcipher_encdec(&sk, 1);
182
end = ktime_get_ns();
183
184
if (ret)
185
goto out;
186
187
pr_info("%s tfm encryption successful, took %lld nsec\n", name, end - start);
188
189
if (debug)
190
print_hex_dump(KERN_INFO, "encr:", DUMP_PREFIX_OFFSET,
191
16, 1, cipher,
192
(data_size > 64 ? 64 : data_size), 1);
193
194
/* Prepare for decryption */
195
memset(iv, 'I', sizeof(iv));
196
197
sg_init_one(&sk.sginp, cipher, data_size);
198
sg_init_one(&sk.sgout, revert, data_size);
199
skcipher_request_set_crypt(req, &sk.sginp, &sk.sgout,
200
data_size, iv);
201
crypto_init_wait(&sk.wait);
202
203
/* Decrypt data */
204
start = ktime_get_ns();
205
ret = test_skcipher_encdec(&sk, 0);
206
end = ktime_get_ns();
207
208
if (ret)
209
goto out;
210
211
pr_info("%s tfm decryption successful, took %lld nsec\n", name, end - start);
212
213
if (debug)
214
print_hex_dump(KERN_INFO, "decr:", DUMP_PREFIX_OFFSET,
215
16, 1, revert,
216
(data_size > 64 ? 64 : data_size), 1);
217
218
/* Dump some internal skcipher data */
219
if (debug)
220
pr_info("skcipher %s: cryptlen %d blksize %d stride %d "
221
"ivsize %d alignmask 0x%x\n",
222
name, sk.req->cryptlen,
223
crypto_skcipher_blocksize(sk.tfm),
224
crypto_skcipher_alg(sk.tfm)->walksize,
225
crypto_skcipher_ivsize(sk.tfm),
226
crypto_skcipher_alignmask(sk.tfm));
227
228
out:
229
if (skcipher)
230
crypto_free_skcipher(skcipher);
231
if (req)
232
skcipher_request_free(req);
233
return ret;
234
}
235
236
static int __init chacha_s390_test_init(void)
237
{
238
u8 *plain = NULL, *revert = NULL;
239
u8 *cipher_generic = NULL, *cipher_s390 = NULL;
240
int ret = -1;
241
242
pr_info("s390 ChaCha20 test module: size=%d debug=%d\n",
243
data_size, debug);
244
245
/* Allocate and fill buffers */
246
plain = vmalloc(data_size);
247
if (!plain) {
248
pr_info("could not allocate plain buffer\n");
249
ret = -2;
250
goto out;
251
}
252
memset(plain, 'a', data_size);
253
get_random_bytes(plain, (data_size > 256 ? 256 : data_size));
254
255
cipher_generic = vzalloc(data_size);
256
if (!cipher_generic) {
257
pr_info("could not allocate cipher_generic buffer\n");
258
ret = -2;
259
goto out;
260
}
261
262
cipher_s390 = vzalloc(data_size);
263
if (!cipher_s390) {
264
pr_info("could not allocate cipher_s390 buffer\n");
265
ret = -2;
266
goto out;
267
}
268
269
revert = vzalloc(data_size);
270
if (!revert) {
271
pr_info("could not allocate revert buffer\n");
272
ret = -2;
273
goto out;
274
}
275
276
if (debug)
277
print_hex_dump(KERN_INFO, "src: ", DUMP_PREFIX_OFFSET,
278
16, 1, plain,
279
(data_size > 64 ? 64 : data_size), 1);
280
281
/* Use chacha20 generic */
282
ret = test_skcipher("chacha20-generic", revert, cipher_generic, plain);
283
if (ret)
284
goto out;
285
286
if (memcmp(plain, revert, data_size)) {
287
pr_info("generic en/decryption check FAILED\n");
288
ret = -2;
289
goto out;
290
}
291
else
292
pr_info("generic en/decryption check OK\n");
293
294
memset(revert, 0, data_size);
295
296
/* Use chacha20 s390 */
297
ret = test_skcipher("chacha20-s390", revert, cipher_s390, plain);
298
if (ret)
299
goto out;
300
301
if (memcmp(plain, revert, data_size)) {
302
pr_info("s390 en/decryption check FAILED\n");
303
ret = -2;
304
goto out;
305
}
306
else
307
pr_info("s390 en/decryption check OK\n");
308
309
if (memcmp(cipher_generic, cipher_s390, data_size)) {
310
pr_info("s390 vs generic check FAILED\n");
311
ret = -2;
312
goto out;
313
}
314
else
315
pr_info("s390 vs generic check OK\n");
316
317
memset(cipher_s390, 0, data_size);
318
memset(revert, 0, data_size);
319
320
/* Use chacha20 lib */
321
test_lib_chacha(revert, cipher_s390, plain);
322
323
if (memcmp(plain, revert, data_size)) {
324
pr_info("lib en/decryption check FAILED\n");
325
ret = -2;
326
goto out;
327
}
328
else
329
pr_info("lib en/decryption check OK\n");
330
331
if (memcmp(cipher_generic, cipher_s390, data_size)) {
332
pr_info("lib vs generic check FAILED\n");
333
ret = -2;
334
goto out;
335
}
336
else
337
pr_info("lib vs generic check OK\n");
338
339
pr_info("--- chacha20 s390 test end ---\n");
340
341
out:
342
if (plain)
343
vfree(plain);
344
if (cipher_generic)
345
vfree(cipher_generic);
346
if (cipher_s390)
347
vfree(cipher_s390);
348
if (revert)
349
vfree(revert);
350
351
return -1;
352
}
353
354
static void __exit chacha_s390_test_exit(void)
355
{
356
pr_info("s390 ChaCha20 test module exit\n");
357
}
358
359
module_param_named(size, data_size, uint, 0660);
360
module_param(debug, int, 0660);
361
MODULE_PARM_DESC(size, "Size of a plaintext");
362
MODULE_PARM_DESC(debug, "Debug level (0=off,1=on)");
363
364
module_init(chacha_s390_test_init);
365
module_exit(chacha_s390_test_exit);
366
367
MODULE_DESCRIPTION("s390 ChaCha20 self-test");
368
MODULE_AUTHOR("Vladis Dronov <[email protected]>");
369
MODULE_LICENSE("GPL v2");
370
371