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