1*63f89caaSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2*63f89caaSJens Wiklander /* 3*63f89caaSJens Wiklander * Copyright (c) 2017-2020, Linaro Limited 4*63f89caaSJens Wiklander */ 5*63f89caaSJens Wiklander 6*63f89caaSJens Wiklander #include <bitstring.h> 7*63f89caaSJens Wiklander #include <pkcs11_ta.h> 8*63f89caaSJens Wiklander #include <stdlib.h> 9*63f89caaSJens Wiklander #include <string.h> 10*63f89caaSJens Wiklander #include <util.h> 11*63f89caaSJens Wiklander #include <tee_internal_api.h> 12*63f89caaSJens Wiklander #include <tee_internal_api_extensions.h> 13*63f89caaSJens Wiklander #include <trace.h> 14*63f89caaSJens Wiklander 15*63f89caaSJens Wiklander #include "attributes.h" 16*63f89caaSJens Wiklander #include "pkcs11_helpers.h" 17*63f89caaSJens Wiklander #include "sanitize_object.h" 18*63f89caaSJens Wiklander #include "serializer.h" 19*63f89caaSJens Wiklander #include "token_capabilities.h" 20*63f89caaSJens Wiklander 21*63f89caaSJens Wiklander /* 22*63f89caaSJens Wiklander * Functions to generate a serialized object. 23*63f89caaSJens Wiklander * References are pointers to struct serializer. 24*63f89caaSJens Wiklander */ 25*63f89caaSJens Wiklander 26*63f89caaSJens Wiklander bool sanitize_consistent_class_and_type(struct obj_attrs *attrs) 27*63f89caaSJens Wiklander { 28*63f89caaSJens Wiklander switch (get_class(attrs)) { 29*63f89caaSJens Wiklander case PKCS11_CKO_DATA: 30*63f89caaSJens Wiklander return true; 31*63f89caaSJens Wiklander case PKCS11_CKO_SECRET_KEY: 32*63f89caaSJens Wiklander return key_type_is_symm_key(get_key_type(attrs)); 33*63f89caaSJens Wiklander case PKCS11_CKO_MECHANISM: 34*63f89caaSJens Wiklander return mechanism_is_valid(get_mechanism_type(attrs)); 35*63f89caaSJens Wiklander case PKCS11_CKO_PUBLIC_KEY: 36*63f89caaSJens Wiklander case PKCS11_CKO_PRIVATE_KEY: 37*63f89caaSJens Wiklander return key_type_is_asymm_key(get_key_type(attrs)); 38*63f89caaSJens Wiklander case PKCS11_CKO_OTP_KEY: 39*63f89caaSJens Wiklander case PKCS11_CKO_CERTIFICATE: 40*63f89caaSJens Wiklander case PKCS11_CKO_DOMAIN_PARAMETERS: 41*63f89caaSJens Wiklander case PKCS11_CKO_HW_FEATURE: 42*63f89caaSJens Wiklander default: 43*63f89caaSJens Wiklander return false; 44*63f89caaSJens Wiklander } 45*63f89caaSJens Wiklander 46*63f89caaSJens Wiklander return false; 47*63f89caaSJens Wiklander } 48*63f89caaSJens Wiklander 49*63f89caaSJens Wiklander static enum pkcs11_rc read_attr_advance(void *buf, size_t blen, size_t *pos, 50*63f89caaSJens Wiklander struct pkcs11_attribute_head *attr, 51*63f89caaSJens Wiklander void **data) 52*63f89caaSJens Wiklander { 53*63f89caaSJens Wiklander uint8_t *b = buf; 54*63f89caaSJens Wiklander size_t data_pos = 0; 55*63f89caaSJens Wiklander size_t next_pos = 0; 56*63f89caaSJens Wiklander 57*63f89caaSJens Wiklander if (ADD_OVERFLOW(*pos, sizeof(*attr), &data_pos) || data_pos > blen) 58*63f89caaSJens Wiklander return PKCS11_CKR_FUNCTION_FAILED; 59*63f89caaSJens Wiklander TEE_MemMove(attr, b + *pos, sizeof(*attr)); 60*63f89caaSJens Wiklander 61*63f89caaSJens Wiklander if (ADD_OVERFLOW(data_pos, attr->size, &next_pos) || next_pos > blen) 62*63f89caaSJens Wiklander return PKCS11_CKR_FUNCTION_FAILED; 63*63f89caaSJens Wiklander 64*63f89caaSJens Wiklander *data = b + data_pos; 65*63f89caaSJens Wiklander *pos = next_pos; 66*63f89caaSJens Wiklander 67*63f89caaSJens Wiklander return PKCS11_CKR_OK; 68*63f89caaSJens Wiklander } 69*63f89caaSJens Wiklander 70*63f89caaSJens Wiklander /* Sanitize class/type in a client attribute list */ 71*63f89caaSJens Wiklander static enum pkcs11_rc sanitize_class_and_type(struct obj_attrs **dst, void *src, 72*63f89caaSJens Wiklander size_t src_size) 73*63f89caaSJens Wiklander { 74*63f89caaSJens Wiklander uint32_t class_found = PKCS11_CKO_UNDEFINED_ID; 75*63f89caaSJens Wiklander size_t pos = sizeof(struct pkcs11_object_head); 76*63f89caaSJens Wiklander struct pkcs11_attribute_head cli_ref = { }; 77*63f89caaSJens Wiklander uint32_t type_found = PKCS11_UNDEFINED_ID; 78*63f89caaSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 79*63f89caaSJens Wiklander void *data = NULL; 80*63f89caaSJens Wiklander 81*63f89caaSJens Wiklander while (pos != src_size) { 82*63f89caaSJens Wiklander rc = read_attr_advance(src, src_size, &pos, &cli_ref, &data); 83*63f89caaSJens Wiklander if (rc) 84*63f89caaSJens Wiklander goto err; 85*63f89caaSJens Wiklander 86*63f89caaSJens Wiklander if (cli_ref.id == PKCS11_CKA_CLASS) { 87*63f89caaSJens Wiklander uint32_t class = 0; 88*63f89caaSJens Wiklander 89*63f89caaSJens Wiklander if (cli_ref.size != sizeof(class)) { 90*63f89caaSJens Wiklander rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; 91*63f89caaSJens Wiklander goto err; 92*63f89caaSJens Wiklander } 93*63f89caaSJens Wiklander 94*63f89caaSJens Wiklander TEE_MemMove(&class, data, sizeof(class)); 95*63f89caaSJens Wiklander 96*63f89caaSJens Wiklander if (class_found != PKCS11_CKO_UNDEFINED_ID && 97*63f89caaSJens Wiklander class_found != class) { 98*63f89caaSJens Wiklander EMSG("Conflicting class value"); 99*63f89caaSJens Wiklander rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; 100*63f89caaSJens Wiklander goto err; 101*63f89caaSJens Wiklander } 102*63f89caaSJens Wiklander 103*63f89caaSJens Wiklander class_found = class; 104*63f89caaSJens Wiklander continue; 105*63f89caaSJens Wiklander } 106*63f89caaSJens Wiklander 107*63f89caaSJens Wiklander /* The attribute is a type-in-class */ 108*63f89caaSJens Wiklander if (pkcs11_attr_is_type(cli_ref.id)) { 109*63f89caaSJens Wiklander uint32_t type = 0; 110*63f89caaSJens Wiklander 111*63f89caaSJens Wiklander if (cli_ref.size != sizeof(type)) { 112*63f89caaSJens Wiklander rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; 113*63f89caaSJens Wiklander goto err; 114*63f89caaSJens Wiklander } 115*63f89caaSJens Wiklander 116*63f89caaSJens Wiklander TEE_MemMove(&type, data, sizeof(type)); 117*63f89caaSJens Wiklander 118*63f89caaSJens Wiklander if (type_found != PKCS11_CKK_UNDEFINED_ID && 119*63f89caaSJens Wiklander type_found != type) { 120*63f89caaSJens Wiklander EMSG("Conflicting type-in-class value"); 121*63f89caaSJens Wiklander rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; 122*63f89caaSJens Wiklander goto err; 123*63f89caaSJens Wiklander } 124*63f89caaSJens Wiklander 125*63f89caaSJens Wiklander type_found = type; 126*63f89caaSJens Wiklander } 127*63f89caaSJens Wiklander } 128*63f89caaSJens Wiklander 129*63f89caaSJens Wiklander if (class_found != PKCS11_CKO_UNDEFINED_ID) { 130*63f89caaSJens Wiklander rc = add_attribute(dst, PKCS11_CKA_CLASS, 131*63f89caaSJens Wiklander &class_found, sizeof(class_found)); 132*63f89caaSJens Wiklander if (rc) 133*63f89caaSJens Wiklander return rc; 134*63f89caaSJens Wiklander } 135*63f89caaSJens Wiklander 136*63f89caaSJens Wiklander if (type_found != PKCS11_UNDEFINED_ID) { 137*63f89caaSJens Wiklander rc = add_attribute(dst, PKCS11_CKA_KEY_TYPE, 138*63f89caaSJens Wiklander &type_found, sizeof(type_found)); 139*63f89caaSJens Wiklander if (rc) 140*63f89caaSJens Wiklander return rc; 141*63f89caaSJens Wiklander } 142*63f89caaSJens Wiklander 143*63f89caaSJens Wiklander return PKCS11_CKR_OK; 144*63f89caaSJens Wiklander 145*63f89caaSJens Wiklander err: 146*63f89caaSJens Wiklander trace_attributes_from_api_head("bad-template", src, src_size); 147*63f89caaSJens Wiklander 148*63f89caaSJens Wiklander return rc; 149*63f89caaSJens Wiklander } 150*63f89caaSJens Wiklander 151*63f89caaSJens Wiklander static enum pkcs11_rc sanitize_boolprops(struct obj_attrs **dst, void *src, 152*63f89caaSJens Wiklander size_t src_size) 153*63f89caaSJens Wiklander { 154*63f89caaSJens Wiklander bitstr_t bit_decl(seen_attrs, PKCS11_BOOLPROPS_MAX_COUNT) = { 0 }; 155*63f89caaSJens Wiklander bitstr_t bit_decl(boolprops, PKCS11_BOOLPROPS_MAX_COUNT) = { 0 }; 156*63f89caaSJens Wiklander size_t pos = sizeof(struct pkcs11_object_head); 157*63f89caaSJens Wiklander struct pkcs11_attribute_head cli_ref = { }; 158*63f89caaSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 159*63f89caaSJens Wiklander bool value = false; 160*63f89caaSJens Wiklander void *data = NULL; 161*63f89caaSJens Wiklander int idx = 0; 162*63f89caaSJens Wiklander 163*63f89caaSJens Wiklander /* 164*63f89caaSJens Wiklander * We're keeping track of seen boolean attributes in the bitstring 165*63f89caaSJens Wiklander * seen_attrs. The bitstring boolprops holds the recorded value 166*63f89caaSJens Wiklander * once seen_attrs has been updated. 167*63f89caaSJens Wiklander */ 168*63f89caaSJens Wiklander 169*63f89caaSJens Wiklander while (pos != src_size) { 170*63f89caaSJens Wiklander rc = read_attr_advance(src, src_size, &pos, &cli_ref, &data); 171*63f89caaSJens Wiklander if (rc) 172*63f89caaSJens Wiklander return rc; 173*63f89caaSJens Wiklander 174*63f89caaSJens Wiklander idx = pkcs11_attr2boolprop_shift(cli_ref.id); 175*63f89caaSJens Wiklander if (idx < 0) 176*63f89caaSJens Wiklander continue; /* skipping non-boolean attributes */ 177*63f89caaSJens Wiklander 178*63f89caaSJens Wiklander if (idx >= PKCS11_BOOLPROPS_MAX_COUNT || 179*63f89caaSJens Wiklander cli_ref.size != sizeof(uint8_t)) 180*63f89caaSJens Wiklander return PKCS11_CKR_FUNCTION_FAILED; 181*63f89caaSJens Wiklander 182*63f89caaSJens Wiklander value = *(uint8_t *)data; 183*63f89caaSJens Wiklander 184*63f89caaSJens Wiklander /* 185*63f89caaSJens Wiklander * If this attribute has already been seen, check that it 186*63f89caaSJens Wiklander * still holds the same value as last time. 187*63f89caaSJens Wiklander */ 188*63f89caaSJens Wiklander if (bit_test(seen_attrs, idx) && 189*63f89caaSJens Wiklander value != (bool)bit_test(boolprops, idx)) 190*63f89caaSJens Wiklander return PKCS11_CKR_TEMPLATE_INCONSISTENT; 191*63f89caaSJens Wiklander 192*63f89caaSJens Wiklander if (value) 193*63f89caaSJens Wiklander bit_set(boolprops, idx); 194*63f89caaSJens Wiklander 195*63f89caaSJens Wiklander if (!bit_test(seen_attrs, idx)) { 196*63f89caaSJens Wiklander uint8_t pkcs11_bool = value; 197*63f89caaSJens Wiklander 198*63f89caaSJens Wiklander rc = add_attribute(dst, cli_ref.id, &pkcs11_bool, 199*63f89caaSJens Wiklander sizeof(pkcs11_bool)); 200*63f89caaSJens Wiklander if (rc) 201*63f89caaSJens Wiklander return rc; 202*63f89caaSJens Wiklander } 203*63f89caaSJens Wiklander bit_set(seen_attrs, idx); 204*63f89caaSJens Wiklander } 205*63f89caaSJens Wiklander 206*63f89caaSJens Wiklander return PKCS11_CKR_OK; 207*63f89caaSJens Wiklander } 208*63f89caaSJens Wiklander 209*63f89caaSJens Wiklander static uint32_t sanitize_indirect_attr(struct obj_attrs **dst, 210*63f89caaSJens Wiklander struct pkcs11_attribute_head *cli_ref, 211*63f89caaSJens Wiklander char *data) 212*63f89caaSJens Wiklander { 213*63f89caaSJens Wiklander struct obj_attrs *obj2 = NULL; 214*63f89caaSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 215*63f89caaSJens Wiklander enum pkcs11_class_id class = get_class(*dst); 216*63f89caaSJens Wiklander 217*63f89caaSJens Wiklander if (class == PKCS11_CKO_UNDEFINED_ID) 218*63f89caaSJens Wiklander return PKCS11_CKR_GENERAL_ERROR; 219*63f89caaSJens Wiklander 220*63f89caaSJens Wiklander /* 221*63f89caaSJens Wiklander * Serialized attributes: current applicable only to the key 222*63f89caaSJens Wiklander * templates which are tables of attributes. 223*63f89caaSJens Wiklander */ 224*63f89caaSJens Wiklander switch (cli_ref->id) { 225*63f89caaSJens Wiklander case PKCS11_CKA_WRAP_TEMPLATE: 226*63f89caaSJens Wiklander case PKCS11_CKA_UNWRAP_TEMPLATE: 227*63f89caaSJens Wiklander case PKCS11_CKA_DERIVE_TEMPLATE: 228*63f89caaSJens Wiklander break; 229*63f89caaSJens Wiklander default: 230*63f89caaSJens Wiklander return PKCS11_RV_NOT_FOUND; 231*63f89caaSJens Wiklander } 232*63f89caaSJens Wiklander /* Such attributes are expected only for keys (and vendor defined) */ 233*63f89caaSJens Wiklander if (pkcs11_attr_class_is_key(class)) 234*63f89caaSJens Wiklander return PKCS11_CKR_TEMPLATE_INCONSISTENT; 235*63f89caaSJens Wiklander 236*63f89caaSJens Wiklander rc = init_attributes_head(&obj2); 237*63f89caaSJens Wiklander if (rc) 238*63f89caaSJens Wiklander return rc; 239*63f89caaSJens Wiklander 240*63f89caaSJens Wiklander /* Build a new serial object while sanitizing the attributes list */ 241*63f89caaSJens Wiklander rc = sanitize_client_object(&obj2, data, cli_ref->size); 242*63f89caaSJens Wiklander if (rc) 243*63f89caaSJens Wiklander goto out; 244*63f89caaSJens Wiklander 245*63f89caaSJens Wiklander rc = add_attribute(dst, cli_ref->id, obj2, 246*63f89caaSJens Wiklander sizeof(*obj2) + obj2->attrs_size); 247*63f89caaSJens Wiklander out: 248*63f89caaSJens Wiklander TEE_Free(obj2); 249*63f89caaSJens Wiklander return rc; 250*63f89caaSJens Wiklander } 251*63f89caaSJens Wiklander 252*63f89caaSJens Wiklander enum pkcs11_rc sanitize_client_object(struct obj_attrs **dst, void *src, 253*63f89caaSJens Wiklander size_t size) 254*63f89caaSJens Wiklander { 255*63f89caaSJens Wiklander struct pkcs11_attribute_head cli_ref = { }; 256*63f89caaSJens Wiklander struct pkcs11_object_head head = { }; 257*63f89caaSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 258*63f89caaSJens Wiklander size_t pos = sizeof(head); 259*63f89caaSJens Wiklander size_t sz_from_hdr = 0; 260*63f89caaSJens Wiklander void *data = NULL; 261*63f89caaSJens Wiklander 262*63f89caaSJens Wiklander if (size < sizeof(head)) 263*63f89caaSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 264*63f89caaSJens Wiklander 265*63f89caaSJens Wiklander TEE_MemMove(&head, src, sizeof(head)); 266*63f89caaSJens Wiklander 267*63f89caaSJens Wiklander if (ADD_OVERFLOW(sizeof(head), head.attrs_size, &sz_from_hdr) || 268*63f89caaSJens Wiklander size < sz_from_hdr) 269*63f89caaSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 270*63f89caaSJens Wiklander 271*63f89caaSJens Wiklander rc = init_attributes_head(dst); 272*63f89caaSJens Wiklander if (rc) 273*63f89caaSJens Wiklander return rc; 274*63f89caaSJens Wiklander 275*63f89caaSJens Wiklander rc = sanitize_class_and_type(dst, src, sz_from_hdr); 276*63f89caaSJens Wiklander if (rc) 277*63f89caaSJens Wiklander return rc; 278*63f89caaSJens Wiklander 279*63f89caaSJens Wiklander rc = sanitize_boolprops(dst, src, sz_from_hdr); 280*63f89caaSJens Wiklander if (rc) 281*63f89caaSJens Wiklander return rc; 282*63f89caaSJens Wiklander 283*63f89caaSJens Wiklander while (pos != sz_from_hdr) { 284*63f89caaSJens Wiklander rc = read_attr_advance(src, sz_from_hdr, &pos, &cli_ref, &data); 285*63f89caaSJens Wiklander if (rc) 286*63f89caaSJens Wiklander return rc; 287*63f89caaSJens Wiklander 288*63f89caaSJens Wiklander if (cli_ref.id == PKCS11_CKA_CLASS || 289*63f89caaSJens Wiklander pkcs11_attr_is_type(cli_ref.id) || 290*63f89caaSJens Wiklander pkcs11_attr_is_boolean(cli_ref.id)) 291*63f89caaSJens Wiklander continue; 292*63f89caaSJens Wiklander 293*63f89caaSJens Wiklander rc = sanitize_indirect_attr(dst, &cli_ref, data); 294*63f89caaSJens Wiklander if (rc == PKCS11_CKR_OK) 295*63f89caaSJens Wiklander continue; 296*63f89caaSJens Wiklander if (rc != PKCS11_RV_NOT_FOUND) 297*63f89caaSJens Wiklander return rc; 298*63f89caaSJens Wiklander 299*63f89caaSJens Wiklander if (!valid_pkcs11_attribute_id(cli_ref.id, cli_ref.size)) { 300*63f89caaSJens Wiklander EMSG("Invalid attribute id %#"PRIx32, cli_ref.id); 301*63f89caaSJens Wiklander return PKCS11_CKR_TEMPLATE_INCONSISTENT; 302*63f89caaSJens Wiklander } 303*63f89caaSJens Wiklander 304*63f89caaSJens Wiklander rc = add_attribute(dst, cli_ref.id, data, cli_ref.size); 305*63f89caaSJens Wiklander if (rc) 306*63f89caaSJens Wiklander return rc; 307*63f89caaSJens Wiklander } 308*63f89caaSJens Wiklander 309*63f89caaSJens Wiklander return rc; 310*63f89caaSJens Wiklander } 311*63f89caaSJens Wiklander 312*63f89caaSJens Wiklander /* 313*63f89caaSJens Wiklander * Debug: dump object attribute array to output trace 314*63f89caaSJens Wiklander */ 315*63f89caaSJens Wiklander 316*63f89caaSJens Wiklander static void __trace_attributes(char *prefix, void *src, void *end) 317*63f89caaSJens Wiklander { 318*63f89caaSJens Wiklander size_t next = 0; 319*63f89caaSJens Wiklander char *prefix2 = NULL; 320*63f89caaSJens Wiklander size_t prefix_len = strlen(prefix); 321*63f89caaSJens Wiklander char *cur = src; 322*63f89caaSJens Wiklander 323*63f89caaSJens Wiklander /* append 4 spaces to the prefix plus terminal '\0' */ 324*63f89caaSJens Wiklander prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO); 325*63f89caaSJens Wiklander if (!prefix2) 326*63f89caaSJens Wiklander return; 327*63f89caaSJens Wiklander 328*63f89caaSJens Wiklander TEE_MemMove(prefix2, prefix, prefix_len + 1); 329*63f89caaSJens Wiklander TEE_MemFill(prefix2 + prefix_len, ' ', 4); 330*63f89caaSJens Wiklander *(prefix2 + prefix_len + 4) = '\0'; 331*63f89caaSJens Wiklander 332*63f89caaSJens Wiklander for (; cur < (char *)end; cur += next) { 333*63f89caaSJens Wiklander struct pkcs11_attribute_head pkcs11_ref; 334*63f89caaSJens Wiklander uint8_t data[4] = { 0 }; 335*63f89caaSJens Wiklander uint32_t data_u32 = 0; 336*63f89caaSJens Wiklander 337*63f89caaSJens Wiklander TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); 338*63f89caaSJens Wiklander TEE_MemMove(&data[0], cur + sizeof(pkcs11_ref), 339*63f89caaSJens Wiklander MIN(pkcs11_ref.size, sizeof(data))); 340*63f89caaSJens Wiklander TEE_MemMove(&data_u32, cur + sizeof(pkcs11_ref), 341*63f89caaSJens Wiklander sizeof(data_u32)); 342*63f89caaSJens Wiklander 343*63f89caaSJens Wiklander next = sizeof(pkcs11_ref) + pkcs11_ref.size; 344*63f89caaSJens Wiklander 345*63f89caaSJens Wiklander DMSG_RAW("%s Attr %s / %s (%#04"PRIx32" %"PRIu32"-byte)", 346*63f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 347*63f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, pkcs11_ref.size, 348*63f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 349*63f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size); 350*63f89caaSJens Wiklander 351*63f89caaSJens Wiklander switch (pkcs11_ref.size) { 352*63f89caaSJens Wiklander case 0: 353*63f89caaSJens Wiklander break; 354*63f89caaSJens Wiklander case 1: 355*63f89caaSJens Wiklander DMSG_RAW("%s Attr byte value: %02x", prefix, data[0]); 356*63f89caaSJens Wiklander break; 357*63f89caaSJens Wiklander case 2: 358*63f89caaSJens Wiklander DMSG_RAW("%s Attr byte value: %02x %02x", 359*63f89caaSJens Wiklander prefix, data[0], data[1]); 360*63f89caaSJens Wiklander break; 361*63f89caaSJens Wiklander case 3: 362*63f89caaSJens Wiklander DMSG_RAW("%s Attr byte value: %02x %02x %02x", 363*63f89caaSJens Wiklander prefix, data[0], data[1], data[2]); 364*63f89caaSJens Wiklander break; 365*63f89caaSJens Wiklander case 4: 366*63f89caaSJens Wiklander DMSG_RAW("%s Attr byte value: %02x %02x %02x %02x", 367*63f89caaSJens Wiklander prefix, data[0], data[1], data[2], data[3]); 368*63f89caaSJens Wiklander break; 369*63f89caaSJens Wiklander default: 370*63f89caaSJens Wiklander DMSG_RAW("%s Attr byte value: %02x %02x %02x %02x ...", 371*63f89caaSJens Wiklander prefix, data[0], data[1], data[2], data[3]); 372*63f89caaSJens Wiklander break; 373*63f89caaSJens Wiklander } 374*63f89caaSJens Wiklander 375*63f89caaSJens Wiklander switch (pkcs11_ref.id) { 376*63f89caaSJens Wiklander case PKCS11_CKA_WRAP_TEMPLATE: 377*63f89caaSJens Wiklander case PKCS11_CKA_UNWRAP_TEMPLATE: 378*63f89caaSJens Wiklander case PKCS11_CKA_DERIVE_TEMPLATE: 379*63f89caaSJens Wiklander trace_attributes_from_api_head(prefix2, 380*63f89caaSJens Wiklander cur + sizeof(pkcs11_ref), 381*63f89caaSJens Wiklander (char *)end - cur); 382*63f89caaSJens Wiklander break; 383*63f89caaSJens Wiklander default: 384*63f89caaSJens Wiklander break; 385*63f89caaSJens Wiklander } 386*63f89caaSJens Wiklander } 387*63f89caaSJens Wiklander 388*63f89caaSJens Wiklander /* Sanity */ 389*63f89caaSJens Wiklander if (cur != (char *)end) 390*63f89caaSJens Wiklander EMSG("Warning: unexpected alignment issue"); 391*63f89caaSJens Wiklander 392*63f89caaSJens Wiklander TEE_Free(prefix2); 393*63f89caaSJens Wiklander } 394*63f89caaSJens Wiklander 395*63f89caaSJens Wiklander void trace_attributes_from_api_head(const char *prefix, void *ref, size_t size) 396*63f89caaSJens Wiklander { 397*63f89caaSJens Wiklander struct pkcs11_object_head head = { }; 398*63f89caaSJens Wiklander char *pre = NULL; 399*63f89caaSJens Wiklander size_t offset = 0; 400*63f89caaSJens Wiklander 401*63f89caaSJens Wiklander TEE_MemMove(&head, ref, sizeof(head)); 402*63f89caaSJens Wiklander 403*63f89caaSJens Wiklander if (size > sizeof(head) + head.attrs_size) { 404*63f89caaSJens Wiklander EMSG("template overflows client buffer (%zu/%zu)", 405*63f89caaSJens Wiklander size, sizeof(head) + head.attrs_size); 406*63f89caaSJens Wiklander return; 407*63f89caaSJens Wiklander } 408*63f89caaSJens Wiklander 409*63f89caaSJens Wiklander pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO); 410*63f89caaSJens Wiklander if (!pre) { 411*63f89caaSJens Wiklander EMSG("%s: out of memory", prefix); 412*63f89caaSJens Wiklander return; 413*63f89caaSJens Wiklander } 414*63f89caaSJens Wiklander if (prefix) 415*63f89caaSJens Wiklander TEE_MemMove(pre, prefix, strlen(prefix)); 416*63f89caaSJens Wiklander 417*63f89caaSJens Wiklander DMSG_RAW("%s,--- (serial object) Attributes list --------", pre); 418*63f89caaSJens Wiklander DMSG_RAW("%s| %"PRIu32" item(s) - %"PRIu32" bytes", 419*63f89caaSJens Wiklander pre, head.attrs_count, head.attrs_size); 420*63f89caaSJens Wiklander 421*63f89caaSJens Wiklander offset = sizeof(head); 422*63f89caaSJens Wiklander pre[prefix ? strlen(prefix) : 0] = '|'; 423*63f89caaSJens Wiklander __trace_attributes(pre, (char *)ref + offset, 424*63f89caaSJens Wiklander (char *)ref + offset + head.attrs_size); 425*63f89caaSJens Wiklander 426*63f89caaSJens Wiklander DMSG_RAW("%s`-----------------------", prefix ? prefix : ""); 427*63f89caaSJens Wiklander 428*63f89caaSJens Wiklander TEE_Free(pre); 429*63f89caaSJens Wiklander } 430