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