一、概述
在上一篇博客OpenHarmony解读之设备认证:pake协议-客户端发起start请求中讲到,客户端设备向服务端设备发起请求,本文将介绍服务端设备是如何响应客户端设备的请求并作出具体回复的。接收消息数据的过程在前面的博客中已经有所介绍,这里不再赘述。
二、源码分析
这一模块的源码位于:/base/security/deviceauth。
1. 首先执行函数parse_pake_request解析pake请求消息。
/*
函数功能:解析pake协议请求消息
函数参数:
payload:消息负载地址
data_type:json对象的数据类型
函数返回值:
成功:返回解析完成的消息负载地址
失败:返回NULL
*/
void *parse_pake_request(const char *payload, enum json_object_data_type data_type)
{
struct pake_start_request_data *pake_request =
(struct pake_start_request_data *)MALLOC(sizeof(struct pake_start_request_data));//为pake协议的请求消息数据结构申请空间
if (pake_request == NULL) {//申请失败
return NULL;
}
(void)memset_s(pake_request, sizeof(*pake_request), 0, sizeof(*pake_request));//清空pake协议的请求消息数据结构空间
json_handle obj = parse_payload(payload, data_type);//解析消息数据为cjson结构体对象类型
if (obj == NULL) {//解析失败
LOGE("Parse Pake Request parse payload failed");
goto error;
}
/* op */
int32_t op = get_json_int(obj, FIELD_OPERATION_CODE);//获取操作码"operationCode"
if (op == -1) {
LOGE("Parse Pake Request failed, field is null in operationCode");//解析失败,打印日志
goto error;
}
pake_request->operation_code = op;//将获取到的操作码赋值给pake_request结构
/* version */
json_pobject obj_ver = get_json_obj(obj, FIELD_VERSION);//解析获取"version"子对象,即版本号
bool ret = parse_version(obj_ver, &pake_request->peer_version, &pake_request->peer_support_version);//解析出对端的当前版本号以及最低支持的版本号
if (!ret) {
LOGE("Parse Pake Request failed, field is null in version");
goto error;
}
/* support 256 mod 是否支持256位模运算???*/
int32_t support_256_mod = get_json_bool(obj, FIELD_SUPPORT_256_MOD);//获取子对象"support256mod"的值
if (support_256_mod == 1) {
pake_request->epk_len = HC_BIG_PRIME_MAX_LEN;//若支持,epk_len为HC_BIG_PRIME_MAX_LEN
} else {
pake_request->epk_len = HC_BIG_PRIME_MAX_LEN_384;//若不支持,epk_len为HC_BIG_PRIME_MAX_LEN_384
}
free_payload(obj, data_type);
return (void *)pake_request;
error:
free_payload(obj, data_type);
FREE(pake_request);
return NULL;
}
/*
函数功能:如果消息负载为json格式的字符串,则将json格式的数据解析成cjson结构体对象;如果消息负载为cjson结构体对象类型,则返回原内容;否则返回NULL
函数参数:
payload:消息负载地址
data_type:数据类型:只有JSON_STRING_DATA和JSON_OBJECT_DATA
*/
void *parse_payload(const char *payload, enum json_object_data_type data_type)
{
if (data_type == JSON_STRING_DATA) {//如果json对象类型为:json格式的字符串
return parse_json(payload);//将json格式的数据解析成cjson结构体对象
} else if (data_type == JSON_OBJECT_DATA) {//如果json对象类型为:cjson结构体对象
return (void *)payload;//直接返回原内容
} else {
return NULL;//如果都不是,返回NULL
}
}
/*
函数功能:解析版本号
函数参数:
obj_ver:cjson结构体版本号对象
min_ver:最小版本号
cur_ver:当前版本号
函数返回值:
成功返回true,失败返回false
*/
bool parse_version(json_pobject obj_ver, struct key_agreement_version *min_ver, struct key_agreement_version *cur_ver)
{
const char *str_cur_ver = get_json_string(obj_ver, FIELD_CURRENT_VERSION); /* version---cur 获取当前版本号,为字符串类型*/
if (str_cur_ver == NULL) {
return false;//失败返回false
}
char *sub_cur_ver = NULL;//子当前版本号
char *next = NULL;
int32_t len_cur_ver = strlen(str_cur_ver);//获取当前版本号长度
char *tmp_cur_ver = (char *)MALLOC(len_cur_ver + 1);//申请当前版本号临时空间
if (tmp_cur_ver == NULL) {
return false;
}
(void)memset_s(tmp_cur_ver, len_cur_ver + 1, 0, len_cur_ver + 1);//清空临时空间
if (strcpy_s(tmp_cur_ver, len_cur_ver + 1, str_cur_ver) != EOK) {//将获取到的当前版本号拷贝到临时空间
FREE(tmp_cur_ver);
tmp_cur_ver = NULL;
return false;
}
split_ver(tmp_cur_ver, sub_cur_ver, min_ver, next);//分割出子当前版本号first,second,third保存在min_ver中???
FREE(tmp_cur_ver);
tmp_cur_ver = NULL;
const char *str_min_ver = get_json_string(obj_ver, FIELD_MIN_VERSION); /* version---min 获取最小版本号,为字符串类型*/
if (str_min_ver == NULL) {
return false;
}
char *sub_min_ver = NULL;//子最小版本号
int32_t len_min_ver = strlen(str_min_ver);//获取最小版本号长度
char *tmp_min_ver = (char *)MALLOC(len_min_ver + 1);//申请最小版本号临时空间
if (tmp_min_ver == NULL) {
return false;
}
(void)memset_s(tmp_min_ver, len_min_ver + 1, 0, len_min_ver + 1);//清空临时空间
if (strcpy_s(tmp_min_ver, len_min_ver + 1, str_min_ver) != EOK) {//将获取到的最小版本号拷贝到临时空间
FREE(tmp_min_ver);
tmp_min_ver = NULL;
return false;
}
split_ver(tmp_min_ver, sub_min_ver, cur_ver, next);//分割出子最小版本号first,second,third保存在cur_ver中???
FREE(tmp_min_ver);
tmp_min_ver = NULL;
return true;
}
//按指定分隔符分割版本号
static void split_ver(char *tmp_ver, const char *sub_ver, struct key_agreement_version *cur_ver, char *next)
{
sub_ver = strtok_s(tmp_ver, ".", &next);//按 "."分割出first子版本号
if (sub_ver != NULL) {
cur_ver->first = strtoul(sub_ver, NULL, HC_VERSION_DEC); /* first 把参数 sub_ver 所指向的字符串根据给定的 base 转换为一个无符号长整数(类型为 unsigned long int 型)*/
}
sub_ver = strtok_s(NULL, ".", &next);//按 "."分割出second子版本号
if (sub_ver != NULL) {
cur_ver->second = strtoul(sub_ver, NULL, HC_VERSION_DEC); /* second 把分割出来的字符串转为无符号长整数*/
}
sub_ver = strtok_s(NULL, ".", &next);//按 "."分割出third子版本号
if (sub_ver != NULL) {
cur_ver->third = strtoul(sub_ver, NULL, HC_VERSION_DEC); /* third 把分割出来的字符串转为无符号长整数*/
}
}
2. 根据全局消息码表G_MESSAGE_CODE_MAP创建对应的hc子对象,此处应创建pake服务端对象,调用函数build_pake_server_object实现。
/*
函数功能:创建pake服务端对象
函数参数:
hichain:hichain实例
params:创建参数
函数返回值:返回对象地址
*/
static void *build_pake_server_object(struct hichain *hichain, const void *params)
{
(void)params;//未使用参数,防止编译器发出警告
struct hc_pin pin = { 0, {0} };//初始化PIN码
struct operation_parameter para;//定义操作参数
(void)memset_s(¶, sizeof(para), 0, sizeof(para));//清空操作参数空间
hichain->cb.get_protocol_params(&hichain->identity, hichain->operation_code, &pin, ¶);//获取协议参数主,要获取认证会话密钥长度、对端认证id和本端认证id
if (check_param_is_valid(¶) == false) {//检查参数是否有效
LOGE("Param invalid");
return NULL;
}
if (pin.length > HC_PIN_BUFF_LEN) {//PIN码不规范
LOGE("PIN invalid");
return NULL;
}
return build_pake_server(&pin, para.key_length, ¶.peer_auth_id, ¶.self_auth_id);//创建pake客户端对象
}
/*
函数功能:创建pake服务端对象
函数参数:
pin:PIN码
key_length:密钥长度
client:客户端认证id
server:服务端认证id
函数返回值:返回对象地址
*/
struct pake_server *build_pake_server(const struct hc_pin *pin, uint32_t key_length, const struct hc_auth_id *client,
const struct hc_auth_id *server)
{
struct pake_server *pake_server = (struct pake_server *)MALLOC(sizeof(struct pake_server));//为该对象申请内存空间
if (pake_server == NULL) {
LOGE("Build pake server object failed");
return NULL;
}
(void)memset_s(pake_server, sizeof(*pake_server), 0, sizeof(*pake_server));//清空该内存空间
const struct server_virtual_func_group funcs = { parse_start_request_data, build_start_response_data,
parse_end_request_data, build_end_response_data };//赋值服务端虚函数组
init_server(&pake_server->server_info, &funcs);//初始化服务端状态和打包函数
pake_server->pin = *pin;//赋值PIN
pake_server->key_length = key_length;//赋值密钥长度
pake_server->self_id = *server;//赋值本端认证id
pake_server->peer_id = *client;//赋值对端认证id
pake_server->prime_type = NUM_LEN_384;//质数长度
LOGI("Build pake server object %u success", pake_server_sn(pake_server));
return pake_server;
}
三、小结
由于篇幅原因,本篇博客就介绍到此处,剩余内容将在下篇博客中叙述。