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 return (NULL);
81 }
82
83 op->in = (char *)arg->in;
84 op->out = (char *)arg->out;
85 op->key = (char *)arg->key;
86 op->param = (char *)arg->param;
87
88 op->inlen = arg->inlen;
89 op->outlen = arg->outlen;
90 op->keylen = arg->keylen * 8; /* kcf uses keylen in bits */
91 op->paramlen = arg->plen;
92 op->updatelen = arg->updatelen;
93
94 op->mechname = arg->mechname;
95
96 op->hsession = CRYPTO_INVALID_SESSION;
97 op->fg = fg;
98
99 if (op->out == NULL)
100 op->outlen = op->inlen;
101 return (op);
102 }
103
104 int
105 cryptotest_close_session(crypto_session_id_t session)
106 {
107 crypto_close_session_t cs;
108
109 cs.cs_session = session;
110 return (kcf_do_ioctl(CRYPTO_CLOSE_SESSION, (uint_t *)&cs, "session"));
111 }
112
113 int
114 cryptotest_close(crypto_op_t *op)
115 {
116 if (op->hsession != CRYPTO_INVALID_SESSION)
117 (void) cryptotest_close_session(op->hsession);
118 free(op);
119 if (fd >= 0)
120 return (close(fd));
121 return (0);
122 }
123
124 int
125 get_mech_info(crypto_op_t *op)
126 {
127 crypto_get_mechanism_number_t get_number;
128
129 bzero(&get_number, sizeof (get_number));
130
131 get_number.pn_mechanism_string = op->mechname;
132 get_number.pn_mechanism_len = strlen(op->mechname) + 1;
133
134 if (kcf_do_ioctl(CRYPTO_GET_MECHANISM_NUMBER,
135 (uint_t *)&get_number, "get_mech_info") != CRYPTO_SUCCESS) {
136 (void) fprintf(stderr, "failed to resolve mechanism name %s\n",
137 op->mechname);
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 return (CTEST_MECH_NO_PROVIDER);
162 }
163
164 op->hsession = mech.session_id;
165
166 return (CRYPTO_SUCCESS);
167 }
168
169 /*
170 * CRYPTO_MAC_* functions
171 */
172 int
173 mac_init(crypto_op_t *op)
174 {
175 crypto_mac_init_t init;
176
177 bzero((void *)&init, sizeof (init));
178
179 init.mi_session = op->hsession;
180
181 init.mi_key.ck_data = op->key;
182 init.mi_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
183 init.mi_key.ck_length = op->keylen;
184
185 init.mi_mech.cm_type = op->mech;
186 init.mi_mech.cm_param = NULL;
187 init.mi_mech.cm_param_len = 0;
188
189 return (kcf_do_ioctl(CRYPTO_MAC_INIT, (uint_t *)&init, "init"));
190 }
191
192 int
193 mac_single(crypto_op_t *op)
194 {
195 crypto_mac_t mac;
196
197 bzero(&mac, sizeof (mac));
198 mac.cm_session = op->hsession;
199 mac.cm_datalen = op->inlen;
200 mac.cm_databuf = op->in;
201 mac.cm_maclen = op->outlen;
202 mac.cm_macbuf = op->out;
203
204 return (kcf_do_ioctl(CRYPTO_MAC, (uint_t *)&mac, "single"));
205 }
206
207 int
208 mac_update(crypto_op_t *op, int offset)
209 {
210 crypto_mac_update_t update;
211
212 bzero((void *)&update, sizeof (update));
213
214 update.mu_session = op->hsession;
215 update.mu_databuf = op->in + offset;
216 update.mu_datalen = op->updatelen;
217
218 return (kcf_do_ioctl(CRYPTO_MAC_UPDATE, (uint_t *)&update, "update"));
219 }
220
221 int
222 mac_final(crypto_op_t *op)
223 {
224 crypto_mac_final_t final;
225
226 bzero((void *)&final, sizeof (final));
227
228 final.mf_session = op->hsession;
229 final.mf_maclen = op->outlen;
230 final.mf_macbuf = op->out;
231
232 return (kcf_do_ioctl(CRYPTO_MAC_FINAL, (uint_t *)&final, "final"));
233 }
234
235
236 /*
237 * CRYPTO_ENCRYPT_* functions
238 */
239
240 int
241 encrypt_init(crypto_op_t *op)
242 {
243 crypto_encrypt_init_t init;
244
245 bzero((void *)&init, sizeof (init));
246
247 init.ei_session = op->hsession;
248
249 init.ei_key.ck_data = op->key;
250 init.ei_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
251 init.ei_key.ck_length = op->keylen;
252
253 init.ei_mech.cm_type = op->mech;
254 init.ei_mech.cm_param = op->param;
255 init.ei_mech.cm_param_len = op->paramlen;
256
257 return (kcf_do_ioctl(CRYPTO_ENCRYPT_INIT, (uint_t *)&init, "init"));
258 }
259
260 int
261 encrypt_single(crypto_op_t *op)
262 {
263 crypto_encrypt_t encrypt;
264
265 bzero(&encrypt, sizeof (encrypt));
266 encrypt.ce_session = op->hsession;
267 encrypt.ce_datalen = op->inlen;
268 encrypt.ce_databuf = op->in;
269 encrypt.ce_encrlen = op->outlen;
270 encrypt.ce_encrbuf = op->out;
271
272 return (kcf_do_ioctl(CRYPTO_ENCRYPT, (uint_t *)&encrypt, "single"));
273 }
274
275 int
276 encrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
277 {
278 crypto_encrypt_update_t update;
279 int ret;
280 bzero((void *)&update, sizeof (update));
281
282 update.eu_session = op->hsession;
283 update.eu_databuf = op->in + offset;
284 update.eu_datalen = op->updatelen;
285 update.eu_encrlen = op->outlen - *encrlen;
286 update.eu_encrbuf = op->out + *encrlen;
287
288 ret = kcf_do_ioctl(CRYPTO_ENCRYPT_UPDATE, (uint_t *)&update, "update");
289 *encrlen += update.eu_encrlen;
290 return (ret);
291 }
292
293 int
294 encrypt_final(crypto_op_t *op, size_t encrlen)
295 {
296 crypto_encrypt_final_t final;
297
298 bzero((void *)&final, sizeof (final));
299
300 final.ef_session = op->hsession;
301 final.ef_encrlen = op->outlen - encrlen;
302 final.ef_encrbuf = op->out + encrlen;
303
304 return (kcf_do_ioctl(CRYPTO_ENCRYPT_FINAL, (uint_t *)&final, "final"));
305 }
306
307 /*
308 * CRYPTO_DECRYPT_* functions
309 */
310
311 int
312 decrypt_init(crypto_op_t *op)
313 {
314 crypto_decrypt_init_t init;
315
316 bzero((void *)&init, sizeof (init));
317
318 init.di_session = op->hsession;
319
320 init.di_key.ck_data = op->key;
321 init.di_key.ck_format = CRYPTO_KEY_RAW; /* must be this */
322 init.di_key.ck_length = op->keylen;
323
324 init.di_mech.cm_type = op->mech;
325 init.di_mech.cm_param = op->param;
326 init.di_mech.cm_param_len = op->paramlen;
327
328 return (kcf_do_ioctl(CRYPTO_DECRYPT_INIT, (uint_t *)&init, "init"));
329 }
330
331 int
332 decrypt_single(crypto_op_t *op)
333 {
334 crypto_decrypt_t decrypt;
335
336 bzero(&decrypt, sizeof (decrypt));
337 decrypt.cd_session = op->hsession;
338 decrypt.cd_datalen = op->outlen;
339 decrypt.cd_databuf = op->out;
340 decrypt.cd_encrlen = op->inlen;
341 decrypt.cd_encrbuf = op->in;
342
343 return (kcf_do_ioctl(CRYPTO_DECRYPT, (uint_t *)&decrypt, "single"));
344 }
345
346 int
347 decrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
348 {
349 crypto_decrypt_update_t update;
350 int ret;
351
352 bzero((void *)&update, sizeof (update));
353
354 update.du_session = op->hsession;
355 update.du_databuf = op->out + *encrlen;
356 update.du_datalen = op->outlen - *encrlen;
357 update.du_encrlen = op->updatelen;
358 update.du_encrbuf = op->in + offset;
359
360 ret = kcf_do_ioctl(CRYPTO_DECRYPT_UPDATE, (uint_t *)&update, "update");
361 *encrlen += update.du_datalen;
362 return (ret);
363 }
364
365 int
366 decrypt_final(crypto_op_t *op, size_t encrlen)
367 {
368 crypto_decrypt_final_t final;
369
370 bzero((void *)&final, sizeof (final));
371
372 final.df_session = op->hsession;
373 final.df_datalen = op->outlen - encrlen;
374 final.df_databuf = op->out + encrlen;
375
376 return (kcf_do_ioctl(CRYPTO_DECRYPT_FINAL, (uint_t *)&final, "final"));
377 }
378
379 int
380 digest_init(crypto_op_t *op)
381 {
382 crypto_digest_init_t init;
383
384 bzero(&init, sizeof (init));
385
386 init.di_session = op->hsession;
387
388 init.di_mech.cm_type = op->mech;
389 init.di_mech.cm_param = NULL;
390 init.di_mech.cm_param_len = 0;
391
392 return (kcf_do_ioctl(CRYPTO_DIGEST_INIT, (uint_t *)&init, "init"));
393 }
394
395 int
396 digest_single(crypto_op_t *op)
397 {
398 crypto_digest_t digest;
399
400 bzero(&digest, sizeof (digest));
401
402 digest.cd_session = op->hsession;
403
404 digest.cd_datalen = op->inlen;
405 digest.cd_databuf = op->in;
406 digest.cd_digestlen = op->outlen;
407 digest.cd_digestbuf = op->out;
408
409 return (kcf_do_ioctl(CRYPTO_DIGEST, (uint_t *)&digest, "digest"));
410 }
411
412 int
413 digest_update(crypto_op_t *op, int offset)
414 {
415 crypto_digest_update_t update;
416
417 bzero(&update, sizeof (update));
418
419 update.du_session = op->hsession;
420
421 update.du_datalen = op->updatelen;
422 update.du_databuf = op->in + offset;
423
424 return (kcf_do_ioctl(CRYPTO_DIGEST_UPDATE, (uint_t *)&update,
425 "update"));
426 }
427
428 int
429 digest_final(crypto_op_t *op)
430 {
431 crypto_digest_final_t final;
432
433 bzero(&final, sizeof (final));
434
435 final.df_session = op->hsession;
436
437 final.df_digestlen = op->outlen;
438 final.df_digestbuf = op->out;
439
440 return (kcf_do_ioctl(CRYPTO_DIGEST_FINAL, (uint_t *)&final, "final"));
441 }
442 void
443 ccm_init_params(void *buf, ulong_t ulDataLen, uchar_t *pNonce,
444 ulong_t ulNonceLen, uchar_t *pAAD, ulong_t ulAADLen, ulong_t ulMACLen)
445 {
446 CK_AES_CCM_PARAMS *pp = buf;
447
448 pp->ulDataSize = ulDataLen;
449 pp->nonce = pNonce;
450 pp->ulNonceSize = ulNonceLen;
451 pp->authData = pAAD;
452 pp->ulAuthDataSize = ulAADLen;
453 pp->ulMACSize = ulMACLen;
454 }
455
456 size_t
457 ccm_param_len(void)
458 {
459 return (sizeof (CK_AES_CCM_PARAMS));
460 }