密钥管理工具接口
为了方便客户定制化管理密钥,提供了密钥管理工具接口供用户调用。
- 管理工具创建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
失败,返回错误码。
- 删除指定内置密钥。
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;
}