1/* 2 * Copyright (C) 2023-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "attribute.h" 17 18#include "securec.h" 19 20#include "adaptor_log.h" 21#include "adaptor_memory.h" 22 23#ifdef IAM_TEST_ENABLE 24#define IAM_STATIC 25#else 26#define IAM_STATIC static 27#endif 28 29#define SUCCESS RESULT_SUCCESS 30#define GENERAL_ERROR RESULT_GENERAL_ERROR 31#define INVALID_PARAMETERS RESULT_BAD_PARAM 32 33AttributeKey g_attributeKeyArray[] = { 34 ATTR_RESULT_CODE, 35 ATTR_SIGNATURE, 36 ATTR_IDENTIFY_MODE, 37 ATTR_TEMPLATE_ID, 38 ATTR_TEMPLATE_ID_LIST, 39 ATTR_REMAIN_ATTEMPTS, 40 ATTR_LOCKOUT_DURATION, 41 ATTR_SCHEDULE_ID, 42 ATTR_DATA, 43 ATTR_PIN_SUB_TYPE, 44 ATTR_SCHEDULE_MODE, 45 ATTR_PROPERTY_MODE, 46 ATTR_TYPE, 47 ATTR_CREDENTIAL_ID, 48 ATTR_CONTROLLER, 49 ATTR_CALLER_UID, 50 ATTR_RESULT, 51 ATTR_CAPABILITY_LEVEL, 52 ATTR_ALGORITHM_INFO, 53 ATTR_TIME_STAMP, 54 ATTR_ROOT_SECRET, 55 ATTR_ROOT, 56 ATTR_ATTRS, 57 ATTR_EXECUTOR_INDEX, 58 ATTR_PUBLIC_KEY, 59 ATTR_EXECUTOR_MATCHER, 60 ATTR_LOCAL_UDID, 61 ATTR_PEER_UDID, 62 ATTR_LOCKOUT_DURATION, 63 ATTR_REMAIN_ATTEMPTS, 64 ATTR_USER_ID, 65 ATTR_TOKEN, 66 ATTR_EXECUTOR_ROLE, 67 ATTR_ESL, 68 ATTR_VERIFIER_UDID, 69 ATTR_COLLECTOR_UDID, 70 ATTR_CHALLENGE, 71 ATTR_EXPIRED_SYS_TIME, 72}; 73 74#define ARRAY_LENGTH(array) (uint32_t)(sizeof(array) / sizeof((array)[0])) 75#define ATTRIBUTE_LEN (ARRAY_LENGTH(g_attributeKeyArray)) 76 77typedef struct { 78 Uint8Array *values[ATTRIBUTE_LEN]; 79} AttributeImpl; 80 81IAM_STATIC uint32_t Ntohl32(uint32_t in) 82{ 83 return in; 84} 85 86IAM_STATIC uint32_t Htonl32(uint32_t in) 87{ 88 return in; 89} 90 91IAM_STATIC uint64_t Ntohl64(uint64_t in) 92{ 93 return in; 94} 95 96IAM_STATIC uint64_t Htonl64(uint64_t in) 97{ 98 return in; 99} 100 101IAM_STATIC void Ntohl64Array(Uint64Array *array) 102{ 103 for (uint32_t i = 0; i < array->len; i++) { 104 array->data[i] = Ntohl64(array->data[i]); 105 } 106} 107 108IAM_STATIC void Htonl64Array(Uint64Array *array) 109{ 110 for (uint32_t i = 0; i < array->len; i++) { 111 array->data[i] = Htonl64(array->data[i]); 112 } 113} 114 115IAM_STATIC ResultCode GetAttributeIndex(AttributeKey key, uint32_t *index) 116{ 117 for (uint32_t i = 0; i < ATTRIBUTE_LEN; ++i) { 118 if (g_attributeKeyArray[i] == key) { 119 *index = i; 120 return SUCCESS; 121 } 122 } 123 124 return GENERAL_ERROR; 125} 126 127IAM_STATIC ResultCode ReadDataFromMsg(const Uint8Array msg, uint32_t *readIndex, Uint8Array *retData) 128{ 129 if (msg.len <= *readIndex) { 130 LOG_ERROR("msg length is not enough"); 131 return GENERAL_ERROR; 132 } 133 134 if (msg.len - *readIndex < retData->len) { 135 LOG_ERROR("remain data length is not enough"); 136 return GENERAL_ERROR; 137 } 138 139 if (memcpy_s(retData->data, retData->len, msg.data + *readIndex, retData->len) != EOK) { 140 LOG_ERROR("memcpy_s fail"); 141 return GENERAL_ERROR; 142 } 143 144 *readIndex += retData->len; 145 return SUCCESS; 146} 147 148IAM_STATIC ResultCode ReadUint32FromMsg(const Uint8Array msg, uint32_t *readIndex, uint32_t *retValue) 149{ 150 uint32_t netOrderValue; 151 Uint8Array uint8Data = { (uint8_t *)&netOrderValue, sizeof(netOrderValue) }; 152 ResultCode result = ReadDataFromMsg(msg, readIndex, &uint8Data); 153 if (result != SUCCESS) { 154 LOG_ERROR("read data fail"); 155 return GENERAL_ERROR; 156 } 157 158 *retValue = Ntohl32(netOrderValue); 159 return SUCCESS; 160} 161 162IAM_STATIC ResultCode WriteDataToMsg(Uint8Array *msg, uint32_t *writeIndex, const Uint8Array data) 163{ 164 if (msg->len <= *writeIndex) { 165 LOG_ERROR("msg length is not enough"); 166 return GENERAL_ERROR; 167 } 168 169 if (msg->len - *writeIndex < data.len) { 170 LOG_ERROR("remain data size is not enough"); 171 return GENERAL_ERROR; 172 } 173 174 if (memcpy_s(msg->data + *writeIndex, msg->len - *writeIndex, data.data, data.len) != EOK) { 175 LOG_ERROR("memcpy_s fail"); 176 return GENERAL_ERROR; 177 } 178 179 *writeIndex += data.len; 180 return SUCCESS; 181} 182 183IAM_STATIC ResultCode WriteUInt32ToMsg(Uint8Array *msg, uint32_t *writeIndex, uint32_t value) 184{ 185 uint32_t netOrderValue = Htonl32(value); 186 ResultCode result = 187 WriteDataToMsg(msg, writeIndex, (Uint8Array){ (uint8_t *)&netOrderValue, sizeof(netOrderValue) }); 188 if (result != SUCCESS) { 189 LOG_ERROR("write data fail"); 190 return GENERAL_ERROR; 191 } 192 return SUCCESS; 193} 194 195IAM_STATIC ResultCode ParseAttributeSerializedMsgInner(Attribute *attribute, const Uint8Array msg, 196 const Uint8Array *readBuffer) 197{ 198 uint32_t readIndex = 0; 199 while (readIndex < msg.len) { 200 uint32_t type; 201 ResultCode readTypeResult = ReadUint32FromMsg(msg, &readIndex, &type); 202 IF_TRUE_LOGE_AND_RETURN_VAL(readTypeResult != SUCCESS, GENERAL_ERROR); 203 204 uint32_t length; 205 ResultCode readLengthResult = ReadUint32FromMsg(msg, &readIndex, &length); 206 IF_TRUE_LOGE_AND_RETURN_VAL(readLengthResult != SUCCESS, GENERAL_ERROR); 207 IF_TRUE_LOGE_AND_RETURN_VAL(length > readBuffer->len, GENERAL_ERROR); 208 209 Uint8Array readData = { readBuffer->data, length }; 210 if (length > 0) { 211 ResultCode readDataResult = ReadDataFromMsg(msg, &readIndex, &readData); 212 IF_TRUE_LOGE_AND_RETURN_VAL(readDataResult != SUCCESS, GENERAL_ERROR); 213 } 214 215 ResultCode setAttrResult = SetAttributeUint8Array(attribute, type, readData); 216 IF_TRUE_LOGE_AND_RETURN_VAL(setAttrResult != SUCCESS, GENERAL_ERROR); 217 } 218 219 return SUCCESS; 220} 221 222IAM_STATIC ResultCode ParseAttributeSerializedMsg(Attribute *attribute, const Uint8Array msg) 223{ 224 Uint8Array *readBuffer = CreateUint8ArrayBySize(MAX_EXECUTOR_MSG_LEN); 225 IF_TRUE_LOGE_AND_RETURN_VAL(readBuffer == NULL, GENERAL_ERROR); 226 227 ResultCode result = ParseAttributeSerializedMsgInner(attribute, msg, readBuffer); 228 if (result != SUCCESS) { 229 LOG_ERROR("ParseAttributeSerializedMsgInner fail"); 230 } 231 DestroyUint8Array(&readBuffer); 232 233 return result; 234} 235 236ResultCode ParseMultiDataSerializedMsg(const Uint8Array msg, Uint8Array *subMsgData, int *subMsgSize) 237{ 238 IF_TRUE_LOGE_AND_RETURN_VAL(subMsgSize == NULL, GENERAL_ERROR); 239 IF_TRUE_LOGE_AND_RETURN_VAL(subMsgData == NULL, GENERAL_ERROR); 240 241 uint32_t readIndex = 0; 242 uint32_t subMsgIndex = 0; 243 while (readIndex < msg.len) { 244 uint32_t length; 245 ResultCode readLengthResult = ReadUint32FromMsg(msg, &readIndex, &length); 246 IF_TRUE_LOGE_AND_RETURN_VAL(readLengthResult != SUCCESS, GENERAL_ERROR); 247 248 if (length > 0) { 249 IF_TRUE_LOGE_AND_RETURN_VAL(subMsgIndex >= *subMsgSize, GENERAL_ERROR); 250 // subMsgData is freed in outer function 251 subMsgData[subMsgIndex] = (Uint8Array){ Malloc(length), length }; 252 IF_TRUE_LOGE_AND_RETURN_VAL(subMsgData[subMsgIndex].data == NULL, GENERAL_ERROR); 253 ResultCode readDataResult = ReadDataFromMsg(msg, &readIndex, &subMsgData[subMsgIndex]); 254 IF_TRUE_LOGE_AND_RETURN_VAL(readDataResult != SUCCESS, GENERAL_ERROR); 255 subMsgIndex++; 256 } 257 } 258 259 *subMsgSize = subMsgIndex; 260 return SUCCESS; 261} 262 263Attribute *CreateEmptyAttribute(void) 264{ 265 AttributeImpl *attribute = Malloc(sizeof(AttributeImpl)); 266 IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, NULL); 267 (void)memset_s(attribute, sizeof(AttributeImpl), 0, sizeof(AttributeImpl)); 268 269 return attribute; 270} 271 272Attribute *CreateAttributeFromSerializedMsg(const Uint8Array msg) 273{ 274 IF_TRUE_LOGE_AND_RETURN_VAL(IS_ARRAY_NULL(msg), NULL); 275 276 Attribute *attribute = CreateEmptyAttribute(); 277 if (attribute == NULL) { 278 LOG_ERROR("CreateEmptyAttribute failed"); 279 return NULL; 280 } 281 282 ResultCode result = ParseAttributeSerializedMsg(attribute, msg); 283 if (result != SUCCESS) { 284 LOG_ERROR("ParseAttributeSerializedMsg failed"); 285 FreeAttribute((Attribute **)&attribute); 286 return NULL; 287 } 288 289 return attribute; 290} 291 292ResultCode GetAttributeSerializedMsg(const Attribute *attributePublic, Uint8Array *retMsg) 293{ 294 IF_TRUE_LOGE_AND_RETURN_VAL(attributePublic == NULL, INVALID_PARAMETERS); 295 IF_TRUE_LOGE_AND_RETURN_VAL(retMsg == NULL, INVALID_PARAMETERS); 296 IF_TRUE_LOGE_AND_RETURN_VAL(IS_ARRAY_NULL(*retMsg), INVALID_PARAMETERS); 297 298 const AttributeImpl *attribute = (const AttributeImpl *)attributePublic; 299 uint32_t writeIndex = 0; 300 for (uint32_t i = 0; i < ATTRIBUTE_LEN; i++) { 301 Uint8Array *array = attribute->values[i]; 302 if (array == NULL) { 303 continue; 304 } 305 306 ResultCode writeTypeResult = WriteUInt32ToMsg(retMsg, &writeIndex, g_attributeKeyArray[i]); 307 IF_TRUE_LOGE_AND_RETURN_VAL(writeTypeResult != SUCCESS, GENERAL_ERROR); 308 309 ResultCode writeLengthResult = WriteUInt32ToMsg(retMsg, &writeIndex, array->len); 310 IF_TRUE_LOGE_AND_RETURN_VAL(writeLengthResult != SUCCESS, GENERAL_ERROR); 311 312 if (array->len == 0) { 313 continue; 314 } 315 ResultCode writeDataResult = 316 WriteDataToMsg(retMsg, &writeIndex, *array); 317 IF_TRUE_LOGE_AND_RETURN_VAL(writeDataResult != SUCCESS, GENERAL_ERROR); 318 } 319 320 retMsg->len = writeIndex; 321 return SUCCESS; 322} 323 324void FreeAttribute(Attribute **attribute) 325{ 326 IF_TRUE_LOGE_AND_RETURN(attribute == NULL); 327 IF_TRUE_LOGE_AND_RETURN(*attribute == NULL); 328 AttributeImpl *impl = (AttributeImpl *)*attribute; 329 for (uint32_t i = 0; i < ATTRIBUTE_LEN; ++i) { 330 DestroyUint8Array(&impl->values[i]); 331 } 332 333 IAM_FREE_AND_SET_NULL(*attribute); 334} 335 336ResultCode GetAttributeUint32(const Attribute *attribute, AttributeKey key, uint32_t *value) 337{ 338 IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS); 339 IF_TRUE_LOGE_AND_RETURN_VAL(value == NULL, INVALID_PARAMETERS); 340 341 uint32_t netOrderValue; 342 Uint8Array uint32Data = { (uint8_t *)&netOrderValue, sizeof(netOrderValue) }; 343 ResultCode getAttrResult = GetAttributeUint8Array(attribute, key, &uint32Data); 344 IF_TRUE_LOGE_AND_RETURN_VAL(getAttrResult != SUCCESS, GENERAL_ERROR); 345 IF_TRUE_LOGE_AND_RETURN_VAL(uint32Data.len != sizeof(netOrderValue), GENERAL_ERROR); 346 347 *value = Ntohl32(netOrderValue); 348 return SUCCESS; 349} 350 351ResultCode SetAttributeUint32(Attribute *attribute, AttributeKey key, const uint32_t value) 352{ 353 IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS); 354 355 uint32_t netOrderValue = Htonl32(value); 356 ResultCode result = 357 SetAttributeUint8Array(attribute, key, (Uint8Array) { (uint8_t *)&netOrderValue, sizeof(netOrderValue) }); 358 IF_TRUE_LOGE_AND_RETURN_VAL(result != SUCCESS, GENERAL_ERROR); 359 360 return result; 361} 362 363ResultCode GetAttributeInt32(const Attribute *attribute, AttributeKey key, int32_t *retValue) 364{ 365 IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS); 366 IF_TRUE_LOGE_AND_RETURN_VAL(retValue == NULL, INVALID_PARAMETERS); 367 368 return GetAttributeUint32(attribute, key, (uint32_t *)retValue); 369} 370 371ResultCode SetAttributeInt32(Attribute *attribute, AttributeKey key, const int32_t value) 372{ 373 IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS); 374 375 return SetAttributeUint32(attribute, key, (uint32_t)value); 376} 377 378ResultCode GetAttributeUint64(const Attribute *attribute, AttributeKey key, uint64_t *retValue) 379{ 380 IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS); 381 IF_TRUE_LOGE_AND_RETURN_VAL(retValue == NULL, INVALID_PARAMETERS); 382 383 uint64_t netOrderValue; 384 Uint8Array uint64Data = { (uint8_t *)&netOrderValue, sizeof(netOrderValue) }; 385 ResultCode getAttrResult = GetAttributeUint8Array(attribute, key, &uint64Data); 386 IF_TRUE_LOGE_AND_RETURN_VAL(getAttrResult != SUCCESS, GENERAL_ERROR); 387 IF_TRUE_LOGE_AND_RETURN_VAL(uint64Data.len != sizeof(netOrderValue), GENERAL_ERROR); 388 389 *retValue = Ntohl64(netOrderValue); 390 return SUCCESS; 391} 392 393ResultCode SetAttributeUint64(Attribute *attribute, AttributeKey key, const uint64_t value) 394{ 395 IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS); 396 397 uint64_t netOrderValue = Htonl64(value); 398 ResultCode setAttrResult = 399 SetAttributeUint8Array(attribute, key, (Uint8Array){ (uint8_t *)&netOrderValue, sizeof(netOrderValue) }); 400 IF_TRUE_LOGE_AND_RETURN_VAL(setAttrResult != SUCCESS, GENERAL_ERROR); 401 402 return SUCCESS; 403} 404 405ResultCode GetAttributeUint8Array(const Attribute *attributePub, AttributeKey key, Uint8Array *retData) 406{ 407 IF_TRUE_LOGE_AND_RETURN_VAL(attributePub == NULL, INVALID_PARAMETERS); 408 IF_TRUE_LOGE_AND_RETURN_VAL(retData == NULL, INVALID_PARAMETERS); 409 IF_TRUE_LOGE_AND_RETURN_VAL(IS_ARRAY_NULL(*retData), INVALID_PARAMETERS); 410 411 const AttributeImpl *attribute = (const AttributeImpl *)attributePub; 412 413 uint32_t attributeIndex; 414 ResultCode getAttrIndexResult = GetAttributeIndex(key, &attributeIndex); 415 IF_TRUE_LOGE_AND_RETURN_VAL(getAttrIndexResult != SUCCESS, GENERAL_ERROR); 416 417 if (attribute->values[attributeIndex] == NULL) { 418 LOG_ERROR("data is not set"); 419 return GENERAL_ERROR; 420 } 421 422 if (attribute->values[attributeIndex]->data != NULL && attribute->values[attributeIndex]->len != 0) { 423 errno_t memcpyRet = memcpy_s(retData->data, retData->len, attribute->values[attributeIndex]->data, 424 attribute->values[attributeIndex]->len); 425 IF_TRUE_LOGE_AND_RETURN_VAL(memcpyRet != EOK, GENERAL_ERROR); 426 } else { 427 LOG_INFO("the current data is an empty array"); 428 } 429 retData->len = attribute->values[attributeIndex]->len; 430 431 return SUCCESS; 432} 433 434ResultCode SetAttributeUint8Array(Attribute *attributePub, AttributeKey key, const Uint8Array data) 435{ 436 IF_TRUE_LOGE_AND_RETURN_VAL(attributePub == NULL, INVALID_PARAMETERS); 437 IF_TRUE_LOGE_AND_RETURN_VAL(!IS_ARRAY_VALID(data), INVALID_PARAMETERS); 438 439 AttributeImpl *attribute = (AttributeImpl *)attributePub; 440 441 uint32_t attributeIndex; 442 ResultCode getAttrIndexResult = GetAttributeIndex(key, &attributeIndex); 443 IF_TRUE_LOGE_AND_RETURN_VAL(getAttrIndexResult != SUCCESS, GENERAL_ERROR); 444 445 DestroyUint8Array(&attribute->values[attributeIndex]); 446 attribute->values[attributeIndex] = CreateUint8ArrayByData(data.data, data.len); 447 if (attribute->values[attributeIndex] == NULL) { 448 LOG_ERROR("CreateUint8ArrayByData fail"); 449 return GENERAL_ERROR; 450 } 451 452 return SUCCESS; 453} 454 455ResultCode GetAttributeUint64Array(const Attribute *attribute, AttributeKey key, Uint64Array *retData) 456{ 457 IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS); 458 IF_TRUE_LOGE_AND_RETURN_VAL(retData == NULL, INVALID_PARAMETERS); 459 IF_TRUE_LOGE_AND_RETURN_VAL(IS_ARRAY_NULL(*retData), INVALID_PARAMETERS); 460 461 Uint8Array uint64ArrayData = { (uint8_t *)retData->data, retData->len * sizeof(uint64_t) }; 462 ResultCode getAttrResult = GetAttributeUint8Array(attribute, key, &uint64ArrayData); 463 IF_TRUE_LOGE_AND_RETURN_VAL(getAttrResult != SUCCESS, GENERAL_ERROR); 464 if (uint64ArrayData.len % sizeof(uint64_t) != 0) { 465 LOG_ERROR("uint8 length %u is incorrect", uint64ArrayData.len); 466 return GENERAL_ERROR; 467 } 468 Ntohl64Array(retData); 469 470 retData->len = uint64ArrayData.len / sizeof(uint64_t); 471 return SUCCESS; 472} 473 474ResultCode SetAttributeUint64Array(Attribute *attribute, AttributeKey key, const Uint64Array data) 475{ 476 IF_TRUE_LOGE_AND_RETURN_VAL(attribute == NULL, INVALID_PARAMETERS); 477 IF_TRUE_LOGE_AND_RETURN_VAL(!IS_ARRAY_VALID(data), INVALID_PARAMETERS); 478 479 Uint64Array *netOrderData = CreateUint64ArrayByData(data.data, data.len); 480 IF_TRUE_LOGE_AND_RETURN_VAL(netOrderData == NULL, GENERAL_ERROR); 481 482 ResultCode result = GENERAL_ERROR; 483 do { 484 Htonl64Array(netOrderData); 485 if (netOrderData->len > UINT32_MAX / sizeof(uint64_t)) { 486 LOG_ERROR("netOrderData->len is invalid"); 487 break; 488 } 489 result = SetAttributeUint8Array(attribute, key, 490 (Uint8Array) { (uint8_t *)netOrderData->data, netOrderData->len * sizeof(uint64_t) }); 491 if (result != SUCCESS) { 492 LOG_ERROR("SetAttributeUint8Array fail"); 493 break; 494 } 495 } while (0); 496 497 DestroyUint64Array(&netOrderData); 498 return result; 499} 500 501ResultCode GetMultiDataSerializedMsg(Uint8Array *sourceArrayMsg, uint32_t size, Uint8Array *retMsg) 502{ 503 IF_TRUE_LOGE_AND_RETURN_VAL(sourceArrayMsg == NULL, INVALID_PARAMETERS); 504 IF_TRUE_LOGE_AND_RETURN_VAL(retMsg == NULL, INVALID_PARAMETERS); 505 IF_TRUE_LOGE_AND_RETURN_VAL(IS_ARRAY_NULL(*retMsg), INVALID_PARAMETERS); 506 507 uint32_t writeIndex = 0; 508 for (uint32_t i = 0; i < size; i++) { 509 IF_TRUE_LOGE_AND_RETURN_VAL(sourceArrayMsg[i].data == NULL, GENERAL_ERROR); 510 Uint8Array sourceMsg = sourceArrayMsg[i]; 511 if (sourceMsg.len == 0) { 512 continue; 513 } 514 ResultCode writeLengthResult = WriteUInt32ToMsg(retMsg, &writeIndex, sourceMsg.len); 515 IF_TRUE_LOGE_AND_RETURN_VAL(writeLengthResult != SUCCESS, GENERAL_ERROR); 516 517 ResultCode writeDataResult = WriteDataToMsg(retMsg, &writeIndex, sourceMsg); 518 IF_TRUE_LOGE_AND_RETURN_VAL(writeDataResult != SUCCESS, GENERAL_ERROR); 519 } 520 retMsg->len = writeIndex; 521 return SUCCESS; 522} 523