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 */ 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 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 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 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 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 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 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 150 bool serialargs_remaining_bytes(struct serialargs *args) 151 { 152 return args->next < args->start + args->size; 153 } 154 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 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