鲲鹏社区首页
中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

密钥管理工具接口

为了方便客户定制化管理密钥,提供了密钥管理工具接口供用户调用。

  • 管理工具创建session用户。
    int ECM_OpenSession(void *hDeviceHandle, void **phSessionHandle);
    表1 参数说明

    参数

    描述

    hDeviceHandle[in]

    已打开的设备句柄。

    phSessionHandle[out]

    与密码设备已建立的会话句柄。

    表2 返回值说明

    返回值

    说明

    0

    成功。

    非0

    失败,返回错误码。

  • 创建设备内置密钥并设置密码。
    int ECM_GenerateKey(void *hSessionHandle, unsigned int uiKeyIndex, unsigned char *pucPassword, unsigned int uiPwdLength);
    表3 参数说明

    参数

    描述

    hSessionHandle[in]

    与设备建立的会话句柄。

    uiKeyIndex[in]

    密码设备存储私钥的索引值,包括密钥类型与索引下标。

    pucPassword[in]

    使用私钥权限的标识码。

    uiPwdLength[in]

    使用私钥权限标识码的长度,范围8-128字节。

    表4 返回值说明

    返回值

    说明

    0

    成功。

    非0

    失败,返回错误码。

    • uiKeyIndex[in]:内部密钥索引信息,长度32位bit,高12位表示key的类型,低20位表示key的下标。

      key的类型中,当前可选类型为:

      • SDF_SM2_SIGN:签名密钥对。
      • SDF_SM2_ENC:加密密钥对。
      • SDF_SM4: SM4加密密钥。
    • 用户密钥包括加密密钥对和签名密钥对,因此调用此接口时应调用两次才能完成用户密钥的生成。
  • 删除指定内置密钥。
    int ECM_DeleteKey(void *hSessionHandle, unsigned int uiKeyIndex);
    表5 参数说明

    参数

    描述

    hSessionHandle[in]

    与设备建立的会话句柄。

    uiKeyIndex[in]

    密码设备存储私钥的索引值,由密钥类型与索引下标组成。

    表6 返回值说明

    返回值

    说明

    0

    成功。

    非0

    失败,返回错误码。

  • 查询内置密钥状态。
    int ECM_QueryKey(void *hSessionHandle, unsigned int uiKeyIndex, unsigned int *uiKeyInfo);
    表7 参数说明

    参数

    描述

    hSessionHandle[in]

    与设备建立的会话句柄。

    uiKeyIndex[in]

    密码设备存储私钥的索引值,由密钥类型与索引下标组成。

    uiKeyInfo[out]

    密码设备内置密钥信息。

    • 0:密钥存在。
    • 非0:密钥不存在。
    表8 返回值说明

    返回值

    说明

    0

    成功。

    非0

    失败,返回错误码。

  • 修改指定私钥的权限标识码。
    int ECM_ChangePassword(void *hSessionHandle, unsigned int uiKeyIndex, unsigned char *prePassword, unsigned int prePasswordLen, unsigned char *newPassword, unsigned int newPasswordLen);
    表9 参数说明

    参数

    描述

    hSessionHandle[in]

    与设备建立的会话句柄。

    uiKeyIndex[in]

    密码设备存储私钥的索引值,由密钥类型与索引下标组成。

    prePassword[in]

    当前使用私钥权限的标识码。

    prePasswordLen[in]

    当前私钥权限标识码的长度,范围8-128字节。

    newPassword[in]

    新设置的私钥权限标识码。

    newPasswordLen[in]

    新设置的私钥权限标识码长度,范围8-128字节。

    表10 返回值说明

    返回值

    说明

    0

    成功。

    非0

    失败,返回错误码。

  • 导出对应内置密钥。
    int ECM_ExportKey(void *hSessionHandle, unsigned int uiKeyIndex, unsigned char *keyFileBuffer, unsigned int *keyBufferLength, unsigned char *keySalt);
    表11 参数说明

    参数

    描述

    hSessionHandle[in]

    与设备建立的会话句柄。

    uiKeyIndex[in]

    密码设备存储私钥的索引值,由密钥类型与索引下标组成。

    keyFileBuffer[out]

    缓冲区指针,用于存放导出的内置密钥密文。

    keyBufferLength[out]

    导出的内置密钥密文长度。

    keySalt[in]

    加密盐值,最大长度16字节。

    表12 返回值说明

    返回值

    说明

    0

    成功。

    非0

    失败,返回错误码。

  • 导入密钥到指定索引下标。
    int ECM_ImportKey(void *hSessionHandle, unsigned int uiKeyIndex, unsigned char *keyFileBuffer, unsigned int keyBufferLength, unsigned char *keySalt);
    表13 参数说明

    参数

    描述

    hSessionHandle[in]

    与设备建立的会话句柄。

    uiKeyIndex[in]

    密码设备存储私钥的索引值,由密钥类型与索引下标组成。

    keyFileBuffer[in]

    缓冲区指针,用于存放准备导入的密钥密文。

    keyBufferLength[out]

    待导入的密钥密文长度。

    keySalt[in]

    解密盐值,最大长度16字节。

    表14 返回值说明

    返回值

    说明

    0

    成功。

    非0

    失败,返回错误码。

  • 设置可以访问内置密钥的应用路径。
    int ECM_SetAccessRight(void *hSessionHandle, unsigned int uiKeyIndex, unsigned char *pucAccessInfo, unsigned char *pucPassword, unsigned int uiPwdLength);
    表15 参数说明

    参数

    描述

    hSessionHandle[in]

    与设备建立的会话句柄。

    uiKeyIndex[in]

    密码设备存储私钥的索引值,由密钥类型与索引下标组成。

    pucAccessInfo[in]

    缓冲区指针,用于存放允许访问的应用hash值,长度固定32字节。

    pucPassword[out]

    使用私钥权限的标识码。

    uiPwdLength[in]

    使用私钥权限标识码的长度,长度8-128字节。

    表16 返回值说明

    返回值

    说明

    0

    成功。

    非0

    失败,返回错误码。

    CA应用的hash值计算方式为:SHA256(CA的路径||用户名),即CA路径拼接上用户名,再计算SHA256得到的值。注意用户名长度需固定为256字节,长度不足时需补零。

  • 删除可以访问内置密钥的应用路径。
    int ECM_DelAccessRight(void *hSessionHandle, unsigned int uiKeyIndex, unsigned char *pucAccessInfo, unsigned char *pucPassword, unsigned int uiPwdLength);
    表17 参数说明

    参数

    描述

    hSessionHandle[in]

    与设备建立的会话句柄。

    uiKeyIndex[in]

    密码设备存储私钥的索引值,由密钥类型与索引下标组成。

    pucAccessInfo[in]

    缓冲区指针,用于存放允许访问的应用hash值,长度固定32字节。

    pucPassword[out]

    使用私钥权限的标识码。

    uiPwdLength[in]

    使用私钥权限标识码的长度,长度8-128字节。

    表18 返回值说明

    返回值

    说明

    0

    成功。

    非0

    失败,返回错误码。

  • 恢复出厂设置。
    int ECM_FactoryReset();
    表19 返回值说明

    返回值

    说明

    0

    成功。

    非0

    失败,返回错误码。

规格限制

集成这些接口的应用应以root用户执行,并只能在host上运行。

密钥管理接口示例

如下提供示例代码演示了上述接口的使用方式,以SM2用户密钥为例,包括密钥的创建、密钥标识码的修改、密钥访问权限路径添加与删除、导出导入密钥,删除密钥。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>
#include "sdf.h"

#define MAX_KEY_FILE_SIZE (1024 * 1024)
#define EXPORT_SALT "123456789"
#define CA_PATH "./test_sdf"
#define USER_NAME "root"
#define PASSWD "Huawei123."
#define NEWPASSWD "Huawei321."
#define ALG_FLAG_OFFSET 20

int generate_key(void *session, unsigned int key_id, unsigned char *password)
{
    int ret;
    // sm2签名及加密密钥
    unsigned int sign_info = SDF_SM2_SIGN << ALG_FLAG_OFFSET | key_id;
    unsigned int enc_info = SDF_SM2_ENC << ALG_FLAG_OFFSET | key_id;
    ret = ECM_GenerateKey(session, sign_info, password, strlen(password));
    if (ret != SDR_OK) {
        printf("ECM_GenerateKey sign key failed, ret = 0x%x\n", ret);
        return ret;
    }
    
    ret = ECM_GenerateKey(session, enc_info, password, strlen(password));
    if (ret != SDR_OK) {
        printf("ECM_GenerateKey enc key failed, ret = 0x%x\n", ret);
        return ret;
    }
    return ret;
}
int delete_key(void *session, unsigned int key_id)
{
    int ret;
    unsigned int sign_info = SDF_SM2_SIGN << ALG_FLAG_OFFSET | key_id;
    unsigned int enc_info = SDF_SM2_ENC << ALG_FLAG_OFFSET | key_id;
    ret = ECM_DeleteKey(session, sign_info);
    if (ret != SDR_OK) {
        printf("ECM_DeleteKey key_index %d failed, ret = 0x%x\n", key_id, ret);
        return ret;
    }
    ret = ECM_DeleteKey(session, enc_info);
    if (ret != SDR_OK) {
        printf("ECM_DeleteKey key_index %d failed, ret = 0x%x\n", key_id, ret);
    }
    return ret;
}
int export_import_key(void *session, unsigned int key_id1, unsigned int key_id2)
{
    int ret = -1;
    uint8_t *key_data = NULL;
    uint32_t key_data_len = MAX_KEY_FILE_SIZE;
    unsigned int sign_key_info1 = SDF_SM2_SIGN << ALG_FLAG_OFFSET | key_id1;
    unsigned int sign_key_info2 = SDF_SM2_SIGN << ALG_FLAG_OFFSET | key_id2;
    unsigned int enc_key_info1 = SDF_SM2_ENC << ALG_FLAG_OFFSET | key_id1;
    unsigned int enc_key_info2 = SDF_SM2_ENC << ALG_FLAG_OFFSET | key_id2;
    key_data = (uint8_t *)malloc(key_data_len);
    if (key_data == NULL) {
        printf("malloc failed\n");
        return -1;
    }
    // 导出导入签名密钥
    ret = ECM_ExportKey(session, sign_key_info1, key_data, &key_data_len, EXPORT_SALT);
    if (ret) {
        printf("ECM_ExportKey sign key failed, ret = 0x%x, %d\n", ret, key_data_len);
        goto free;
    }
    ret = ECM_ImportKey(session, sign_key_info2, key_data, key_data_len, EXPORT_SALT);
    if (ret) {
        printf("ECM_ImportKey sign key failed, ret = 0x%x\n", ret);
        goto free;
    }
    // 导出导入加密密钥
    ret = ECM_ExportKey(session, enc_key_info1, key_data, &key_data_len, EXPORT_SALT);
    if (ret) {
        printf("ECM_ExportKey enc key failed, ret = 0x%x, %d\n", ret, key_data_len);
        goto free;
    }
    ret = ECM_ImportKey(session, enc_key_info2, key_data, key_data_len, EXPORT_SALT);
    if (ret) {
        printf("ECM_ImportKey enc key failed, ret = 0x%x\n", ret);
        goto free;
    }
free:
    free(key_data);
    return ret;
}
int change_passwd(void *session, unsigned int key_id, char *passwd, char *new_passwd)
{
    int ret;
    unsigned int sign_info = SDF_SM2_SIGN << ALG_FLAG_OFFSET | key_id;
    unsigned int enc_info = SDF_SM2_ENC << ALG_FLAG_OFFSET | key_id;
    ret = ECM_ChangePassword(session, sign_info, passwd, strlen(passwd), new_passwd, strlen(new_passwd));
    if (ret != SDR_OK) {
        printf("ECM_ChangePassword sign key failed, ret = 0x%x\n", ret);
        return ret;
    }
    ret = ECM_ChangePassword(session, enc_info, passwd, strlen(passwd), new_passwd, strlen(new_passwd));
    if (ret != SDR_OK) {
        printf("ECM_ChangePassword sign key failed, ret = 0x%x\n", ret);
    }
    return ret;
}
void calculate_cainfo(const char *ca_path, const char *user_name, unsigned char hash[32])
{
    char plan[256] = {0};
    memcpy(plan, user_name, strlen(user_name));
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, ca_path, strlen(ca_path));
    SHA256_Update(&sha256, plan, 256);
    SHA256_Final(hash, &sha256);
    for (size_t i = 0; i < 32; i++) {
        printf("%02x", hash[i]);
    }
    printf("\n");
}
int set_ca_access_right(void *session, unsigned int key_id, char *ca_path, char *user_name, char *passwd)
{
    int ret;
    unsigned int sign_info = SDF_SM2_SIGN << ALG_FLAG_OFFSET | key_id;
    unsigned int enc_info = SDF_SM2_ENC << ALG_FLAG_OFFSET | key_id;
    unsigned char hash[32] = {0};
    unsigned char hash2[32] = {0};
    calculate_cainfo(ca_path, user_name, hash);
    ret = ECM_SetAccessRight(session, sign_info, hash, passwd, strlen(passwd));
    if (ret != SDR_OK) {
        printf("ECM_SetAccessRight sign key failed, ret = 0x%x\n", ret);
        return ret;
    }
    ret = ECM_SetAccessRight(session, enc_info, hash, passwd, strlen(passwd));
    if (ret != SDR_OK) {
        printf("ECM_SetAccessRight sign key failed, ret = 0x%x\n", ret);
    }
    return ret;
}
int delete_ca_access_right(void *session, unsigned int key_id, char *ca_path, char *user_name, char *passwd)
{
    int ret;
    unsigned int sign_info = SDF_SM2_SIGN << ALG_FLAG_OFFSET | key_id;
    unsigned int enc_info = SDF_SM2_ENC << ALG_FLAG_OFFSET | key_id;
    unsigned char hash[32] = {0};
    calculate_cainfo(ca_path, user_name, hash);
    ret = ECM_DelAccessRight(session, sign_info, hash, passwd, strlen(passwd));
    if (ret != SDR_OK) {
        printf("ECM_SetAccessRight sign key failed, ret = 0x%x\n", ret);
        return ret;
    }
    ret = ECM_DelAccessRight(session, enc_info, hash, passwd, strlen(passwd));
    if (ret != SDR_OK) {
        printf("ECM_SetAccessRight sign key failed, ret = 0x%x\n", ret);
    }
    return ret;
}
int main()
{
    int ret = -1;
    int key_idx1 = 1, key_idx2 = 2;
    void *device = NULL, *session = NULL;
    ret = SDF_OpenDevice(&device);
    if (ret != SDR_OK) {
        printf("sdf open device failed, ret = 0x%x\n", ret);
        return ret;
    }
    ret = ECM_OpenSession(device, &session);
    if (ret != SDR_OK) {
        printf("sdf open session failed, ret = 0x%x\n", ret);
        goto close;
    }
    ret = generate_key(session, key_idx1, PASSWD);
    if (ret != SDR_OK) {
        printf("generate_key failed, ret = 0x%x\n", ret);
        goto close;
    }
    printf("generate key success\n");
    // 修改密码
    ret = change_passwd(session, key_idx1, PASSWD, NEWPASSWD);
    if (ret != SDR_OK) {
        printf("chage key passwd failed, ret = 0x%x\n", ret);
        goto close;
    }
    printf("change passwd success\n");
    // 添加CA访问权限
    ret = set_ca_access_right(session, key_idx1, CA_PATH, USER_NAME, NEWPASSWD);
    if (ret != SDR_OK) {
        printf("set ca access right failed, ret = 0x%x\n", ret);
        goto close;
    }
    printf("set ca path success\n");
    // 删除CA访问权限。
    ret = delete_ca_access_right(session, key_idx1, CA_PATH, USER_NAME, NEWPASSWD);
    if (ret != SDR_OK) {
        printf("delete ca access right failed, ret = 0x%x\n", ret);
        goto close;
    }
    printf("delete ca path success\n");
    // 导入密钥到key_idx2
    ret = export_import_key(session, key_idx1, key_idx2);
    if (ret != SDR_OK) {
        printf("export_import_key failed, ret = 0x%x\n", ret);
        goto close;
    }
    printf("export key %d, import to key %d success\n", key_idx1, key_idx2);
    ret = delete_key(session, key_idx1);
    if (ret != SDR_OK) {
        printf("ECM_DeleteKey failed, ret = 0x%x\n", ret);
        goto close;
    }
    ret = delete_key(session, key_idx2);
    if (ret != SDR_OK) {
        printf("ECM_DeleteKey failed, ret = 0x%x\n", ret);
        goto close;
    }
    printf("delete key success\n");
close:
    if (session != NULL) {
        (void)SDF_CloseSession(session);
    }
    if (device != NULL) {
        (void)SDF_CloseDevice(device);
    }
    return ret;
}