接口调用示例
本章节介绍了SM2密钥管理接口的示例代码及编译运行步骤。
密钥管理接口示例
如下提供示例代码演示了上述接口的使用方式,以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 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");
// 导入密钥到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;
}
gcc -I/path/to/sdf.h/ test.c -lsdf -lcrypto
密钥使用接口示例
- 下载本模块的接口头文件。
git clone https://gitee.com/openeuler/itrustee_sdk.git
- 在代码中引用sdf.h头文件,即可进行应用开发,以获取设备信息为例。
vim test_sdf.c
创建test_sdf.c源文件,添加如下内容。
#include <stdio.h> #include "sdf.h" int main() { int ret = -1; void *hDeviceHandle = NULL; void *hSessionHandle = NULL; DEVICEINFO info = {0}; ret = SDF_OpenDevice(&hDeviceHandle); if (ret != SDR_OK) { printf("sdf open device failed, ret = 0x%x\n", ret); return ret; } ret = SDF_OpenSession(hDeviceHandle, &hSessionHandle); if (ret != SDR_OK) { printf("sdf open session failed, ret = 0x%x\n", ret); return ret; } printf("sdf open device and session success\n"); ret = SDF_GetDeviceInfo(hSessionHandle, &info); if (ret != SDR_OK) { printf("sdf get device info failed, ret = 0x%x\n", ret); return ret; } printf("sdf get device info success\n"); printf("Device Name: %s\n", info.DeviceName); return 0; } - 完毕后可参考如下命令编译:
gcc test_sdf.c -lsdf -ldl -I/path/to/itrustee_sdk/include/SDF/ -o test_sdf
- 执行应用,可成功打印设备名字。
./test_sdf
父主题: 编程接口与调用