1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2020, Linaro Limited
4  */
5 
6 #include <pkcs11_ta.h>
7 #include <stdbool.h>
8 #include <stdint.h>
9 #include <tee_internal_api_extensions.h>
10 #include <tee_internal_api.h>
11 #include <trace.h>
12 #include <util.h>
13 
14 #include "pkcs11_token.h"
15 #include "serializer.h"
16 
17 /*
18  * Util routines for serializes unformatted arguments in a client memref
19  */
serialargs_init(struct serialargs * args,void * in,size_t size)20 void serialargs_init(struct serialargs *args, void *in, size_t size)
21 {
22 	args->start = in;
23 	args->next = in;
24 	args->size = size;
25 }
26 
serialargs_get(struct serialargs * args,void * out,size_t size)27 enum pkcs11_rc serialargs_get(struct serialargs *args, void *out, size_t size)
28 {
29 	enum pkcs11_rc rc = PKCS11_CKR_OK;
30 	void *src = NULL;
31 
32 	rc = serialargs_get_ptr(args, &src, size);
33 	if (!rc)
34 		TEE_MemMove(out, src, size);
35 
36 	return rc;
37 }
38 
alloc_and_get(struct serialargs * args,char * orig_next,const void * buf0,size_t buf0_sz,void ** out,size_t size)39 static enum pkcs11_rc alloc_and_get(struct serialargs *args, char *orig_next,
40 				    const void *buf0, size_t buf0_sz,
41 				    void **out, size_t size)
42 {
43 	enum pkcs11_rc rc = PKCS11_CKR_OK;
44 	uint8_t *ptr = NULL;
45 	void *src = NULL;
46 	size_t sz = 0;
47 
48 	if (ADD_OVERFLOW(buf0_sz, size, &sz))
49 		return PKCS11_CKR_ARGUMENTS_BAD;
50 
51 	if (!sz) {
52 		*out = NULL;
53 		return PKCS11_CKR_OK;
54 	}
55 
56 	rc = serialargs_get_ptr(args, &src, size);
57 	if (rc)
58 		return rc;
59 
60 	ptr = TEE_Malloc(sz, TEE_MALLOC_FILL_ZERO);
61 	if (!ptr) {
62 		args->next = orig_next;
63 		return PKCS11_CKR_DEVICE_MEMORY;
64 	}
65 
66 	TEE_MemMove(ptr, buf0, buf0_sz);
67 	TEE_MemMove(ptr + buf0_sz, src, size);
68 
69 	*out = ptr;
70 
71 	return PKCS11_CKR_OK;
72 }
73 
serialargs_alloc_and_get(struct serialargs * args,void ** out,size_t size)74 enum pkcs11_rc serialargs_alloc_and_get(struct serialargs *args,
75 					void **out, size_t size)
76 {
77 	return alloc_and_get(args, args->next, NULL, 0, out, size);
78 }
79 
serialargs_get_ptr(struct serialargs * args,void ** out,size_t size)80 enum pkcs11_rc serialargs_get_ptr(struct serialargs *args, void **out,
81 				  size_t size)
82 {
83 	void *ptr = args->next;
84 	vaddr_t next_end = 0;
85 
86 	if (ADD_OVERFLOW((vaddr_t)args->next, size, &next_end))
87 		return PKCS11_CKR_ARGUMENTS_BAD;
88 
89 	if (!size) {
90 		*out = NULL;
91 		return PKCS11_CKR_OK;
92 	}
93 
94 	if ((char *)next_end > args->start + args->size) {
95 		EMSG("arg too short: full %zd, remain %zd, expect %zd",
96 		     args->size, args->size - (args->next - args->start), size);
97 		return PKCS11_CKR_ARGUMENTS_BAD;
98 	}
99 
100 	args->next += size;
101 	*out = ptr;
102 
103 	return PKCS11_CKR_OK;
104 }
105 
106 enum pkcs11_rc
serialargs_alloc_get_one_attribute(struct serialargs * args,struct pkcs11_attribute_head ** out)107 serialargs_alloc_get_one_attribute(struct serialargs *args,
108 				   struct pkcs11_attribute_head **out)
109 {
110 	struct pkcs11_attribute_head head = { };
111 	enum pkcs11_rc rc = PKCS11_CKR_OK;
112 	char *orig_next = args->next;
113 	void *p = NULL;
114 
115 	rc = serialargs_get(args, &head, sizeof(head));
116 	if (rc)
117 		return rc;
118 
119 	rc = alloc_and_get(args, orig_next, &head, sizeof(head), &p, head.size);
120 	if (rc)
121 		return rc;
122 
123 	*out = p;
124 
125 	return PKCS11_CKR_OK;
126 }
127 
serialargs_alloc_get_attributes(struct serialargs * args,struct pkcs11_object_head ** out)128 enum pkcs11_rc serialargs_alloc_get_attributes(struct serialargs *args,
129 					       struct pkcs11_object_head **out)
130 {
131 	struct pkcs11_object_head attr = { };
132 	enum pkcs11_rc rc = PKCS11_CKR_OK;
133 	char *orig_next = args->next;
134 	void *p = NULL;
135 
136 	rc = serialargs_get(args, &attr, sizeof(attr));
137 	if (rc)
138 		return rc;
139 
140 	rc = alloc_and_get(args, orig_next, &attr, sizeof(attr), &p,
141 			   attr.attrs_size);
142 	if (rc)
143 		return rc;
144 
145 	*out = p;
146 
147 	return PKCS11_CKR_OK;
148 }
149 
serialargs_remaining_bytes(struct serialargs * args)150 bool serialargs_remaining_bytes(struct serialargs *args)
151 {
152 	return args->next < args->start + args->size;
153 }
154 
serialargs_get_session_from_handle(struct serialargs * args,struct pkcs11_client * client,struct pkcs11_session ** sess)155 enum pkcs11_rc serialargs_get_session_from_handle(struct serialargs *args,
156 						  struct pkcs11_client *client,
157 						  struct pkcs11_session **sess)
158 {
159 	uint32_t rv = PKCS11_CKR_GENERAL_ERROR;
160 	uint32_t session_handle = 0;
161 	struct pkcs11_session *session = NULL;
162 
163 	rv = serialargs_get(args, &session_handle, sizeof(uint32_t));
164 	if (rv)
165 		return rv;
166 
167 	session = pkcs11_handle2session(session_handle, client);
168 	if (!session)
169 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
170 
171 	*sess = session;
172 
173 	return PKCS11_CKR_OK;
174 }
175 
serialize(char ** bstart,size_t * blen,void * data,size_t len)176 enum pkcs11_rc serialize(char **bstart, size_t *blen, void *data, size_t len)
177 {
178 	char *buf = NULL;
179 	size_t nlen = 0;
180 
181 	if (ADD_OVERFLOW(*blen, len, &nlen))
182 		return PKCS11_CKR_ARGUMENTS_BAD;
183 
184 	buf = TEE_Realloc(*bstart, nlen);
185 	if (!buf)
186 		return PKCS11_CKR_DEVICE_MEMORY;
187 
188 	TEE_MemMove(buf + *blen, data, len);
189 
190 	*blen = nlen;
191 	*bstart = buf;
192 
193 	return PKCS11_CKR_OK;
194 }
195 
196