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