]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/intel-ipsec-mb/LibTestApp/chained_test.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / intel-ipsec-mb / LibTestApp / chained_test.c
CommitLineData
f67539c2
TL
1/*****************************************************************************
2 Copyright (c) 2019, Intel Corporation
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice,
8 this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of Intel Corporation nor the names of its contributors
13 may be used to endorse or promote products derived from this software
14 without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*****************************************************************************/
27
28#include <stdint.h>
29#include <stdlib.h>
30#include <stdio.h>
31#include <string.h>
32#include <assert.h>
33
34#include <intel-ipsec-mb.h>
35
36#include "gcm_ctr_vectors_test.h"
37#include "utils.h"
38
39#define SHA1_BLOCK_SIZE 64
40#define SHA1_DIGEST_SIZE 20
41
42int chained_test(const enum arch_type arch, struct MB_MGR *mb_mgr);
43
44struct chained_vector {
45 const uint8_t *cipher_key; /* cipher key */
46 uint32_t cipher_key_len; /* cipher key length */
47 const uint8_t *IV; /* initialization vector */
48 const uint8_t *PT; /* plaintext */
49 uint64_t PTlen; /* plaintext length */
50 const uint8_t *CT; /* ciphertext - same length as PT */
51 const uint8_t *hash_key; /* hash key */
52 uint32_t hash_key_len; /* hash key length */
53 const uint8_t *Digest_PT; /* digest for plaintext */
54 const uint8_t *Digest_CT; /* digest for ciphertext */
55 uint32_t Digest_len; /* digest length */
56};
57
58const struct test_set {
59 JOB_CIPHER_DIRECTION dir;
60 JOB_CHAIN_ORDER order;
61 const char *set_name;
62} test_sets[] = {
63 {
64 .dir = ENCRYPT,
65 .order = CIPHER_HASH,
66 .set_name = "encrypt-hash"
67 },
68 {
69 .dir = DECRYPT,
70 .order = CIPHER_HASH,
71 .set_name = "decrypt-hash"
72 },
73 {
74 .dir = ENCRYPT,
75 .order = HASH_CIPHER,
76 .set_name = "hash-encrypt"
77 },
78 {
79 .dir = DECRYPT,
80 .order = HASH_CIPHER,
81 .set_name = "hash-decrypt"
82 },
83
84};
85
86const char *place_str[] = {"out-of-place", "in-place"};
87
88/* AES-CBC + SHA1-HMAC test vectors */
89
90/* 128-bit */
91static const uint8_t K1[] = {
92 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
93 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
94};
95static const uint8_t IV1[] = {
96 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
97 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
98};
99static const uint8_t P1[] = {
100 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
101 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
102 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
103 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
104 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
105 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
106 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
107 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
108};
109static const uint8_t C1[] = {
110 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46,
111 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
112 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee,
113 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
114 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b,
115 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
116 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09,
117 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7
118};
119static const uint8_t DP1[] = {
120 0x6F, 0xA4, 0x7D, 0x1B, 0x8E, 0xAB, 0x1D, 0xB9,
121 0x8B, 0x62, 0xC9, 0xF2, 0xDF, 0xA2, 0xCC, 0x46,
122 0x37, 0xB8, 0xD7, 0xB1
123};
124static const uint8_t DC1[] = {
125 0xDF, 0x1E, 0x5A, 0xDB, 0xE7, 0x5A, 0xAB, 0xAE,
126 0x0B, 0x98, 0x34, 0x30, 0xE8, 0x40, 0x8B, 0xB4,
127 0xDB, 0x22, 0x3A, 0x89
128};
129
130/* Same key for cipher and hash */
131static const struct chained_vector chained_vectors[] = {
132 {K1, sizeof(K1), IV1, P1, sizeof(P1), C1,
133 K1, sizeof(K1), DP1, DC1, sizeof(DP1)},
134};
135
136static int
137chained_job_ok(const JOB_AES_HMAC *job,
138 const unsigned num_vec,
139 const uint8_t *expected_text,
140 const unsigned text_len,
141 const uint8_t *received_text,
142 const uint8_t *expected_digest,
143 const unsigned digest_len,
144 const uint8_t *received_digest,
145 const uint8_t *padding,
146 const size_t sizeof_padding)
147{
148 if (job->status != STS_COMPLETED) {
149 printf("%d error status:%d, job %d",
150 __LINE__, job->status, num_vec);
151 return 0;
152 }
153
154 /* cipher checks */
155 if (memcmp(expected_text, received_text + sizeof_padding,
156 text_len)) {
157 printf("cipher %d mismatched\n", num_vec);
158 hexdump(stderr, "Received", received_text + sizeof_padding,
159 text_len);
160 hexdump(stderr, "Expected", expected_text,
161 text_len);
162 return 0;
163 }
164
165 if (memcmp(padding, received_text, sizeof_padding)) {
166 printf("cipher %d overwrite head\n", num_vec);
167 hexdump(stderr, "Target", received_text, sizeof_padding);
168 return 0;
169 }
170
171 if (memcmp(padding,
172 received_text + sizeof_padding + text_len,
173 sizeof_padding)) {
174 printf("cipher %d overwrite tail\n", num_vec);
175 hexdump(stderr, "Target",
176 received_text + sizeof_padding + text_len,
177 sizeof_padding);
178 return 0;
179 }
180
181 /* hash checks */
182 if (memcmp(expected_digest, received_digest + sizeof_padding,
183 digest_len)) {
184 printf("hash %d mismatched\n", num_vec);
185 hexdump(stderr, "Received", received_digest + sizeof_padding,
186 digest_len);
187 hexdump(stderr, "Expected", expected_digest,
188 digest_len);
189 return 0;
190 }
191
192 if (memcmp(padding, received_digest, sizeof_padding)) {
193 printf("hash %d overwrite head\n", num_vec);
194 hexdump(stderr, "Target", received_digest, sizeof_padding);
195 return 0;
196 }
197
198 if (memcmp(padding, received_digest + sizeof_padding + digest_len,
199 sizeof_padding)) {
200 printf("hash %d overwrite tail\n", num_vec);
201 hexdump(stderr, "Target",
202 received_digest + sizeof_padding + digest_len,
203 sizeof_padding);
204 return 0;
205 }
206
207
208 return 1;
209}
210
211static int
212test_chained_many(struct MB_MGR *mb_mgr,
213 const void *enc_keys,
214 const void *dec_keys,
215 const struct chained_vector *vec,
216 JOB_CIPHER_DIRECTION dir,
217 JOB_CHAIN_ORDER order,
218 JOB_CIPHER_MODE cipher,
219 JOB_HASH_ALG hash,
220 const void *ipad_hash,
221 const void *opad_hash,
222 const unsigned in_place,
223 const unsigned num_jobs)
224{
225 struct JOB_AES_HMAC *job;
226 uint8_t padding[16];
227 uint8_t **targets = NULL;
228 uint8_t **auths = NULL;
229 unsigned i, jobs_rx = 0;
230 int ret = -1;
231 const unsigned cipher_key_size = vec->cipher_key_len;
232 const void *iv = vec->IV;
233 const unsigned text_len = (unsigned) vec->PTlen;
234 const unsigned digest_size = vec->Digest_len;
235 const uint8_t *in_text = (dir == ENCRYPT) ? vec->PT : vec->CT;
236 const uint8_t *out_text = (dir == ENCRYPT) ? vec->CT : vec->PT;
237 const uint8_t *digest;
238
239 if (num_jobs == 0)
240 return 0;
241
242 if ((dir == ENCRYPT && order == CIPHER_HASH) ||
243 (dir == DECRYPT && order == HASH_CIPHER))
244 digest = vec->Digest_CT;
245 else
246 digest = vec->Digest_PT;
247
248 targets = malloc(num_jobs * sizeof(void *));
249 if (targets == NULL) {
250 fprintf(stderr, "Can't allocate memory for targets array\n");
251 goto end;
252 }
253 memset(targets, 0, num_jobs * sizeof(void *));
254 auths = malloc(num_jobs * sizeof(void *));
255 if (auths == NULL) {
256 fprintf(stderr, "Can't allocate memory for auths array\n");
257 goto end;
258 }
259 memset(auths, 0, num_jobs * sizeof(void *));
260
261 memset(padding, -1, sizeof(padding));
262
263 for (i = 0; i < num_jobs; i++) {
264 targets[i] = malloc(text_len + (sizeof(padding) * 2));
265 if (targets[i] == NULL) {
266 fprintf(stderr, "Can't allocate buffer memory\n");
267 goto end;
268 }
269 memset(targets[i], -1, text_len + (sizeof(padding) * 2));
270 if (in_place) {
271 /* copy input text to the allocated buffer */
272 memcpy(targets[i] + sizeof(padding), in_text, text_len);
273 }
274
275 auths[i] = malloc(digest_size + (sizeof(padding) * 2));
276 if (auths[i] == NULL) {
277 fprintf(stderr, "Can't allocate buffer memory\n");
278 goto end;
279 }
280 memset(auths[i], -1, digest_size + (sizeof(padding) * 2));
281 }
282
283 /* flush the scheduler */
284 while ((job = IMB_FLUSH_JOB(mb_mgr)) != NULL)
285 ;
286
287 for (i = 0; i < num_jobs; i++) {
288 job = IMB_GET_NEXT_JOB(mb_mgr);
289 job->cipher_direction = dir;
290 job->chain_order = order;
291 if (in_place) {
292 job->dst = targets[i] + sizeof(padding);
293 job->src = targets[i] + sizeof(padding);
294 } else {
295 job->dst = targets[i] + sizeof(padding);
296 job->src = in_text;
297 }
298 job->cipher_mode = cipher;
299 job->aes_enc_key_expanded = enc_keys;
300 job->aes_dec_key_expanded = dec_keys;
301 job->aes_key_len_in_bytes = cipher_key_size;
302
303 job->iv = iv;
304 job->iv_len_in_bytes = 16;
305 job->cipher_start_src_offset_in_bytes = 0;
306 job->msg_len_to_cipher_in_bytes = text_len;
307 job->user_data = (void *)((uint64_t)i);
308
309 job->hash_alg = hash;
310 job->auth_tag_output = auths[i] + sizeof(padding);
311 job->auth_tag_output_len_in_bytes = digest_size;
312 /*
313 * If operation is out of place and hash operation is done
314 * after encryption/decryption, hash operation needs to be
315 * done in the destination buffer.
316 * Since hash_start_src_offset_in_bytes refers to the offset
317 * in the source buffer, this offset is set to point at
318 * the destination buffer.
319 */
320 if (!in_place && (job->chain_order == CIPHER_HASH)) {
321 const uintptr_t u_src = (const uintptr_t) job->src;
322 const uintptr_t u_dst = (const uintptr_t) job->dst;
323 const uintptr_t offset = (u_dst > u_src) ?
324 (u_dst - u_src) :
325 (UINTPTR_MAX - u_src + u_dst + 1);
326
327 job->hash_start_src_offset_in_bytes = (uint64_t)offset;
328 } else {
329 job->hash_start_src_offset_in_bytes = 0;
330 }
331 job->msg_len_to_hash_in_bytes = text_len;
332 job->u.HMAC._hashed_auth_key_xor_ipad = ipad_hash;
333 job->u.HMAC._hashed_auth_key_xor_opad = opad_hash;
334
335 job = IMB_SUBMIT_JOB(mb_mgr);
336 if (job != NULL) {
337 jobs_rx++;
338 const unsigned num =
339 (const unsigned)((uint64_t)job->user_data);
340
341 if (!chained_job_ok(job, num, out_text, text_len,
342 targets[num],
343 digest, digest_size, auths[num],
344 padding, sizeof(padding)))
345 goto end;
346 }
347 }
348
349 while ((job = IMB_FLUSH_JOB(mb_mgr)) != NULL) {
350 jobs_rx++;
351 const int num = (const unsigned)((uint64_t)job->user_data);
352
353 if (!chained_job_ok(job, num, out_text, text_len, targets[num],
354 digest, digest_size, auths[num],
355 padding, sizeof(padding)))
356 goto end;
357 }
358
359 if (jobs_rx != num_jobs) {
360 printf("Expected %d jobs, received %d\n", num_jobs, jobs_rx);
361 goto end;
362 }
363 ret = 0;
364
365 end:
366 while ((job = IMB_FLUSH_JOB(mb_mgr)) != NULL)
367 ;
368
369 for (i = 0; i < num_jobs; i++) {
370 if (targets != NULL)
371 free(targets[i]);
372 if (auths != NULL)
373 free(auths[i]);
374 }
375 free(targets);
376 free(auths);
377 return ret;
378}
379
380static int
381test_chained_vectors(struct MB_MGR *mb_mgr, const int vec_cnt,
382 const struct chained_vector *vec_tab, const char *banner,
383 const JOB_CIPHER_MODE cipher,
384 const JOB_HASH_ALG hash,
385 unsigned hash_block_size, int num_jobs)
386{
387 int vect, errors = 0;
388 DECLARE_ALIGNED(uint32_t enc_keys[15*4], 16);
389 DECLARE_ALIGNED(uint32_t dec_keys[15*4], 16);
390 uint8_t *buf = NULL;
391 uint8_t *hash_key = NULL;
392 DECLARE_ALIGNED(uint8_t ipad_hash[128], 16);
393 DECLARE_ALIGNED(uint8_t opad_hash[128], 16);
394 unsigned hash_key_len, i;
395
396 buf = malloc(hash_block_size);
397 if (buf == NULL) {
398 fprintf(stderr, "Can't allocate buffer memory\n");
399 goto exit;
400 }
401
402 hash_key = malloc(hash_block_size);
403 if (hash_key == NULL) {
404 fprintf(stderr, "Can't allocate key memory\n");
405 goto exit;
406 }
407
408 printf("%s (N jobs = %d):\n", banner, num_jobs);
409 for (vect = 0; vect < vec_cnt; vect++) {
410#ifdef DEBUG
411 printf("[%d/%d] Standard vector key_len:%d\n",
412 vect + 1, vec_cnt,
413 (int) vec_tab[vect].cipher_key_len);
414#else
415 printf(".");
416#endif
417 /* prepare the cipher key */
418 switch (vec_tab[vect].cipher_key_len) {
419 case 16:
420 IMB_AES_KEYEXP_128(mb_mgr, vec_tab[vect].cipher_key,
421 enc_keys, dec_keys);
422 break;
423 case 24:
424 IMB_AES_KEYEXP_192(mb_mgr, vec_tab[vect].cipher_key,
425 enc_keys, dec_keys);
426 break;
427 case 32:
428 default:
429 IMB_AES_KEYEXP_256(mb_mgr, vec_tab[vect].cipher_key,
430 enc_keys, dec_keys);
431 break;
432 }
433
434 /* prepare the hash key */
435 memset(hash_key, 0, hash_block_size);
436 if (vec_tab[vect].hash_key_len <= hash_block_size) {
437 memcpy(hash_key, vec_tab[vect].hash_key,
438 vec_tab[vect].hash_key_len);
439 hash_key_len = (int) vec_tab[vect].hash_key_len;
440 } else {
441 IMB_SHA1(mb_mgr, vec_tab[vect].hash_key,
442 vec_tab[vect].hash_key_len, hash_key);
443 hash_key_len = hash_block_size;
444 }
445
446 /* compute ipad hash */
447 memset(buf, 0x36, hash_block_size);
448 for (i = 0; i < hash_key_len; i++)
449 buf[i] ^= hash_key[i];
450 IMB_SHA1_ONE_BLOCK(mb_mgr, buf, ipad_hash);
451
452 /* compute opad hash */
453 memset(buf, 0x5c, hash_block_size);
454 for (i = 0; i < hash_key_len; i++)
455 buf[i] ^= hash_key[i];
456 IMB_SHA1_ONE_BLOCK(mb_mgr, buf, opad_hash);
457
458 for (i = 0; i < DIM(test_sets); i++) {
459 unsigned in_place;
460
461 for (in_place = 0; in_place < DIM(place_str);
462 in_place++) {
463 if (test_chained_many(mb_mgr,
464 enc_keys, dec_keys,
465 &vec_tab[vect],
466 test_sets[i].dir,
467 test_sets[i].order,
468 cipher, hash,
469 ipad_hash, opad_hash,
470 in_place, num_jobs)) {
471 printf("error #%d %s %s\n", vect + 1,
472 test_sets[i].set_name,
473 place_str[in_place]);
474 errors++;
475 }
476 }
477 }
478 }
479 printf("\n");
480
481exit:
482 free(buf);
483 free(hash_key);
484 return errors;
485}
486
487int
488chained_test(const enum arch_type arch,
489 struct MB_MGR *mb_mgr)
490{
491 const int num_jobs_tab[] = {
492 1, 3, 4, 5, 7, 8, 9, 15, 16, 17
493 };
494 unsigned i;
495 int errors = 0;
496
497 (void) arch; /* unused */
498
499 for (i = 0; i < DIM(num_jobs_tab); i++)
500 errors += test_chained_vectors(mb_mgr, DIM(chained_vectors),
501 chained_vectors,
502 "AES-CBC + SHA1-HMAC standard test vectors",
503 CBC, SHA1, SHA1_BLOCK_SIZE,
504 num_jobs_tab[i]);
505 if (0 == errors)
506 printf("...Pass\n");
507 else
508 printf("...Fail\n");
509
510 return errors;
511}