Device authentication interpreted by OpenHarmony: data receiving management - obtaining HiChain instances

1, Overview

In OpenHarmony, the device authentication module, as a sub module of the security subsystem, is responsible for the management of the whole life cycle such as the establishment, maintenance, use and revocation of the trusted relationship between devices, and the realization of mutual trust authentication and secure session key negotiation between trusted devices. It is the basic platform capability for trusted interconnection of devices equipped with OpenHarmony.
In the last blog post OpenHarmony in-depth interpretation of distributed soft bus: source code analysis of HiChain mechanism As mentioned in, HiChain mechanism is a protocol mechanism for OpenHarmony to realize device interconnection security. The next blog will follow the previous logic and focus on further parsing the data packets received at the local end, that is, message parsing into the real device authentication Module. After the previous packet field parsing, the value of the field Module is in MODULE_HICHAIN to Module_ Auth_ Between SDKs, it will enter the HiChain mechanism processing stage. This article focuses on the HiChain instance acquisition stage, that is, the preparation stage of device authentication.

2, Source code analysis

The source code of this module is located at: /base/security/deviceauth.

1. HiChain instances are obtained mainly in hichain C file get_instance function. Let's analyze this function in detail:
/*
Function function: get hichain instance
 Function parameters:
    identity: Session basic information
    type: hichain Equipment type
    call_back: hichain Callback function
 Function return value:
    Success: return hichain structure address
    Failed: return NULL
*/
DLL_API_PUBLIC hc_handle get_instance(const struct session_identity *identity, enum hc_type type,
    const struct hc_call_back *call_back)
{
    LOGI("Begin get instance");
    if (check_identity(identity) != HC_OK) {//Check whether the basic information of hc meets the specification
        LOGE("Identity error");
        return NULL;
    }
    if (check_call_back(call_back) != HC_OK) {//Check whether the function pointer of the callback structure is null
        LOGE("Call back error");
        return NULL;
    }

#if !(defined(_CUT_STS_) || defined(_CUT_STS_SERVER_) || defined(_CUT_EXCHANGE_) || defined(_CUT_EXCHANGE_SERVER_))
    int32_t ret = key_info_init();//Initialize key information
    if (ret != HC_OK) {
        LOGE("Call key info init failed, status=%d", ret);
        return NULL;
    }
#endif

    struct hichain *hichain = (struct hichain *)MALLOC(sizeof(struct hichain));//Define a hichain instance and apply for space for it
    if (hichain == NULL) {//Failed to request memory
        LOGE("Alloc memory failed");
        return NULL;
    }
    (void)memset_s(hichain, sizeof(*hichain), 0, sizeof(*hichain));//Empty the instance space
    //Initialize the relevant properties of the hichain instance object
    hichain->identity = *identity;//hichain basic information
    hichain->type = type;//hichain device type
    hichain->state = INIT_STATE;//hichain status is initialized
    hichain->last_state = INIT_STATE;//hichain final status
    hichain->cb = *call_back;//hichain callback function

#if !(defined(_CUT_STS_) || defined(_CUT_STS_SERVER_) || defined(_CUT_EXCHANGE_) || defined(_CUT_EXCHANGE_SERVER_))
    build_self_lt_key_pair(hichain);//Create your own long store/term key pair
#endif

    LOGI("Get instance success");
    return hichain;
}
2. in get_ In the instance function, first check whether the HC session ID information and the callback function are valid, and then use the function check_identity and check_call_back implementation. The specific source code analysis is as follows:
/*Check whether the basic information of hc meets the specification*/
static int32_t check_identity(const struct session_identity *identity)
{
    check_ptr_return_val(identity, HC_INPUT_ERROR);//Whether the robustness check identity is empty
    if (identity->package_name.length > HC_PACKAGE_NAME_BUFF_LEN) {//If the name length of the session package is greater than the size of the name buffer, an error is returned
        LOGE("Package name length error, %u > %u", identity->package_name.length, HC_PACKAGE_NAME_BUFF_LEN);
        return HC_INPUT_ERROR;
    }
    if (identity->service_type.length > HC_SERVICE_TYPE_BUFF_LEN) {//If the length of the service type is greater than the reserved buffer size, an error is returned
        LOGE("Service type length error, %u > %u", identity->service_type.length, HC_SERVICE_TYPE_BUFF_LEN);
        return HC_INPUT_ERROR;
    }
    return HC_OK;
}
/*Check whether the callback function is empty*/
static int32_t check_call_back(const struct hc_call_back *call_back)
{
    check_ptr_return_val(call_back, HC_INPUT_ERROR);//Check call_ Whether back is empty. If it is empty, the error code will be returned directly
    check_ptr_return_val(call_back->transmit, HC_INPUT_ERROR);//Check whether transmit is empty. If it is empty, the error code will be returned directly
    check_ptr_return_val(call_back->get_protocol_params, HC_INPUT_ERROR);//Check get_ Protocol_ Whether params is empty. If it is empty, the error code will be returned directly
    check_ptr_return_val(call_back->set_session_key, HC_INPUT_ERROR);//Check set_ Session_ Whether the key is empty. If it is empty, the error code will be returned directly
    check_ptr_return_val(call_back->set_service_result, HC_INPUT_ERROR);//Check set_ Service_ Whether the result is empty. If it is empty, the error code will be returned directly
    check_ptr_return_val(call_back->confirm_receive_request, HC_INPUT_ERROR);//Check confirm_ Receive_ Whether the request is empty. If it is empty, the error code will be returned directly
    return HC_OK;
}

#Define check_ PTR_ Return_ Val (d\u PTR, d\u VAL) \ / / check the parameter d_ Whether PTR is empty
    do { \
        if ((d_ptr) == NULL) { \//If empty
            return (d_val); \//Parameter D is returned directly_ Val
        } \
    } while (0)
3. next, in the function key_info_init performs initialization key information. The specific function analysis is as follows:
/*
Function function: initialize key information
 Function parameters: None
 Function return value:
    Success: return success code
    Failure: return failure code
*/
int32_t key_info_init(void)
{
    int32_t hks_status = hks_init();//Hksinitialization
#if (defined(_SUPPORT_SEC_CLONE_) || defined(_SUPPORT_SEC_CLONE_SERVER_))
    return hks_status;
#else
    if (hks_status == 0) {//If the status of hks is 0, success will be returned directly
        return ERROR_CODE_SUCCESS;
    } else if ((hks_status == HKS_ERROR_INVALID_KEY_FILE) || (hks_status == HKS_ERROR_READ_FILE_FAIL)) {//If the hks status is "invalid key file error" and "read file failure error"
        LOGE("Key info init failed, status=%d", hks_status);
        hks_status = hks_refresh_key_info();//HK mechanism refreshes key information and root key information
        if (hks_status == 0) {//If the status is 0 after refresh, success is returned
            return ERROR_CODE_SUCCESS;
        }
        LOGE("Key info refresh failed, status=%u", hks_status);//If the refresh fails, the failure code is returned
        return ERROR_CODE_FAILED;
    }

    return ERROR_CODE_FAILED;
#endif
}

3, Summary

This article focuses on some contents of hichain instance acquisition, such as initial information check and key information initialization. The rest will be introduced in the next blog.

Tags: TCP/IP Distribution network harmonyos

Posted by mclordgt on Tue, 31 May 2022 20:14:09 +0530