1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2020, Linaro Limited
4  */
5 
6 #include <ck_debug.h>
7 #include <inttypes.h>
8 #include <pkcs11.h>
9 #include <pkcs11_ta.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "ck_helpers.h"
14 #include "local_utils.h"
15 #include "serializer.h"
16 #include "serialize_ck.h"
17 
18 /*
19  * Serialization and de-serialization logic
20  *
21  * Cryptoki API works in a way that user application uses memory references
22  * in object attributes description. TA can be invoked with only a small set
23  * of possible references to caller memory. Thus a Cryptoki object, made of
24  * data and pointers to data, is reassembled into a byte array where each
25  * attribute info (ID, value size, value) is appended with byte alignment. This
26  * so-called serialized object can be passed through the TA API.
27  *
28  * Initial entry to PKCS11 TA uses serialize_ck_attributes(). When TA
29  * returns with updated serialized data to be passed back to caller, we call
30  * deserialize_ck_attributes().
31  *
32  * Special handling is performed for CK_ULONG passing which may be either 32
33  * bits or 64 bits depending on target device architecture. In TA interface
34  * this is handled as unsigned 32 bit data type.
35  *
36  * When user application is querying attributes in example with
37  * C_GetAttributeValue() user may allocate larger value buffers. During entry
38  * to TA shared buffer is allocated in serialize_ck_attributes() based on
39  * caller's arguments. For each attribute TA verifies if value fits in
40  * the buffer and if it does, value is returned. Value size in buffer is
41  * updated to indicate real size of the value. When call is returned back to
42  * REE deserialize_ck_attributes() is invoked and then both input arguments and
43  * serialization buffer are used to return values to caller. Provided input
44  * arguments from caller are used to determine serialization buffer structure
45  * and then actual values and value sizes are then decoded from serialization
46  * buffer and returned to caller in caller's allocated memory.
47  */
48 
49 /*
50  * Generic way of serializing CK keys, certificates, mechanism parameters, ...
51  * In cryptoki 2.40 parameters are almost all packaged as structure below:
52  */
53 struct ck_ref {
54 	CK_ULONG id;
55 	CK_BYTE_PTR ptr;
56 	CK_ULONG len;
57 };
58 
59 /*
60  * This is for attributes that contains data memory indirections.
61  * In other words, an attributes that defines a list of attributes.
62  * They are identified from the attribute type CKA_...
63  *
64  * @obj - ref used to track the serial object being created
65  * @attribute - pointer to a structure aligned of the CK_ATTRIBUTE struct
66  */
serialize_indirect_attribute(struct serializer * obj,CK_ATTRIBUTE_PTR attribute)67 static CK_RV serialize_indirect_attribute(struct serializer *obj,
68 					  CK_ATTRIBUTE_PTR attribute)
69 {
70 	CK_ATTRIBUTE_PTR attr = NULL;
71 	CK_ULONG count = 0;
72 	CK_RV rv = CKR_GENERAL_ERROR;
73 	struct serializer obj2 = { 0 };
74 
75 	switch (attribute->type) {
76 	/* These are serialized each separately */
77 	case CKA_DERIVE_TEMPLATE:
78 	case CKA_WRAP_TEMPLATE:
79 	case CKA_UNWRAP_TEMPLATE:
80 		count = attribute->ulValueLen / sizeof(CK_ATTRIBUTE);
81 		attr = (CK_ATTRIBUTE_PTR)attribute->pValue;
82 		break;
83 	default:
84 		return CKR_NO_EVENT;
85 	}
86 
87 	/* Create a serialized object for the content */
88 	rv = serialize_ck_attributes(&obj2, attr, count);
89 	if (rv)
90 		return rv;
91 
92 	/*
93 	 * Append the created serialized object into target object:
94 	 * [attrib-id][byte-size][attributes-data]
95 	 */
96 	rv = serialize_32b(obj, attribute->type);
97 	if (rv)
98 		goto out;
99 
100 	rv = serialize_32b(obj, obj2.size);
101 	if (rv)
102 		goto out;
103 
104 	rv = serialize_buffer(obj, obj2.buffer, obj2.size);
105 	if (rv)
106 		goto out;
107 
108 	obj->item_count++;
109 out:
110 	release_serial_object(&obj2);
111 
112 	return rv;
113 }
114 
deserialize_indirect_attribute(struct pkcs11_attribute_head * obj,CK_ATTRIBUTE_PTR attribute)115 static CK_RV deserialize_indirect_attribute(struct pkcs11_attribute_head *obj,
116 					    CK_ATTRIBUTE_PTR attribute)
117 {
118 	CK_ULONG count = 0;
119 	CK_ATTRIBUTE_PTR attr = NULL;
120 
121 	switch (attribute->type) {
122 	/* These are serialized each separately */
123 	case CKA_DERIVE_TEMPLATE:
124 	case CKA_WRAP_TEMPLATE:
125 	case CKA_UNWRAP_TEMPLATE:
126 		count = attribute->ulValueLen / sizeof(CK_ATTRIBUTE);
127 		attr = (CK_ATTRIBUTE_PTR)attribute->pValue;
128 		break;
129 	default:
130 		return CKR_GENERAL_ERROR;
131 	}
132 
133 	return deserialize_ck_attributes(obj->data, attr, count);
134 }
135 
ck_attr_is_ulong(CK_ATTRIBUTE_TYPE attribute_id)136 static int ck_attr_is_ulong(CK_ATTRIBUTE_TYPE attribute_id)
137 {
138 	switch (attribute_id) {
139 	case CKA_CLASS:
140 	case CKA_CERTIFICATE_TYPE:
141 	case CKA_CERTIFICATE_CATEGORY:
142 	case CKA_NAME_HASH_ALGORITHM:
143 	case CKA_KEY_TYPE:
144 	case CKA_HW_FEATURE_TYPE:
145 	case CKA_MECHANISM_TYPE:
146 	case CKA_KEY_GEN_MECHANISM:
147 	case CKA_VALUE_LEN:
148 	case CKA_MODULUS_BITS:
149 		return true;
150 	default:
151 		return false;
152 	}
153 }
154 
serialize_ck_attribute(struct serializer * obj,CK_ATTRIBUTE * attr)155 static CK_RV serialize_ck_attribute(struct serializer *obj, CK_ATTRIBUTE *attr)
156 {
157 	CK_MECHANISM_TYPE *type = NULL;
158 	uint32_t pkcs11_size = 0;
159 	uint32_t pkcs11_data32 = 0;
160 	void *pkcs11_pdata = NULL;
161 	uint32_t *mech_buf = NULL;
162 	CK_RV rv = CKR_GENERAL_ERROR;
163 	unsigned int n = 0;
164 	unsigned int m = 0;
165 
166 	if (attr->type == PKCS11_UNDEFINED_ID)
167 		return CKR_ATTRIBUTE_TYPE_INVALID;
168 
169 	switch (attr->type) {
170 	case CKA_DERIVE_TEMPLATE:
171 	case CKA_WRAP_TEMPLATE:
172 	case CKA_UNWRAP_TEMPLATE:
173 		return serialize_indirect_attribute(obj, attr);
174 	case CKA_ALLOWED_MECHANISMS:
175 		n = attr->ulValueLen / sizeof(CK_ULONG);
176 		pkcs11_size = n * sizeof(uint32_t);
177 		mech_buf = malloc(pkcs11_size);
178 		if (!mech_buf)
179 			return CKR_HOST_MEMORY;
180 
181 		type = attr->pValue;
182 		for (m = 0; m < n; m++) {
183 			mech_buf[m] = type[m];
184 			if (mech_buf[m] == PKCS11_UNDEFINED_ID) {
185 				rv = CKR_MECHANISM_INVALID;
186 				goto out;
187 			}
188 		}
189 		pkcs11_pdata = mech_buf;
190 		break;
191 	/* Attributes which data value do not need conversion (aside ulong) */
192 	default:
193 		pkcs11_pdata = attr->pValue;
194 		if (!attr->pValue) {
195 			pkcs11_size = 0;
196 		} else if (ck_attr_is_ulong(attr->type)) {
197 			CK_ULONG ck_ulong = 0;
198 
199 			if (attr->ulValueLen < sizeof(CK_ULONG))
200 				return CKR_ATTRIBUTE_VALUE_INVALID;
201 
202 			memcpy(&ck_ulong, attr->pValue, sizeof(ck_ulong));
203 			pkcs11_data32 = ck_ulong;
204 			pkcs11_pdata = &pkcs11_data32;
205 			pkcs11_size = sizeof(uint32_t);
206 		} else {
207 			pkcs11_size = attr->ulValueLen;
208 		}
209 		break;
210 	}
211 
212 	rv = serialize_32b(obj, attr->type);
213 	if (rv)
214 		goto out;
215 
216 	rv = serialize_32b(obj, pkcs11_size);
217 	if (rv)
218 		goto out;
219 
220 	rv = serialize_buffer(obj, pkcs11_pdata, pkcs11_size);
221 	if (rv)
222 		goto out;
223 
224 	obj->item_count++;
225 out:
226 	free(mech_buf);
227 
228 	return rv;
229 }
230 
231 /* CK attribute reference arguments are list of attribute item */
serialize_ck_attributes(struct serializer * obj,CK_ATTRIBUTE_PTR attributes,CK_ULONG count)232 CK_RV serialize_ck_attributes(struct serializer *obj,
233 			      CK_ATTRIBUTE_PTR attributes, CK_ULONG count)
234 {
235 	CK_ULONG n = 0;
236 	CK_RV rv = CKR_OK;
237 
238 	rv = init_serial_object(obj);
239 	if (rv)
240 		return rv;
241 
242 	for (n = 0; n < count; n++) {
243 		rv = serialize_ck_attribute(obj, attributes + n);
244 		if (rv)
245 			break;
246 	}
247 
248 	if (rv)
249 		release_serial_object(obj);
250 	else
251 		finalize_serial_object(obj);
252 
253 	return rv;
254 }
255 
deserialize_mecha_list(CK_MECHANISM_TYPE * dst,void * src,size_t count)256 static CK_RV deserialize_mecha_list(CK_MECHANISM_TYPE *dst, void *src,
257 				    size_t count)
258 {
259 	char *ta_src = src;
260 	size_t n = 0;
261 	uint32_t mecha_id = 0;
262 
263 	for (n = 0; n < count; n++) {
264 		memcpy(&mecha_id, ta_src + n * sizeof(mecha_id),
265 		       sizeof(mecha_id));
266 		dst[n] = mecha_id;
267 	}
268 
269 	return CKR_OK;
270 }
271 
deserialize_ck_attribute(struct pkcs11_attribute_head * in,uint8_t * data,CK_ATTRIBUTE_PTR out)272 static CK_RV deserialize_ck_attribute(struct pkcs11_attribute_head *in,
273 				      uint8_t *data, CK_ATTRIBUTE_PTR out)
274 {
275 	CK_ULONG ck_ulong = 0;
276 	uint32_t pkcs11_data32 = 0;
277 	CK_RV rv = CKR_OK;
278 
279 	out->type = in->id;
280 
281 	if (in->size == PKCS11_CK_UNAVAILABLE_INFORMATION) {
282 		out->ulValueLen = CK_UNAVAILABLE_INFORMATION;
283 		return CKR_OK;
284 	}
285 
286 	if (!out->pValue && ck_attr_is_ulong(out->type)) {
287 		out->ulValueLen = sizeof(CK_ULONG);
288 		return CKR_OK;
289 	}
290 
291 	if (out->ulValueLen < in->size) {
292 		out->ulValueLen = in->size;
293 		return CKR_OK;
294 	}
295 
296 	if (!out->pValue)
297 		return CKR_OK;
298 
299 	/* Specific ulong encoded as 32bit in PKCS11 TA API */
300 	if (ck_attr_is_ulong(out->type)) {
301 		if (out->ulValueLen < sizeof(CK_ULONG))
302 			return CKR_ATTRIBUTE_VALUE_INVALID;
303 
304 		memcpy(&pkcs11_data32, data, sizeof(uint32_t));
305 		if (out->type == CKA_KEY_GEN_MECHANISM &&
306 		    pkcs11_data32 == PKCS11_CK_UNAVAILABLE_INFORMATION)
307 			ck_ulong = CK_UNAVAILABLE_INFORMATION;
308 		else
309 			ck_ulong = pkcs11_data32;
310 
311 		memcpy(out->pValue, &ck_ulong, sizeof(CK_ULONG));
312 		out->ulValueLen = sizeof(CK_ULONG);
313 		return CKR_OK;
314 	}
315 
316 	switch (out->type) {
317 	case CKA_DERIVE_TEMPLATE:
318 	case CKA_WRAP_TEMPLATE:
319 	case CKA_UNWRAP_TEMPLATE:
320 		rv = deserialize_indirect_attribute(in, out->pValue);
321 		break;
322 	case CKA_ALLOWED_MECHANISMS:
323 		rv = deserialize_mecha_list(out->pValue, data,
324 					    in->size / sizeof(uint32_t));
325 		out->ulValueLen = in->size / sizeof(uint32_t) *
326 				  sizeof(CK_ULONG);
327 		break;
328 	/* Attributes which data value do not need conversion (aside ulong) */
329 	default:
330 		memcpy(out->pValue, data, in->size);
331 		out->ulValueLen = in->size;
332 		break;
333 	}
334 
335 	return rv;
336 }
337 
deserialize_ck_attributes(uint8_t * in,CK_ATTRIBUTE_PTR attributes,CK_ULONG count)338 CK_RV deserialize_ck_attributes(uint8_t *in, CK_ATTRIBUTE_PTR attributes,
339 				CK_ULONG count)
340 {
341 	CK_ATTRIBUTE_PTR cur_attr = attributes;
342 	CK_ULONG n = 0;
343 	CK_RV rv = CKR_OK;
344 	uint8_t *curr_head = in;
345 	size_t len = 0;
346 
347 	curr_head += sizeof(struct pkcs11_object_head);
348 
349 	for (n = count; n > 0; n--, cur_attr++, curr_head += len) {
350 		struct pkcs11_attribute_head *cli_ref = (void *)curr_head;
351 		struct pkcs11_attribute_head cli_head = { 0 };
352 		void *data_ptr = NULL;
353 
354 		/* Make copy if header so that is aligned properly. */
355 		memcpy(&cli_head, cli_ref, sizeof(cli_head));
356 
357 		/* Get real data pointer from template data */
358 		data_ptr = cli_ref->data;
359 
360 		len = sizeof(cli_head);
361 
362 		/* Advance by size provisioned in input serialized buffer */
363 		if (cur_attr->pValue) {
364 			if (ck_attr_is_ulong(cur_attr->type))
365 				len += sizeof(uint32_t);
366 			else
367 				len += cur_attr->ulValueLen;
368 		}
369 
370 		rv = deserialize_ck_attribute(&cli_head, data_ptr, cur_attr);
371 		if (rv)
372 			return rv;
373 	}
374 
375 	return rv;
376 }
377 
378 /*
379  * Serialization of CK mechanism parameters
380  *
381  * Most mechanism have no parameters.
382  * Some mechanism have a single 32bit parameter.
383  * Some mechanism have a specific parameter structure which may contain
384  * indirected data (data referred by a buffer pointer).
385  *
386  * Below are each structure specific mechanisms parameters.
387  */
388 
serialize_mecha_aes_ctr(struct serializer * obj,CK_MECHANISM_PTR mecha)389 static CK_RV serialize_mecha_aes_ctr(struct serializer *obj,
390 				     CK_MECHANISM_PTR mecha)
391 {
392 	CK_AES_CTR_PARAMS_PTR param = mecha->pParameter;
393 	CK_RV rv = CKR_GENERAL_ERROR;
394 	uint32_t size = 0;
395 
396 	rv = serialize_32b(obj, obj->type);
397 	if (rv)
398 		return rv;
399 
400 	size = sizeof(uint32_t) + sizeof(param->cb);
401 	rv = serialize_32b(obj, size);
402 	if (rv)
403 		return rv;
404 
405 	rv = serialize_ck_ulong(obj, param->ulCounterBits);
406 	if (rv)
407 		return rv;
408 
409 	rv = serialize_buffer(obj, param->cb, sizeof(param->cb));
410 	if (rv)
411 		return rv;
412 
413 	return rv;
414 }
415 
serialize_mecha_aes_gcm(struct serializer * obj,CK_MECHANISM_PTR mecha)416 static CK_RV serialize_mecha_aes_gcm(struct serializer *obj,
417 				     CK_MECHANISM_PTR mecha)
418 {
419 	CK_GCM_PARAMS_PTR param = mecha->pParameter;
420 	CK_RV rv = CKR_GENERAL_ERROR;
421 	CK_ULONG aad_len = 0;
422 
423 	/* AAD is not manadatory */
424 	if (param->pAAD)
425 		aad_len = param->ulAADLen;
426 
427 	if (!param->pIv)
428 		return CKR_MECHANISM_PARAM_INVALID;
429 
430 	rv = serialize_32b(obj, obj->type);
431 	if (rv)
432 		return rv;
433 
434 	rv = serialize_32b(obj, 3 * sizeof(uint32_t) +
435 				param->ulIvLen + aad_len);
436 	if (rv)
437 		return rv;
438 
439 	rv = serialize_ck_ulong(obj, param->ulIvLen);
440 	if (rv)
441 		return rv;
442 
443 	rv = serialize_buffer(obj, param->pIv, param->ulIvLen);
444 	if (rv)
445 		return rv;
446 
447 	rv = serialize_ck_ulong(obj, aad_len);
448 	if (rv)
449 		return rv;
450 
451 	rv = serialize_buffer(obj, param->pAAD, aad_len);
452 	if (rv)
453 		return rv;
454 
455 	return serialize_ck_ulong(obj, param->ulTagBits);
456 }
457 
serialize_mecha_aes_iv(struct serializer * obj,CK_MECHANISM_PTR mecha)458 static CK_RV serialize_mecha_aes_iv(struct serializer *obj,
459 				    CK_MECHANISM_PTR mecha)
460 {
461 	uint32_t iv_size = mecha->ulParameterLen;
462 	CK_RV rv = CKR_GENERAL_ERROR;
463 
464 	rv = serialize_32b(obj, obj->type);
465 	if (rv)
466 		return rv;
467 
468 	rv = serialize_32b(obj, iv_size);
469 	if (rv)
470 		return rv;
471 
472 	return serialize_buffer(obj, mecha->pParameter, mecha->ulParameterLen);
473 }
474 
serialize_mecha_key_deriv_str(struct serializer * obj,CK_MECHANISM_PTR mecha)475 static CK_RV serialize_mecha_key_deriv_str(struct serializer *obj,
476 					   CK_MECHANISM_PTR mecha)
477 {
478 	CK_KEY_DERIVATION_STRING_DATA_PTR param = mecha->pParameter;
479 	CK_RV rv = CKR_GENERAL_ERROR;
480 	uint32_t size = 0;
481 
482 	rv = serialize_32b(obj, obj->type);
483 	if (rv)
484 		return rv;
485 
486 	size = sizeof(uint32_t) + param->ulLen;
487 	rv = serialize_32b(obj, size);
488 	if (rv)
489 		return rv;
490 
491 	rv = serialize_ck_ulong(obj, param->ulLen);
492 	if (rv)
493 		return rv;
494 
495 	return serialize_buffer(obj, param->pData, param->ulLen);
496 }
497 
serialize_mecha_ecdh1_derive_param(struct serializer * obj,CK_MECHANISM_PTR mecha)498 static CK_RV serialize_mecha_ecdh1_derive_param(struct serializer *obj,
499 						CK_MECHANISM_PTR mecha)
500 {
501 	CK_ECDH1_DERIVE_PARAMS *params = mecha->pParameter;
502 	CK_RV rv = CKR_GENERAL_ERROR;
503 	size_t params_size = 3 * sizeof(uint32_t) + params->ulSharedDataLen +
504 			     params->ulPublicDataLen;
505 
506 	rv = serialize_32b(obj, obj->type);
507 	if (rv)
508 		return rv;
509 
510 	rv = serialize_32b(obj, params_size);
511 	if (rv)
512 		return rv;
513 
514 	rv = serialize_32b(obj, params->kdf);
515 	if (rv)
516 		return rv;
517 
518 	rv = serialize_32b(obj, params->ulSharedDataLen);
519 	if (rv)
520 		return rv;
521 
522 	rv = serialize_buffer(obj, params->pSharedData,
523 			      params->ulSharedDataLen);
524 	if (rv)
525 		return rv;
526 
527 	rv = serialize_32b(obj, params->ulPublicDataLen);
528 	if (rv)
529 		return rv;
530 
531 	return serialize_buffer(obj, params->pPublicData,
532 				params->ulPublicDataLen);
533 }
534 
serialize_mecha_aes_cbc_encrypt_data(struct serializer * obj,CK_MECHANISM_PTR mecha)535 static CK_RV serialize_mecha_aes_cbc_encrypt_data(struct serializer *obj,
536 						  CK_MECHANISM_PTR mecha)
537 {
538 	CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR param = mecha->pParameter;
539 	CK_RV rv = CKR_GENERAL_ERROR;
540 	uint32_t size = 0;
541 
542 	rv = serialize_32b(obj, obj->type);
543 	if (rv)
544 		return rv;
545 
546 	size = sizeof(param->iv) + sizeof(uint32_t) + param->length;
547 	rv = serialize_32b(obj, size);
548 	if (rv)
549 		return rv;
550 
551 	rv = serialize_buffer(obj, param->iv, sizeof(param->iv));
552 	if (rv)
553 		return rv;
554 
555 	rv = serialize_ck_ulong(obj, param->length);
556 	if (rv)
557 		return rv;
558 
559 	return serialize_buffer(obj, param->pData, param->length);
560 }
561 
serialize_mecha_rsa_pss_param(struct serializer * obj,CK_MECHANISM_PTR mecha)562 static CK_RV serialize_mecha_rsa_pss_param(struct serializer *obj,
563 					   CK_MECHANISM_PTR mecha)
564 {
565 	CK_RSA_PKCS_PSS_PARAMS *params = mecha->pParameter;
566 	CK_RV rv = CKR_GENERAL_ERROR;
567 	uint32_t params_size = 3 * sizeof(uint32_t);
568 
569 	if (mecha->ulParameterLen != sizeof(*params))
570 		return CKR_ARGUMENTS_BAD;
571 
572 	rv = serialize_32b(obj, obj->type);
573 	if (rv)
574 		return rv;
575 
576 	rv = serialize_32b(obj, params_size);
577 	if (rv)
578 		return rv;
579 
580 	rv = serialize_ck_ulong(obj, params->hashAlg);
581 	if (rv)
582 		return rv;
583 
584 	rv = serialize_ck_ulong(obj, params->mgf);
585 	if (rv)
586 		return rv;
587 
588 	return serialize_ck_ulong(obj, params->sLen);
589 }
590 
serialize_mecha_rsa_oaep_param(struct serializer * obj,CK_MECHANISM_PTR mecha)591 static CK_RV serialize_mecha_rsa_oaep_param(struct serializer *obj,
592 					    CK_MECHANISM_PTR mecha)
593 {
594 	CK_RSA_PKCS_OAEP_PARAMS *params = mecha->pParameter;
595 	CK_RV rv = CKR_GENERAL_ERROR;
596 	size_t params_size = 4 * sizeof(uint32_t) + params->ulSourceDataLen;
597 
598 	if (mecha->ulParameterLen != sizeof(*params))
599 		return CKR_ARGUMENTS_BAD;
600 
601 	rv = serialize_32b(obj, obj->type);
602 	if (rv)
603 		return rv;
604 
605 	rv = serialize_32b(obj, params_size);
606 	if (rv)
607 		return rv;
608 
609 	rv = serialize_ck_ulong(obj, params->hashAlg);
610 	if (rv)
611 		return rv;
612 
613 	rv = serialize_ck_ulong(obj, params->mgf);
614 	if (rv)
615 		return rv;
616 
617 	rv = serialize_ck_ulong(obj, params->source);
618 	if (rv)
619 		return rv;
620 
621 	rv = serialize_ck_ulong(obj, params->ulSourceDataLen);
622 	if (rv)
623 		return rv;
624 
625 	return serialize_buffer(obj, params->pSourceData,
626 				params->ulSourceDataLen);
627 }
628 
serialize_mecha_rsa_aes_key_wrap(struct serializer * obj,CK_MECHANISM_PTR mecha)629 static CK_RV serialize_mecha_rsa_aes_key_wrap(struct serializer *obj,
630 					      CK_MECHANISM_PTR mecha)
631 {
632 	CK_RSA_AES_KEY_WRAP_PARAMS *params = mecha->pParameter;
633 	CK_RSA_PKCS_OAEP_PARAMS *aes_params = params->pOAEPParams;
634 	CK_RV rv = CKR_GENERAL_ERROR;
635 	size_t params_size = 5 * sizeof(uint32_t) + aes_params->ulSourceDataLen;
636 
637 	if (mecha->ulParameterLen != sizeof(*params))
638 		return CKR_ARGUMENTS_BAD;
639 
640 	rv = serialize_32b(obj, obj->type);
641 	if (rv)
642 		return rv;
643 
644 	rv = serialize_32b(obj, params_size);
645 	if (rv)
646 		return rv;
647 
648 	rv = serialize_ck_ulong(obj, params->ulAESKeyBits);
649 	if (rv)
650 		return rv;
651 
652 	rv = serialize_ck_ulong(obj, aes_params->hashAlg);
653 	if (rv)
654 		return rv;
655 
656 	rv = serialize_ck_ulong(obj, aes_params->mgf);
657 	if (rv)
658 		return rv;
659 
660 	rv = serialize_ck_ulong(obj, aes_params->source);
661 	if (rv)
662 		return rv;
663 
664 	rv = serialize_ck_ulong(obj, aes_params->ulSourceDataLen);
665 	if (rv)
666 		return rv;
667 
668 	return serialize_buffer(obj, aes_params->pSourceData,
669 				aes_params->ulSourceDataLen);
670 }
671 
serialize_mecha_eddsa(struct serializer * obj,CK_MECHANISM_PTR mecha)672 static CK_RV serialize_mecha_eddsa(struct serializer *obj,
673 				   CK_MECHANISM_PTR mecha)
674 {
675 	CK_RV rv = CKR_GENERAL_ERROR;
676 	CK_EDDSA_PARAMS *params = mecha->pParameter;
677 	CK_ULONG params_len = mecha->ulParameterLen;
678 	/*
679 	 * When no parameter is provided, the expected operation is
680 	 * no-prehash and no-context.
681 	 */
682 	CK_EDDSA_PARAMS default_params = {
683 		.phFlag = 0,
684 		.ulContextDataLen = 0,
685 	};
686 
687 	if (params_len == 0) {
688 		params = &default_params;
689 		params_len = sizeof(*params);
690 	}
691 
692 	if (params_len != sizeof(*params))
693 		return CKR_ARGUMENTS_BAD;
694 
695 	rv = serialize_32b(obj, obj->type);
696 	if (rv)
697 		return rv;
698 
699 	rv = serialize_32b(obj, 2 * sizeof(uint32_t) + params->ulContextDataLen);
700 	if (rv)
701 		return rv;
702 
703 	rv = serialize_32b(obj, params->phFlag);
704 	if (rv)
705 		return rv;
706 
707 	rv = serialize_32b(obj, params->ulContextDataLen);
708 	if (rv)
709 		return rv;
710 
711 	return serialize_buffer(obj, params->pContextData, params->ulContextDataLen);
712 }
713 
serialize_mecha_mac_general_param(struct serializer * obj,CK_MECHANISM_PTR mecha)714 static CK_RV serialize_mecha_mac_general_param(struct serializer *obj,
715 					       CK_MECHANISM_PTR mecha)
716 {
717 	CK_RV rv = CKR_GENERAL_ERROR;
718 	CK_ULONG ck_data = 0;
719 
720 	if (mecha->ulParameterLen != sizeof(ck_data))
721 		return CKR_ARGUMENTS_BAD;
722 
723 	memcpy(&ck_data, mecha->pParameter, mecha->ulParameterLen);
724 
725 	rv = serialize_32b(obj, obj->type);
726 	if (rv)
727 		return rv;
728 
729 	rv = serialize_32b(obj, sizeof(uint32_t));
730 	if (rv)
731 		return rv;
732 
733 	return serialize_ck_ulong(obj, ck_data);
734 }
735 
736 /**
737  * serialize_ck_mecha_params - serialize a mechanism type & params
738  *
739  * @obj - serializer used to track the serialization
740  * @mechanism - pointer of the in structure aligned CK_MECHANISM.
741  *
742  * Serialized content:
743  *	[mechanism-type][mechanism-param-blob]
744  *
745  * [mechanism-param-blob] depends on mechanism type ID, see
746  * serialize_mecha_XXX().
747  */
serialize_ck_mecha_params(struct serializer * obj,CK_MECHANISM_PTR mechanism)748 CK_RV serialize_ck_mecha_params(struct serializer *obj,
749 				CK_MECHANISM_PTR mechanism)
750 {
751 	CK_MECHANISM mecha = { 0 };
752 	CK_RV rv = CKR_GENERAL_ERROR;
753 
754 	memset(obj, 0, sizeof(*obj));
755 
756 	obj->object = PKCS11_CKO_MECHANISM;
757 
758 	mecha = *mechanism;
759 	obj->type = mecha.mechanism;
760 	if (obj->type == PKCS11_UNDEFINED_ID)
761 		return CKR_MECHANISM_INVALID;
762 
763 	switch (mecha.mechanism) {
764 	case CKM_GENERIC_SECRET_KEY_GEN:
765 	case CKM_AES_KEY_GEN:
766 	case CKM_AES_ECB:
767 	case CKM_AES_CMAC:
768 	case CKM_MD5:
769 	case CKM_SHA_1:
770 	case CKM_SHA224:
771 	case CKM_SHA256:
772 	case CKM_SHA384:
773 	case CKM_SHA512:
774 	case CKM_MD5_HMAC:
775 	case CKM_SHA_1_HMAC:
776 	case CKM_SHA224_HMAC:
777 	case CKM_SHA256_HMAC:
778 	case CKM_SHA384_HMAC:
779 	case CKM_SHA512_HMAC:
780 	case CKM_EC_KEY_PAIR_GEN:
781 	case CKM_EC_EDWARDS_KEY_PAIR_GEN:
782 	case CKM_ECDSA:
783 	case CKM_ECDSA_SHA1:
784 	case CKM_ECDSA_SHA224:
785 	case CKM_ECDSA_SHA256:
786 	case CKM_ECDSA_SHA384:
787 	case CKM_ECDSA_SHA512:
788 	case CKM_RSA_PKCS_KEY_PAIR_GEN:
789 	case CKM_RSA_PKCS:
790 	case CKM_RSA_X_509:
791 	case CKM_MD5_RSA_PKCS:
792 	case CKM_SHA1_RSA_PKCS:
793 	case CKM_SHA224_RSA_PKCS:
794 	case CKM_SHA256_RSA_PKCS:
795 	case CKM_SHA384_RSA_PKCS:
796 	case CKM_SHA512_RSA_PKCS:
797 		/* No parameter expected, size shall be 0 */
798 		if (mechanism->ulParameterLen)
799 			return CKR_MECHANISM_PARAM_INVALID;
800 
801 		rv = serialize_32b(obj, obj->type);
802 		if (rv)
803 			return rv;
804 
805 		return serialize_32b(obj, 0);
806 
807 	case CKM_EDDSA:
808 		return serialize_mecha_eddsa(obj, &mecha);
809 
810 	case CKM_AES_CBC:
811 	case CKM_AES_CBC_PAD:
812 	case CKM_AES_CTS:
813 		return serialize_mecha_aes_iv(obj, &mecha);
814 
815 	case CKM_AES_CTR:
816 		return serialize_mecha_aes_ctr(obj, &mecha);
817 
818 	case CKM_AES_GCM:
819 		return serialize_mecha_aes_gcm(obj, &mecha);
820 
821 	case CKM_AES_ECB_ENCRYPT_DATA:
822 		return serialize_mecha_key_deriv_str(obj, &mecha);
823 
824 	case CKM_AES_CBC_ENCRYPT_DATA:
825 		return serialize_mecha_aes_cbc_encrypt_data(obj, &mecha);
826 
827 	case CKM_ECDH1_DERIVE:
828 	case CKM_ECDH1_COFACTOR_DERIVE:
829 		return serialize_mecha_ecdh1_derive_param(obj, &mecha);
830 
831 	case CKM_RSA_PKCS_PSS:
832 	case CKM_SHA1_RSA_PKCS_PSS:
833 	case CKM_SHA256_RSA_PKCS_PSS:
834 	case CKM_SHA384_RSA_PKCS_PSS:
835 	case CKM_SHA512_RSA_PKCS_PSS:
836 	case CKM_SHA224_RSA_PKCS_PSS:
837 		return serialize_mecha_rsa_pss_param(obj, &mecha);
838 
839 	case CKM_RSA_PKCS_OAEP:
840 		return serialize_mecha_rsa_oaep_param(obj, &mecha);
841 
842 	case CKM_AES_CMAC_GENERAL:
843 	case CKM_MD5_HMAC_GENERAL:
844 	case CKM_SHA_1_HMAC_GENERAL:
845 	case CKM_SHA224_HMAC_GENERAL:
846 	case CKM_SHA256_HMAC_GENERAL:
847 	case CKM_SHA384_HMAC_GENERAL:
848 	case CKM_SHA512_HMAC_GENERAL:
849 		return serialize_mecha_mac_general_param(obj, &mecha);
850 	case CKM_RSA_AES_KEY_WRAP:
851 		return serialize_mecha_rsa_aes_key_wrap(obj, &mecha);
852 
853 	default:
854 		return CKR_MECHANISM_INVALID;
855 	}
856 }
857