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