本节中的示例生成了一个用于对简单字符串进行签名和检验的 RSA 密钥对。此示例执行以下步骤:
定义密钥对象。
设置公钥模板。
设置私钥模板。
创建样例消息。
指定用于生成密钥对象的 genmech 机制。
指定用于对密钥对进行签名的 smech 机制。
初始化 cryptoki 库。
通过用于生成和检验密钥对并对其进行签名的机制来查找插槽。此任务将使用一个名为 getMySlot() 的函数来执行以下步骤:
调用 C_GetSlotList() 函数以获取可用插槽的列表。
与 PKCS #11 约定中所建议的一样,C_GetSlotList() 需要调用两次。第一次调用 C_GetSlotList() 用于获取进行内存分配的插槽数量,第二次调用 C_GetSlotList() 用于检索插槽。
查找可以提供所需机制的插槽。
对于每个插槽,该函数都会调用 GetMechanismInfo() 以查找可用于生成密钥对并对其进行签名的机制。如果插槽不支持这些机制,则 GetMechanismInfo() 将返回错误。如果 GetMechanismInfo() 成功返回,则将检查机制标志,以确保这些机制可以执行所需的操作。
调用 C_OpenSession() 来打开会话。
关闭会话。
下面是签名和检验示例的源代码。
此示例的源代码也可以通过 Sun 下载中心获取。请访问 http://www.sun.com/download/products.xml?id=41912db5
#include <stdio.h> #include <fcntl.h> #include <errno.h> #include <sys/types.h> #include <security/cryptoki.h> #include <security/pkcs11.h> #define BUFFERSIZ 8192 /* Define key template */ static CK_BBOOL truevalue = TRUE; static CK_BBOOL falsevalue = FALSE; static CK_ULONG modulusbits = 1024; static CK_BYTE public_exponent[] = {3}; boolean_t GetMySlot(CK_MECHANISM_TYPE sv_mech, CK_MECHANISM_TYPE kpgen_mech, CK_SLOT_ID_PTR pslot); /* Example signs and verifies a simple string, using a public/private * key pair. */ void main(int argc, char **argv) { CK_RV rv; CK_MECHANISM genmech, smech; CK_SESSION_HANDLE hSession; CK_SESSION_INFO sessInfo; CK_SLOT_ID slotID; int error, i = 0; CK_OBJECT_HANDLE privatekey, publickey; /* Set public key. */ CK_ATTRIBUTE publickey_template[] = { {CKA_VERIFY, &truevalue, sizeof (truevalue)}, {CKA_MODULUS_BITS, &modulusbits, sizeof (modulusbits)}, {CKA_PUBLIC_EXPONENT, &public_exponent, sizeof (public_exponent)} }; /* Set private key. */ CK_ATTRIBUTE privatekey_template[] = { {CKA_SIGN, &truevalue, sizeof (truevalue)}, {CKA_TOKEN, &falsevalue, sizeof (falsevalue)}, {CKA_SENSITIVE, &truevalue, sizeof (truevalue)}, {CKA_EXTRACTABLE, &truevalue, sizeof (truevalue)} }; /* Create sample message. */ CK_ATTRIBUTE getattributes[] = { {CKA_MODULUS_BITS, NULL_PTR, 0}, {CKA_MODULUS, NULL_PTR, 0}, {CKA_PUBLIC_EXPONENT, NULL_PTR, 0} }; CK_ULONG messagelen, slen, template_size; boolean_t found_slot = B_FALSE; uchar_t *message = (uchar_t *)"Simple message for signing & verifying."; uchar_t *modulus, *pub_exponent; char sign[BUFFERSIZ]; slen = BUFFERSIZ; messagelen = strlen((char *)message); /* Set up mechanism for generating key pair */ genmech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; genmech.pParameter = NULL_PTR; genmech.ulParameterLen = 0; /* Set up the signing mechanism */ smech.mechanism = CKM_RSA_PKCS; smech.pParameter = NULL_PTR; smech.ulParameterLen = 0; /* Initialize the CRYPTOKI library */ rv = C_Initialize(NULL_PTR); if (rv != CKR_OK) { fprintf(stderr, "C_Initialize: Error = 0x%.8X\n", rv); exit(1); } found_slot = GetMySlot(smech.mechanism, genmech.mechanism, &slotID); if (!found_slot) { fprintf(stderr, "No usable slot was found.\n"); goto exit_program; } fprintf(stdout, "selected slot: %d\n", slotID); /* Open a session on the slot found */ rv = C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession); if (rv != CKR_OK) { fprintf(stderr, "C_OpenSession: rv = 0x%.8X\n", rv); error = 1; goto exit_program; } fprintf(stdout, "Generating keypair....\n"); /* Generate Key pair for signing/verifying */ rv = C_GenerateKeyPair(hSession, &genmech, publickey_template, (sizeof (publickey_template) / sizeof (CK_ATTRIBUTE)), privatekey_template, (sizeof (privatekey_template) / sizeof (CK_ATTRIBUTE)), &publickey, &privatekey); if (rv != CKR_OK) { fprintf(stderr, "C_GenerateKeyPair: rv = 0x%.8X\n", rv); error = 1; goto exit_session; } /* Display the publickey. */ template_size = sizeof (getattributes) / sizeof (CK_ATTRIBUTE); rv = C_GetAttributeValue(hSession, publickey, getattributes, template_size); if (rv != CKR_OK) { /* not fatal, we can still sign/verify if this failed */ fprintf(stderr, "C_GetAttributeValue: rv = 0x%.8X\n", rv); error = 1; } else { /* Allocate memory to hold the data we want */ for (i = 0; i < template_size; i++) { getattributes[i].pValue = malloc (getattributes[i].ulValueLen * sizeof(CK_VOID_PTR)); if (getattributes[i].pValue == NULL) { int j; for (j = 0; j < i; j++) free(getattributes[j].pValue); goto sign_cont; } } /* Call again to get actual attributes */ rv = C_GetAttributeValue(hSession, publickey, getattributes, template_size); if (rv != CKR_OK) { /* not fatal, we can still sign/verify if failed */ fprintf(stderr, "C_GetAttributeValue: rv = 0x%.8X\n", rv); error = 1; } else { /* Display public key values */ fprintf(stdout, "Public Key data:\n\tModulus bits: " "%d\n", *((CK_ULONG_PTR)(getattributes[0].pValue))); fprintf(stdout, "\tModulus: "); modulus = (uchar_t *)getattributes[1].pValue; for (i = 0; i < getattributes[1].ulValueLen; i++) { fprintf(stdout, "%.2x", modulus[i]); } fprintf(stdout, "\n\tPublic Exponent: "); pub_exponent = (uchar_t *)getattributes[2].pValue; for (i = 0; i< getattributes[2].ulValueLen; i++) { fprintf(stdout, "%.2x", pub_exponent[i]); } fprintf(stdout, "\n"); } } sign_cont: rv = C_SignInit(hSession, &smech, privatekey); if (rv != CKR_OK) { fprintf(stderr, "C_SignInit: rv = 0x%.8X\n", rv); error = 1; goto exit_session; } rv = C_Sign(hSession, (CK_BYTE_PTR)message, messagelen, (CK_BYTE_PTR)sign, &slen); if (rv != CKR_OK) { fprintf(stderr, "C_Sign: rv = 0x%.8X\n", rv); error = 1; goto exit_session; } fprintf(stdout, "Message was successfully signed with private key!\n"); rv = C_VerifyInit(hSession, &smech, publickey); if (rv != CKR_OK) { fprintf(stderr, "C_VerifyInit: rv = 0x%.8X\n", rv); error = 1; goto exit_session; } rv = C_Verify(hSession, (CK_BYTE_PTR)message, messagelen, (CK_BYTE_PTR)sign, slen); if (rv != CKR_OK) { fprintf(stderr, "C_Verify: rv = 0x%.8X\n", rv); error = 1; goto exit_session; } fprintf(stdout, "Message was successfully verified with public key!\n"); exit_session: (void) C_CloseSession(hSession); exit_program: (void) C_Finalize(NULL_PTR); for (i = 0; i < template_size; i++) { if (getattributes[i].pValue != NULL) free(getattributes[i].pValue); } exit(error); } /* Find a slot capable of: * . signing and verifying with sv_mech * . generating a key pair with kpgen_mech * Returns B_TRUE when successful. */ boolean_t GetMySlot(CK_MECHANISM_TYPE sv_mech, CK_MECHANISM_TYPE kpgen_mech, CK_SLOT_ID_PTR pSlotID) { CK_SLOT_ID_PTR pSlotList = NULL_PTR; CK_SLOT_ID SlotID; CK_ULONG ulSlotCount = 0; CK_MECHANISM_INFO mech_info; int i; boolean_t returnval = B_FALSE; CK_RV rv; /* Get slot list for memory alloction */ rv = C_GetSlotList(0, NULL_PTR, &ulSlotCount); if ((rv == CKR_OK) && (ulSlotCount > 0)) { fprintf(stdout, "slotCount = %d\n", ulSlotCount); pSlotList = malloc(ulSlotCount * sizeof (CK_SLOT_ID)); if (pSlotList == NULL) { fprintf(stderr, "System error: unable to allocate " "memory\n"); return (returnval); } /* Get the slot list for processing */ rv = C_GetSlotList(0, pSlotList, &ulSlotCount); if (rv != CKR_OK) { fprintf(stderr, "GetSlotList failed: unable to get " "slot count.\n"); goto cleanup; } } else { fprintf(stderr, "GetSlotList failed: unable to get slot " "list.\n"); return (returnval); } /* Find a slot capable of specified mechanism */ for (i = 0; i < ulSlotCount; i++) { SlotID = pSlotList[i]; /* Check if this slot is capable of signing and * verifying with sv_mech. */ rv = C_GetMechanismInfo(SlotID, sv_mech, &mech_info); if (rv != CKR_OK) { continue; } if (!(mech_info.flags & CKF_SIGN && mech_info.flags & CKF_VERIFY)) { continue; } /* Check if the slot is capable of key pair generation * with kpgen_mech. */ rv = C_GetMechanismInfo(SlotID, kpgen_mech, &mech_info); if (rv != CKR_OK) { continue; } if (!(mech_info.flags & CKF_GENERATE_KEY_PAIR)) { continue; } /* If we get this far, this slot supports our mechanisms. */ returnval = B_TRUE; *pSlotID = SlotID; break; } cleanup: if (pSlotList) free(pSlotList); return (returnval); }