## Cryptoki 库概述 Solaris [加密](https://so.csdn.net/so/search?q=%E5%8A%A0%E5%AF%86&spm=1001.2101.3001.7020)框架中的用户级应用程序通过 libpkcs11.so 模块中所提供的 cryptoki 库来访问 PKCS #11 函数。pkcs11_softtoken.so 模块是由 Sun Microsystems, Inc. 提供的 PKCS #11 软令牌实现,用于提供加密机制。软令牌插件是缺省的机制源。加密机制还可以通过第三方插件提供。 本节列出了软令牌所支持的 PKCS #11 函数和返回值,返回代码根据插入到[框架](https://so.csdn.net/so/search?q=%E6%A1%86%E6%9E%B6&spm=1001.2101.3001.7020)中的提供者而异。本节还介绍了一些常见的函数。有关 cryptoki 库中所有元素的完整说明,请参阅相应的手册页或[http://www.rsasecurity.com/rsalabs/pkcs/pkcs-11](http://www.rsasecurity.com/rsalabs/pkcs/pkcs-11)。 ### PKCS #11 函数列表 下面列出了 Solaris 加密框架中的 pkcs11_softtoken.so 所支持的 PKCS #11 函数类别以及相关函数: - **通用**-**C_Initialize()**、**C_Finalize()**、**C_GetInfo()** 和 **C_GetFunctionList()** - **会话管理**-**C_OpenSession()**、**C_CloseSession()**、**C_GetSessionInfo()**、**C_CloseAllSessions()**、**C_Login()**和 **C_Logout()** - **插槽和令牌管理**-**C_GetSlotList()**、**C_GetSlotInfo()**、**C_GetMechanismList()**、**C_GetMechanismInfo()** 和**C_SetPIN()** - **加密和解密**-**C_EncryptInit()**、**C_Encrypt()**、**C_EncryptUpdate()**、**C_EncryptFinal()**、**C_DecryptInit()**、**C_Decrypt()**、**C_DecryptUpdate()**和 **C_DecryptFinal()** - **消息摘要**-**C_DigestInit()**、**C_Digest()**、**C_DigestKey()**、**C_DigestUpdate()** 和**C_DigestFinal()** - **MAC 的签名和应用**-**C_Sign()**、**C_SignInit()**、**C_SignUpdate()**、**C_SignFinal()**、**C_SignRecoverInit()** 和**C_SignRecover()** - **签名检验**-**C_Verify()**、**C_VerifyInit()**、**C_VerifyUpdate()**、**C_VerifyFinal()**、**C_VerifyRecoverInit()**和 **C_VerifyRecover()** - **双重用途加密函数**-**C_DigestEncryptUpdate()**、**C_DecryptDigestUpdate()**、**C_SignEncryptUpdate()** 和**C_DecryptVerifyUpdate()** - **随机数生成**-**C_SeedRandom()** 和 **C_GenerateRandom()** - **对象管理**-**C_CreateObject()**、**C_DestroyObject()**、**C_CopyObject()**、**C_FindObjects()**、**C_FindObjectsInit()**、**C_FindObjectsFinal()**、**C_GetAttributeValue()**和 **C_SetAttributeValue()** - **密钥管理**-**C_GenerateKey()**、**C_GenerateKeyPair()** 和 **C_DeriveKey()** ### 使用 PKCS #11 的函数 本节提供了以下使用 PKCS #11 的函数的说明: - [PKCS #11 函数: **C_Initialize()**](http://docs.sun.com/app/docs/doc/819-7056/6n91eac56?l=zh&a=view#chapter2-9d) - [PKCS #11 函数: **C_GetInfo()**](http://docs.sun.com/app/docs/doc/819-7056/6n91eac56?l=zh&a=view#chapter2-7) - [PKCS #11 函数: **C_GetSlotList()**](http://docs.sun.com/app/docs/doc/819-7056/6n91eac56?l=zh&a=view#chapter2-9) - [PKCS #11 函数: **C_GetTokenInfo()**](http://docs.sun.com/app/docs/doc/819-7056/6n91eac56?l=zh&a=view#chapter2-9a) - [PKCS #11 函数: **C_OpenSession()**](http://docs.sun.com/app/docs/doc/819-7056/6n91eac56?l=zh&a=view#chapter2-9f) - [PKCS #11 函数: **C_GetMechanismList()**](http://docs.sun.com/app/docs/doc/819-7056/6n91eac56?l=zh&a=view#chapter2-9b) --- 注 – 所有的 PKCS #11 函数都可以从 libpkcs11.so 库中获取,不必使用 **C_GetFunctionList()** 函数来获取可用函数的列表。 --- #### PKCS #11 函数: **C_Initialize()** **C_Initialize()** 可用于初始化 PKCS #11 库。**C_Initialize()** 使用以下语法: C_Initialize(CK_VOID_PTR pInitArgs); pInitArgs 是空值 NULL_PTR 或是指向 CK_C_INITIALIZE_ARGS 结构的指针。通过 NULL_PTR,该库可以将 Solaris 互斥锁用作锁定原语,在多个线程之间仲裁对内部共享结构的访问。请注意,Solaris 加密框架不接受互斥锁。由于cryptoki 库的此实现可以安全高效地处理多线程,因此建议使用 NULL_PTR。应用程序还可以使用 pInitArgs 来设置诸如 CKF_LIBRARY_CANT_CREATE_OS_THREADS 之类的标志。**C_Finalize()** 表示应用程序使用 PKCS #11 库结束会话。 --- 注 – **C_Finalize()** 绝不应当通过库进行调用。按照惯例,应用程序负责调用 **C_Finalize()** 来关闭会话。 --- 除了 CKR_FUNCTION_FAILED、CKR_GENERAL_ERROR、CKR_HOST_MEMORY 和 CKR_OK 以外,**C_Initialize()** 还会使用以下返回值: - CKR_ARGUMENTS_BAD - CKR_CANT_LOCK - CKR_CRYPTOKI_ALREADY_INITIALIZED-此错误不是致命的。 #### PKCS #11 函数: **C_GetInfo()** **C_GetInfo()** 使用的是有关 cryptoki 库的制造商和版本信息。**C_GetInfo()** 使用以下语法: C_GetInfo(CK_INFO_PTR pInfo); **C_GetInfo()** 会返回以下值: - cryptokiVersion = 2, 11 - manufacturerID = Sun Microsystems, Inc. 除了 CKR_FUNCTION_FAILED、CKR_GENERAL_ERROR、CKR_HOST_MEMORY 和 CKR_OK 以外,**C_GetInfo()** 还可以获取以下返回值: - CKR_ARGUMENTS_BAD - CKR_CRYPTOKI_NOT_INITIALIZED #### PKCS #11 函数: **C_GetSlotList()** **C_GetSlotList()** 使用的是可用插槽的列表。如果除了 pkcs11_softtoken.so 以外尚未安装任何其他加密提供者,则 **C_GetSlotList()** 仅返回缺省插槽。**C_GetSlotList()** 使用以下语法: C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount); 如果 tokenPresent 设置为 TRUE,则会将搜索限制在那些存在令牌的插槽。 如果 pSlotList 设置为 NULL_PTR,则 **C_GetSlotlist()** 仅返回插槽的数量。pulCount 是指向用于接收插槽计数的位置的指针。 如果 pSlotList 指向用于接收插槽的缓冲区,则 *pulCount 将设置为 CK_SLOT_ID 元素的最大预期数量。在返回时,*pulCount 将设置为 CK_SLOT_ID 元素的实际数量。 通常,PKCS #11 应用程序会调用 **C_GetSlotList()** 两次。第一次调用 **C_GetSlotList()** 用于获取进行内存分配的插槽数量,第二次调用 **C_GetSlotList()** 用于获取插槽。 除了 CKR_FUNCTION_FAILED、CKR_GENERAL_ERROR、CKR_HOST_MEMORY 和 CKR_OK 以外,**C_GetSlotlist()** 还可以获取以下返回值: - CKR_ARGUMENTS_BAD - CKR_BUFFER_TOO_SMALL - CKR_CRYPTOKI_NOT_INITIALIZED #### PKCS #11 函数: **C_GetTokenInfo()** **C_GetTokenInfo()** 可用于获取有关特定令牌的信息。**C_GetTokenInfo()** 使用以下语法: C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); slotID 用于标识令牌的插槽。slotID 必须是由 **C_GetSlotList()** 返回的有效 ID。pInfo 是指向用于接收令牌信息的位置的指针。 如果 pkcs11_softtoken.so 是所安装的唯一提供者,则 **C_GetTokenInfo()** 将返回以下字段和值: - 标记-Sun Software PKCS#11 软令牌。 - 标志-CKF_DUAL_CRYPTO_OPERATIONS、CKF_TOKEN_INITIALIZED、CKF_RNG、CKF_USER_PIN_INITIALIZED 和CKF_LOGIN_REQUIRED,这些标志设置为 1。 - ulMaxSessionCount-设置为 CK_EFFECTIVELY_INFINITE。 - ulMaxRwSessionCount-设置为 CK_EFFECTIVELY_INFINITE。 - ulMaxPinLen-设置为 256。 - ulMinPinLen-设置为 1。 - ulTotalPublicMemory-设置为 CK_UNAVAILABLE_INFORMATION。 - ulFreePublicMemory-设置为 CK_UNAVAILABLE_INFORMATION。 - ulTotalPrivateMemory-设置为 CK_UNAVAILABLE_INFORMATION。 - ulFreePrivateMemory-设置为 CK_UNAVAILABLE_INFORMATION。 除了 CKR_FUNCTION_FAILED、CKR_GENERAL_ERROR、CKR_HOST_MEMORY 和 CKR_OK 以外,**C_GetSlotlist()** 还可以获取以下返回值: - CKR_ARGUMENTS_BAD - CKR_BUFFER_TOO_SMALL - CKR_CRYPTOKI_NOT_INITIALIZED - CKR_SLOT_ID_INVALID 以下返回值与具有硬件令牌的插件相关: - CKR_DEVICE_ERROR - CKR_DEVICE_MEMORY - CKR_DEVICE_REMOVED - CKR_TOKEN_NOT_PRESENT - CKR_TOKEN_NOT_RECOGNIZED #### PKCS #11 函数: **C_OpenSession()** 应用程序可使用 **C_OpenSession()** 来启动特定插槽中具有特定令牌的加密会话。**C_OpenSession()** 使用以下语法: C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession); slotID 用于标识插槽。flags 用于指示会话是只读的还是可读写的。pApplication 是应用程序所定义的用于回调的指针。Notify 用于存放可选回调函数的地址。phSession 是指向会话句柄的位置的指针。 除了 CKR_FUNCTION_FAILED、CKR_GENERAL_ERROR、CKR_HOST_MEMORY 和 CKR_OK 以外,**C_OpenSession()** 还可以获取以下返回值: - CKR_ARGUMENTS_BAD - CKR_CRYPTOKI_NOT_INITIALIZED - CKR_SLOT_ID_INVALID - CKR_TOKEN_WRITE_PROTECTED-随受写保护的令牌出现。 以下返回值与具有硬件令牌的插件相关: - CKR_DEVICE_ERROR - CKR_DEVICE_MEMORY - CKR_DEVICE_REMOVED - CKR_SESSION_COUNT - CKR_SESSION_PARALLEL_NOT_SUPPORTED - CKR_SESSION_READ_WRITE_SO_EXISTS - CKR_TOKEN_NOT_PRESENT - CKR_TOKEN_NOT_RECOGNIZED #### PKCS #11 函数: **C_GetMechanismList()** **C_GetMechanismList()** 可用于获取指定令牌所支持的机制类型的列表。**C_GetMechanismList()** 使用以下语法: C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount); slotID 用于标识令牌的插槽。pulCount 是指向用于接收机制数量的位置的指针。 如果 pMechanismList 设置为 NULL_PTR,则 *pulCount 将返回机制的数量。否则,必须将 *pulCount 设置为列表的大小,pMechanismList 必须指向用于存放列表的缓冲区。 如果已插入 PKCS #11 软令牌,则 **C_GetMechanismList()** 将返回以下列出的支持的机制: - CKM_AES_CBC - CKM_AES_CBC_PAD - CKM_AES_ECB - CKM_AES_KEY_GEN - CKM_DES_CBC - CKM_DES_CBC_PAD - CKM_DES_ECB - CKM_DES_KEY_GEN - CKM_DES_MAC - CKM_DES_MAC_GENERAL - CKM_DES3_CBC - CKM_DES3_CBC_PAD - CKM_DES3_ECB - CKM_DES3_KEY_GEN - CKM_DH_PKCS_DERIVE - CKM_DH_PKCS_KEY_PAIR_GEN - CKM_DSA - CKM_DSA_KEY_PAIR_GEN - CKM_DSA_SHA_1 - CKM_MD5 - CKM_MD5_KEY_DERIVATION - CKM_MD5_RSA_PKCS - CKM_MD5_HMAC - CKM_MD5_HMAC_GENERAL - CKM_PBE_SHA1_RC4_128 - CKM_PKCS5_PBKD2 - CKM_RC4 - CKM_RC4_KEY_GEN - CKM_RSA_PKCS - CKM_RSA_X_509 - CKM_RSA_PKCS_KEY_PAIR_GEN - CKM_SHA_1 - CKM_SHA_1_HMAC_GENERAL - CKM_SHA_1_HMAC - CKM_SHA_1_KEY_DERIVATION - CKM_SHA_1_RSA_PKCS - CKM_SSL3_KEY_AND_MAC_DERIVE - CKM_SSL3_MASTER_KEY_DERIVE - CKM_SSL3_MASTER_KEY_DERIVE_DH - CKM_SSL3_MD5_MAC - CKM_SSL3_PRE_MASTER_KEY_GEN - CKM_SSL3_SHA1_MAC - CKM_TLS_KEY_AND_MAC_DERIVE - CKM_TLS_MASTER_KEY_DERIVE - CKM_TLS_MASTER_KEY_DERIVE_DH - CKM_TLS_PRE_MASTER_KEY_GEN 除了 CKR_FUNCTION_FAILED、CKR_GENERAL_ERROR、CKR_HOST_MEMORY 和 CKR_OK 以外,**C_GetSlotlist()** 还使用以下返回值: - CKR_ARGUMENTS_BAD - CKR_BUFFER_TOO_SMALL - CKR_CRYPTOKI_NOT_INITIALIZED - CKR_SLOT_ID_INVALID 以下返回值与具有硬件令牌的插件相关: - CKR_DEVICE_ERROR - CKR_DEVICE_MEMORY - CKR_DEVICE_REMOVED - CKR_TOKEN_NOT_PRESENT - CKR_TOKEN_NOT_RECOGNIZED ### 扩展的 PKCS #11 函数 除了标准的 PKCS #11 函数以外,Solaris 加密框架还附带了两个便利函数: - [扩展的 PKCS #11 函数: **SUNW_C_GetMechSession()**](http://docs.sun.com/app/docs/doc/819-7056/6n91eac56?l=zh&a=view#efuser-5) - [扩展的 PKCS #11 函数: SUNW_C_KeyToObject](http://docs.sun.com/app/docs/doc/819-7056/6n91eac56?l=zh&a=view#efuser-6) #### 扩展的 PKCS #11 函数: **SUNW_C_GetMechSession()** **SUNW_C_GetMechSession()** 是一个便利函数,用于初始化 Solaris 加密框架。该函数随后会使用指定的机制启动会话。**SUNW_C_GetMechSession()** 使用以下语法: SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech, C/ K_SESSION_HANDLE_PTR hSession) mech 参数用于指定要使用的机制。hSession 是指向会话位置的指针。 **SUNW_C_GetMechSession()** 在内部调用 **C_Initialize()** 以初始化 cryptoki库。**SUNW_C_GetMechSession()** 接着会使用指定的机制调用 **C_GetSlotList()** 和**C_GetMechanismInfo()**,在可用插槽中搜索令牌。如果找到了机制,**SUNW_C_GetMechSession()** 会调用**C_OpenSession()** 来打开会话。 **SUNW_C_GetMechSession()** 只需要调用一次。不过,多次调用 **SUNW_C_GetMechSession()** 也不会造成任何问题。 #### 扩展的 PKCS #11 函数: SUNW_C_KeyToObject **SUNW_C_KeyToObject()** 可用于创建私钥对象。调用程序必须指定要使用的机制以及原始密钥数据。**SUNW_C_KeyToObject()** 可在内部确定指定机制的密钥类型。通用密钥对象是通过 **C_CreateObject()** 创建的。**SUNW_C_KeyToObject()** 接着会调用 **C_GetSessionInfo()** 和 **C_GetMechanismInfo()** 来获取插槽和机制。**C_SetAttributeValue()** 随后会根据机制的类型为密钥对象设置属性标志。