1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
14  * Copyright 2018, Joyent, Inc.
15  */
16 
17 #include <fcntl.h>
18 #include <strings.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #include "cryptotest.h"
25 
26 struct crypto_op {
27 	char *in;
28 	char *out;
29 	char *key;
30 	char *param;
31 
32 	size_t inlen;
33 	size_t outlen;
34 	size_t keylen;
35 	size_t paramlen;
36 	size_t updatelen;
37 
38 	char *mechname;
39 
40 	/* internal */
41 	crypto_mech_type_t mech;
42 	crypto_session_id_t hsession;
43 	crypto_func_group_t fg;
44 };
45 
46 static int fd;
47 static const char CRYPTO_DEVICE[] = "/dev/crypto";
48 
49 int
50 kcf_do_ioctl(int opcode, uint_t *arg, char *opstr)
51 {
52 	int ret;
53 
54 	while ((ret = ioctl(fd, opcode, arg)) < 0) {
55 		if (errno != EINTR)
56 			break;
57 	}
58 
59 	if (ret < 0 || *arg != CRYPTO_SUCCESS)
60 		(void) fprintf(stderr, "%s: Error = %d %d 0x%02x\n",
61 		    (opstr == NULL) ? "ioctl" : opstr,
62 		    ret, errno, *arg);
63 
64 	if (ret < 0)
65 		return (errno);
66 
67 	return (*arg);
68 }
69 
70 crypto_op_t *
71 cryptotest_init(cryptotest_t *arg, crypto_func_group_t fg)
72 {
73 	crypto_op_t *op = malloc(sizeof (*op));
74 
75 	if (op == NULL)
76 		return (NULL);
77 
78 	while ((fd = open(CRYPTO_DEVICE, O_RDWR)) < 0) {
79 		if (errno != EINTR) {
80 			free(op);
81 			return (NULL);
82 		}
83 	}
84 
85 	op->in = (char *)arg->in;
86 	op->out = (char *)arg->out;
87 	op->key = (char *)arg->key;
88 	op->param = (char *)arg->param;
89 
90 	op->inlen = arg->inlen;
91 	op->outlen = arg->outlen;
92 	op->keylen = arg->keylen * 8; /* kcf uses keylen in bits */
93 	op->paramlen = arg->plen;
94 	op->updatelen = arg->updatelen;
95 
96 	op->mechname = arg->mechname;
97 
98 	op->hsession = CRYPTO_INVALID_SESSION;
99 	op->fg = fg;
100 
101 	if (op->out == NULL)
102 		op->outlen = op->inlen;
103 	return (op);
104 }
105 
106 int
107 cryptotest_close_session(crypto_session_id_t session)
108 {
109 	crypto_close_session_t cs;
110 
111 	cs.cs_session = session;
112 	return (kcf_do_ioctl(CRYPTO_CLOSE_SESSION, (uint_t *)&cs, "session"));
113 }
114 
115 int
116 cryptotest_close(crypto_op_t *op)
117 {
118 	if (op->hsession != CRYPTO_INVALID_SESSION)
119 		(void) cryptotest_close_session(op->hsession);
120 	free(op);
121 	if (fd >= 0)
122 		return (close(fd));
123 	return (0);
124 }
125 
126 int
127 get_mech_info(crypto_op_t *op)
128 {
129 	crypto_get_mechanism_number_t get_number;
130 
131 	bzero(&get_number, sizeof (get_number));
132 
133 	get_number.pn_mechanism_string = op->mechname;
134 	get_number.pn_mechanism_len = strlen(op->mechname) + 1;
135 
136 	if (kcf_do_ioctl(CRYPTO_GET_MECHANISM_NUMBER,
137 	    (uint_t *)&get_number, "get_mech_info") != CRYPTO_SUCCESS) {
138 		(void) fprintf(stderr, "failed to resolve mechanism name %s\n",
139 		    op->mechname);
140 		return (CTEST_NAME_RESOLVE_FAILED);
141 	}
142 	op->mech = get_number.pn_internal_number;
143 	return (CRYPTO_SUCCESS);
144 }
145 
146 int
147 get_hsession_by_mech(crypto_op_t *op)
148 {
149 	crypto_by_mech_t mech;
150 	int rv;
151 
152 	mech.mech_keylen = op->keylen;
153 	mech.mech_type = op->mech;
154 	mech.mech_fg = op->fg;
155 
156 	rv = kcf_do_ioctl(CRYPTO_GET_PROVIDER_BY_MECH, (uint_t *)&mech,
157 	    "get_hsession_by_mech");
158 
159 	if (rv != 0 || mech.rv != CRYPTO_SUCCESS) {
160 		(void) fprintf(stderr,
161 		    "could not find provider for mechanism %llu\n",
162 		    mech.mech_type);
163 		return (CTEST_MECH_NO_PROVIDER);
164 	}
165 
166 	op->hsession = mech.session_id;
167 
168 	return (CRYPTO_SUCCESS);
169 }
170 
171 /*
172  * CRYPTO_MAC_* functions
173  */
174 int
175 mac_init(crypto_op_t *op)
176 {
177 	crypto_mac_init_t init;
178 
179 	bzero((void *)&init, sizeof (init));
180 
181 	init.mi_session = op->hsession;
182 
183 	init.mi_key.ck_data = op->key;
184 	init.mi_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
185 	init.mi_key.ck_length = op->keylen;
186 
187 	init.mi_mech.cm_type = op->mech;
188 	init.mi_mech.cm_param = NULL;
189 	init.mi_mech.cm_param_len = 0;
190 
191 	return (kcf_do_ioctl(CRYPTO_MAC_INIT, (uint_t *)&init, "init"));
192 }
193 
194 int
195 mac_single(crypto_op_t *op)
196 {
197 	crypto_mac_t mac;
198 
199 	bzero(&mac, sizeof (mac));
200 	mac.cm_session = op->hsession;
201 	mac.cm_datalen = op->inlen;
202 	mac.cm_databuf = op->in;
203 	mac.cm_maclen = op->outlen;
204 	mac.cm_macbuf = op->out;
205 
206 	return (kcf_do_ioctl(CRYPTO_MAC, (uint_t *)&mac, "single"));
207 }
208 
209 int
210 mac_update(crypto_op_t *op, int offset)
211 {
212 	crypto_mac_update_t update;
213 
214 	bzero((void *)&update, sizeof (update));
215 
216 	update.mu_session = op->hsession;
217 	update.mu_databuf = op->in + offset;
218 	update.mu_datalen = op->updatelen;
219 
220 	return (kcf_do_ioctl(CRYPTO_MAC_UPDATE, (uint_t *)&update, "update"));
221 }
222 
223 int
224 mac_final(crypto_op_t *op)
225 {
226 	crypto_mac_final_t final;
227 
228 	bzero((void *)&final, sizeof (final));
229 
230 	final.mf_session = op->hsession;
231 	final.mf_maclen = op->outlen;
232 	final.mf_macbuf = op->out;
233 
234 	return (kcf_do_ioctl(CRYPTO_MAC_FINAL, (uint_t *)&final, "final"));
235 }
236 
237 
238 /*
239  * CRYPTO_ENCRYPT_* functions
240  */
241 
242 int
243 encrypt_init(crypto_op_t *op)
244 {
245 	crypto_encrypt_init_t init;
246 
247 	bzero((void *)&init, sizeof (init));
248 
249 	init.ei_session = op->hsession;
250 
251 	init.ei_key.ck_data = op->key;
252 	init.ei_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
253 	init.ei_key.ck_length = op->keylen;
254 
255 	init.ei_mech.cm_type = op->mech;
256 	init.ei_mech.cm_param = op->param;
257 	init.ei_mech.cm_param_len = op->paramlen;
258 
259 	return (kcf_do_ioctl(CRYPTO_ENCRYPT_INIT, (uint_t *)&init, "init"));
260 }
261 
262 int
263 encrypt_single(crypto_op_t *op)
264 {
265 	crypto_encrypt_t encrypt;
266 
267 	bzero(&encrypt, sizeof (encrypt));
268 	encrypt.ce_session = op->hsession;
269 	encrypt.ce_datalen = op->inlen;
270 	encrypt.ce_databuf = op->in;
271 	encrypt.ce_encrlen = op->outlen;
272 	encrypt.ce_encrbuf = op->out;
273 
274 	return (kcf_do_ioctl(CRYPTO_ENCRYPT, (uint_t *)&encrypt, "single"));
275 }
276 
277 int
278 encrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
279 {
280 	crypto_encrypt_update_t update;
281 	int ret;
282 	bzero((void *)&update, sizeof (update));
283 
284 	update.eu_session = op->hsession;
285 	update.eu_databuf = op->in + offset;
286 	update.eu_datalen = op->updatelen;
287 	update.eu_encrlen = op->outlen - *encrlen;
288 	update.eu_encrbuf = op->out + *encrlen;
289 
290 	ret = kcf_do_ioctl(CRYPTO_ENCRYPT_UPDATE, (uint_t *)&update, "update");
291 	*encrlen += update.eu_encrlen;
292 	return (ret);
293 }
294 
295 int
296 encrypt_final(crypto_op_t *op, size_t encrlen)
297 {
298 	crypto_encrypt_final_t final;
299 
300 	bzero((void *)&final, sizeof (final));
301 
302 	final.ef_session = op->hsession;
303 	final.ef_encrlen = op->outlen - encrlen;
304 	final.ef_encrbuf = op->out + encrlen;
305 
306 	return (kcf_do_ioctl(CRYPTO_ENCRYPT_FINAL, (uint_t *)&final, "final"));
307 }
308 
309 /*
310  * CRYPTO_DECRYPT_* functions
311  */
312 
313 int
314 decrypt_init(crypto_op_t *op)
315 {
316 	crypto_decrypt_init_t init;
317 
318 	bzero((void *)&init, sizeof (init));
319 
320 	init.di_session = op->hsession;
321 
322 	init.di_key.ck_data = op->key;
323 	init.di_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
324 	init.di_key.ck_length = op->keylen;
325 
326 	init.di_mech.cm_type = op->mech;
327 	init.di_mech.cm_param = op->param;
328 	init.di_mech.cm_param_len = op->paramlen;
329 
330 	return (kcf_do_ioctl(CRYPTO_DECRYPT_INIT, (uint_t *)&init, "init"));
331 }
332 
333 int
334 decrypt_single(crypto_op_t *op)
335 {
336 	crypto_decrypt_t decrypt;
337 
338 	bzero(&decrypt, sizeof (decrypt));
339 	decrypt.cd_session = op->hsession;
340 	decrypt.cd_datalen = op->outlen;
341 	decrypt.cd_databuf = op->out;
342 	decrypt.cd_encrlen = op->inlen;
343 	decrypt.cd_encrbuf = op->in;
344 
345 	return (kcf_do_ioctl(CRYPTO_DECRYPT, (uint_t *)&decrypt, "single"));
346 }
347 
348 int
349 decrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
350 {
351 	crypto_decrypt_update_t update;
352 	int ret;
353 
354 	bzero((void *)&update, sizeof (update));
355 
356 	update.du_session = op->hsession;
357 	update.du_databuf = op->out + *encrlen;
358 	update.du_datalen = op->outlen - *encrlen;
359 	update.du_encrlen = op->updatelen;
360 	update.du_encrbuf = op->in + offset;
361 
362 	ret = kcf_do_ioctl(CRYPTO_DECRYPT_UPDATE, (uint_t *)&update, "update");
363 	*encrlen += update.du_datalen;
364 	return (ret);
365 }
366 
367 int
368 decrypt_final(crypto_op_t *op, size_t encrlen)
369 {
370 	crypto_decrypt_final_t final;
371 
372 	bzero((void *)&final, sizeof (final));
373 
374 	final.df_session = op->hsession;
375 	final.df_datalen = op->outlen - encrlen;
376 	final.df_databuf = op->out + encrlen;
377 
378 	return (kcf_do_ioctl(CRYPTO_DECRYPT_FINAL, (uint_t *)&final, "final"));
379 }
380 
381 int
382 digest_init(crypto_op_t *op)
383 {
384 	crypto_digest_init_t init;
385 
386 	bzero(&init, sizeof (init));
387 
388 	init.di_session = op->hsession;
389 
390 	init.di_mech.cm_type = op->mech;
391 	init.di_mech.cm_param = NULL;
392 	init.di_mech.cm_param_len = 0;
393 
394 	return (kcf_do_ioctl(CRYPTO_DIGEST_INIT, (uint_t *)&init, "init"));
395 }
396 
397 int
398 digest_single(crypto_op_t *op)
399 {
400 	crypto_digest_t digest;
401 
402 	bzero(&digest, sizeof (digest));
403 
404 	digest.cd_session = op->hsession;
405 
406 	digest.cd_datalen = op->inlen;
407 	digest.cd_databuf = op->in;
408 	digest.cd_digestlen = op->outlen;
409 	digest.cd_digestbuf = op->out;
410 
411 	return (kcf_do_ioctl(CRYPTO_DIGEST, (uint_t *)&digest, "digest"));
412 }
413 
414 int
415 digest_update(crypto_op_t *op, int offset)
416 {
417 	crypto_digest_update_t update;
418 
419 	bzero(&update, sizeof (update));
420 
421 	update.du_session = op->hsession;
422 
423 	update.du_datalen = op->updatelen;
424 	update.du_databuf = op->in + offset;
425 
426 	return (kcf_do_ioctl(CRYPTO_DIGEST_UPDATE, (uint_t *)&update,
427 	    "update"));
428 }
429 
430 int
431 digest_final(crypto_op_t *op)
432 {
433 	crypto_digest_final_t final;
434 
435 	bzero(&final, sizeof (final));
436 
437 	final.df_session = op->hsession;
438 
439 	final.df_digestlen = op->outlen;
440 	final.df_digestbuf = op->out;
441 
442 	return (kcf_do_ioctl(CRYPTO_DIGEST_FINAL, (uint_t *)&final, "final"));
443 }
444 void
445 ccm_init_params(void *buf, ulong_t ulDataLen, uchar_t *pNonce,
446     ulong_t ulNonceLen, uchar_t *pAAD, ulong_t ulAADLen, ulong_t ulMACLen)
447 {
448 	CK_AES_CCM_PARAMS *pp = buf;
449 
450 	pp->ulDataSize = ulDataLen;
451 	pp->nonce = pNonce;
452 	pp->ulNonceSize = ulNonceLen;
453 	pp->authData = pAAD;
454 	pp->ulAuthDataSize = ulAADLen;
455 	pp->ulMACSize = ulMACLen;
456 }
457 
458 size_t
459 ccm_param_len(void)
460 {
461 	return (sizeof (CK_AES_CCM_PARAMS));
462 }
463