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.