OpenHarmony解读之设备认证:数据接收管理-消息处理(1)

发布时间:2022-08-19 11:47

一、概述

本文将承接上一篇博客OpenHarmony解读之设备认证:数据接收管理-消息解析的内容,主要介绍HiChain本端接收数据的处理过程中的消息处理阶段

二、源码分析

这一模块的源码位于:/base/security/deviceauth。

  1. receive_data函数中,首先执行deserialize_message函数将消息解析完毕保存在struct message结构中,然后调用navigate_message函数,根据消息码得到消息类型msg_type和消息模块modular,具体分析如下:
//导航消息,得到 "消息模块-消息类型(消息码低四位)-是否请求消息" 一一对应
struct header_analysis navigate_message(uint32_t message_code)
{
    struct header_analysis nav = { INVALID_MODULAR, 0, 0 };

    for (uint32_t i = 0; i < sizeof(G_MESSAGE_CODE_MAP) / sizeof(G_MESSAGE_CODE_MAP[0]); i++) {//sizeof(G_MESSAGE_CODE_MAP) / sizeof(G_MESSAGE_CODE_MAP[0])表示消息码数组的元素个数
        if (G_MESSAGE_CODE_MAP[i].code == message_code) {//根据消息码查表,如果存在,就进行相关数据更新
            nav.modular = G_MESSAGE_CODE_MAP[i].modular;//赋予消息模块
            nav.msg_type = message_code & 0xf; /* message_code & 0xf get low four bits of message code 获取低四位的消息码作为msg_type*/
            nav.is_request_msg = G_MESSAGE_CODE_MAP[i].is_request_msg;
            break;
        }
    }
    LOGI("Message code %u, nav is %d, %d, %d", message_code, nav.modular, nav.msg_type, nav.is_request_msg);
    return nav;
}
  1. 然后执行check_message_support函数检查消息是否可支持,对该函数的分析如下:
/*
函数功能:检查消息是否是系统可支持
函数参数:
    hichain:HiChain实例
    nav:导航消息头
    receive:解析后的消息
函数返回值:
    成功:返回0
    失败:返回错误码
详细:将解析出来的操作码保存到hichain中且与消息码对应正确,一致
*/
int32_t check_message_support(struct hichain *hichain, const struct header_analysis *nav,
    const struct message *receive)
{
    if (nav->modular == 0) {//表示未知消息
        LOGE("Receive unknow message, message code is 0x%04x", receive->msg_code);
        return HC_UNKNOW_MESSAGE;
    }

    if (!check_hichain_state_is_success(hichain, nav)) {//检查hichain实例的状态是否正确
        return HC_STATE_ERROR;
    }

    int32_t operation_code = get_operation_code(nav, receive);//根据消息模块类型获取解析不同协议的操作码,这里有PAKE和STS协议
    if (operation_code == INVALID_OPERATION_CODE) {//如果操作码无效,则返回错误码
        return HC_OPERATION_CODE_ERROR;
    } else if (operation_code == NO_OPERATION_CODE) {//如果操作码为0,表示“无操作”
        /* compare with recorded operation code and verify */
        if (is_message_illegal(hichain->operation_code, nav->modular)) {//判断消息是否属于非法消息
            LOGE("Operation code is %d, message code is %u, it is inconsistency",
                hichain->operation_code, receive->msg_code);
            return HC_MESSAGE_INCONSISTENCY;//返回'消息不一致'的代码
        }
    } else {//如果是其他操作码
        int32_t ret = hichain->cb.confirm_receive_request(&hichain->identity, operation_code);//确认收到的请求,调用HC回调函数处理,目前版本暂不可用
        if (ret != 0) {
            LOGE("Service does not allow response %d", operation_code);
            return HC_SERVICE_CONFIRM_ERROR;
        }
        hichain->operation_code = operation_code;
    }

    return HC_OK;
}
  1. 在函数check_message_support中:首先执行check_hichain_state_is_success函数检查hichain实例的状态是否正确,具体函数分析如下:
//检查hichain实例的状态是否正确,成功返回true,失败返回false
static bool check_hichain_state_is_success(struct hichain *hichain, const struct header_analysis *nav)
{
    if ((nav->modular == PAKE_MODULAR) || (nav->modular == STS_MODULAR)) {//如果消息属于PAKE协议或者STS协议的消息,则判断其状态是否是初始化状态和密钥协商状态
        if ((hichain->state != INIT_STATE) && (hichain->state != KEY_AGREEMENT_STATE) &&
            (hichain->last_state != INIT_STATE) && (hichain->last_state != KEY_AGREEMENT_STATE)) {//如果状态不是初始化状态和密钥协商状态,返回失败
            goto error;
        }
    } else {//如果属于其他类型的消息,则判断其状态是否是密钥协商状态和操作状态
        if ((hichain->state != KEY_AGREEMENT_STATE) && (hichain->state != OPERATION_STATE) &&
            (hichain->last_state != KEY_AGREEMENT_STATE) && (hichain->last_state != OPERATION_STATE)) {
            goto error;//如果状态不是密钥协商状态和运行状态,返回失败
        }
    }
    return true;//返回正确

error:
    LOGE("Check hichain state failed, state is %d, message nav is %d-%d-%d", hichain->state, nav->modular,
        nav->msg_type, nav->is_request_msg);//处理错误,打印错误日志信息
    return false;//返回错误
}
  1. 然后执行get_operation_code函数获取操作码:
static int32_t get_operation_from_pake(void *payload);//函数声明
static int32_t get_operation_from_sts(void *payload);//函数声明
//根据消息模块类型获取解析不同协议的操作码,这里有PAKE和STS协议
static int32_t get_operation_code(const struct header_analysis *nav, const struct message *receive)
{
    int32_t operation_code = NO_OPERATION_CODE;//初始化为无操作

    if ((nav->modular == PAKE_MODULAR) && (nav->msg_type == PAKE_START_MSG) && nav->is_request_msg) {//如果消息属于PAKE协议,且是"请求开始"消息,则获取PAKE协议的操作码
        operation_code = get_operation_from_pake(receive->payload);//获取解析出的pake协议的操作码
    } else if ((nav->modular == STS_MODULAR) && (nav->msg_type == STS_START_MSG) && nav->is_request_msg) {//如果消息属于STS协议,且是"请求开始"消息,则获取STS协议的操作码
        operation_code = get_operation_from_sts(receive->payload);//获取解析出的sts协议的操作码
    }
    LOGI("Receive message had operation code is %d", operation_code);
    return operation_code;
}

//获取解析出的pake协议的操作码
static int32_t get_operation_from_pake(void *payload)
#if !(defined(_CUT_PAKE_) || defined(_CUT_PAKE_SERVER_))
{
    int32_t permissible_code[] = { BIND, AUTH_KEY_AGREEMENT };//允许的操作码,目前有:BIND(绑定),AUTH_KEY_AGREEMENT(认证密钥协商)
    struct pake_start_request_data *data = payload;//结构体强转,解析出该消息的操作码

    for (uint32_t i = 0; i < sizeof(permissible_code) / sizeof(int32_t); i++) {
        if (permissible_code[i] == data->operation_code) {//查询该操作码是否属于允许的操作码,是就返回,否则返回无效,即-1
            return data->operation_code;
        }
    }
    LOGE("Receive operation code %d is error", data->operation_code);
    return INVALID_OPERATION_CODE;
}

//获取解析出的sts协议的操作码
static int32_t get_operation_from_sts(void *payload)
#if !(defined(_CUT_STS_) || defined(_CUT_STS_SERVER_))
{
    int32_t permissible_code[] = { AUTHENTICATE, ADD_AUTHINFO, REMOVE_AUTHINFO, UNBIND, SEC_CLONE_OP };//允许的操作码,
    struct sts_start_request_data *data = payload;//结构体强转,解析出该消息的操作码

    for (uint32_t i = 0; i < sizeof(permissible_code) / sizeof(int32_t); i++) {//查询该操作码是否属于允许的操作码,是就返回,否则返回无效,即-1
        if (permissible_code[i] == data->operation_code) {
            return data->operation_code;
        }
    }
    LOGE("Receive operation code %d is error", data->operation_code);
    return INVALID_OPERATION_CODE;
}
  1. 接着执行is_message_illegal函数检查消息是否合法:
//检查消息是否为非法消息,是非法消息则返回true,否则返回false
static bool is_message_illegal(int32_t operation_code, int32_t modular)
{
    //合法消息表
    struct check_message_powered table[] = { { BIND, PAKE_MODULAR },
                                             { BIND, EXCHANGE_MODULAR },
                                             { AUTH_KEY_AGREEMENT, PAKE_MODULAR },
                                             { UNBIND, STS_MODULAR },
                                             { UNBIND, REMOVE_MODULAR },
                                             { AUTHENTICATE, STS_MODULAR },
                                             { ADD_AUTHINFO, STS_MODULAR },
                                             { ADD_AUTHINFO, ADD_MODULAR },
                                             { REMOVE_AUTHINFO, STS_MODULAR },
                                             { REMOVE_AUTHINFO, REMOVE_MODULAR },
                                             { SEC_CLONE_OP, STS_MODULAR },
                                             { SEC_CLONE_OP, SEC_CLONE_MODULAR } };

    for (uint32_t i = 0; i < sizeof(table) / sizeof(table[0]); i++) {//遍历合法消息表,查询对应的消息是否存在
        if ((modular == table[i].modular) && (operation_code == table[i].operation_code)) {
            return false;//若存在,返回消息合法
        }
    }
    return true;//不存在,返回消息不合法
}

三、小结

本文主要介绍了导航消息模块和检查消息合法性模块,其余内容将在下一篇博客中介绍。

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号