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