* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ka_errno_pub.h"
#include "ka_base_pub.h"
#include "ka_common_pub.h"
#include "ka_fs_pub.h"
#include "securec.h"
#include "dms_custom_common.h"
#include "dms_template.h"
#include "dms/dms_cmd_def.h"
#include "dms_custom_common.h"
int dms_save_sign_flag_to_file(unsigned int device_id, char *buffer, unsigned int buff_size)
{
int ret;
char dst_path[CUSTOM_SIGN_CONF_FILE_PATH_MAX] = {0};
ret = snprintf_s(dst_path, CUSTOM_SIGN_CONF_FILE_PATH_MAX, CUSTOM_SIGN_CONF_FILE_PATH_MAX - 1, CUSTOM_SIGN_CONF_FLAG_PATH, device_id);
if (ret < 0) {
dms_err("Failed to invoke snprintf_s. (device_id=%u; ret=%d).\n", device_id, ret);
return -EINVAL;
}
ret = dms_sign_write_file(dst_path, buffer, buff_size);
if (ret != 0) {
dms_err("Failed to write sign flag to file. (dst_path=%s).\n", dst_path);
return -EINVAL;
}
return 0;
}
int dms_save_sign_cert_to_file(unsigned int device_id, unsigned int sub_cmd, char *buffer, unsigned int buff_size)
{
int ret;
char dst_path[CUSTOM_SIGN_CONF_FILE_PATH_MAX] = {0};
ret = dms_custom_get_file_name(device_id, sub_cmd, dst_path);
if (ret < 0) {
dms_err("Failed to invoke dms_custom_get_file_name, (device_id=%u; ret=%d).\n", device_id, ret);
return -EINVAL;
}
ret = dms_sign_write_file(dst_path, buffer, buff_size);
if (ret != 0) {
dms_err("Failed to write sign cert to file, (dst_path=%s).\n", dst_path);
return -EINVAL;
}
return 0;
}
int dms_custom_get_file_name(unsigned int dev_id, unsigned int sub_cmd, char *file_name)
{
int ret;
switch(sub_cmd) {
case DSMI_SEC_SUB_CMD_CUST_SIGN_VENDOR_CERT:
ret = snprintf_s(file_name, CUSTOM_SIGN_CONF_FILE_PATH_MAX, CUSTOM_SIGN_CONF_FILE_PATH_MAX - 1, CUSTOM_SIGN_CONF_VENDOR_CERT_PATH, dev_id);
break;
case DSMI_SEC_SUB_CMD_CUST_SIGN_USER_CERT:
ret = snprintf_s(file_name, CUSTOM_SIGN_CONF_FILE_PATH_MAX, CUSTOM_SIGN_CONF_FILE_PATH_MAX - 1, CUSTOM_SIGN_CONF_USER_CERT_PATH, dev_id);
break;
case DSMI_SEC_SUB_CMD_CUST_SIGN_CMTY_CERT:
ret = snprintf_s(file_name, CUSTOM_SIGN_CONF_FILE_PATH_MAX, CUSTOM_SIGN_CONF_FILE_PATH_MAX - 1, CUSTOM_SIGN_CONF_CMTY_CERT_PATH, dev_id);
break;
default:
dms_err("File type invalid. (dev_id=%u; sub_cmd=%u)\n", dev_id, sub_cmd);
return -EINVAL;
}
return ret;
}
int dms_custom_is_file_exist(const char *file_name, int *is_exist)
{
int ret;
ka_file_t *filp = NULL;
filp = ka_fs_filp_open(file_name, KA_O_RDONLY, 0);
if (KA_IS_ERR_OR_NULL(filp)) {
ret = (int)KA_PTR_ERR(filp);
if (ret == -ENOENT) {
*is_exist = 0;
return 0;
}
*is_exist = 1;
return -EINVAL;
}
(void)ka_fs_filp_close(filp, NULL);
filp = NULL;
*is_exist = 1;
return 0;
}
int dms_custom_get_file_size(const char *file_name, unsigned long long *file_size)
{
ka_file_t *filp = NULL;
filp = ka_fs_filp_open(file_name, KA_O_RDONLY, 0);
if (KA_IS_ERR_OR_NULL(filp)) {
dms_err("Unable to open file. (file_name=%s; errno=%ld)\n", file_name, KA_PTR_ERR(filp));
return (int)KA_PTR_ERR(filp);
}
if (filp->f_inode == NULL) {
(void)ka_fs_filp_close(filp, NULL);
filp = NULL;
dms_err("File inode is NULL.\n");
return -ENOENT;
}
*file_size = (unsigned long long)filp->f_inode->i_size;
(void)ka_fs_filp_close(filp, NULL);
filp = NULL;
return 0;
}
int dms_custom_read_file(const char *file_name, char *buf, unsigned int size)
{
ka_file_t *filp = NULL;
loff_t offset_tmp = 0;
ssize_t result;
filp = ka_fs_filp_open(file_name, KA_O_RDONLY, 0);
if (KA_IS_ERR_OR_NULL(filp)) {
dms_err("Unable to open file. (file_name=%s; errno=%ld)\n", file_name, KA_PTR_ERR(filp));
return (int)KA_PTR_ERR(filp);
}
result = ka_fs_kernel_read(filp, buf, size, &offset_tmp);
if (result != (ssize_t)size) {
dms_err("Kernel read file error. (result=%ld; size=%u)\n", result, size);
(void)ka_fs_filp_close(filp, NULL);
filp = NULL;
return -EINVAL;
}
(void)ka_fs_filp_close(filp, NULL);
filp = NULL;
return 0;
}
int dms_sign_write_file(char *file_path, char *buffer, int size)
{
ka_file_t *filp = NULL;
loff_t offset_tmp = 0;
int ret;
int rw_len;
filp = ka_fs_filp_open(file_path, KA_O_WRONLY | KA_O_TRUNC, 0);
if (KA_IS_ERR_OR_NULL(filp)) {
ret = (int)KA_PTR_ERR(filp);
if (ret != -ENOENT) {
dms_err("Unable to open file. (file_name=%s; err=%ld)\n", file_path, KA_PTR_ERR(filp));
}
return ret;
}
rw_len = ka_fs_kernel_write(filp, buffer, size, &offset_tmp);
(void)ka_fs_filp_close(filp, NULL);
filp = NULL;
if (rw_len != size) {
dms_err("File write failed. (file_name=%s; rw_len=%d; w_len=%d)\n", file_path, rw_len, size);
return -EINVAL;
}
return 0;
}
int search_key_and_get_value(char *buff, const char *split, const char *key, char *value, int len)
{
char *left = NULL;
char *right = NULL;
char *p_save = NULL;
if (len <= 0 || len > CUSTOM_SIGN_CONF_VALLUE_MAX_LEN) {
dms_err("The variable len is invalid. (len=%d)\n", len);
return -EINVAL;
}
if (ka_base_strlen(buff) == 0) {
return -EINVAL;
}
if (buff[ka_base_strlen(buff) - 1] == '\n') {
buff[ka_base_strlen(buff) - 1] = '\0';
}
if (ka_base_strstr(buff, key) == NULL) {
return -EINVAL;
}
left = strtok_s(buff, split, &p_save);
if (left == NULL) {
return -EINVAL;
}
if (ka_base_strcmp(key, left) != 0) {
return -EINVAL;
}
if ((right = strtok_s(NULL, split, &p_save)) != NULL) {
if (strcpy_s(value, len, right) != 0) {
dms_err("Failed to invoke strcpy_s to copy the variable right.\n");
return -EINVAL;
}
return 0;
}
return -EINVAL;
}