密码设备(一):应用接口规范

1 密码设备应用接口在PKI应用技术体系框架中的位置

        在公钥密码基础设施(PKI,Public Key Infrastructure)应用技术体系框架中,密码设备服务层由密码机、密码卡、智能密码终端等设备组成,通过密码设备应用接口向通用密码服务层提供基础密码服务,如下图所示。基础密码服务包括密钥生成、单一的密码运算、文件管理等的服务。

 2 数据结构

2.1 设备信息

typedef struct DeviceInfo_st {
    unsigned char IssuerName[40];      // 设备生产厂商名称
    unsigned char DeviceName[16];      // 设备型号
    unsigned char DeviceSerial[16];    // 设备编号,包含:日期(8字符)、批次号(3字符)、流水号(5字符)
    unsigned int  DeviceVersion;       // 密码设备内部软件的版本号
    unsigned int  StandardVersion;     // 密码设备支持的接口规范版本号
    unsigned int  AsymAlgAbility[2];   // 前4字节表示支持的算法,表示方法为非对称算法标识按位或的结果; 后4字节表示算法的最大模长,表示方法为支持的模长按位或的结果
    unsigned int  SymAlgAbility;       // 所有支持的对称算法,表示方法为对称算法标识按位或运算结果
    unsigned int  HashAlgAbility;      // 所有支持的杂凑算法,表示方法为杂凑算法标识按位或运算结果
    unsigned int  BufferSize;          // 支持的最大文件存储空间(单位字节)
} DEVICEINFO;

2.2 密钥分类

 2.2.1 设备密钥与用户密钥

        设备密钥只能在设备初始化时生成或安装,用户密钥通过密码设备管理工具生成或安装。

        设备密钥和用户密钥存放于密钥存储区,索引号从0开始检索,每个案引号对应一个签名密钥对和一个加密密钥对。

        其中,索引号为0表示设备密钥。索引号从1开始表示用户密。

密钥对索引号公钥私钥
0x00设备签名公钥设备签名私钥
设备加密公钥设备加密私钥
0x01用户签名公钥用户签名私钥
用户加密公钥用户加密私钥
..................
............

2.2.2  密钥加密密钥

        密钥加密密钥通过密码设备管理工具生成或安装,密钥长度为128位,存放于密钥存储区,使用索引号从1开始。

密钥索引号密钥加密密钥
0x01密钥加密密钥 001
............

2.2.3 会话密钥

        会话密钥使用设备接口函数生成或导人,会话密钥使用句柄检索。

2.3 RSA密钥数据结构

        RSA密钥结构存储时顺序为从高到低,即密钥存放时从密钥结构数组的最高位开始,最高字节填在最高位,不足位填充数据0。 

#define RSAref_MAX_BITS                        2048
#define RSAref_MAX_LEN                         ((RSAref_MAX_BITS + 7) / 8)   //256
#define RSAref_MAX_PBITS                       ((RSAref_MAX_BITS + 1) / 2)   //1024
#define RSAref_MAX_PLEN                        ((RSAref_MAX_PBITS + 7)/ 8)   //128 

// RSA 公钥数据结构
typedef struct RSArefPublicKey_st {
    unsigned int bits;
    unsigned char m[RSAref_MAX_LEN];
    unsigned char e[RSAref_MAX_LEN];
} RSArefPublicKey;

// RSA 私钥数据结构
typedef struct RSArefPrivateKey_st {
    unsigned int bits;
    unsigned char m[RSAref_MAX_LEN];
    unsigned char e[RSAref_MAX_LEN];
    unsigned char d[RSAref_MAX_LEN];
    unsigned char prime[2][RSAref_MAX_PLEN];
    unsigned char pexp[2][RSAref_MAX_PLEN];
    unsigned char coef[RSAref_MAX_PLEN];
} RSArefPrivateKey;

2.4 ECC密钥数据结构

#define ECCref_MAX_BITS                        512
#define ECCref_MAX_LEN                         ((ECCref_MAX_BITS+7) / 8)

// ECC 公钥数据结构
typedef struct ECCrefPublicKey_st {
    unsigned int bits;                 // 密钥位长
    unsigned char x[ECCref_MAX_LEN];   // 公钥 x 坐标
    unsigned char y[ECCref_MAX_LEN];   // 公钥 y 坐标
} ECCrefPublicKey;

// ECC 私钥数据结构
typedef struct ECCrefPrivateKey_st {
    unsigned int bits;                 // 密钥位长
    unsigned char  K[ECCref_MAX_LEN];  // 私钥
} ECCrefPrivateKey;

// ECC 加密数据结构
typedef struct ECCCipher_st {
    unsigned char x[ECCref_MAX_LEN];   // X 分量
    unsigned char y[ECCref_MAX_LEN];   // Y 分量
    unsigned char M[32];               // 明文的杂凑值
    unsigned int L;                    // 密文数据长度
    unsigned char C[1];                // 密文数据
} ECCCipher;

// ECC 签名数据结构
typedef struct ECCSignature_st {
    unsigned char r[ECCref_MAX_LEN];   // 签名的 r 部分
    unsigned char s[ECCref_MAX_LEN];   // 签名的 s 部分
} ECCSignature;

 2.5 ECC加密密钥对保护结构

        密钥管理系统下发到设备中的 ECC加密密钥对使用以下结构表示。

typedef struct SDF_ENVELOPEDKEYBLOB {
    unsigned long ulAsymmAlgID;              //保护对称密钥的非对称算法标识
    unsigned long ulSymmAlgID;               //对称算法标识, 必须为ECB模式
    ECCCIPHERBLOB ECCCipherBlob;             //对称密钥密文
    ECCPUBLICKEYBLOB PubKey;                 //加密密钥对的公钥
    unsigned char cbEncryptedPrivKey[64];    //加密密钥对的私钥密文
} ENVELOPEDKEYBLOB, *PENVELOPEDKEYBLOB;

        上述ECC加密密钥对保护结构中的对称密钥密文结构和加密密钥对公钥的结构为《GM/T 0016-2012 智能密码钥匙密码应用接口规范》中定义的结构,如下所示:

#define ECC_MAX_XCOORDINATE_BITS_LEN   512   // ECC算法X坐标的最大长度
#define ECC_MAX_YCOORDINATE_BITS_LEN   512   // ECC算法Y坐标的最大长度

// ECC 密文数据结构
typedef struct Struct_ECCCIPHERBLOB{
	BYTE  	XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];
	BYTE  	YCoordinate[ECC_MAX_YCOORDINATE_BITS_LEN/8];
	BYTE  	Hash[32];    // 明文的杂凑值
	ULONG	CipherLen;   // 密文的数据长度
	BYTE  	Cipher[1];   // 密文数据,实际长度为 CipherLen
}ECCCIPHERBLOB, *PECCCIPHERBLOB;

// ECC 公钥数据结构
typedef struct Struct_ECCPUBLICKEYBLOB{
	ULONG	BitLen;   // 模数的实际位长度, 必须是8的倍数
	BYTE	XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];  // 曲线上点的X坐标
	BYTE	YCoordinate[ECC_MAX_YCOORDINATE_BITS_LEN/8];  // 曲线上点的Y坐标
}ECCPUBLICKEYBLOB, *PECCPUBLICKEYBLOB;

         同时,应注意与《GM/T 0016-2012 智能密码钥匙密码应用接口规范》中定义的ECC加密密钥对保护结构(如下所示)做区分。

typedef struct SKF_ENVELOPEDKEYBLOB{
	ULONG 	Version;                  // 版本号,当前版本为1
	ULONG 	ulSymmAlgID;              // 对称算法标识,必须为ECB模式
	ULONG 	ulBits;					  // 加密密钥对的密钥位长度
	BYTE 	cbEncryptedPriKey[64];    // 加密密钥对的私钥的密文
	ECCPUBLICKEYBLOB PubKey;          // 加密密钥对的公钥
	ECCCIPHERBLOB 	ECCCipherBlob;    // 用保护公钥加密的对称密钥密文
}ENVELOPEDKEYBLOB, *PENVELOPEDKEYBLOB;

 3 设备接口

        以下接口涉及密码设备存储的密钥对索引值的起始索引值为1,最大为n,密码设备的实际存储容量决定n值。

3.1 设备管理类接口

// 打开设备
int SDF_OpenDevice(void** phDeviceHandle);

// 关闭密码设备, 并释放相关资源
int SDF_CloseDevice(void* hDeviceHandle);

// 创建与密码设备的会话
int SDF_OpenSession(void* hDeviceHandle, void** phSessionHandle);

// 关闭与密码设备已建立的会话, 并释放相关资源
int SDF_CloseSession(void* hSessionHandle);

// 获取密码设备能力描述
int SDF_GetDeviceInfo(
                 void* hSessionHandle,
                 DEVICEINFO *pstDeviceInfo);

// 获取指定长度的随机数
int SDF_GenerateRandom(
                 void* hSessionHandle,
                 unsigned int uiLength,
                 unsigned char* pucRandom);

// 获取密码设备内部存储的指定索引私钥的使用权
int SDF_GetPrivateKeyAccessRight(
                 void* hSessionHandle,
                 unsigned int uiKeyIndex,
                 unsigned char* pucPassword,
                 unsigned int uiPwdLength);

// 释放密码设备存储的指定索引私钥的使用授权
int SDF_ReleasePrivateKeyAccessRight(
                 void* hSessionHandle,
                 unsigned int uiKeyIndex);

       3.1.1 设备打开关闭接口示例

int DevManage_OpenCloseDevice()
{
    int rv, i;
    void* devHandle = NULL;

    rv = SDF_OpenDevice((HANDLE *)&devHandle);
    if(rv != SDR_OK) {
        printf("SDF_OpenDevice is error 0x%x\n", rv);
        return rv;
    }

    rv = SDF_CloseDevice(devHandle);
    if(rv != SDR_OK) {
        printf("SDF_CloseDevice is error 0x%x\n", rv);
        return rv;
    }

    return 0;
}

         3.1.2 会话打开关闭接口示例

int DevManage_OpenCloseSession()
{
    int rv,i = 0;
    void* phSessionHandle;
    void* devHandle;

    rv = SDF_OpenDevice((HANDLE *)&devHandle);
    if(rv != SDR_OK) {
        printf("SDF_OpenDevice is error 0x%x\n", rv);
        return rv;
    }

    rv = SDF_OpenSession(devHandle,(HANDLE *)&phSessionHandle);
    if(rv != SDR_OK) {
        printf("SDF_OpenSession is error 0x%x\n", rv);
        goto err;
    }

    rv = SDF_CloseSession(phSessionHandle);
    if(rv != SDR_OK) {
        printf("SDF_CloseSession is error 0x%x\n", rv);
        goto err;
    }

    rv = SDF_CloseDevice(devHandle);
    if(rv != SDR_OK) {
        printf("SDF_CloseDevice is error 0x%x\n",rv);
        return rv;
    }

    return 0;

err:
    SDF_CloseDevice(devHandle);

    return rv;
}

        3.1.3 获取设备信息接口示例

int DevManage_GetDevInfo(void* phSessionHandle)
{
    int rv;
    DEVICEINFO pstDeviceInfo;

    rv = SDF_GetDeviceInfo(phSessionHandle, &pstDeviceInfo);
    if(rv != SDR_OK) {
        printf("SDF_GetDeviceInfo is error %d\n",rv);
        return rv;
    }

    return 0;
}

        3.1.4 产生随机数接口示例

int DevManage_GenRandom(void* phSessionHandle)
{
    int rv, randLen = 1024;
    unsigned char randData[1024] = {0};

    rv = SDF_GenerateRandom(phSessionHandle, randLen, randData);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom is error 0x%x\n", rv);
        return rv;
    }

    return 0;
}

        3.1.5 获取与释放私钥使用权限接口示例

#define KEY_IDX				1
#define KEY_PIN 			"12345678"

int DevManage_CorrectPriKeyAccess(void* phSessionHandle)
{
    int rv;
    ECCSignature sign;
    char randData[32];
    int randLen = 32;

    rv = SDF_GetPrivateKeyAccessRight(phSessionHandle, KEY_IDX, KEY_PIN, 8);
    if(rv != SDR_OK) {
        printf("SDF_GetPrivateKeyAccessRight is error 0x%x\n", rv);
        return rv;
    }

    rv = SDF_GenerateRandom(phSessionHandle, randLen, randData);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom is error 0x%x\n", rv);
        goto err;
    }

    rv = SDF_InternalSign_ECC(phSessionHandle, KEY_IDX, randData, randLen, &sign);
    if(rv != SDR_OK) {
        printf("SDF_InternalSign_ECC is error 0x%x\n", rv);
        goto err;
    }

    rv = SDF_ReleasePrivateKeyAccessRight(phSessionHandle, KEY_IDX);
    if(rv != SDR_OK) {
        printf("SDF_ReleasePrivateKeyAccessRight is error 0x%x\n", rv);
        return rv;
    }

    return 0;

err:
    SDF_ReleasePrivateKeyAccessRight(phSessionHandle, KEY_IDX);
    return rv;
}

 3.2 密钥管理类接口

3.2.1 RSA密钥管理类接口

// 导出密码设备内部存储的指定索引位置的签名公钥
int SDF_ExportSignPublicKey_RSA(
                 void* hSessionHandle,
                 unsigned int uiKeyIndex,
                 RSArefPublicKey *pucPublicKey);

// 导出密码设备内部存储的指定索引位置的加密公钥
int SDF_ExportEncPublicKey_RSA(
                 void* hSessionHandle,
                 unsigned int uiKeyIndex,
                 RSArefPublicKey *pucPublicKey);

// 请求密码设备产生指定模长的RSA密钥对
int SDF_GenerateKeyPair_RSA(
                 void* hSessionHandle,
                 unsigned int uiKeyBits,
                 RSArefPublicKey *pucPublicKey,
                 RSArefPrivateKey *pucPrivateKey);

// 生成会话密钥并用指定索引的内部加密公钥加密输出, 同时返回密钥句柄
int SDF_GenerateKeyWithIPK_RSA(
                 void* hSessionHandle,
                 unsigned int uiIPKIndex,
                 unsigned int uiKeyBits,
                 unsigned char* pucKey,
                 unsigned int* puiKeyLength,
                 void** phKeyHandle);

// 生成会话密钥并用外部公钥加密输出, 同时返回密钥句柄
int SDF_GenerateKeyWithEPK_RSA(
                 void* hSessionHandle,
                 unsigned int uiKeyBits,
                 RSArefPublicKey *pucPublicKey,
                 unsigned char* pucKey,
                 unsigned int* puiKeyLength,
                 void** phKeyHandle);

// 导入会话密钥并用内部私钥解密, 同时返回密钥句柄
int SDF_ImportKeyWithISK_RSA(
                 void* hSessionHandle,
                 unsigned int uiISKIndex,
                 unsigned char* pucKey,
                 unsigned int uiKeyLength,
                 void** phKeyHandle);

// 将由内部加密公钥加密的会话密钥转换为由外部指定的公钥加密, 可用于数字信封转换
int SDF_ExchangeDigitEnvelopeBaseOnRSA(
                 void* hSessionHandle,
                 unsigned int uiKeyIndex,
                 RSArefPublicKey *pucPublicKey,
                 unsigned char* pucDEInput,
                 unsigned int uiDELength,
                 unsigned char* pucDEOutput,
                 unsigned int *puiDELength);
3.2.1.1 导出RSA公钥接口示例
#define KEY_IDX				1

int KeyManage_ExportRSAPublicKey(void* phSessionHandle)
{
    int rv;
    RSArefPublicKey pubSigKey, pubEncKey;

    rv = SDF_ExportSignPublicKey_RSA(phSessionHandle, KEY_IDX, &pubSigKey);
    if(rv != SDR_OK) {
        printf("SDF_ExportSignPublicKey_RSA error! rv = 0x%x\n", rv);
        return rv;
    }

    rv = SDF_ExportEncPublicKey_RSA(phSessionHandle, KEY_IDX, &pubEncKey);
    if(rv != SDR_OK) {
        printf("SDF_ExportEncPublicKey_RSA error! rv = 0x%x\n", rv);
        return rv;
    }

    return 0;
}
3.2.1.2 产生RSA密钥对并输出接口示例 
int KeyManage_GenRSAKeyPair(void* phSessionHandle)
{
    int rv;
    RSArefPublicKey rsapuk;
    RSArefPrivateKey rsaprk;

    memset(&rsapuk, 0x00, sizeof(RSArefPublicKey));
    memset(&rsaprk, 0x00, sizeof(RSArefPrivateKey));

    rv = SDF_GenerateKeyPair_RSA(phSessionHandle, 2048, &rsapuk, &rsaprk);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyPair_RSA  2048 error! rv = 0x%x\n", rv);
        return rv;
    }

    return 0;
}
3.2.1.3 会话密钥生成和导入接口示例1
#define KEY_IDX				1

int KeyManage_SessionKey_RSA1(void* phSessionHandle)
{
    int rv;
    void* hkey1 = NULL, hkey2 = NULL;
    char enckey[4096];
    char randData[16], cipher[128], plain[128];
    int randLen = 16, cipherLen, plainLen, enckeyLen;

    rv = SDF_GenerateKeyWithIPK_RSA(phSessionHandle, KEY_IDX, 128, enckey, &enckeyLen, &hkey1);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyWithIPK_RSA is error 0x%x\n",rv);
        return rv;
    }

    rv = SDF_ImportKeyWithISK_RSA(phSessionHandle, KEY_IDX, enckey, enckeyLen, &hkey2);
    if(rv != SDR_OK) {
        printf("SDF_ImportKeyWithISK_RSA is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_GenerateRandom(phSessionHandle, randLen, randData);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Encrypt(phSessionHandle, hkey1, SGD_SM4_ECB, NULL, randData, randLen, cipher, &cipherLen);
    if(rv != SDR_OK) {
        printf("SDF_Encrypt is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Decrypt(phSessionHandle, hkey2, SGD_SM4_ECB, NULL, cipher, cipherLen, plain, &plainLen);
    if(rv != SDR_OK) {
        printf("SDF_Decrypt is error 0x%x\n",rv);
        goto err;
    }

    if(plainLen != randLen || memcmp(plain, randData, randLen) != 0) {
        printf("Decrypt Result diff inData, Session Key Test1 failed!\n");
        goto err;
    }

    printf("会话密钥测试: 生成会话密钥并用内部RSA公钥加密输出成功!\n");
    printf("会话密钥测试: 导入会话密钥并用内部RSA私钥解密成功!\n");

    rv = SDF_DestroyKey(phSessionHandle, hkey2);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_DestroyKey(phSessionHandle, hkey1);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        return rv;
    }
    printf("会话密钥测试: 销毁会话密钥成功!\n");
    return 0;

err:
    SDF_DestroyKey(phSessionHandle, hkey2);
err1:
    SDF_DestroyKey(phSessionHandle, hkey1);

    return rv;
}
3.2.1.4 会话密钥生成和导入接口示例2
#define KEY_IDX				1

int KeyManage_SessionKey_RSA2(void* phSessionHandle)
{
    int rv;
    void* hkey1, hkey2;
    char enckey[4096], key[16];
    char randData[16], cipher[128], plain[128];
    int randLen = 16, cipherLen, plainLen, enckeyLen, keyLen = 16;
    RSArefPublicKey rsapuk;

    rv = SDF_ExportEncPublicKey_RSA(phSessionHandle, KEY_IDX, &rsapuk);
    if(rv != SDR_OK) {
        printf("SDF_ExportEncPublicKey_RSA is error 0x%x\n",rv);
        return rv;
    }

    rv = SDF_GenerateKeyWithEPK_RSA(phSessionHandle, 128, &rsapuk, enckey, &enckeyLen, &hkey1);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyWithEPK_RSA is error 0x%x\n",rv);
        return rv;
    }

    rv = SDF_ImportKeyWithISK_RSA(phSessionHandle, KEY_IDX, enckey, enckeyLen, &hkey2);
    if(rv != SDR_OK) {
        printf("SDF_ImportKeyWithISK_RSA is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_GenerateRandom(phSessionHandle, randLen, randData);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Encrypt(phSessionHandle, hkey1, SGD_SM4_ECB, NULL, randData, randLen, cipher, &cipherLen);
    if(rv != SDR_OK) {
        printf("SDF_Encrypt is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Decrypt(phSessionHandle, hkey2, SGD_SM4_ECB, NULL, cipher, cipherLen, plain, &plainLen);
    if(rv != SDR_OK) {
        printf("SDF_Decrypt is error 0x%x\n",rv);
        goto err;
    }

    if(plainLen != randLen || memcmp(plain, randData, randLen) != 0) {
        printf("Decrypt Result diff inData, Session Key Test1 failed!\n");
        goto err;
    }

    printf("会话密钥测试: 生成会话密钥并用外部RSA公钥加密输出成功!\n");
    printf("会话密钥测试: 导入会话密钥并用内部RSA私钥解密成功!\n");

    rv = SDF_DestroyKey(phSessionHandle, hkey2);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_DestroyKey(phSessionHandle, hkey1);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        return rv;
    }
    printf("会话密钥测试: 销毁会话密钥成功!\n");

    return 0;

err:
    SDF_DestroyKey(phSessionHandle, hkey2);
err1:
    SDF_DestroyKey(phSessionHandle, hkey1);

    return rv;
}
 3.2.1.5 数字信封转换接口示例
#define KEY_IDX				1
#define KEY_IDX_2			2

int KeyManage_ExchangeDigitEnvelopeBaseRSA(void* phSessionHandle)
{
    int rv;
    void* hkey1 = NULL, hkey2 = NULL;
    char encKey[4096], outEncKey[4096];
    RSArefPublicKey rsapuk;
    char randData[16], cipher[128], plain[128];
    int randLen = 16, cipherLen, plainLen, enckeyLen, outEncLen;

    rv = SDF_GenerateKeyWithIPK_RSA(phSessionHandle, KEY_IDX, 128, encKey, &enckeyLen, &hkey1);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyWithIPK_RSA is error 0x%x\n", rv);
        return rv;
    }

    rv = SDF_ExportEncPublicKey_RSA(phSessionHandle, KEY_IDX_2, &rsapuk);
    if(rv != SDR_OK) {
        printf("SDF_ExportEncPublicKey_RSA is error 0x%x\n", rv);
        goto err1;
    }

    rv = SDF_ExchangeDigitEnvelopeBaseOnRSA(phSessionHandle, KEY_IDX, &rsapuk, encKey, enckeyLen, outEncKey, &outEncLen);
    if(rv != SDR_OK) {
        printf("SDF_ExchangeDigitEnvelopeBaseOnRSA is error 0x%x\n", rv);
        goto err1;
    }

    rv = SDF_ImportKeyWithISK_RSA(phSessionHandle, KEY_IDX_2, outEncKey, outEncLen, &hkey2);
    if(rv != SDR_OK) {
        printf("SDF_ImportKeyWithISK_ECC is error 0x%x\n", rv);
        goto err1;
    }

    rv = SDF_GenerateRandom(phSessionHandle, randLen, randData);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Encrypt(phSessionHandle, hkey1, SGD_SM4_ECB, NULL, randData, randLen, cipher, &cipherLen);
    if(rv != SDR_OK) {
        printf("SDF_Encrypt is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Decrypt(phSessionHandle, hkey2, SGD_SM4_ECB, NULL, cipher, cipherLen, plain, &plainLen);
    if(rv != SDR_OK) {
        printf("SDF_Decrypt is error 0x%x\n",rv);
        goto err;
    }

    if(plainLen != randLen || memcmp(plain, randData, randLen) != 0) {
        printf("Decrypt Result diff inData, Session Key Test1 failed!\n");
        rv = -1;
        goto err;
    }

    printf("RSA数字信封转换成功!\n");

    rv = SDF_DestroyKey(phSessionHandle, hkey2);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_DestroyKey(phSessionHandle, hkey1);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        return rv;
    }

    return 0;

err:
    SDF_DestroyKey(phSessionHandle, hkey2);
err1:
    SDF_DestroyKey(phSessionHandle, hkey1);

    return rv;
}

3.2.2 ECC密钥管理类接口

// 导出密码设备内部存储的指定索引位置的签名公钥
int SDF_ExportSignPublicKey_ECC(
                 void* hSessionHandle,
                 unsigned int uiKeyIndex,
                 ECCrefPublicKey *pucPublicKey);

// 导出密码设备内部存储的指定索引位置的加密公钥
int SDF_ExportEncPublicKey_ECC(
                 void* hSessionHandle,
                 unsigned int uiKeyId,
                 ECCrefPublicKey *pucPublicKey);

// 请求密码设备产生指定类型和模长的ECC密钥对
int SDF_GenerateKeyPair_ECC(
                 void* hSessionHandle,
                 unsigned int uiAlgID,
                 unsigned int uiKeyBits,
                 ECCrefPublicKey *pucPublicKey,
                 ECCrefPrivateKey *pucPrivateKey);

// 生成会话密钥并用指定索引的内部ECC加密公钥加密输出, 同时返回密钥句柄
int SDF_GenerateKeyWithIPK_ECC(
                 void* hSessionHandle,
                 unsigned int uiIPKIndex,
                 unsigned int uiKeyBits,
                 ECCCipher *pucKey,
                 void** phKeyHandle);

// 生成会话密钥并用外部ECC公钥加密输出, 同时返回密钥句柄
int SDF_GenerateKeyWithEPK_ECC(
                 void* hSessionHandle,
                 unsigned int uiKeyBits,
                 unsigned int uiAlgID,
                 ECCrefPublicKey *pucPublicKey,
                 ECCCipher *pucKey,
                 void** phKeyHandle);

// 导入会话密钥并用内部ECC加密私钥解密, 同时返回密钥句柄
int SDF_ImportKeyWithISK_ECC(
                 void* hSessionHandle,
                 unsigned int uiISKIndex,
                 ECCCipher *pucKey,
                 void** phKeyHandle);

// 生成密钥协商参数并输出
int SDF_GenerateAgreementDataWithECC(
                 void* hSessionHandle,
                 unsigned int uiISKIndex,
                 unsigned int uiKeyBits,
                 unsigned char* pucSponsorID,
                 unsigned int uiSponsorIDLength,
                 ECCrefPublicKey *pucSponsorPublicKey,
                 ECCrefPublicKey *pucSponsorTmpPublicKey,
                 void** phAgreementHandle);

// 计算会话密钥
int SDF_GenerateKeyWithECC(
                 void* hSessionHandle,
                 unsigned char* pucResponseID,
                 unsigned int uiResponseIDLength,
                 ECCrefPublicKey *pucResponsePublicKey,
                 ECCrefPublicKey *pucResponseTmpPublicKey,
                 void* phAgreementHandle,
                 void** phKeyHandle);

// 产生协商参数并计算会话密钥
int SDF_GenerateAgreementDataAndKeyWithECC(
                 void* hSessionHandle,
                 unsigned int uiISKIndex,
                 unsigned int uiKeyBits,
                 unsigned char* pucResponseID,
                 unsigned int uiResponseIDLength,
                 unsigned char* pucSponsorID,
                 unsigned int uiSponsorIDLength,
                 ECCrefPublicKey *pucSponsorPublicKey,
                 ECCrefPublicKey *pucSponsorTmpPublicKey,
                 ECCrefPublicKey *pucResponsePublicKey,
                 ECCrefPublicKey *pucResponseTmpPublicKey,
                 void** phKeyHandle);

// 将由内部加密公钥加密的会话密钥转换为由外部指定的公钥加密, 可用于数字信封转换
int SDF_ExchangeDigitEnvelopeBaseOnECC(
                 void* hSessionHandle,
                 unsigned int uiKeyIndex,
                 unsigned int uiAlgID,
                 ECCrefPublicKey *pucPublicKey,
                 ECCCipher *pucEncDataIn,
                 ECCCipher *pucEncDataOut);
3.2.2.1 导出ECC公钥接口示例
#define KEY_IDX				1

int KeyManage_ExportSM2PublicKey(void* phSessionHandle)
{
    int rv;
    ECCrefPublicKey pubSigKey, pubEncKey;

    rv = SDF_ExportSignPublicKey_ECC(phSessionHandle, KEY_IDX, &pubSigKey);
    if(rv != SDR_OK) {
        printf("SDF_ExportSignPublicKey_ECC error! rv = 0x%x\n", rv);
        return rv;
    }

    rv = SDF_ExportEncPublicKey_ECC(phSessionHandle, KEY_IDX, &pubEncKey);
    if(rv != SDR_OK) {
        printf("SDF_ExportEncPublicKey_ECC error! rv = 0x%x\n", rv);
        return rv;
    }

    return 0;
}
3.2.2.2  产生ECC密钥对并输出接口示例
int KeyManage_GenSM2KeyPair(void* phSessionHandle)
{
    int rv;
    ECCrefPublicKey eccpuk;
    ECCrefPrivateKey eccprk;

    rv = SDF_GenerateKeyPair_ECC(phSessionHandle, SGD_SM2, 256, &eccpuk, &eccprk);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyPair_ECC error! rv = 0x%x\n", rv);
        return rv;
    }

    return 0;
}
3.2.2.3 会话密钥生成和导入接口示例1
#define KEY_IDX				1

int KeyManage_SessionKey1(void* phSessionHandle)
{
    int rv;
    void* hkey1 = NULL, hkey2 = NULL;
    ECCCipher encKey;
    char randData[16], cipher[128], plain[128];
    int randLen = 16, cipherLen, plainLen;

    rv = SDF_GenerateKeyWithIPK_ECC(phSessionHandle, KEY_IDX, 128, &encKey, &hkey1);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyWithIPK_ECC is error 0x%x\n",rv);
        return rv;
    }

    rv = SDF_ImportKeyWithISK_ECC(phSessionHandle, KEY_IDX, &encKey, &hkey2);
    if(rv != SDR_OK) {
        printf("SDF_ImportKeyWithISK_ECC is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_GenerateRandom(phSessionHandle, randLen, randData);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Encrypt(phSessionHandle, hkey1, SGD_SM4_ECB, NULL, randData, randLen, cipher, &cipherLen);
    if(rv != SDR_OK) {
        printf("SDF_Encrypt is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Decrypt(phSessionHandle, hkey2, SGD_SM4_ECB, NULL, cipher, cipherLen, plain, &plainLen);
    if(rv != SDR_OK) {
        printf("SDF_Decrypt is error 0x%x\n",rv);
        goto err;
    }

    if(plainLen != randLen || memcmp(plain, randData, randLen) != 0) {
        printf("Decrypt Result diff inData, Session Key Test1 failed!\n");
        rv = -1;
        goto err;
    }

    printf("会话密钥测试1: 生成会话密钥并用内部ECC公钥加密输出成功!\n");
    printf("会话密钥测试1: 导入会话密钥并用内部ECC私钥解密成功!\n");

    rv = SDF_DestroyKey(phSessionHandle, hkey2);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_DestroyKey(phSessionHandle, hkey1);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        return rv;
    }

    printf("会话密钥测试1: 销毁会话密钥成功!\n");
    return 0;

err:
    SDF_DestroyKey(phSessionHandle, hkey2);
err1:
    SDF_DestroyKey(phSessionHandle, hkey1);

    return rv;
}
 3.2.2.4 会话密钥生成和导入接口示例2
#define KEY_IDX				1

int KeyManage_SessionKey2(void* phSessionHandle)
{
    int rv;
    void* hkey1 = NULL, hkey2 = NULL;
    ECCCipher encKey;
    ECCrefPublicKey encpuk;
    char randData[16], cipher[128], plain[128];
    int randLen = 16, cipherLen, plainLen;

    rv = SDF_ExportEncPublicKey_ECC(phSessionHandle, KEY_IDX, &encpuk);
    if(rv != SDR_OK) {
        printf("SDF_ExportEncPublicKey_ECC error! rv = 0x%x\n", rv);
        return rv;
    }

    rv = SDF_GenerateKeyWithEPK_ECC(phSessionHandle, 128, SGD_SM2_3, &encpuk, &encKey, &hkey1);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyWithEPK_ECC is error 0x%x\n",rv);
        return rv;
    }

    rv = SDF_ImportKeyWithISK_ECC(phSessionHandle, KEY_IDX, &encKey, &hkey2);
    if(rv != SDR_OK) {
        printf("SDF_ImportKeyWithISK_ECC is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_GenerateRandom(phSessionHandle, randLen, randData);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Encrypt(phSessionHandle, hkey1, SGD_SM4_ECB, NULL, randData, randLen, cipher, &cipherLen);
    if(rv != SDR_OK) {
        printf("SDF_Encrypt is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Decrypt(phSessionHandle, hkey2, SGD_SM4_ECB, NULL, cipher, cipherLen, plain, &plainLen);
    if(rv != SDR_OK) {
        printf("SDF_Decrypt is error 0x%x\n",rv);
        goto err;
    }

    if(plainLen != randLen || memcmp(plain, randData, randLen) != 0) {
        printf("Decrypt Result diff inData, Session Key Test1 failed!\n");
        rv = -1;
        goto err;
    }

    printf("会话密钥测试2: 生成会话密钥并用外部ECC公钥加密输出成功!\n");
    printf("会话密钥测试2: 导入会话密钥并用内部ECC私钥解密成功!\n");

    rv = SDF_DestroyKey(phSessionHandle, hkey2);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_DestroyKey(phSessionHandle, hkey1);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        return rv;
    }
    printf("会话密钥测试2: 销毁会话密钥成功!\n");

    return 0;

err:
    SDF_DestroyKey(phSessionHandle, hkey2);
err1:
    SDF_DestroyKey(phSessionHandle, hkey1);

    return rv;
}
3.2.2.5  协商会话密钥接口示例
#define KEY_IDX				1
#define KEY_IDX_2			2

int KeyManage_Agreement(void* phSessionHandle)
{
    int 				rv;
    ECCrefPublicKey 	Selfpuk,Selfpuktmp,Otherpuk,Otherpuktemp;
    void				*hkey1=NULL,*hkey2=NULL,*AgreementHandle;
    unsigned char		inbuf[128],outbuf[256],temp[256];
    unsigned int		inlen = 16,outlen,templen=128;

    memset(&Selfpuk, 0x00, sizeof(ECCrefPublicKey));
    memset(&Selfpuktmp, 0x00, sizeof(ECCrefPublicKey));
    memset(&Otherpuk, 0x00, sizeof(ECCrefPublicKey));
    memset(&Otherpuktemp, 0x00, sizeof(ECCrefPublicKey));

    rv = SDF_GenerateAgreementDataWithECC(phSessionHandle,KEY_IDX,128,(u8 *)"0123456789",10,&Otherpuk,&Otherpuktemp,&AgreementHandle);
    if(rv != SDR_OK) {
        printf("SDF_GenerateAgreementDataWithECC is error 0x%x\n",rv);
        return rv;
    }

    rv = SDF_GenerateAgreementDataAndKeyWithECC(phSessionHandle,KEY_IDX_2,128,(u8 *)"0123456789",10,(u8 *)"0123456789",10,&Otherpuk,&Otherpuktemp,&Selfpuk,&Selfpuktmp,&hkey1);
    if(rv != SDR_OK) {
        printf("SDF_GenerateAgreementDataAndKeyWithECC is error 0x%x\n",rv);
        return rv;
    }

    rv = SDF_GenerateKeyWithECC(phSessionHandle,(u8 *)"0123456789",10,&Selfpuk,&Selfpuktmp,AgreementHandle,&hkey2);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyWithECC is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_GenerateRandom(phSessionHandle, inlen, inbuf);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Encrypt(phSessionHandle,hkey1,SGD_SM4_ECB,NULL,inbuf,inlen,outbuf, &outlen);
    if(rv != SDR_OK) {
        printf("SDF_Encrypt hkey1 is error 0x%x\n",rv);
        goto err;
    }
    rv = SDF_Decrypt(phSessionHandle,hkey2,SGD_SM4_ECB,NULL,outbuf,outlen,temp, &templen);
    if(rv != SDR_OK) {
        printf("SDF_Encrypt hkey2 is error 0x%x\n",rv);
        goto err;
    }

    if((templen != inlen) || (memcmp(inbuf,temp,inlen) != 0)) {
        printf("SM2 agreement test is ERRPR\n");
        rv = -1;
        goto err;
    }

    rv = SDF_DestroyKey(phSessionHandle, hkey2);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey hkey1 is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_DestroyKey(phSessionHandle, hkey1);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey hkey2 is error 0x%x\n",rv);
        return rv;
    }

    printf("SM2密钥协商成功!\n");

    return 0;

err:
    SDF_DestroyKey(phSessionHandle, hkey2);
err1:
    SDF_DestroyKey(phSessionHandle, hkey1);

    return rv;
}
3.2.2.6 数字信封转换接口示例
#define KEY_IDX				1
#define KEY_IDX_2			2

int KeyManage_ExchangeDigitEnvelopeBaseECC(void* phSessionHandle)
{
    int rv;
    void* hkey1 = NULL, hkey2 = NULL;
    ECCCipher encKey, outEncKey;
    ECCrefPublicKey encpuk;
    char randData[16], cipher[128], plain[128];
    int randLen = 16, cipherLen, plainLen;

    rv = SDF_GenerateKeyWithIPK_ECC(phSessionHandle, KEY_IDX, 128, &encKey, &hkey1);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyWithIPK_ECC is error 0x%x\n", rv);
        return rv;
    }

    rv = SDF_ExportEncPublicKey_ECC(phSessionHandle, KEY_IDX_2, &encpuk);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyWithIPK_ECC is error 0x%x\n", rv);
        goto err1;
    }

    rv = SDF_ExchangeDigitEnvelopeBaseOnECC(phSessionHandle, KEY_IDX, SGD_SM2_3, &encpuk, &encKey, &outEncKey);
    if(rv != SDR_OK) {
        printf("SDF_ExchangeDigitEnvelopeBaseOnECC is error 0x%x\n", rv);
        goto err1;
    }

    rv = SDF_ImportKeyWithISK_ECC(phSessionHandle, KEY_IDX_2, &outEncKey, &hkey2);
    if(rv != SDR_OK) {
        printf("SDF_ImportKeyWithISK_ECC is error 0x%x\n", rv);
        goto err1;
    }

    rv = SDF_GenerateRandom(phSessionHandle, randLen, randData);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Encrypt(phSessionHandle, hkey1, SGD_SM4_ECB, NULL, randData, randLen, cipher, &cipherLen);
    if(rv != SDR_OK) {
        printf("SDF_Encrypt is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Decrypt(phSessionHandle, hkey2, SGD_SM4_ECB, NULL, cipher, cipherLen, plain, &plainLen);
    if(rv != SDR_OK) {
        printf("SDF_Decrypt is error 0x%x\n",rv);
        goto err;
    }

    if(plainLen != randLen || memcmp(plain, randData, randLen) != 0) {
        printf("Decrypt Result diff inData, Session Key Test1 failed!\n");
        rv = -1;
        goto err;
    }

    printf("SM2数字信封转换成功!\n");

    rv = SDF_DestroyKey(phSessionHandle, hkey2);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_DestroyKey(phSessionHandle, hkey1);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        return rv;
    }

    return 0;

err:
    SDF_DestroyKey(phSessionHandle, hkey2);
err1:
    SDF_DestroyKey(phSessionHandle, hkey1);

    return rv;
}

 3.2.3 KEK密钥管理类接口

// 生成会话密钥并用密钥加密密钥加密输出, 同时返回密钥句柄
int SDF_GenerateKeyWithKEK(
                 void* hSessionHandle,
                 unsigned int uiKeyBits,
                 unsigned int uiAlgID,
                 unsigned int uiKEKIndex,
                 unsigned char* pucKey,
                 unsigned int* puiKeyLength,
                 void** phKeyHandle);

// 导入会话密钥并用密钥加密密钥解密, 同时返回会话密钥句柄
int SDF_ImportKeyWithKEK(
                 void* hSessionHandle,
                 unsigned int uiAlgID,
                 unsigned int uiKEKIndex,
                 unsigned char* pucKey,
                 unsigned int uiKeyLength,
                 void** phKeyHandle);

// 销毁会话密钥, 并释放为密钥句柄分配的内存等资源
int SDF_DestroyKey(
                 void* hSessionHandle,
                 void* hKeyHandle);

         会话密钥生成和导入接口示例

#define KEY_IDX				1

int KeyManage_SessionKey_KEK(void* phSessionHandle)
{
    int rv;
    void* hkey1 = NULL, hkey2 = NULL;
    char enckey[128];
    char randData[16], cipher[128], plain[128];
    int randLen = 16, cipherLen, plainLen, enckeyLen;

    rv = SDF_GenerateKeyWithKEK(phSessionHandle, 128, SGD_SM4_ECB, KEY_IDX, &enckey, &enckeyLen, &hkey1);
    if(rv != SDR_OK) {
        printf("SDF_GenerateKeyWithKEKis error 0x%x\n",rv);
        return rv;
    }

    rv = SDF_ImportKeyWithKEK(phSessionHandle, SGD_SM4_ECB, KEY_IDX, &enckey, enckeyLen, &hkey2);
    if(rv != SDR_OK) {
        printf("SDF_ImportKeyWithKEK is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_GenerateRandom(phSessionHandle, randLen, randData);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Encrypt(phSessionHandle, hkey1, SGD_SM4_ECB, NULL, randData, randLen, cipher, &cipherLen);
    if(rv != SDR_OK) {
        printf("SDF_Encrypt is error 0x%x\n",rv);
        goto err;
    }

    rv = SDF_Decrypt(phSessionHandle, hkey2, SGD_SM4_ECB, NULL, cipher, cipherLen, plain, &plainLen);
    if(rv != SDR_OK) {
        printf("SDF_Decrypt is error 0x%x\n",rv);
        goto err;
    }

    if(plainLen != randLen || memcmp(plain, randData, randLen) != 0) {
        printf("Decrypt Result diff inData, Session Key Test1 failed!\n");
        rv = -1;
        goto err;
    }

    printf("会话密钥测试: 生成会话密钥并用密钥加密密钥加密输出成功!\n");
    printf("会话密钥测试: 导入会话密钥并用密钥加密密钥解密成功!\n");

    rv = SDF_DestroyKey(phSessionHandle, hkey2);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        goto err1;
    }

    rv = SDF_DestroyKey(phSessionHandle, hkey1);
    if(rv != SDR_OK) {
        printf("SDF_DestroyKey is error 0x%x\n",rv);
        return rv;
    }
    printf("会话密钥测试: 销毁会话密钥成功!\n");

    return 0;

err:
    SDF_DestroyKey(phSessionHandle, hkey2);
err1:
    SDF_DestroyKey(phSessionHandle, hkey1);

    return rv;
}

 3.3 非对称算法运算类接口

3.3.1 RSA算法运算类接口

// 指定使用外部公钥对数据进行运算
int SDF_ExternalPublicKeyOperation_RSA(
                 void* hSessionHandle,
                 RSArefPublicKey *pucPublicKey,
                 unsigned char* pucDataInput,
                 unsigned int uiInputLength,
                 unsigned char* pucDataOutput,
                 unsigned int *puiOutputLength);

// 使用内部指定索引的公钥对数据进行运算
int SDF_InternalPublicKeyOperation_RSA(
                 void* hSessionHandle,
                 unsigned int uiKeyIndex,
                 unsigned char* pucDataInput,
                 unsigned int uiInputLength,
                 unsigned char* pucDataOutput,
                 unsigned int *puiOutputLength);

// 使用内部指定索引的私钥对数据进行运算
int SDF_InternalPrivateKeyOperation_RSA(
                 void* hSessionHandle,
                 unsigned int uiKeyIndex,
                 unsigned char* pucDataInput,
                 unsigned int uiInputLength,
                 unsigned char* pucDataOutput,
                 unsigned int *puiOutputLength);
3.3.1.1  内部RSA签名验签示例
#define KEY_IDX				1

int AsymOperation_RSA_InternalSignVerify(void* phSessionHandle)
{
    int rv;
    int deInLen, deOutLen, deTmpLen;
    char deIn[4096];
    char deOut[4096];
    char deTmp[4096];

    deInLen = 256;

    rv = SDF_GenerateRandom(phSessionHandle, deInLen, deIn);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom error! rv = 0x%x\n", rv);
        return rv;
    }

    deIn[0] = 0;

    rv = SDF_InternalPrivateKeyOperation_RSA(phSessionHandle, KEY_IDX, deIn, deInLen, deTmp, &deTmpLen);
    if(rv != SDR_OK) {
        printf("SDF_InternalPrivateKeyOperation_RSA error! rv = 0x%x\n", rv);
        return rv;
    }

    rv = SDF_InternalPublicKeyOperation_RSA(phSessionHandle, KEY_IDX, deTmp, deTmpLen, deOut, &deOutLen);
    if(rv != SDR_OK) {
        printf("SDF_InternalPublicKeyOperation_RSA error! rv = 0x%x\n", rv);
        return rv;
    }

    if(deInLen != deOutLen || memcmp(deIn, deOut, deInLen) != 0) {
        return rv;
    }

    printf("内部密钥RSA签名验签成功!\n");

    return 0;
}
3.3.1.2 内部RSA加密解密示例 
#define KEY_IDX				1

int AsymOperation_RSA_InternalEncDecData(void* phSessionHandle)
{
    int rv;
    int deInLen, deOutLen, deTmpLen;
    char deIn[4096];
    char deOut[4096];
    char deTmp[4096];

    deInLen = 256;

    rv = SDF_GenerateRandom(phSessionHandle, deInLen, deIn);
    if(rv != SDR_OK) {
        printf("SDF_GenerateRandom error! rv = 0x%x\n", rv);
        return rv;
    }
    deIn[0] = 0;

    rv = SDF_InternalPublicKeyOperation_RSA(phSessionHandle, KEY_IDX, deIn, deInLen, deTmp, &deTmpLen);
    if(rv != SDR_OK) {
        printf("SDF_InternalPublicKeyOperation_RSA error! rv = 0x%x\n", rv);
        return rv;
    }

    rv = SDF_InternalPrivateKeyOperation_RSA(phSessionHandle, KEY_IDX, deTmp, deTmpLen, deOut, &deOutLen);
    if(rv != SDR_OK) {
        printf("SDF_InternalPrivateKeyOperation_RSA error! rv = 0x%x\n", rv);
        return rv;
    }

    if(deInLen != deOutLen || memcmp(deIn, deOut, deInLen) != 0) {
        return rv;
    }

    printf("内部密钥RSA加密解密成功!\n");

    return 0;
}

3.3.2 ECC算法运算类接口

// 使用外部ECC公钥对ECC签名值进行验证运算
int SDF_ExternalVerify_ECC(
                 void* hSessionHandle,
                 unsigned int uiAlgID,
                 ECCrefPublicKey *pucPublicKey,
                 unsigned char* pucDataInput,
                 unsigned int uiInputLength,
                 ECCSignature *pucSignature);

// 使用内部ECC私钥对数据进行签名运算
int SDF_InternalSign_ECC(
                 void* hSessionHandle,
                 unsigned int uiISKIndex,
                 unsigned char* pucData,
                 unsigned int uiDataLength,
                 ECCSignature *pucSignature);

// 使用内部ECC公钥对ECC签名值进行验证运算
int SDF_InternalVerify_ECC(
                 void* hSessionHandle,
                 unsigned int uiISKIndex,
                 unsigned char* pucData,
                 unsigned int uiDataLength,
                 ECCSignature *pucSignature);

// 使用外部ECC公钥对数据进行加密运算
int SDF_ExternalEncrypt_ECC(
                 void* hSessionHandle,
                 unsigned int uiAlgID,
                 ECCrefPublicKey *pucPublicKey,
                 unsigned char* pucData,
                 unsigned int uiDataLength,
                 ECCCipher *pucEncData);

         内部ECC签名验签接口示例

#define KEY_IDX				1

int AsymOperation_ECC_InternalSignVerify(void* phSessionHandle)
{
    int 				rv,j;
    unsigned char		inbuf[64];
    unsigned int		inlen;
    ECCSignature		signstruct;
    ECCrefPublicKey 	eccpub;

    inlen = 32;
    memset(&signstruct,0,sizeof(signstruct));

    rv = SDF_GenerateRandom(phSessionHandle, inlen, inbuf);
    if(rv != 0) {
        printf("SDF_GenerateRandom error! rv = 0x%x\n", rv);
        return rv;
    }

    rv = SDF_InternalSign_ECC(phSessionHandle,KEY_IDX,inbuf,inlen,&signstruct);
    if(rv != SDR_OK) {
        printf("SDF_InternalSign_ECC is error 0x%x\n",rv);
        return rv;
    }

    rv = SDF_InternalVerify_ECC(phSessionHandle, KEY_IDX, inbuf, inlen, &signstruct);
    if(rv != SDR_OK) {
        printf("SDF_InternalVerify_ECC is error 0x%x\n",rv);
        return rv;
    }

    printf("内部密钥ECC签名验签成功!\n");

    return 0;
}

3.4 对称算法运算类接口

// 使用指定的密钥句柄和IV对数据进行对称加密运算
int SDF_Encrypt(
                 void* hSessionHandle,
                 void* hKeyHandle,
                 unsigned int uiAlgID,
                 unsigned char* pucIV,
                 unsigned char* pucData,
                 unsigned int uiDataLength,
                 unsigned char* pucEncData,
                 unsigned int *puiEncDataLength);

// 使用指定的密钥句柄和IV对数据进行对称解密运算
int SDF_Decrypt(
                 void* hSessionHandle,
                 void* hKeyHandle,
                 unsigned int uiAlgID,
                 unsigned char* pucIV,
                 unsigned char* pucEncData,
                 unsigned int uiEncDataLength,
                 unsigned char* pucData,
                 unsigned int *puiDataLength);

// 使用指定的密钥句柄和IV对数据进行MAC运算
int SDF_CalculateMAC(
                 void* hSessionHandle,
                 void* hKeyHandle,
                 unsigned int uiAlgID,
                 unsigned char* pucIV,
                 unsigned char* pucData,
                 unsigned int uiDataLength,
                 unsigned char* pucMAC,
                 unsigned int *puiMACLength);

3.5  杂凑运算类接口

// 三步式数据杂凑运算第一步
int SDF_HashInit(
                 void* hSessionHandle,
                 unsigned int uiAlgID,
                 ECCrefPublicKey *pucPublicKey,
                 unsigned char* pucID,
                 unsigned int uiIDLength);

// 三步式数据杂凑运算第二步,对输入的明文进行杂凑运算
int SDF_HashUpdate(
                 void* hSessionHandle,
                 unsigned char* pucData,
                 unsigned int uiDataLength);

// 三步式数据杂凑运算第三步,杂凑运算结束返回杂凑数据并清除中间数据
int SDF_HashFinal(
                 void* hSessionHandle,
                 unsigned char* pucHash,
                 unsigned int *puiHashLength);

        杂凑运算接口示例

int HashOperation_SM3_Public(void* phSessionHandle)
{
    int rv, inlen = 128, hashLen;
    char hash[32], in[128];
    char px[] = "\x11\x46\xA3\xF4\x7D\x6E\xCE\xF9\x0B\xDA\xF0\x7B\x57\xEC\x8F\x5D\x54\xBE\xE6\x88\x34\x1E\x0A\xBD\x66\x40\x5C\x67\x75\x57\xD0\x1E";
    char py[] = "\x3B\x2F\x33\x85\xE2\xDC\x6F\xDB\x5A\xA6\x05\x94\x61\xAA\x58\x0D\x2D\x2A\xA7\x23\x40\x18\xF1\xA0\x1A\xE4\x38\xE2\x8E\xE8\x1C\xF5";
    char id[] = "1234567812345678";
    ECCrefPublicKey eccpub;

    eccpub.bits = 256;
    memcpy(eccpub.x+32, px, 32);
    memcpy(eccpub.y+32, py, 32);

    rv = SDF_GenerateRandom(phSessionHandle, inlen, in);
    if(rv != 0) {
        printf("SDF_GenerateRandom error! rv = 0x%x\n", rv);
        return rv;
    }

    rv = SDF_HashInit(phSessionHandle, SGD_SM3, &eccpub, id, 16);
    if (rv != 0) {
        printf("SDF_HashInit error!\n");
        return rv;
    }

    rv = SDF_HashUpdate(phSessionHandle, (u8 *)in, (u32)inlen);
    if (rv != 0) {
        printf("SDF_HashUpdate error!\n");
        return rv;
    }

    rv = SDF_HashFinal(phSessionHandle, (u8 *)hash, (u32*)&hashLen);
    if (rv != 0) {
        printf("SDF_HashFinal error!\n");
        return rv;
    }

    printf("SM3运算(带公钥和ID)成功!\n");

    return 0;
}

int HashOperation_SM3_NoPublic(void* phSessionHandle)
{
    int rv, inlen = 128, hashLen;
    char hash[32], in[128] = {0};

    rv = SDF_HashInit(phSessionHandle, SGD_SM3, NULL, NULL, 0);
    if (rv != 0) {
        printf("SDF_HashInit error!\n");
        return rv;
    }

    rv = SDF_HashUpdate(phSessionHandle, (u8 *)in, (u32)inlen);
    if (rv != 0) {
        printf("SDF_HashUpdate error!\n");
        return rv;
    }

    rv = SDF_HashFinal(phSessionHandle, (u8 *)hash, (u32*)&hashLen);
    if (rv != 0) {
        printf("SDF_HashFinal error!\n");
        return rv;
    }

    printf("SM3运算(不带公钥和ID)成功!\n");

    return 0;
}

3.6 用户文件操作类接口

// 在密码设备内部创建用于存储用户数据的文件
int SDF_CreateFile(
                 void* hSessionHandle,
                 unsigned char* pucFileName,
                 unsigned int uiNameLen,
                 unsigned int uiFileSize);

// 读取在密码设备内部存储用户数据的文件的内容
int SDF_ReadFile(
                 void* hSessionHandle,
                 unsigned char* pucFileName,
                 unsigned int uiNameLen,
                 unsigned int uiOffset,
                 unsigned int *puiFileLength,
                 unsigned char* pucBuffer);

// 向密码设备内部存储用户数据的文件中写入内容
int SDF_WriteFile(
                 void* hSessionHandle,
                 unsigned char* pucFileName,
                 unsigned int uiNameLen,
                 unsigned int uiOffset,
                 unsigned int uiFileLength,
                 unsigned char* pucBuffer);

// 删除指定文件名的密码设备内部存储用户数据的文件
int SDF_DeleteFile(
                 void* hSessionHandle,
                 unsigned char* pucFileName,
                 unsigned int uiNameLen);

4 设备状态要求

  1. 密码设备应具有 初始就绪 两个状态;
  2. 未安装设备密钥的密码设备应处于初始状态,已安装设备密钥的密码设备应处于就绪状态;
  3. 在初始状态下,除可读取设备信息、设备密钥的生成或恢复操作外,不能执行任何操作,生成或恢复设备密钥后,密码设备处于就绪状态;
  4. 在就绪状态下,除设备密钥的生成或恢复操作外,应能执行任何操作;
  5. 在就绪状态下进行的密钥操作,设备操作员应经过密码设备的认证。
  • 23
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
GMT 0018-2012密码设备应用接口规范是由国家密码管理局制定的密码设备应用接口标准。该规范的目的是为了确保密码设备与各种应用系统之间的安全通信和交互。这个规范提供了一套统一的接口标准,使得不同厂家生产的密码设备可以与各种应用系统进行兼容和互操作。 GMT 0018-2012规范主要包括以下几个方面的内容: 1. 接口定义和功能:规范密码设备应用系统之间的接口定义,包括协议、数据格式、指令和响应等。同时规范密码设备的各种功能,如密码输入、验证、生成等。 2. 安全保护:规范密码设备应用系统之间的数据传输和存储的安全保护措施,包括加密、签名、认证等技术。确保传输的数据不被篡改,存储的数据不被盗取。 3. 设备管理:规范密码设备的管理方法,包括设备初始化、密钥管理、权限管理等。同时规范密码设备的日志记录和审计功能,方便对设备的使用进行监控和追溯。 4. 设备适配性:规范密码设备的硬件和软件要求,保证密码设备能够在不同的环境和平台上正常运行。同时还规定了设备接口类型和连接方式,方便设备的集成和使用。 GMT 0018-2012密码设备应用接口规范的制定和推广,有助于提高密码设备的安全性、互操作性和普及度。使得密码设备能够更好地服务于各种应用系统,保护用户的信息安全。同时也为密码设备厂商和应用系统开发者提供了一套统一的标准,方便互联互通和合作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值