xref: /optee_os/ta/pkcs11/src/serializer.c (revision 55dcd3cc83c75032cb58ef579ac2054cca440466)
14f8a354fSEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
24f8a354fSEtienne Carriere /*
34f8a354fSEtienne Carriere  * Copyright (c) 2017-2020, Linaro Limited
44f8a354fSEtienne Carriere  */
54f8a354fSEtienne Carriere 
64f8a354fSEtienne Carriere #include <pkcs11_ta.h>
74f8a354fSEtienne Carriere #include <stdbool.h>
84f8a354fSEtienne Carriere #include <stdint.h>
9*55dcd3ccSJens Wiklander #include <tee_internal_api_extensions.h>
104f8a354fSEtienne Carriere #include <tee_internal_api.h>
114f8a354fSEtienne Carriere #include <trace.h>
12*55dcd3ccSJens Wiklander #include <util.h>
134f8a354fSEtienne Carriere 
143158faf6SEtienne Carriere #include "pkcs11_token.h"
154f8a354fSEtienne Carriere #include "serializer.h"
164f8a354fSEtienne Carriere 
174f8a354fSEtienne Carriere /*
184f8a354fSEtienne Carriere  * Util routines for serializes unformatted arguments in a client memref
194f8a354fSEtienne Carriere  */
serialargs_init(struct serialargs * args,void * in,size_t size)204f8a354fSEtienne Carriere void serialargs_init(struct serialargs *args, void *in, size_t size)
214f8a354fSEtienne Carriere {
224f8a354fSEtienne Carriere 	args->start = in;
234f8a354fSEtienne Carriere 	args->next = in;
244f8a354fSEtienne Carriere 	args->size = size;
254f8a354fSEtienne Carriere }
264f8a354fSEtienne Carriere 
serialargs_get(struct serialargs * args,void * out,size_t size)274daf39b3SJens Wiklander enum pkcs11_rc serialargs_get(struct serialargs *args, void *out, size_t size)
284f8a354fSEtienne Carriere {
29*55dcd3ccSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
30*55dcd3ccSJens Wiklander 	void *src = NULL;
31*55dcd3ccSJens Wiklander 
32*55dcd3ccSJens Wiklander 	rc = serialargs_get_ptr(args, &src, size);
33*55dcd3ccSJens Wiklander 	if (!rc)
34*55dcd3ccSJens Wiklander 		TEE_MemMove(out, src, size);
35*55dcd3ccSJens Wiklander 
36*55dcd3ccSJens Wiklander 	return rc;
374f8a354fSEtienne Carriere }
384f8a354fSEtienne Carriere 
alloc_and_get(struct serialargs * args,char * orig_next,const void * buf0,size_t buf0_sz,void ** out,size_t size)39*55dcd3ccSJens Wiklander static enum pkcs11_rc alloc_and_get(struct serialargs *args, char *orig_next,
40*55dcd3ccSJens Wiklander 				    const void *buf0, size_t buf0_sz,
41*55dcd3ccSJens Wiklander 				    void **out, size_t size)
42*55dcd3ccSJens Wiklander {
43*55dcd3ccSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
44*55dcd3ccSJens Wiklander 	uint8_t *ptr = NULL;
45*55dcd3ccSJens Wiklander 	void *src = NULL;
46*55dcd3ccSJens Wiklander 	size_t sz = 0;
474f8a354fSEtienne Carriere 
48*55dcd3ccSJens Wiklander 	if (ADD_OVERFLOW(buf0_sz, size, &sz))
49*55dcd3ccSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
50*55dcd3ccSJens Wiklander 
51*55dcd3ccSJens Wiklander 	if (!sz) {
52*55dcd3ccSJens Wiklander 		*out = NULL;
53*55dcd3ccSJens Wiklander 		return PKCS11_CKR_OK;
54*55dcd3ccSJens Wiklander 	}
55*55dcd3ccSJens Wiklander 
56*55dcd3ccSJens Wiklander 	rc = serialargs_get_ptr(args, &src, size);
57*55dcd3ccSJens Wiklander 	if (rc)
58*55dcd3ccSJens Wiklander 		return rc;
59*55dcd3ccSJens Wiklander 
60*55dcd3ccSJens Wiklander 	ptr = TEE_Malloc(sz, TEE_MALLOC_FILL_ZERO);
61*55dcd3ccSJens Wiklander 	if (!ptr) {
62*55dcd3ccSJens Wiklander 		args->next = orig_next;
63*55dcd3ccSJens Wiklander 		return PKCS11_CKR_DEVICE_MEMORY;
64*55dcd3ccSJens Wiklander 	}
65*55dcd3ccSJens Wiklander 
66*55dcd3ccSJens Wiklander 	TEE_MemMove(ptr, buf0, buf0_sz);
67*55dcd3ccSJens Wiklander 	TEE_MemMove(ptr + buf0_sz, src, size);
68*55dcd3ccSJens Wiklander 
69*55dcd3ccSJens Wiklander 	*out = ptr;
704f8a354fSEtienne Carriere 
714f8a354fSEtienne Carriere 	return PKCS11_CKR_OK;
724f8a354fSEtienne Carriere }
734f8a354fSEtienne Carriere 
serialargs_alloc_and_get(struct serialargs * args,void ** out,size_t size)744daf39b3SJens Wiklander enum pkcs11_rc serialargs_alloc_and_get(struct serialargs *args,
754f8a354fSEtienne Carriere 					void **out, size_t size)
764f8a354fSEtienne Carriere {
77*55dcd3ccSJens Wiklander 	return alloc_and_get(args, args->next, NULL, 0, out, size);
784f8a354fSEtienne Carriere }
794f8a354fSEtienne Carriere 
serialargs_get_ptr(struct serialargs * args,void ** out,size_t size)804daf39b3SJens Wiklander enum pkcs11_rc serialargs_get_ptr(struct serialargs *args, void **out,
814daf39b3SJens Wiklander 				  size_t size)
824f8a354fSEtienne Carriere {
834f8a354fSEtienne Carriere 	void *ptr = args->next;
84*55dcd3ccSJens Wiklander 	vaddr_t next_end = 0;
85*55dcd3ccSJens Wiklander 
86*55dcd3ccSJens Wiklander 	if (ADD_OVERFLOW((vaddr_t)args->next, size, &next_end))
87*55dcd3ccSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
884f8a354fSEtienne Carriere 
894f8a354fSEtienne Carriere 	if (!size) {
904f8a354fSEtienne Carriere 		*out = NULL;
914f8a354fSEtienne Carriere 		return PKCS11_CKR_OK;
924f8a354fSEtienne Carriere 	}
934f8a354fSEtienne Carriere 
94*55dcd3ccSJens Wiklander 	if ((char *)next_end > args->start + args->size) {
954f8a354fSEtienne Carriere 		EMSG("arg too short: full %zd, remain %zd, expect %zd",
964f8a354fSEtienne Carriere 		     args->size, args->size - (args->next - args->start), size);
974f8a354fSEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
984f8a354fSEtienne Carriere 	}
994f8a354fSEtienne Carriere 
1004f8a354fSEtienne Carriere 	args->next += size;
1014f8a354fSEtienne Carriere 	*out = ptr;
1024f8a354fSEtienne Carriere 
1034f8a354fSEtienne Carriere 	return PKCS11_CKR_OK;
1044f8a354fSEtienne Carriere }
1054f8a354fSEtienne Carriere 
106*55dcd3ccSJens Wiklander enum pkcs11_rc
serialargs_alloc_get_one_attribute(struct serialargs * args,struct pkcs11_attribute_head ** out)107*55dcd3ccSJens Wiklander serialargs_alloc_get_one_attribute(struct serialargs *args,
108*55dcd3ccSJens Wiklander 				   struct pkcs11_attribute_head **out)
109*55dcd3ccSJens Wiklander {
110*55dcd3ccSJens Wiklander 	struct pkcs11_attribute_head head = { };
111*55dcd3ccSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
112*55dcd3ccSJens Wiklander 	char *orig_next = args->next;
113*55dcd3ccSJens Wiklander 	void *p = NULL;
114*55dcd3ccSJens Wiklander 
115*55dcd3ccSJens Wiklander 	rc = serialargs_get(args, &head, sizeof(head));
116*55dcd3ccSJens Wiklander 	if (rc)
117*55dcd3ccSJens Wiklander 		return rc;
118*55dcd3ccSJens Wiklander 
119*55dcd3ccSJens Wiklander 	rc = alloc_and_get(args, orig_next, &head, sizeof(head), &p, head.size);
120*55dcd3ccSJens Wiklander 	if (rc)
121*55dcd3ccSJens Wiklander 		return rc;
122*55dcd3ccSJens Wiklander 
123*55dcd3ccSJens Wiklander 	*out = p;
124*55dcd3ccSJens Wiklander 
125*55dcd3ccSJens Wiklander 	return PKCS11_CKR_OK;
126*55dcd3ccSJens Wiklander }
127*55dcd3ccSJens Wiklander 
serialargs_alloc_get_attributes(struct serialargs * args,struct pkcs11_object_head ** out)128*55dcd3ccSJens Wiklander enum pkcs11_rc serialargs_alloc_get_attributes(struct serialargs *args,
129*55dcd3ccSJens Wiklander 					       struct pkcs11_object_head **out)
130*55dcd3ccSJens Wiklander {
131*55dcd3ccSJens Wiklander 	struct pkcs11_object_head attr = { };
132*55dcd3ccSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
133*55dcd3ccSJens Wiklander 	char *orig_next = args->next;
134*55dcd3ccSJens Wiklander 	void *p = NULL;
135*55dcd3ccSJens Wiklander 
136*55dcd3ccSJens Wiklander 	rc = serialargs_get(args, &attr, sizeof(attr));
137*55dcd3ccSJens Wiklander 	if (rc)
138*55dcd3ccSJens Wiklander 		return rc;
139*55dcd3ccSJens Wiklander 
140*55dcd3ccSJens Wiklander 	rc = alloc_and_get(args, orig_next, &attr, sizeof(attr), &p,
141*55dcd3ccSJens Wiklander 			   attr.attrs_size);
142*55dcd3ccSJens Wiklander 	if (rc)
143*55dcd3ccSJens Wiklander 		return rc;
144*55dcd3ccSJens Wiklander 
145*55dcd3ccSJens Wiklander 	*out = p;
146*55dcd3ccSJens Wiklander 
147*55dcd3ccSJens Wiklander 	return PKCS11_CKR_OK;
148*55dcd3ccSJens Wiklander }
149*55dcd3ccSJens Wiklander 
serialargs_remaining_bytes(struct serialargs * args)1504f8a354fSEtienne Carriere bool serialargs_remaining_bytes(struct serialargs *args)
1514f8a354fSEtienne Carriere {
1524f8a354fSEtienne Carriere 	return args->next < args->start + args->size;
1534f8a354fSEtienne Carriere }
1543158faf6SEtienne Carriere 
serialargs_get_session_from_handle(struct serialargs * args,struct pkcs11_client * client,struct pkcs11_session ** sess)1553158faf6SEtienne Carriere enum pkcs11_rc serialargs_get_session_from_handle(struct serialargs *args,
1563158faf6SEtienne Carriere 						  struct pkcs11_client *client,
1573158faf6SEtienne Carriere 						  struct pkcs11_session **sess)
1583158faf6SEtienne Carriere {
1593158faf6SEtienne Carriere 	uint32_t rv = PKCS11_CKR_GENERAL_ERROR;
1603158faf6SEtienne Carriere 	uint32_t session_handle = 0;
1613158faf6SEtienne Carriere 	struct pkcs11_session *session = NULL;
1623158faf6SEtienne Carriere 
1633158faf6SEtienne Carriere 	rv = serialargs_get(args, &session_handle, sizeof(uint32_t));
1643158faf6SEtienne Carriere 	if (rv)
1653158faf6SEtienne Carriere 		return rv;
1663158faf6SEtienne Carriere 
1673158faf6SEtienne Carriere 	session = pkcs11_handle2session(session_handle, client);
1683158faf6SEtienne Carriere 	if (!session)
1693158faf6SEtienne Carriere 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
1703158faf6SEtienne Carriere 
1713158faf6SEtienne Carriere 	*sess = session;
1723158faf6SEtienne Carriere 
1733158faf6SEtienne Carriere 	return PKCS11_CKR_OK;
1743158faf6SEtienne Carriere }
175bd62f6a3SEtienne Carriere 
serialize(char ** bstart,size_t * blen,void * data,size_t len)176bd62f6a3SEtienne Carriere enum pkcs11_rc serialize(char **bstart, size_t *blen, void *data, size_t len)
177bd62f6a3SEtienne Carriere {
178bd62f6a3SEtienne Carriere 	char *buf = NULL;
179bd62f6a3SEtienne Carriere 	size_t nlen = 0;
180bd62f6a3SEtienne Carriere 
181bd62f6a3SEtienne Carriere 	if (ADD_OVERFLOW(*blen, len, &nlen))
182bd62f6a3SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
183bd62f6a3SEtienne Carriere 
184bd62f6a3SEtienne Carriere 	buf = TEE_Realloc(*bstart, nlen);
185bd62f6a3SEtienne Carriere 	if (!buf)
186bd62f6a3SEtienne Carriere 		return PKCS11_CKR_DEVICE_MEMORY;
187bd62f6a3SEtienne Carriere 
188bd62f6a3SEtienne Carriere 	TEE_MemMove(buf + *blen, data, len);
189bd62f6a3SEtienne Carriere 
190bd62f6a3SEtienne Carriere 	*blen = nlen;
191bd62f6a3SEtienne Carriere 	*bstart = buf;
192bd62f6a3SEtienne Carriere 
193bd62f6a3SEtienne Carriere 	return PKCS11_CKR_OK;
194bd62f6a3SEtienne Carriere }
195bd62f6a3SEtienne Carriere 
196