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 <stdio.h>
18 #include <cryptoutil.h>
19 #include <security/cryptoki.h>
20 
21 #include "cryptotest.h"
22 
23 struct crypto_op {
24 	CK_BYTE_PTR in;
25 	CK_BYTE_PTR out;
26 	CK_BYTE_PTR key;
27 	CK_BYTE_PTR param;
28 
29 	size_t inlen;
30 	size_t outlen;
31 	size_t keylen;
32 	size_t paramlen;
33 	size_t updatelen;
34 
35 	char *mechname;
36 
37 	/* internal */
38 	CK_MECHANISM_TYPE mech;
39 	CK_OBJECT_HANDLE keyt;
40 	CK_SESSION_HANDLE hsession;
41 	size_t fg;
42 };
43 
44 static void
45 cryptotest_error(char *name, CK_RV rv)
46 {
47 	(void) fprintf(stderr, "%s: Error = 0x%.8lX '%s'\n",
48 	    name, rv, pkcs11_strerror(rv));
49 }
50 
51 crypto_op_t *
52 cryptotest_init(cryptotest_t *arg, crypto_func_group_t fg)
53 {
54 	crypto_op_t *op = malloc(sizeof (*op));
55 
56 	op->in = (CK_BYTE_PTR)arg->in;
57 	op->out = (CK_BYTE_PTR)arg->out;
58 	op->key = (CK_BYTE_PTR)arg->key;
59 	op->param = (CK_BYTE_PTR)arg->param;
60 
61 	op->inlen = arg->inlen;
62 	op->outlen = arg->outlen;
63 	op->keylen = arg->keylen;
64 	op->paramlen = arg->plen;
65 	op->updatelen = arg->updatelen;
66 
67 	op->mechname = arg->mechname;
68 
69 	op->hsession = CK_INVALID_HANDLE;
70 	op->keyt = CK_INVALID_HANDLE;
71 	op->fg = fg;
72 
73 	if (op->out == NULL)
74 		op->outlen = op->inlen;
75 	return (op);
76 }
77 
78 int
79 cryptotest_close_session(CK_SESSION_HANDLE hsession)
80 {
81 	CK_RV rv;
82 	rv = C_CloseSession(hsession);
83 	if (rv != CKR_OK)
84 		cryptotest_error("cryptotest_close_session", rv);
85 
86 	return (rv);
87 }
88 
89 int
90 cryptotest_close(crypto_op_t *op)
91 {
92 	if (op->keyt != CK_INVALID_HANDLE)
93 		(void) C_DestroyObject(op->hsession, op->keyt);
94 
95 	if (op->hsession != CK_INVALID_HANDLE)
96 		(void) cryptotest_close_session(op->hsession);
97 	free(op);
98 	return (C_Finalize(NULL));
99 }
100 
101 int
102 get_mech_info(crypto_op_t *op)
103 {
104 	CK_RV rv;
105 	rv = pkcs11_str2mech(op->mechname, &op->mech);
106 	if (rv != CKR_OK) {
107 		cryptotest_error("get_mech_info", rv);
108 		(void) fprintf(stderr, "failed to resolve mechanism name %s\n",
109 		    op->mechname);
110 		return (CTEST_NAME_RESOLVE_FAILED);
111 	}
112 	return (rv);
113 }
114 
115 
116 int
117 get_hsession_by_mech(crypto_op_t *op)
118 {
119 	CK_RV rv;
120 	rv = SUNW_C_GetMechSession(op->mech, &op->hsession);
121 	if (rv != CKR_OK) {
122 		cryptotest_error("get_hsession_by_mech", rv);
123 		(void) fprintf(stderr,
124 		    "could not find provider for mechanism %lu\n",
125 		    op->mech);
126 		return (CTEST_MECH_NO_PROVIDER);
127 	}
128 	return (rv);
129 }
130 
131 /*
132  * SIGN_* functions
133  */
134 int
135 sign_init(crypto_op_t *op)
136 {
137 	CK_MECHANISM mech;
138 	CK_RV rv;
139 
140 	mech.mechanism = op->mech;
141 	mech.pParameter = NULL;
142 	mech.ulParameterLen = 0;
143 
144 	rv = SUNW_C_KeyToObject(op->hsession, op->mech,
145 	    op->key, op->keylen, &op->keyt);
146 
147 	if (rv != CKR_OK)
148 		cryptotest_error("SUNW_C_KeyToObject", rv);
149 
150 	rv = C_SignInit(op->hsession, &mech, op->keyt);
151 
152 	if (rv != CKR_OK)
153 		cryptotest_error("C_SignInit", rv);
154 
155 	return (rv);
156 }
157 
158 int
159 sign_single(crypto_op_t *op)
160 {
161 	CK_RV rv;
162 
163 	rv = C_Sign(op->hsession, op->in, op->inlen,
164 	    op->out, (CK_ULONG_PTR)&op->outlen);
165 	if (rv != CKR_OK)
166 		cryptotest_error("C_Sign", rv);
167 	return (rv);
168 }
169 
170 int
171 sign_update(crypto_op_t *op, int offset)
172 {
173 	CK_RV rv;
174 	rv = C_SignUpdate(op->hsession, op->in + offset, op->updatelen);
175 	if (rv != CKR_OK)
176 		cryptotest_error("C_SignUpdate", rv);
177 
178 	return (rv);
179 }
180 
181 int
182 sign_final(crypto_op_t *op)
183 {
184 	CK_RV rv;
185 	rv = C_SignFinal(op->hsession, op->out, (CK_ULONG_PTR)&op->outlen);
186 	if (rv != CKR_OK)
187 		cryptotest_error("C_SignFinal", rv);
188 	return (rv);
189 }
190 
191 /*
192  * MAC_* functions
193  */
194 int
195 mac_init(crypto_op_t *op)
196 {
197 	return (sign_init(op));
198 }
199 
200 int
201 mac_single(crypto_op_t *op)
202 {
203 	return (sign_single(op));
204 }
205 
206 int
207 mac_update(crypto_op_t *op, int offset)
208 {
209 	return (sign_update(op, offset));
210 }
211 
212 int
213 mac_final(crypto_op_t *op)
214 {
215 	return (sign_final(op));
216 }
217 
218 /*
219  * VERIFY_* functions
220  */
221 int
222 verify_init(crypto_op_t *op)
223 {
224 	CK_MECHANISM mech;
225 	CK_RV rv;
226 
227 	mech.mechanism = op->mech;
228 	mech.pParameter = NULL;
229 	mech.ulParameterLen = 0;
230 
231 	rv = SUNW_C_KeyToObject(op->hsession, op->mech,
232 	    op->key, op->keylen, &op->keyt);
233 
234 	if (rv != CKR_OK)
235 		cryptotest_error("SUNW_C_KeyToObject", rv);
236 
237 	rv = C_VerifyInit(op->hsession, &mech, op->keyt);
238 
239 	if (rv != CKR_OK)
240 		cryptotest_error("C_VerifyInit", rv);
241 
242 	return (rv);
243 }
244 
245 int
246 verify_single(crypto_op_t *op)
247 {
248 	CK_RV rv;
249 
250 	rv = C_Verify(op->hsession, op->in, op->inlen, op->out, op->outlen);
251 	if (rv != CKR_OK && rv != CKR_SIGNATURE_INVALID &&
252 	    rv != CKR_SIGNATURE_LEN_RANGE)
253 		cryptotest_error("C_Verify", rv);
254 	return (rv);
255 }
256 
257 int
258 verify_update(crypto_op_t *op, int offset)
259 {
260 	CK_RV rv;
261 	rv = C_VerifyUpdate(op->hsession, op->in + offset, op->updatelen);
262 	if (rv != CKR_OK)
263 		cryptotest_error("C_VerifyUpdate", rv);
264 	return (rv);
265 }
266 
267 int
268 verify_final(crypto_op_t *op)
269 {
270 	CK_RV rv;
271 	rv = C_VerifyFinal(op->hsession, op->out, op->outlen);
272 	if (rv != CKR_OK && rv != CKR_SIGNATURE_INVALID &&
273 	    rv != CKR_SIGNATURE_LEN_RANGE)
274 		cryptotest_error("C_VerifyFinal", rv);
275 	return (rv);
276 }
277 
278 /*
279  * ENCRYPT_* functions
280  */
281 int
282 encrypt_init(crypto_op_t *op)
283 {
284 	CK_MECHANISM mech;
285 	CK_RV rv;
286 
287 	mech.mechanism = op->mech;
288 	mech.pParameter = op->param;
289 	mech.ulParameterLen = op->paramlen;
290 
291 	rv = SUNW_C_KeyToObject(op->hsession, op->mech,
292 	    op->key, op->keylen, &op->keyt);
293 
294 	if (rv != CKR_OK)
295 		cryptotest_error("SUNW_C_KeyToObject", rv);
296 
297 	rv = C_EncryptInit(op->hsession, &mech, op->keyt);
298 
299 	if (rv != CKR_OK)
300 		cryptotest_error("C_EncryptInit", rv);
301 
302 	return (rv);
303 }
304 
305 int
306 encrypt_single(crypto_op_t *op)
307 {
308 	CK_RV rv;
309 
310 	rv = C_Encrypt(op->hsession, op->in, op->inlen,
311 	    op->out, (CK_ULONG_PTR)&op->outlen);
312 	if (rv != CKR_OK)
313 		cryptotest_error("C_Encrypt", rv);
314 	return (rv);
315 }
316 
317 int
318 encrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
319 {
320 	CK_RV rv;
321 	CK_ULONG outlen = op->outlen - *encrlen;
322 	rv = C_EncryptUpdate(op->hsession, op->in + offset, op->updatelen,
323 	    op->out + *encrlen, &outlen);
324 	if (rv != CKR_OK)
325 		cryptotest_error("C_EncryptUpdate", rv);
326 
327 	*encrlen += outlen;
328 	return (rv);
329 }
330 
331 int
332 encrypt_final(crypto_op_t *op, size_t encrlen)
333 {
334 	CK_RV rv;
335 	CK_ULONG outlen = op->outlen - encrlen;
336 	rv = C_EncryptFinal(op->hsession, op->out + encrlen, &outlen);
337 	if (rv != CKR_OK)
338 		cryptotest_error("C_EncryptFinal", rv);
339 	return (rv);
340 }
341 
342 /*
343  * DECRYPT_* functions
344  */
345 int
346 decrypt_init(crypto_op_t *op)
347 {
348 	CK_MECHANISM mech;
349 	CK_RV rv;
350 
351 	mech.mechanism = op->mech;
352 	mech.pParameter = op->param;
353 	mech.ulParameterLen = op->paramlen;
354 
355 	rv = SUNW_C_KeyToObject(op->hsession, op->mech,
356 	    op->key, op->keylen, &op->keyt);
357 
358 	if (rv != CKR_OK)
359 		cryptotest_error("SUNW_C_KeyToObject", rv);
360 
361 	rv = C_DecryptInit(op->hsession, &mech, op->keyt);
362 
363 	if (rv != CKR_OK)
364 		cryptotest_error("C_DecryptInit", rv);
365 
366 	return (rv);
367 }
368 
369 int
370 decrypt_single(crypto_op_t *op)
371 {
372 	CK_RV rv;
373 
374 	rv = C_Decrypt(op->hsession, op->in, op->inlen,
375 	    op->out, (CK_ULONG_PTR)&op->outlen);
376 	if (rv != CKR_OK)
377 		cryptotest_error("C_Decrypt", rv);
378 	return (rv);
379 }
380 
381 int
382 decrypt_update(crypto_op_t *op, int offset, size_t *encrlen)
383 {
384 	CK_RV rv;
385 	CK_ULONG outlen = op->outlen - *encrlen;
386 	rv = C_DecryptUpdate(op->hsession, op->in + offset, op->updatelen,
387 	    op->out + *encrlen, &outlen);
388 	if (rv != CKR_OK)
389 		cryptotest_error("C_DecryptUpdate", rv);
390 
391 	*encrlen += outlen;
392 	return (rv);
393 }
394 
395 int
396 decrypt_final(crypto_op_t *op, size_t encrlen)
397 {
398 	CK_RV rv;
399 	CK_ULONG outlen = op->outlen - encrlen;
400 	rv = C_DecryptFinal(op->hsession, op->out + encrlen, &outlen);
401 	if (rv != CKR_OK)
402 		cryptotest_error("C_DecryptFinal", rv);
403 	return (rv);
404 }
405 
406 /*
407  * DIGEST_ functions
408  */
409 int
410 digest_init(crypto_op_t *op)
411 {
412 	CK_MECHANISM mech;
413 	CK_RV rv;
414 
415 	mech.mechanism = op->mech;
416 	mech.pParameter = op->param;
417 	mech.ulParameterLen = op->paramlen;
418 
419 	rv = C_DigestInit(op->hsession, &mech);
420 	if (rv != CKR_OK)
421 		cryptotest_error("C_DigestInit", rv);
422 	return (rv);
423 }
424 
425 int
426 digest_single(crypto_op_t *op)
427 {
428 	CK_RV rv;
429 
430 	rv = C_Digest(op->hsession, op->in, op->inlen,
431 	    op->out, (CK_ULONG_PTR)&op->outlen);
432 	if (rv != CKR_OK)
433 		cryptotest_error("C_Digest", rv);
434 	return (rv);
435 }
436 
437 int
438 digest_update(crypto_op_t *op, int offset)
439 {
440 	CK_RV rv;
441 
442 	rv = C_DigestUpdate(op->hsession, op->in + offset, op->updatelen);
443 	if (rv != CKR_OK)
444 		cryptotest_error("C_DigestUpdate", rv);
445 	return (rv);
446 }
447 
448 int
449 digest_final(crypto_op_t *op)
450 {
451 	CK_RV rv;
452 
453 	rv = C_DigestFinal(op->hsession, op->out, (CK_ULONG_PTR)&op->outlen);
454 	if (rv != CKR_OK)
455 		cryptotest_error("C_DigestFinal", rv);
456 	return (rv);
457 }
458 
459 void
460 ccm_init_params(void *buf, ulong_t ulDataLen, uchar_t *pNonce,
461     ulong_t ulNonceLen, uchar_t *pAAD, ulong_t ulAADLen, ulong_t ulMACLen)
462 {
463 	CK_CCM_PARAMS *pp = buf;
464 
465 	pp->ulDataLen = ulDataLen;
466 	pp->pNonce = pNonce;
467 	pp->ulNonceLen = ulNonceLen;
468 	pp->pAAD = pAAD;
469 	pp->ulAADLen = ulAADLen;
470 	pp->ulMACLen = ulMACLen;
471 }
472 
473 size_t
474 ccm_param_len(void)
475 {
476 	return (sizeof (CK_CCM_PARAMS));
477 }
478