crypto: implement rfc4231 test cases
[vpp.git] / src / plugins / unittest / crypto_test.c
1 /*
2  * Copyright (c) 2019 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vlib/vlib.h>
16 #include <vppinfra/time.h>
17 #include <vppinfra/cache.h>
18 #include <vppinfra/error.h>
19 #include <vnet/crypto/crypto.h>
20 #include <unittest/crypto/crypto.h>
21
22 crypto_test_main_t crypto_test_main;
23
24 static int
25 sort_registrations (void *a0, void *a1)
26 {
27   unittest_crypto_test_registration_t **r0 = a0;
28   unittest_crypto_test_registration_t **r1 = a1;
29
30   return (r0[0]->op > r1[0]->op);
31 }
32
33 static clib_error_t *
34 test_crypto (vlib_main_t * vm, crypto_test_main_t * tm)
35 {
36   unittest_crypto_test_registration_t *r = tm->test_registrations;
37   unittest_crypto_test_registration_t **rv = 0;
38   vnet_crypto_op_t *ops = 0, *op;
39   u8 *computed_data = 0, *s = 0;
40   u32 computed_data_total_len = 0, n_tests = 0;
41   u32 i;
42
43   /* construct registration vector */
44   while (r)
45     {
46       vec_add1 (rv, r);
47       computed_data_total_len += r->data.length;
48       n_tests += 1;
49       /* next */
50       r = r->next;
51     }
52
53   vec_sort_with_function (rv, sort_registrations);
54
55   vec_validate_aligned (computed_data, computed_data_total_len - 1,
56                         CLIB_CACHE_LINE_BYTES);
57   vec_validate_aligned (ops, n_tests - 1, CLIB_CACHE_LINE_BYTES);
58   computed_data_total_len = 0;
59
60   /* *INDENT-OFF* */
61   vec_foreach_index (i, rv)
62     {
63       r = rv[i];
64       op  = ops + i;
65       op->op = r->op;
66       op->iv = r->iv.data;
67       op->key = r->key.data;
68       op->src = r->data.data;
69       op->dst = computed_data + computed_data_total_len;
70       op->len = r->data.length;
71       op->key_len = r->key.length;
72       op->hmac_trunc_len = r->hmac_trunc_len;
73       computed_data_total_len += r->expected.length;
74       /* next */
75       r = r->next;
76     }
77   /* *INDENT-ON* */
78
79   vnet_crypto_process_ops (vm, ops, vec_len (ops));
80
81   /* *INDENT-OFF* */
82   vec_foreach_index (i, rv)
83     {
84       int fail = 0;
85       r = rv[i];
86       op  = ops + i;
87
88       if (memcmp (op->dst, r->expected.data, r->expected.length) != 0)
89         fail = 1;
90
91       vec_reset_length (s);
92       s = format (s, "%s (%U)", r->name,
93                        format_vnet_crypto_op, r->op);
94
95       vlib_cli_output (vm, "%-60v%s", s, fail ? "FAIL" : "OK");
96       if (fail & tm->verbose)
97         {
98            vlib_cli_output (vm, "Expected:\n%U\nCalculated:\n%U",
99                             format_hexdump, r->expected.data, r->expected.length,
100                             format_hexdump, op->dst, r->expected.length);
101         }
102     }
103   /* *INDENT-ON* */
104
105   vec_free (computed_data);
106   vec_free (ops);
107   vec_free (rv);
108   vec_free (s);
109   return 0;
110 }
111
112 static clib_error_t *
113 test_crypto_command_fn (vlib_main_t * vm,
114                         unformat_input_t * input, vlib_cli_command_t * cmd)
115 {
116   crypto_test_main_t *tm = &crypto_test_main;
117
118   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
119     {
120       if (unformat (input, "verbose %d", &tm->verbose))
121         ;
122       else
123         return clib_error_return (0, "unknown input '%U'",
124                                   format_unformat_error, input);
125     }
126
127   return test_crypto (vm, tm);
128 }
129
130 /* *INDENT-OFF* */
131 VLIB_CLI_COMMAND (test_crypto_command, static) =
132 {
133   .path = "test crypto",
134   .short_help = "test crypto",
135   .function = test_crypto_command_fn,
136 };
137 /* *INDENT-ON* */
138
139 static clib_error_t *
140 crypto_test_init (vlib_main_t * vm)
141 {
142   return (0);
143 }
144
145 VLIB_INIT_FUNCTION (crypto_test_init);
146
147 /*
148  * fd.io coding-style-patch-verification: ON
149  *
150  * Local Variables:
151  * eval: (c-set-style "gnu")
152  * End:
153  */