1cd964fceSMatt Barden /*
2cd964fceSMatt Barden * This file and its contents are supplied under the terms of the
3cd964fceSMatt Barden * Common Development and Distribution License ("CDDL"), version 1.0.
4cd964fceSMatt Barden * You may only use this file in accordance with the terms of version
5cd964fceSMatt Barden * 1.0 of the CDDL.
6cd964fceSMatt Barden *
7cd964fceSMatt Barden * A full copy of the text of the CDDL should have accompanied this
8cd964fceSMatt Barden * source. A copy of the CDDL is also available via the Internet at
9cd964fceSMatt Barden * http://www.illumos.org/license/CDDL.
10cd964fceSMatt Barden */
11cd964fceSMatt Barden
12cd964fceSMatt Barden /*
13cd964fceSMatt Barden * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
14*77de87d2SJason King * Copyright 2019 Joyent, Inc.
15cd964fceSMatt Barden */
16cd964fceSMatt Barden
17cd964fceSMatt Barden #define __EXTENSIONS__
18*77de87d2SJason King #include <limits.h>
19cd964fceSMatt Barden #include <strings.h>
20cd964fceSMatt Barden #include <stdlib.h>
21cd964fceSMatt Barden #include <stdio.h>
22*77de87d2SJason King #include <sys/debug.h>
23cd964fceSMatt Barden #include "cryptotest.h"
24cd964fceSMatt Barden
25*77de87d2SJason King /*
26*77de87d2SJason King * A somewhat arbitrary size that should be large enough to hold the printed
27*77de87d2SJason King * error and size messages.
28*77de87d2SJason King */
29*77de87d2SJason King #define BUFSZ 128
30*77de87d2SJason King
31*77de87d2SJason King #define EXIT_FAILURE_MULTIPART 1
32*77de87d2SJason King #define EXIT_FAILURE_SINGLEPART 2
33*77de87d2SJason King
34*77de87d2SJason King test_fg_t cryptotest_decr_fg = {
35*77de87d2SJason King .tf_fg = CRYPTO_FG_DECRYPT,
36*77de87d2SJason King .tf_init = decrypt_init,
37*77de87d2SJason King .tf_single = decrypt_single,
38*77de87d2SJason King .tf_update = decrypt_update,
39*77de87d2SJason King .tf_final = decrypt_final
40*77de87d2SJason King };
41*77de87d2SJason King
42*77de87d2SJason King test_fg_t cryptotest_encr_fg = {
43*77de87d2SJason King .tf_fg = CRYPTO_FG_ENCRYPT,
44*77de87d2SJason King .tf_init = encrypt_init,
45*77de87d2SJason King .tf_single = encrypt_single,
46*77de87d2SJason King .tf_update = encrypt_update,
47*77de87d2SJason King .tf_final = encrypt_final
48*77de87d2SJason King };
49*77de87d2SJason King
50*77de87d2SJason King test_fg_t cryptotest_mac_fg = {
51*77de87d2SJason King .tf_fg = CRYPTO_FG_MAC,
52*77de87d2SJason King .tf_init = mac_init,
53*77de87d2SJason King .tf_single = mac_single,
54*77de87d2SJason King .tf_update = mac_update,
55*77de87d2SJason King .tf_final = mac_final
56*77de87d2SJason King };
57*77de87d2SJason King
58*77de87d2SJason King test_fg_t cryptotest_digest_fg = {
59*77de87d2SJason King .tf_fg = CRYPTO_FG_DIGEST,
60*77de87d2SJason King .tf_init = digest_init,
61*77de87d2SJason King .tf_single = digest_single,
62*77de87d2SJason King .tf_update = digest_update,
63*77de87d2SJason King .tf_final = digest_final
64*77de87d2SJason King };
65cd964fceSMatt Barden
66cd964fceSMatt Barden /*
67cd964fceSMatt Barden * Utils
68cd964fceSMatt Barden */
69cd964fceSMatt Barden
70*77de87d2SJason King static const char *
ctest_errstr(int e,char * buf,size_t buflen)71*77de87d2SJason King ctest_errstr(int e, char *buf, size_t buflen)
72*77de87d2SJason King {
73*77de87d2SJason King const char *name = NULL;
74*77de87d2SJason King ;
75*77de87d2SJason King switch (e) {
76*77de87d2SJason King case CTEST_INIT_FAILED:
77*77de87d2SJason King name = "CTEST_INIT_FAILED";
78*77de87d2SJason King break;
79*77de87d2SJason King case CTEST_NAME_RESOLVE_FAILED:
80*77de87d2SJason King name = "CTEST_MECH_NO_PROVIDER";
81*77de87d2SJason King break;
82*77de87d2SJason King case CTEST_MECH_NO_PROVIDER:
83*77de87d2SJason King name = "CTEST_MECH_NO_PROVIDER";
84*77de87d2SJason King break;
85*77de87d2SJason King default:
86*77de87d2SJason King name = "Unknown fatal error";
87*77de87d2SJason King break;
88*77de87d2SJason King }
89*77de87d2SJason King
90*77de87d2SJason King (void) snprintf(buf, buflen, "%s (%d)", name, e);
91*77de87d2SJason King return (buf);
92*77de87d2SJason King }
93*77de87d2SJason King
94cd964fceSMatt Barden void
printbuf(uint8_t * buf,char * name,size_t size)95cd964fceSMatt Barden printbuf(uint8_t *buf, char *name, size_t size)
96cd964fceSMatt Barden {
97cd964fceSMatt Barden size_t i;
98cd964fceSMatt Barden
99cd964fceSMatt Barden flockfile(stderr);
100cd964fceSMatt Barden (void) fprintf(stderr, "%s%s", name, (size > 0) ? " " : "");
101cd964fceSMatt Barden for (i = 0; i < size; i++)
102cd964fceSMatt Barden (void) fprintf(stderr, "%02x", buf[i]);
103cd964fceSMatt Barden (void) fputc('\n', stderr);
104cd964fceSMatt Barden funlockfile(stderr);
105cd964fceSMatt Barden }
106cd964fceSMatt Barden
107cd964fceSMatt Barden int
bufcmp(uint8_t * auth,uint8_t * cmp,size_t size)108cd964fceSMatt Barden bufcmp(uint8_t *auth, uint8_t *cmp, size_t size)
109cd964fceSMatt Barden {
110cd964fceSMatt Barden if (memcmp(cmp, auth, size) != 0) {
111*77de87d2SJason King (void) fprintf(stderr, " mismatched result\n\n");
112cd964fceSMatt Barden printbuf(cmp, "calc", size);
113cd964fceSMatt Barden printbuf(auth, "orig", size);
114cd964fceSMatt Barden return (1);
115cd964fceSMatt Barden } else {
116*77de87d2SJason King (void) fprintf(stderr, " result matches\n\n");
117cd964fceSMatt Barden return (0);
118cd964fceSMatt Barden }
119cd964fceSMatt Barden }
120cd964fceSMatt Barden
121cd964fceSMatt Barden static int
test_setup(cryptotest_t * args,test_fg_t * funcs,crypto_op_t ** opp)122*77de87d2SJason King test_setup(cryptotest_t *args, test_fg_t *funcs, crypto_op_t **opp)
123cd964fceSMatt Barden {
124*77de87d2SJason King crypto_op_t *crypto_op = NULL;
125*77de87d2SJason King int ret;
126*77de87d2SJason King
127*77de87d2SJason King switch (funcs->tf_fg) {
128*77de87d2SJason King case CRYPTO_FG_DECRYPT:
129*77de87d2SJason King case CRYPTO_FG_ENCRYPT:
130*77de87d2SJason King if (args->key == NULL)
131*77de87d2SJason King return (CRYPTO_FAILED);
132*77de87d2SJason King break;
133*77de87d2SJason King case CRYPTO_FG_MAC:
134*77de87d2SJason King if (args->in == NULL || args->key == NULL)
135*77de87d2SJason King return (CRYPTO_FAILED);
136*77de87d2SJason King break;
137*77de87d2SJason King case CRYPTO_FG_DIGEST:
138*77de87d2SJason King break;
139*77de87d2SJason King default:
140*77de87d2SJason King (void) fprintf(stderr,
141*77de87d2SJason King "Unexpected function group value %" PRIu32 "\n",
142*77de87d2SJason King funcs->tf_fg);
143*77de87d2SJason King abort();
144*77de87d2SJason King }
145cd964fceSMatt Barden
146*77de87d2SJason King if ((crypto_op = cryptotest_init(args, funcs->tf_fg)) == NULL) {
147*77de87d2SJason King /* cryptotest_init() will prints out a specific error msg */
148*77de87d2SJason King cryptotest_close(NULL);
149cd964fceSMatt Barden return (CTEST_INIT_FAILED);
150cd964fceSMatt Barden }
151cd964fceSMatt Barden
152*77de87d2SJason King if ((ret = get_mech_info(crypto_op)) != CRYPTO_SUCCESS) {
153*77de87d2SJason King cryptotest_close(crypto_op);
154*77de87d2SJason King return (ret);
155cd964fceSMatt Barden }
156cd964fceSMatt Barden
157*77de87d2SJason King if ((ret = get_hsession_by_mech(crypto_op)) != CRYPTO_SUCCESS) {
158*77de87d2SJason King cryptotest_close(crypto_op);
159*77de87d2SJason King return (ret);
160*77de87d2SJason King }
161cd964fceSMatt Barden
162*77de87d2SJason King *opp = crypto_op;
163*77de87d2SJason King return (CRYPTO_SUCCESS);
164cd964fceSMatt Barden }
165cd964fceSMatt Barden
166cd964fceSMatt Barden static int
test_multi(cryptotest_t * args,test_fg_t * funcs,uint8_t * cmp,size_t cmplen)167*77de87d2SJason King test_multi(cryptotest_t *args, test_fg_t *funcs, uint8_t *cmp, size_t cmplen)
168cd964fceSMatt Barden {
169*77de87d2SJason King crypto_op_t *crypto_op = NULL;
170*77de87d2SJason King size_t errs = 0;
171*77de87d2SJason King size_t n;
172*77de87d2SJason King int ret;
173cd964fceSMatt Barden
174*77de87d2SJason King (void) fprintf(stderr, "multi-part:\n");
175cd964fceSMatt Barden
176*77de87d2SJason King if ((ret = test_setup(args, funcs, &crypto_op)) != CRYPTO_SUCCESS) {
177*77de87d2SJason King (void) fprintf(stderr, " fatal error %d\n", ret);
178*77de87d2SJason King exit(EXIT_FAILURE_MULTIPART);
179cd964fceSMatt Barden }
180cd964fceSMatt Barden
181*77de87d2SJason King for (n = 0; args->updatelens[n] != CTEST_UPDATELEN_END; n++) {
182*77de87d2SJason King char errbuf[BUFSZ] = { 0 };
183*77de87d2SJason King char sizebuf[BUFSZ] = { 0 };
184*77de87d2SJason King size_t updatelen = args->updatelens[n];
185*77de87d2SJason King size_t offset = 0;
186*77de87d2SJason King size_t outlen = 0;
187*77de87d2SJason King
188*77de87d2SJason King bzero(args->out, args->outlen);
189*77de87d2SJason King
190*77de87d2SJason King if (updatelen == CTEST_UPDATELEN_WHOLE) {
191*77de87d2SJason King updatelen = args->inlen;
192*77de87d2SJason King (void) snprintf(sizebuf, sizeof (sizebuf),
193*77de87d2SJason King "%zu (whole buffer)", updatelen);
194*77de87d2SJason King } else if (updatelen > args->inlen) {
195*77de87d2SJason King /*
196*77de87d2SJason King * This can sometimes cause the same update size to
197*77de87d2SJason King * be used twice if one is specified larger than the
198*77de87d2SJason King * input and one also specifies a test using the
199*77de87d2SJason King * entire input as the update size. It doesn't
200*77de87d2SJason King * hurt anything other than adding a little extra
201*77de87d2SJason King * time.
202*77de87d2SJason King */
203*77de87d2SJason King updatelen = args->inlen;
204*77de87d2SJason King (void) snprintf(sizebuf, sizeof (sizebuf),
205*77de87d2SJason King "%zu (was %zu but capped at input size)",
206*77de87d2SJason King updatelen, args->updatelens[n]);
207*77de87d2SJason King } else {
208*77de87d2SJason King (void) snprintf(sizebuf, sizeof (sizebuf), "%zu",
209*77de87d2SJason King updatelen);
210*77de87d2SJason King }
211*77de87d2SJason King (void) fprintf(stderr, " update size: %s\n", sizebuf);
212*77de87d2SJason King (void) fflush(stderr);
213cd964fceSMatt Barden
214*77de87d2SJason King if ((ret = funcs->tf_init(crypto_op)) != CRYPTO_SUCCESS) {
215*77de87d2SJason King (void) fprintf(stderr, " fatal error %d\n", ret);
216*77de87d2SJason King exit(EXIT_FAILURE_MULTIPART);
217cd964fceSMatt Barden }
218cd964fceSMatt Barden
219*77de87d2SJason King while (offset < args->inlen) {
220*77de87d2SJason King size_t len = updatelen;
221cd964fceSMatt Barden
222*77de87d2SJason King if (offset + updatelen > args->inlen) {
223*77de87d2SJason King len = args->inlen - offset;
224*77de87d2SJason King }
225cd964fceSMatt Barden
226*77de87d2SJason King ret = funcs->tf_update(crypto_op, offset, len, &outlen);
227*77de87d2SJason King if (ret != CRYPTO_SUCCESS) {
228*77de87d2SJason King /*
229*77de87d2SJason King * The update functions will print out their
230*77de87d2SJason King * own error messages, so we don't need to.
231*77de87d2SJason King */
232*77de87d2SJason King errs += 1;
233*77de87d2SJason King break;
234*77de87d2SJason King }
235cd964fceSMatt Barden
236*77de87d2SJason King offset += len;
237*77de87d2SJason King }
238cd964fceSMatt Barden
239*77de87d2SJason King if (ret != CRYPTO_SUCCESS)
240*77de87d2SJason King continue;
241*77de87d2SJason King
242*77de87d2SJason King ret = funcs->tf_final(crypto_op, outlen);
243*77de87d2SJason King
244*77de87d2SJason King /*
245*77de87d2SJason King * Errors from the crypto frameworks (KCF, PKCS#11) are all
246*77de87d2SJason King * positive (and 0 == success). Negative values are used by
247*77de87d2SJason King * the test framework to signal fatal errors (CTEST_xxx).
248*77de87d2SJason King */
249*77de87d2SJason King if (ret > 0) {
250*77de87d2SJason King (void) fprintf(stderr, " failure %s\n",
251*77de87d2SJason King cryptotest_errstr(ret, errbuf, sizeof (errbuf)));
252*77de87d2SJason King errs += 1;
253*77de87d2SJason King } else if (ret < 0) {
254*77de87d2SJason King (void) fprintf(stderr, " fatal error %s\n",
255*77de87d2SJason King ctest_errstr(ret, errbuf, sizeof (errbuf)));
256*77de87d2SJason King exit(EXIT_FAILURE_MULTIPART);
257*77de87d2SJason King } else {
258*77de87d2SJason King errs += bufcmp(cmp, args->out, cmplen);
259*77de87d2SJason King }
260*77de87d2SJason King }
261cd964fceSMatt Barden
262*77de87d2SJason King VERIFY3U(errs, <=, INT_MAX);
263*77de87d2SJason King cryptotest_close(crypto_op);
264*77de87d2SJason King return (errs);
265cd964fceSMatt Barden }
266cd964fceSMatt Barden
267cd964fceSMatt Barden static int
test_single(cryptotest_t * args,test_fg_t * funcs,uint8_t * cmp,size_t cmplen)268*77de87d2SJason King test_single(cryptotest_t *args, test_fg_t *funcs, uint8_t *cmp, size_t cmplen)
269cd964fceSMatt Barden {
270*77de87d2SJason King crypto_op_t *crypto_op = NULL;
271*77de87d2SJason King char errbuf[BUFSZ] = { 0 };
272*77de87d2SJason King int ret;
273cd964fceSMatt Barden
274*77de87d2SJason King (void) fprintf(stderr, "single part:\n");
275cd964fceSMatt Barden
276*77de87d2SJason King if ((ret = test_setup(args, funcs, &crypto_op)) != CRYPTO_SUCCESS) {
277*77de87d2SJason King (void) fprintf(stderr, " fatal error %d\n", ret);
278*77de87d2SJason King exit(EXIT_FAILURE_SINGLEPART);
279cd964fceSMatt Barden }
280cd964fceSMatt Barden
281*77de87d2SJason King if ((ret = funcs->tf_init(crypto_op)) != CRYPTO_SUCCESS) {
282*77de87d2SJason King (void) fprintf(stderr, " fatal error %d\n", ret);
283*77de87d2SJason King exit(EXIT_FAILURE_SINGLEPART);
284*77de87d2SJason King }
285cd964fceSMatt Barden
286*77de87d2SJason King if ((ret = funcs->tf_single(crypto_op)) != CRYPTO_SUCCESS)
287cd964fceSMatt Barden goto out;
288cd964fceSMatt Barden
289*77de87d2SJason King /*
290*77de87d2SJason King * Errors from the crypto frameworks (KCF, PKCS#11) are all
291*77de87d2SJason King * positive (and 0 == success). Negative values are used by
292*77de87d2SJason King * the test framework to signal fatal errors (CTEST_xxx).
293*77de87d2SJason King */
294*77de87d2SJason King if (ret > 0) {
295*77de87d2SJason King (void) fprintf(stderr, " failure %s\n",
296*77de87d2SJason King cryptotest_errstr(ret, errbuf, sizeof (errbuf)));
297*77de87d2SJason King return (1);
298*77de87d2SJason King } else if (ret < 0) {
299*77de87d2SJason King (void) fprintf(stderr, " fatal error %s\n",
300*77de87d2SJason King ctest_errstr(ret, errbuf, sizeof (errbuf)));
301*77de87d2SJason King exit(EXIT_FAILURE_SINGLEPART);
302cd964fceSMatt Barden } else {
303*77de87d2SJason King ret = bufcmp(cmp, args->out, cmplen);
304cd964fceSMatt Barden }
305cd964fceSMatt Barden
306cd964fceSMatt Barden out:
307cd964fceSMatt Barden (void) cryptotest_close(crypto_op);
308*77de87d2SJason King return ((ret == CRYPTO_SUCCESS) ? 0 : 1);
309cd964fceSMatt Barden }
310cd964fceSMatt Barden
311*77de87d2SJason King /*
312*77de87d2SJason King * Wrapper functions
313*77de87d2SJason King */
314cd964fceSMatt Barden
315cd964fceSMatt Barden int
run_test(cryptotest_t * args,uint8_t * cmp,size_t cmplen,test_fg_t * funcs)316*77de87d2SJason King run_test(cryptotest_t *args, uint8_t *cmp, size_t cmplen,
317*77de87d2SJason King test_fg_t *funcs)
318f3041bfaSJason King {
319*77de87d2SJason King size_t errs = 0;
320*77de87d2SJason King static int i = 0;
321f3041bfaSJason King
322*77de87d2SJason King (void) fprintf(stderr, "%s: run %d\n", args->mechname, ++i);
323f3041bfaSJason King
324*77de87d2SJason King errs += test_multi(args, funcs, cmp, cmplen);
325f3041bfaSJason King
326*77de87d2SJason King bzero(args->out, args->outlen);
327f3041bfaSJason King
328*77de87d2SJason King errs += test_single(args, funcs, cmp, cmplen);
329f3041bfaSJason King
330*77de87d2SJason King VERIFY3U(errs, <=, INT_MAX);
331*77de87d2SJason King return (errs);
332f3041bfaSJason King }
333