xref: /optee_os/ta/pkcs11/src/serializer.c (revision 2c028fdebbedee91f88f6c5325b5064a124dfe46)
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.h>
10 #include <trace.h>
11 
12 #include "pkcs11_token.h"
13 #include "serializer.h"
14 
15 /*
16  * Util routines for serializes unformatted arguments in a client memref
17  */
18 void serialargs_init(struct serialargs *args, void *in, size_t size)
19 {
20 	args->start = in;
21 	args->next = in;
22 	args->size = size;
23 }
24 
25 enum pkcs11_rc serialargs_get(struct serialargs *args, void *out, size_t size)
26 {
27 	if (args->next + size > args->start + args->size) {
28 		EMSG("arg too short: full %zd, remain %zd, expect %zd",
29 		     args->size, args->size - (args->next - args->start), size);
30 		return PKCS11_CKR_ARGUMENTS_BAD;
31 	}
32 
33 	TEE_MemMove(out, args->next, size);
34 
35 	args->next += size;
36 
37 	return PKCS11_CKR_OK;
38 }
39 
40 enum pkcs11_rc serialargs_alloc_and_get(struct serialargs *args,
41 					void **out, size_t size)
42 {
43 	void *ptr = NULL;
44 
45 	if (!size) {
46 		*out = NULL;
47 		return PKCS11_CKR_OK;
48 	}
49 
50 	if (args->next + size > args->start + args->size) {
51 		EMSG("arg too short: full %zd, remain %zd, expect %zd",
52 		     args->size, args->size - (args->next - args->start), size);
53 		return PKCS11_CKR_ARGUMENTS_BAD;
54 	}
55 
56 	ptr = TEE_Malloc(size, TEE_MALLOC_FILL_ZERO);
57 	if (!ptr)
58 		return PKCS11_CKR_DEVICE_MEMORY;
59 
60 	TEE_MemMove(ptr, args->next, size);
61 
62 	args->next += size;
63 	*out = ptr;
64 
65 	return PKCS11_CKR_OK;
66 }
67 
68 enum pkcs11_rc serialargs_get_ptr(struct serialargs *args, void **out,
69 				  size_t size)
70 {
71 	void *ptr = args->next;
72 
73 	if (!size) {
74 		*out = NULL;
75 		return PKCS11_CKR_OK;
76 	}
77 
78 	if (args->next + size > args->start + args->size) {
79 		EMSG("arg too short: full %zd, remain %zd, expect %zd",
80 		     args->size, args->size - (args->next - args->start), size);
81 		return PKCS11_CKR_ARGUMENTS_BAD;
82 	}
83 
84 	args->next += size;
85 	*out = ptr;
86 
87 	return PKCS11_CKR_OK;
88 }
89 
90 bool serialargs_remaining_bytes(struct serialargs *args)
91 {
92 	return args->next < args->start + args->size;
93 }
94 
95 enum pkcs11_rc serialargs_get_session_from_handle(struct serialargs *args,
96 						  struct pkcs11_client *client,
97 						  struct pkcs11_session **sess)
98 {
99 	uint32_t rv = PKCS11_CKR_GENERAL_ERROR;
100 	uint32_t session_handle = 0;
101 	struct pkcs11_session *session = NULL;
102 
103 	rv = serialargs_get(args, &session_handle, sizeof(uint32_t));
104 	if (rv)
105 		return rv;
106 
107 	session = pkcs11_handle2session(session_handle, client);
108 	if (!session)
109 		return PKCS11_CKR_SESSION_HANDLE_INVALID;
110 
111 	*sess = session;
112 
113 	return PKCS11_CKR_OK;
114 }
115