将 C_Sign 调用与 C_Generate 分开

Separate C_Sign call from C_Generate

我正在用 C 代码实现 pkcs11,并尝试实现一个简单的生成、签名、验证工作流程。当我为所有内容调用我的 pkcs11 驱动程序时,该流程有效。但是,我正在尝试分离这些调用,以便我可以生成一个密钥,在稍后阶段将其用于单独的 c_sign 或 c_verify 调用。

我的主要问题是 c_sign 调用需要私钥句柄的 CK_OBJECT_HANDLE 参数,但我不知道稍后如何检索它。它在单个 "generate -> sign -> verify" 流上工作的原因是句柄仍然在生成调用的内存中,使其在后续调用中很容易访问。

我的生成调用如下所示:

C_GenerateKeyPair(hSession, &mechanism, 
                  publicKeyTemplate, 
                  sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE), 
                  privateKeyTemplate, 
                  sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE), 
                  phPublicKey, phPrivateKey);

其中 phPublicKeyphPrivateKey 是存储句柄的位置...

随后的签名函数需要一个 hPrivateKey 参数,用于我要签名的 privKey。

一个句柄绑定到一个会话。在新会话中,句柄不再有效。要维护对键的引用,您需要给它一些唯一的名称。有两种方法可以做到这一点:

  • 任何 object in storage 都可以有一个 CKA_LABEL 属性,其值为可打印字符串。
  • 任何 key object 都可以有一个 CKA_ID 属性,其值为字节数组。

为您的密钥指定唯一 ID 或标签。稍后要打开它,您需要搜索它。这是唯一的方法:PKCS#11 没有办法通过名称直接打开密钥!您需要搜索具有正确 id/label 的对象,如果该属性是唯一的,您就知道找到的第一个就是正确的。 public 密钥和匹配密钥对中的私钥相同 id/label 是可以的(而且确实更方便);在搜索时通过 class 属性指定您想要的。

创作:

CK_BYTE id[] = {0x01, 0x02, 0x03, 0x04};
int generate_key(CK_SESSION_HANDLE hSession, …)
{
    CK_BBOOL ck_true = CK_TRUE;
    CK_ATTRIBUTE publicKeyTemplate[] = {
        {CKA_TOKEN, &ck_true, sizeof(ck_true)},
        {CKA_ID, id, sizeof(id)},
        …
    };
    CK_ATTRIBUTE privateKeyTemplate[] = {
        {CKA_TOKEN, &ck_true, sizeof(ck_true)},
        {CKA_ID, id, sizeof(id)},
        …
    };
    CK_MECHANISM mechanism = …;
    CK_OBJECT_HANDLE hPublicKey = CK_INVALID_HANDLE;
    CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
    C_GenerateKeyPair(hSession, &mechanism, 
                      publicKeyTemplate, 
                      sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE), 
                      privateKeyTemplate, 
                      sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE), 
                      &hPublicKey, &hPrivateKey);
}

使用(省略大部分错误检查):

CK_BYTE id[] = {0x01, 0x02, 0x03, 0x04}; // same as when creating the key
int sign_stuff(CK_SESSION_HANDLE hSession, ) {
    CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
    CK_ATTRIBUTE privateKeyTemplate[] = {
        {CKA_ID, id, sizeof(id)},
        {CKA_CLASS, cko_private_key, sizeof(cko_private_key)},
    };
    C_FindObjectsInit(hSession,
                      privateKeyTemplate, sizeof(privateKeyTemplate)/sizeof(*privateKeyTemplate));
    CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
    CK_ULONG count = 0;
    C_FindObjects(hSession, &hPrivateKey, 1, &count);
    C_FindObjectsFinal(hSession);
    if (count == 0)
        return ERROR_KEY_NOT_FOUND;
    CK_MECHANISM mechanism = …;
    C_SignInit(hSession, &mechanism, hPrivateKey);
    …
}