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 }