xref: /illumos-gate/usr/src/test/crypto-tests/tests/common/cryptotest_kcf.c (revision 7c80a9608efb5c2bb78fb923e352a01088239788)
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  */
15 
16 #include <fcntl.h>
17 #include <strings.h>
18 #include <unistd.h>
19 #include <errno.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 
23 #include "cryptotest.h"
24 
25 struct crypto_op {
26 	char *in;
27 	char *out;
28 	char *key;
29 	char *param;
30 
31 	size_t inlen;
32 	size_t outlen;
33 	size_t keylen;
34 	size_t paramlen;
35 	size_t updatelen;
36 
37 	char *mechname;
38 
39 	/* internal */
40 	crypto_mech_type_t mech;
41 	crypto_session_id_t hsession;
42 	crypto_func_group_t fg;
43 };
44 
45 static int fd;
46 static const char CRYPTO_DEVICE[] = "/dev/crypto";
47 
48 int
49 kcf_do_ioctl(int opcode, uint_t *arg, char *opstr)
50 {
51 	int ret;
52 
53 	while ((ret = ioctl(fd, opcode, arg)) < 0) {
54 		if (errno != EINTR)
55 			break;
56 	}
57 
58 	if (ret < 0 || *arg != CRYPTO_SUCCESS)
59 		(void) fprintf(stderr, "%s: Error = %d %d 0x%02x\n",
60 		    (opstr == NULL) ? "ioctl" : opstr,
61 		    ret, errno, *arg);
62 
63 	if (ret < 0)
64 		return (errno);
65 
66 	return (*arg);
67 }
68 
69 crypto_op_t *
70 cryptotest_init(cryptotest_t *arg, crypto_func_group_t fg)
71 {
72 	crypto_op_t *op = malloc(sizeof (*op));
73 
74 	if (op == NULL)
75 		return (NULL);
76 
77 	while ((fd = open(CRYPTO_DEVICE, O_RDWR)) < 0) {
78 		if (errno != EINTR)
79 			return (NULL);
80 	}
81 
82 	op->in = (char *)arg->in;
83 	op->out = (char *)arg->out;
84 	op->key = (char *)arg->key;
85 	op->param = (char *)arg->param;
86 
87 	op->inlen = arg->inlen;
88 	op->outlen = arg->outlen;
89 	op->keylen = arg->keylen * 8; /* kcf uses keylen in bits */
90 	op->paramlen = arg->plen;
91 	op->updatelen = arg->updatelen;
92 
93 	op->mechname = arg->mechname;
94 
95 	op->hsession = CRYPTO_INVALID_SESSION;
96 	op->fg = fg;
97 
98 	if (op->out == NULL)
99 		op->outlen = op->inlen;
100 	return (op);
101 }
102 
103 int
104 cryptotest_close_session(crypto_session_id_t session)
105 {
106 	crypto_close_session_t cs;
107 
108 	cs.cs_session = session;
109 	return (kcf_do_ioctl(CRYPTO_CLOSE_SESSION, (uint_t *)&cs, "session"));
110 }
111 
112 int
113 cryptotest_close(crypto_op_t *op)
114 {
115 	if (op->hsession != CRYPTO_INVALID_SESSION)
116 		(void) cryptotest_close_session(op->hsession);
117 	free(op);
118 	if (fd >= 0)
119 		return (close(fd));
120 	return (0);
121 }
122 
123 int
124 get_mech_info(crypto_op_t *op)
125 {
126 	crypto_get_mechanism_number_t get_number;
127 
128 	bzero(&get_number, sizeof (get_number));
129 
130 	get_number.pn_mechanism_string = op->mechname;
131 	get_number.pn_mechanism_len = strlen(op->mechname) + 1;
132 
133 	if (kcf_do_ioctl(CRYPTO_GET_MECHANISM_NUMBER,
134 	    (uint_t *)&get_number, "get_mech_info") != CRYPTO_SUCCESS) {
135 		(void) fprintf(stderr, "failed to resolve mechanism name %s\n",
136 		    op->mechname);
137 		(void) cryptotest_close(op);
138 		return (CTEST_NAME_RESOLVE_FAILED);
139 	}
140 	op->mech = get_number.pn_internal_number;
141 	return (CRYPTO_SUCCESS);
142 }
143 
144 int
145 get_hsession_by_mech(crypto_op_t *op)
146 {
147 	crypto_by_mech_t mech;
148 	int rv;
149 
150 	mech.mech_keylen = op->keylen;
151 	mech.mech_type = op->mech;
152 	mech.mech_fg = op->fg;
153 
154 	rv = kcf_do_ioctl(CRYPTO_GET_PROVIDER_BY_MECH, (uint_t *)&mech,
155 	    "get_hsession_by_mech");
156 
157 	if (rv != 0 || mech.rv != CRYPTO_SUCCESS) {
158 		(void) fprintf(stderr,
159 		    "could not find provider for mechanism %llu\n",
160 		    mech.mech_type);
161 		(void) cryptotest_close(op);
162 		return (CTEST_MECH_NO_PROVIDER);
163 	}
164 
165 	op->hsession = mech.session_id;
166 
167 	return (CRYPTO_SUCCESS);
168 }
169 
170 /*
171  * CRYPTO_MAC_* functions
172  */
173 int
174 mac_init(crypto_op_t *op)
175 {
176 	crypto_mac_init_t init;
177 
178 	bzero((void *)&init, sizeof (init));
179 
180 	init.mi_session = op->hsession;
181 
182 	init.mi_key.ck_data = op->key;
183 	init.mi_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
184 	init.mi_key.ck_length = op->keylen;
185 
186 	init.mi_mech.cm_type = op->mech;
187 	init.mi_mech.cm_param = NULL;
188 	init.mi_mech.cm_param_len = 0;
189 
190 	return (kcf_do_ioctl(CRYPTO_MAC_INIT, (uint_t *)&init, "init"));
191 }
192 
193 int
194 mac_single(crypto_op_t *op)
195 {
196 	crypto_mac_t mac;
197 
198 	bzero(&mac, sizeof (mac));
199 	mac.cm_session = op->hsession;
200 	mac.cm_datalen = op->inlen;
201 	mac.cm_databuf = op->in;
202 	mac.cm_maclen = op->outlen;
203 	mac.cm_macbuf = op->out;
204 
205 	return (kcf_do_ioctl(CRYPTO_MAC, (uint_t *)&mac, "single"));
206 }
207 
208 int
209 mac_update(crypto_op_t *op, int offset)
210 {
211 	crypto_mac_update_t update;
212 
213 	bzero((void *)&update, sizeof (update));
214 
215 	update.mu_session = op->hsession;
216 	update.mu_databuf = op->in + offset;
217 	update.mu_datalen = op->updatelen;
218 
219 	return (kcf_do_ioctl(CRYPTO_MAC_UPDATE, (uint_t *)&update, "update"));
220 }
221 
222 int
223 mac_final(crypto_op_t *op)
224 {
225 	crypto_mac_final_t final;
226 
227 	bzero((void *)&final, sizeof (final));
228 
229 	final.mf_session = op->hsession;
230 	final.mf_maclen = op->outlen;
231 	final.mf_macbuf = op->out;
232 
233 	return (kcf_do_ioctl(CRYPTO_MAC_FINAL, (uint_t *)&final, "final"));
234 }
235 
236 
237 /*
238  * CRYPTO_ENCRYPT_* functions
239  */
240 
241 int
242 encrypt_init(crypto_op_t *op)
243 {
244 	crypto_encrypt_init_t init;
245 
246 	bzero((void *)&init, sizeof (init));
247 
248 	init.ei_session = op->hsession;
249 
250 	init.ei_key.ck_data = op->key;
251 	init.ei_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
252 	init.ei_key.ck_length = op->keylen;
253 
254 	init.ei_mech.cm_type = op->mech;
255 	init.ei_mech.cm_param = op->param;
256 	init.ei_mech.cm_param_len = op->paramlen;
257 
258 	return (kcf_do_ioctl(CRYPTO_ENCRYPT_INIT, (uint_t *)&init, "init"));
259 }
260 
261 int
262 encrypt_single(crypto_op_t *op)
263 {
264 	crypto_encrypt_t encrypt;
265 
266 	bzero(&encrypt, sizeof (encrypt));
267 	encrypt.ce_session = op->hsession;
268 	encrypt.ce_datalen = op->inlen;
269 	encrypt.ce_databuf = op->in;
270 	encrypt.ce_encrlen = op->outlen;
271 	encrypt.ce_encrbuf = op->out;
272 
273 	return (kcf_do_ioctl(CRYPTO_ENCRYPT, (uint_t *)&encrypt, "single"));
274 }
275 
276 int
277 encrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
278 {
279 	crypto_encrypt_update_t update;
280 	int ret;
281 	bzero((void *)&update, sizeof (update));
282 
283 	update.eu_session = op->hsession;
284 	update.eu_databuf = op->in + offset;
285 	update.eu_datalen = op->updatelen;
286 	update.eu_encrlen = op->outlen - *encrlen;
287 	update.eu_encrbuf = op->out + *encrlen;
288 
289 	ret = kcf_do_ioctl(CRYPTO_ENCRYPT_UPDATE, (uint_t *)&update, "update");
290 	*encrlen += update.eu_encrlen;
291 	return (ret);
292 }
293 
294 int
295 encrypt_final(crypto_op_t *op, size_t encrlen)
296 {
297 	crypto_encrypt_final_t final;
298 
299 	bzero((void *)&final, sizeof (final));
300 
301 	final.ef_session = op->hsession;
302 	final.ef_encrlen = op->outlen - encrlen;
303 	final.ef_encrbuf = op->out + encrlen;
304 
305 	return (kcf_do_ioctl(CRYPTO_ENCRYPT_FINAL, (uint_t *)&final, "final"));
306 }
307 
308 /*
309  * CRYPTO_DECRYPT_* functions
310  */
311 
312 int
313 decrypt_init(crypto_op_t *op)
314 {
315 	crypto_decrypt_init_t init;
316 
317 	bzero((void *)&init, sizeof (init));
318 
319 	init.di_session = op->hsession;
320 
321 	init.di_key.ck_data = op->key;
322 	init.di_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
323 	init.di_key.ck_length = op->keylen;
324 
325 	init.di_mech.cm_type = op->mech;
326 	init.di_mech.cm_param = op->param;
327 	init.di_mech.cm_param_len = op->paramlen;
328 
329 	return (kcf_do_ioctl(CRYPTO_DECRYPT_INIT, (uint_t *)&init, "init"));
330 }
331 
332 int
333 decrypt_single(crypto_op_t *op)
334 {
335 	crypto_decrypt_t decrypt;
336 
337 	bzero(&decrypt, sizeof (decrypt));
338 	decrypt.cd_session = op->hsession;
339 	decrypt.cd_datalen = op->outlen;
340 	decrypt.cd_databuf = op->out;
341 	decrypt.cd_encrlen = op->inlen;
342 	decrypt.cd_encrbuf = op->in;
343 
344 	return (kcf_do_ioctl(CRYPTO_DECRYPT, (uint_t *)&decrypt, "single"));
345 }
346 
347 int
348 decrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
349 {
350 	crypto_decrypt_update_t update;
351 	int ret;
352 
353 	bzero((void *)&update, sizeof (update));
354 
355 	update.du_session = op->hsession;
356 	update.du_databuf = op->out + *encrlen;
357 	update.du_datalen = op->outlen - *encrlen;
358 	update.du_encrlen = op->updatelen;
359 	update.du_encrbuf = op->in + offset;
360 
361 	ret = kcf_do_ioctl(CRYPTO_DECRYPT_UPDATE, (uint_t *)&update, "update");
362 	*encrlen += update.du_datalen;
363 	return (ret);
364 }
365 
366 int
367 decrypt_final(crypto_op_t *op, size_t encrlen)
368 {
369 	crypto_decrypt_final_t final;
370 
371 	bzero((void *)&final, sizeof (final));
372 
373 	final.df_session = op->hsession;
374 	final.df_datalen = op->outlen - encrlen;
375 	final.df_databuf = op->out + encrlen;
376 
377 	return (kcf_do_ioctl(CRYPTO_DECRYPT_FINAL, (uint_t *)&final, "final"));
378 }
379