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 <assert.h> 7*63f89caaSJens Wiklander #include <compiler.h> 8*63f89caaSJens Wiklander #include <pkcs11_ta.h> 9*63f89caaSJens Wiklander #include <stddef.h> 10*63f89caaSJens Wiklander #include <stdlib.h> 11*63f89caaSJens Wiklander #include <string.h> 12*63f89caaSJens Wiklander #include <string_ext.h> 13*63f89caaSJens Wiklander #include <tee_internal_api.h> 14*63f89caaSJens Wiklander #include <tee_internal_api_extensions.h> 15*63f89caaSJens Wiklander #include <trace.h> 16*63f89caaSJens Wiklander #include <util.h> 17*63f89caaSJens Wiklander 18*63f89caaSJens Wiklander #include "attributes.h" 19*63f89caaSJens Wiklander #include "pkcs11_helpers.h" 20*63f89caaSJens Wiklander #include "serializer.h" 21*63f89caaSJens Wiklander 22*63f89caaSJens Wiklander enum pkcs11_rc init_attributes_head(struct obj_attrs **head) 23*63f89caaSJens Wiklander { 24*63f89caaSJens Wiklander *head = TEE_Malloc(sizeof(**head), TEE_MALLOC_FILL_ZERO); 25*63f89caaSJens Wiklander if (!*head) 26*63f89caaSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY; 27*63f89caaSJens Wiklander 28*63f89caaSJens Wiklander return PKCS11_CKR_OK; 29*63f89caaSJens Wiklander } 30*63f89caaSJens Wiklander 31*63f89caaSJens Wiklander enum pkcs11_rc add_attribute(struct obj_attrs **head, uint32_t attribute, 32*63f89caaSJens Wiklander void *data, size_t size) 33*63f89caaSJens Wiklander { 34*63f89caaSJens Wiklander size_t buf_len = sizeof(struct obj_attrs) + (*head)->attrs_size; 35*63f89caaSJens Wiklander char **bstart = (void *)head; 36*63f89caaSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 37*63f89caaSJens Wiklander uint32_t data32 = 0; 38*63f89caaSJens Wiklander 39*63f89caaSJens Wiklander data32 = attribute; 40*63f89caaSJens Wiklander rc = serialize(bstart, &buf_len, &data32, sizeof(uint32_t)); 41*63f89caaSJens Wiklander if (rc) 42*63f89caaSJens Wiklander return rc; 43*63f89caaSJens Wiklander 44*63f89caaSJens Wiklander data32 = size; 45*63f89caaSJens Wiklander rc = serialize(bstart, &buf_len, &data32, sizeof(uint32_t)); 46*63f89caaSJens Wiklander if (rc) 47*63f89caaSJens Wiklander return rc; 48*63f89caaSJens Wiklander 49*63f89caaSJens Wiklander rc = serialize(bstart, &buf_len, data, size); 50*63f89caaSJens Wiklander if (rc) 51*63f89caaSJens Wiklander return rc; 52*63f89caaSJens Wiklander 53*63f89caaSJens Wiklander /* Alloced buffer is always well aligned */ 54*63f89caaSJens Wiklander head = (void *)bstart; 55*63f89caaSJens Wiklander (*head)->attrs_size += 2 * sizeof(uint32_t) + size; 56*63f89caaSJens Wiklander (*head)->attrs_count++; 57*63f89caaSJens Wiklander 58*63f89caaSJens Wiklander return rc; 59*63f89caaSJens Wiklander } 60*63f89caaSJens Wiklander 61*63f89caaSJens Wiklander void get_attribute_ptrs(struct obj_attrs *head, uint32_t attribute, 62*63f89caaSJens Wiklander void **attr, uint32_t *attr_size, size_t *count) 63*63f89caaSJens Wiklander { 64*63f89caaSJens Wiklander char *cur = (char *)head + sizeof(struct obj_attrs); 65*63f89caaSJens Wiklander char *end = cur + head->attrs_size; 66*63f89caaSJens Wiklander size_t next_off = 0; 67*63f89caaSJens Wiklander size_t max_found = *count; 68*63f89caaSJens Wiklander size_t found = 0; 69*63f89caaSJens Wiklander void **attr_ptr = attr; 70*63f89caaSJens Wiklander uint32_t *attr_size_ptr = attr_size; 71*63f89caaSJens Wiklander 72*63f89caaSJens Wiklander for (; cur < end; cur += next_off) { 73*63f89caaSJens Wiklander /* Structure aligned copy of the pkcs11_ref in the object */ 74*63f89caaSJens Wiklander struct pkcs11_attribute_head pkcs11_ref = { }; 75*63f89caaSJens Wiklander 76*63f89caaSJens Wiklander TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); 77*63f89caaSJens Wiklander next_off = sizeof(pkcs11_ref) + pkcs11_ref.size; 78*63f89caaSJens Wiklander 79*63f89caaSJens Wiklander if (pkcs11_ref.id != attribute) 80*63f89caaSJens Wiklander continue; 81*63f89caaSJens Wiklander 82*63f89caaSJens Wiklander found++; 83*63f89caaSJens Wiklander 84*63f89caaSJens Wiklander if (!max_found) 85*63f89caaSJens Wiklander continue; /* only count matching attributes */ 86*63f89caaSJens Wiklander 87*63f89caaSJens Wiklander if (attr) 88*63f89caaSJens Wiklander *attr_ptr++ = cur + sizeof(pkcs11_ref); 89*63f89caaSJens Wiklander 90*63f89caaSJens Wiklander if (attr_size) 91*63f89caaSJens Wiklander *attr_size_ptr++ = pkcs11_ref.size; 92*63f89caaSJens Wiklander 93*63f89caaSJens Wiklander if (found == max_found) 94*63f89caaSJens Wiklander break; 95*63f89caaSJens Wiklander } 96*63f89caaSJens Wiklander 97*63f89caaSJens Wiklander /* Sanity */ 98*63f89caaSJens Wiklander if (cur > end) { 99*63f89caaSJens Wiklander DMSG("Exceeding serial object length"); 100*63f89caaSJens Wiklander TEE_Panic(0); 101*63f89caaSJens Wiklander } 102*63f89caaSJens Wiklander 103*63f89caaSJens Wiklander *count = found; 104*63f89caaSJens Wiklander } 105*63f89caaSJens Wiklander 106*63f89caaSJens Wiklander enum pkcs11_rc get_attribute_ptr(struct obj_attrs *head, uint32_t attribute, 107*63f89caaSJens Wiklander void **attr_ptr, uint32_t *attr_size) 108*63f89caaSJens Wiklander { 109*63f89caaSJens Wiklander size_t count = 1; 110*63f89caaSJens Wiklander 111*63f89caaSJens Wiklander get_attribute_ptrs(head, attribute, attr_ptr, attr_size, &count); 112*63f89caaSJens Wiklander 113*63f89caaSJens Wiklander if (!count) 114*63f89caaSJens Wiklander return PKCS11_RV_NOT_FOUND; 115*63f89caaSJens Wiklander 116*63f89caaSJens Wiklander if (count != 1) 117*63f89caaSJens Wiklander return PKCS11_CKR_GENERAL_ERROR; 118*63f89caaSJens Wiklander 119*63f89caaSJens Wiklander return PKCS11_CKR_OK; 120*63f89caaSJens Wiklander } 121*63f89caaSJens Wiklander 122*63f89caaSJens Wiklander enum pkcs11_rc get_attribute(struct obj_attrs *head, uint32_t attribute, 123*63f89caaSJens Wiklander void *attr, uint32_t *attr_size) 124*63f89caaSJens Wiklander { 125*63f89caaSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 126*63f89caaSJens Wiklander void *attr_ptr = NULL; 127*63f89caaSJens Wiklander uint32_t size = 0; 128*63f89caaSJens Wiklander 129*63f89caaSJens Wiklander rc = get_attribute_ptr(head, attribute, &attr_ptr, &size); 130*63f89caaSJens Wiklander if (rc) 131*63f89caaSJens Wiklander return rc; 132*63f89caaSJens Wiklander 133*63f89caaSJens Wiklander if (attr_size && *attr_size != size) { 134*63f89caaSJens Wiklander *attr_size = size; 135*63f89caaSJens Wiklander /* This reuses buffer-to-small for any bad size matching */ 136*63f89caaSJens Wiklander return PKCS11_CKR_BUFFER_TOO_SMALL; 137*63f89caaSJens Wiklander } 138*63f89caaSJens Wiklander 139*63f89caaSJens Wiklander if (attr) 140*63f89caaSJens Wiklander TEE_MemMove(attr, attr_ptr, size); 141*63f89caaSJens Wiklander 142*63f89caaSJens Wiklander if (attr_size) 143*63f89caaSJens Wiklander *attr_size = size; 144*63f89caaSJens Wiklander 145*63f89caaSJens Wiklander return PKCS11_CKR_OK; 146*63f89caaSJens Wiklander } 147*63f89caaSJens Wiklander 148*63f89caaSJens Wiklander bool get_bool(struct obj_attrs *head, uint32_t attribute) 149*63f89caaSJens Wiklander { 150*63f89caaSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 151*63f89caaSJens Wiklander uint8_t bbool = 0; 152*63f89caaSJens Wiklander uint32_t size = sizeof(bbool); 153*63f89caaSJens Wiklander 154*63f89caaSJens Wiklander rc = get_attribute(head, attribute, &bbool, &size); 155*63f89caaSJens Wiklander 156*63f89caaSJens Wiklander if (rc == PKCS11_RV_NOT_FOUND) 157*63f89caaSJens Wiklander return false; 158*63f89caaSJens Wiklander 159*63f89caaSJens Wiklander assert(rc == PKCS11_CKR_OK); 160*63f89caaSJens Wiklander return bbool; 161*63f89caaSJens Wiklander } 162*63f89caaSJens Wiklander 163*63f89caaSJens Wiklander #if CFG_TEE_TA_LOG_LEVEL > 0 164*63f89caaSJens Wiklander /* 165*63f89caaSJens Wiklander * Debug: dump CK attribute array to output trace 166*63f89caaSJens Wiklander */ 167*63f89caaSJens Wiklander #define ATTR_TRACE_FMT "%s attr %s / %s\t(0x%04"PRIx32" %"PRIu32"-byte" 168*63f89caaSJens Wiklander #define ATTR_FMT_0BYTE ATTR_TRACE_FMT ")" 169*63f89caaSJens Wiklander #define ATTR_FMT_1BYTE ATTR_TRACE_FMT ": %02x)" 170*63f89caaSJens Wiklander #define ATTR_FMT_2BYTE ATTR_TRACE_FMT ": %02x %02x)" 171*63f89caaSJens Wiklander #define ATTR_FMT_3BYTE ATTR_TRACE_FMT ": %02x %02x %02x)" 172*63f89caaSJens Wiklander #define ATTR_FMT_4BYTE ATTR_TRACE_FMT ": %02x %02x %02x %02x)" 173*63f89caaSJens Wiklander #define ATTR_FMT_ARRAY ATTR_TRACE_FMT ": %02x %02x %02x %02x ...)" 174*63f89caaSJens Wiklander 175*63f89caaSJens Wiklander static void __trace_attributes(char *prefix, void *src, void *end) 176*63f89caaSJens Wiklander { 177*63f89caaSJens Wiklander size_t next_off = 0; 178*63f89caaSJens Wiklander char *prefix2 = NULL; 179*63f89caaSJens Wiklander size_t prefix_len = strlen(prefix); 180*63f89caaSJens Wiklander char *cur = src; 181*63f89caaSJens Wiklander 182*63f89caaSJens Wiklander /* append 4 spaces to the prefix plus terminal '\0' */ 183*63f89caaSJens Wiklander prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO); 184*63f89caaSJens Wiklander if (!prefix2) 185*63f89caaSJens Wiklander return; 186*63f89caaSJens Wiklander 187*63f89caaSJens Wiklander TEE_MemMove(prefix2, prefix, prefix_len + 1); 188*63f89caaSJens Wiklander TEE_MemFill(prefix2 + prefix_len, ' ', 4); 189*63f89caaSJens Wiklander *(prefix2 + prefix_len + 4) = '\0'; 190*63f89caaSJens Wiklander 191*63f89caaSJens Wiklander for (; cur < (char *)end; cur += next_off) { 192*63f89caaSJens Wiklander struct pkcs11_attribute_head pkcs11_ref = { }; 193*63f89caaSJens Wiklander uint8_t data[4] = { 0 }; 194*63f89caaSJens Wiklander 195*63f89caaSJens Wiklander TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); 196*63f89caaSJens Wiklander TEE_MemMove(&data[0], cur + sizeof(pkcs11_ref), 197*63f89caaSJens Wiklander MIN(pkcs11_ref.size, sizeof(data))); 198*63f89caaSJens Wiklander 199*63f89caaSJens Wiklander next_off = sizeof(pkcs11_ref) + pkcs11_ref.size; 200*63f89caaSJens Wiklander 201*63f89caaSJens Wiklander switch (pkcs11_ref.size) { 202*63f89caaSJens Wiklander case 0: 203*63f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_0BYTE, 204*63f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), "*", 205*63f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size); 206*63f89caaSJens Wiklander break; 207*63f89caaSJens Wiklander case 1: 208*63f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_1BYTE, 209*63f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 210*63f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, 211*63f89caaSJens Wiklander pkcs11_ref.size, 212*63f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 213*63f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size, data[0]); 214*63f89caaSJens Wiklander break; 215*63f89caaSJens Wiklander case 2: 216*63f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_2BYTE, 217*63f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 218*63f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, 219*63f89caaSJens Wiklander pkcs11_ref.size, 220*63f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 221*63f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size, data[0], 222*63f89caaSJens Wiklander data[1]); 223*63f89caaSJens Wiklander break; 224*63f89caaSJens Wiklander case 3: 225*63f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_3BYTE, 226*63f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 227*63f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, 228*63f89caaSJens Wiklander pkcs11_ref.size, 229*63f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 230*63f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size, 231*63f89caaSJens Wiklander data[0], data[1], data[2]); 232*63f89caaSJens Wiklander break; 233*63f89caaSJens Wiklander case 4: 234*63f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_4BYTE, 235*63f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 236*63f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, 237*63f89caaSJens Wiklander pkcs11_ref.size, 238*63f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 239*63f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size, 240*63f89caaSJens Wiklander data[0], data[1], data[2], data[3]); 241*63f89caaSJens Wiklander break; 242*63f89caaSJens Wiklander default: 243*63f89caaSJens Wiklander IMSG_RAW(ATTR_FMT_ARRAY, 244*63f89caaSJens Wiklander prefix, id2str_attr(pkcs11_ref.id), 245*63f89caaSJens Wiklander id2str_attr_value(pkcs11_ref.id, 246*63f89caaSJens Wiklander pkcs11_ref.size, 247*63f89caaSJens Wiklander cur + sizeof(pkcs11_ref)), 248*63f89caaSJens Wiklander pkcs11_ref.id, pkcs11_ref.size, 249*63f89caaSJens Wiklander data[0], data[1], data[2], data[3]); 250*63f89caaSJens Wiklander break; 251*63f89caaSJens Wiklander } 252*63f89caaSJens Wiklander 253*63f89caaSJens Wiklander switch (pkcs11_ref.id) { 254*63f89caaSJens Wiklander case PKCS11_CKA_WRAP_TEMPLATE: 255*63f89caaSJens Wiklander case PKCS11_CKA_UNWRAP_TEMPLATE: 256*63f89caaSJens Wiklander case PKCS11_CKA_DERIVE_TEMPLATE: 257*63f89caaSJens Wiklander trace_attributes(prefix2, cur + sizeof(pkcs11_ref)); 258*63f89caaSJens Wiklander break; 259*63f89caaSJens Wiklander default: 260*63f89caaSJens Wiklander break; 261*63f89caaSJens Wiklander } 262*63f89caaSJens Wiklander } 263*63f89caaSJens Wiklander 264*63f89caaSJens Wiklander /* Sanity */ 265*63f89caaSJens Wiklander if (cur != end) 266*63f89caaSJens Wiklander EMSG("Warning: unexpected alignment in object attributes"); 267*63f89caaSJens Wiklander 268*63f89caaSJens Wiklander TEE_Free(prefix2); 269*63f89caaSJens Wiklander } 270*63f89caaSJens Wiklander 271*63f89caaSJens Wiklander void trace_attributes(const char *prefix, void *ref) 272*63f89caaSJens Wiklander { 273*63f89caaSJens Wiklander struct obj_attrs head; 274*63f89caaSJens Wiklander char *pre = NULL; 275*63f89caaSJens Wiklander 276*63f89caaSJens Wiklander TEE_MemMove(&head, ref, sizeof(head)); 277*63f89caaSJens Wiklander 278*63f89caaSJens Wiklander pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO); 279*63f89caaSJens Wiklander if (!pre) { 280*63f89caaSJens Wiklander EMSG("%s: out of memory", prefix); 281*63f89caaSJens Wiklander return; 282*63f89caaSJens Wiklander } 283*63f89caaSJens Wiklander 284*63f89caaSJens Wiklander if (prefix) 285*63f89caaSJens Wiklander TEE_MemMove(pre, prefix, strlen(prefix)); 286*63f89caaSJens Wiklander 287*63f89caaSJens Wiklander IMSG_RAW("%s,--- (serial object) Attributes list --------", pre); 288*63f89caaSJens Wiklander IMSG_RAW("%s| %"PRIu32" item(s) - %"PRIu32" bytes", 289*63f89caaSJens Wiklander pre, head.attrs_count, head.attrs_size); 290*63f89caaSJens Wiklander 291*63f89caaSJens Wiklander pre[prefix ? strlen(prefix) : 0] = '|'; 292*63f89caaSJens Wiklander __trace_attributes(pre, (char *)ref + sizeof(head), 293*63f89caaSJens Wiklander (char *)ref + sizeof(head) + head.attrs_size); 294*63f89caaSJens Wiklander 295*63f89caaSJens Wiklander IMSG_RAW("%s`-----------------------", prefix ? prefix : ""); 296*63f89caaSJens Wiklander 297*63f89caaSJens Wiklander TEE_Free(pre); 298*63f89caaSJens Wiklander } 299*63f89caaSJens Wiklander #endif /*CFG_TEE_TA_LOG_LEVEL*/ 300