/*
* COPYRIGHT (c) International Business Machines Corp. 2020
*
* This program is provided under the terms of the Common Public License,
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
* found in the file LICENSE file or at
* https://opensource.org/licenses/cpl1.0.php
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pkcs11types.h"
#include "regress.h"
static int get_interface_test(void)
{
CK_FUNCTION_LIST_3_0 *tfn;
CK_INTERFACE *interface;
CK_VERSION version, *v;
CK_SLOT_ID slot;
CK_FLAGS flags;
CK_RV rv;
int rc = -1;
testcase_new_assertion();
flags = 0ULL;
rv = funcs3->C_GetInterface(NULL, NULL, NULL, flags);
if (rv != CKR_ARGUMENTS_BAD) {
testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv));
goto ret;
}
flags = ~0ULL;
rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"PKCS 11",
NULL, &interface, flags);
if (rv != CKR_FUNCTION_FAILED) {
testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv));
goto ret;
}
version.major = 0;
version.minor = 0;
flags = 0ULL;
rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"PKCS 11",
&version, &interface, flags);
if (rv != CKR_FUNCTION_FAILED) {
testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv));
goto ret;
}
flags = 0ULL;
rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"INVALID",
NULL, &interface, flags);
if (rv != CKR_FUNCTION_FAILED) {
testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv));
goto ret;
}
flags = 0ULL;
rv = funcs3->C_GetInterface(NULL, NULL, &interface, flags);
if (rv != CKR_OK) {
testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv));
goto ret;
}
v = (CK_VERSION *)interface->pFunctionList;
printf("%s\n", "Default interface:");
printf("pInterfaceName %s\n", interface->pInterfaceName);
printf("pFunctionList version %u.%u\n", v->major, v->minor);
printf("flags 0x%016lx\n", interface->flags);
flags = 0ULL;
rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"PKCS 11",
NULL, &interface, flags);
if (rv != CKR_OK) {
testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv));
goto ret;
}
if (strcmp((char *)interface->pInterfaceName, "PKCS 11") != 0) {
testcase_fail("Returned interface name: %s.\n",
interface->pInterfaceName);
goto ret;
}
v = (CK_VERSION *)interface->pFunctionList;
printf("%s\n", "Default PKCS #11 interface:");
printf("pInterfaceName %s\n", interface->pInterfaceName);
printf("pFunctionList version %u.%u\n", v->major, v->minor);
printf("flags 0x%016lx\n", interface->flags);
version.major = 1;
version.minor = 0;
flags = 0ULL;
rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"Vendor IBM",
NULL, &interface, flags);
if (rv != CKR_OK) {
testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv));
goto ret;
}
if (strcmp((char *)interface->pInterfaceName, "Vendor IBM") != 0) {
testcase_fail("Returned interface name: %s.\n",
interface->pInterfaceName);
goto ret;
}
v = (CK_VERSION *)interface->pFunctionList;
printf("%s\n", "Vendor defined interface (IBM):");
printf("pInterfaceName %s\n", interface->pInterfaceName);
printf("pFunctionList version %u.%u\n", v->major, v->minor);
printf("flags 0x%016lx\n", interface->flags);
version.major = 2;
version.minor = 40;
flags = 0ULL;
rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"PKCS 11",
&version, &interface, flags);
if (rv != CKR_OK) {
testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv));
goto ret;
}
if (strcmp((char *)interface->pInterfaceName, "PKCS 11") != 0) {
testcase_fail("Returned interface name: %s.\n",
interface->pInterfaceName);
goto ret;
}
v = (CK_VERSION *)interface->pFunctionList;
if (v->major != version.major || v->minor != version.minor) {
testcase_fail("Returned version: %u.%u.\n", v->major, v->minor);
goto ret;
}
printf("%s\n", "PKCS #11 version 2.40 interface:");
printf("pInterfaceName %s\n", interface->pInterfaceName);
printf("pFunctionList version %u.%u\n", v->major, v->minor);
printf("flags 0x%016lx\n", interface->flags);
version.major = 3;
version.minor = 0;
flags = 0ULL;
rv = funcs3->C_GetInterface((CK_UTF8CHAR *)"PKCS 11",
&version, &interface, flags);
if (rv != CKR_OK) {
testcase_fail("C_GetInterface returned %s.\n", p11_get_ckr(rv));
goto ret;
}
if (strcmp((char *)interface->pInterfaceName, "PKCS 11") != 0) {
testcase_fail("Returned interface name: %s.\n",
interface->pInterfaceName);
goto ret;
}
v = (CK_VERSION *)interface->pFunctionList;
if (v->major != version.major || v->minor != version.minor) {
testcase_fail("Returned version: %u.%u.\n", v->major, v->minor);
goto ret;
}
printf("%s\n", "PKCS #11 version 3.0 interface:");
printf("pInterfaceName %s\n", interface->pInterfaceName);
printf("pFunctionList version %u.%u\n", v->major, v->minor);
printf("flags 0x%016lx\n", interface->flags);
tfn = (CK_FUNCTION_LIST_3_0 *)interface->pFunctionList;
if (tfn->C_Initialize == NULL
|| tfn->C_Finalize == NULL
|| tfn->C_GetInfo == NULL
|| tfn->C_GetFunctionList == NULL
|| tfn->C_GetSlotList == NULL
|| tfn->C_GetSlotInfo == NULL
|| tfn->C_GetTokenInfo == NULL
|| tfn->C_GetMechanismList == NULL
|| tfn->C_GetMechanismInfo == NULL
|| tfn->C_InitToken == NULL
|| tfn->C_InitPIN == NULL
|| tfn->C_SetPIN == NULL
|| tfn->C_OpenSession == NULL
|| tfn->C_CloseSession == NULL
|| tfn->C_CloseAllSessions == NULL
|| tfn->C_GetSessionInfo == NULL
|| tfn->C_GetOperationState == NULL
|| tfn->C_SetOperationState == NULL
|| tfn->C_Login == NULL
|| tfn->C_Logout == NULL
|| tfn->C_CreateObject == NULL
|| tfn->C_CopyObject == NULL
|| tfn->C_DestroyObject == NULL
|| tfn->C_GetObjectSize == NULL
|| tfn->C_GetAttributeValue == NULL
|| tfn->C_SetAttributeValue == NULL
|| tfn->C_FindObjectsInit == NULL
|| tfn->C_FindObjects == NULL
|| tfn->C_FindObjectsFinal == NULL
|| tfn->C_EncryptInit == NULL
|| tfn->C_Encrypt == NULL
|| tfn->C_EncryptUpdate == NULL
|| tfn->C_EncryptFinal == NULL
|| tfn->C_DecryptInit == NULL
|| tfn->C_Decrypt == NULL
|| tfn->C_DecryptUpdate == NULL
|| tfn->C_DecryptFinal == NULL
|| tfn->C_DigestInit == NULL
|| tfn->C_Digest == NULL
|| tfn->C_DigestUpdate == NULL
|| tfn->C_DigestKey == NULL
|| tfn->C_DigestFinal == NULL
|| tfn->C_SignInit == NULL
|| tfn->C_Sign == NULL
|| tfn->C_SignUpdate == NULL
|| tfn->C_SignFinal == NULL
|| tfn->C_SignRecoverInit == NULL
|| tfn->C_SignRecover == NULL
|| tfn->C_VerifyInit == NULL
|| tfn->C_Verify == NULL
|| tfn->C_VerifyUpdate == NULL
|| tfn->C_VerifyFinal == NULL
|| tfn->C_VerifyRecoverInit == NULL
|| tfn->C_VerifyRecover == NULL
|| tfn->C_DigestEncryptUpdate == NULL
|| tfn->C_DecryptDigestUpdate == NULL
|| tfn->C_SignEncryptUpdate == NULL
|| tfn->C_DecryptVerifyUpdate == NULL
|| tfn->C_GenerateKey == NULL
|| tfn->C_GenerateKeyPair == NULL
|| tfn->C_WrapKey == NULL
|| tfn->C_UnwrapKey == NULL
|| tfn->C_DeriveKey == NULL
|| tfn->C_SeedRandom == NULL
|| tfn->C_GenerateRandom == NULL
|| tfn->C_GetFunctionStatus == NULL
|| tfn->C_CancelFunction == NULL
|| tfn->C_WaitForSlotEvent == NULL
/* Additional PKCS #11 3.0 functions */
|| tfn->C_GetInterfaceList == NULL
|| tfn->C_GetInterface == NULL
|| tfn->C_LoginUser == NULL
|| tfn->C_SessionCancel == NULL
|| tfn->C_MessageEncryptInit == NULL
|| tfn->C_EncryptMessage == NULL
|| tfn->C_EncryptMessageBegin == NULL
|| tfn->C_EncryptMessageNext == NULL
|| tfn->C_MessageEncryptFinal == NULL
|| tfn->C_MessageDecryptInit == NULL
|| tfn->C_DecryptMessage == NULL
|| tfn->C_DecryptMessageBegin == NULL
|| tfn->C_DecryptMessageNext == NULL
|| tfn->C_MessageDecryptFinal == NULL
|| tfn->C_MessageSignInit == NULL
|| tfn->C_SignMessage == NULL
|| tfn->C_SignMessageBegin == NULL
|| tfn->C_SignMessageNext == NULL
|| tfn->C_MessageSignFinal == NULL
|| tfn->C_MessageVerifyInit == NULL
|| tfn->C_VerifyMessage == NULL
|| tfn->C_VerifyMessageBegin == NULL
|| tfn->C_VerifyMessageNext == NULL
|| tfn->C_MessageVerifyFinal == NULL) {
testcase_fail("%s", "Returned CK_FUNCTION_LIST_3_0 contains"
" a NULL function pointer.\n");
goto ret;
}
/*
* Function pointers are != NULL.
* Now check if they are valid.
*/
slot = 0;
tfn->C_Initialize(NULL);
tfn->C_Finalize(NULL);
tfn->C_GetInfo(NULL);
tfn->C_GetFunctionList(NULL);
tfn->C_GetSlotList(CK_FALSE, NULL, NULL);
tfn->C_GetSlotInfo(slot, NULL);
tfn->C_GetTokenInfo(slot, NULL);
tfn->C_GetMechanismList(slot, NULL, NULL);
tfn->C_GetMechanismInfo(slot, 0UL, NULL);
tfn->C_InitToken(slot, NULL, 0UL, NULL);
tfn->C_InitPIN(0UL, NULL, 0UL);
tfn->C_SetPIN(0UL, NULL, 0UL, NULL, 0UL);
tfn->C_OpenSession(slot, 0UL, NULL, NULL, NULL);
tfn->C_CloseSession(0UL);
tfn->C_CloseAllSessions(slot);
tfn->C_GetSessionInfo(0UL, NULL);
tfn->C_GetOperationState(0UL, NULL, NULL);
tfn->C_SetOperationState(0UL, NULL, 0UL, 0UL, 0UL);
tfn->C_Login(0UL, 0UL, NULL, 0UL);
tfn->C_Logout(0UL);
tfn->C_CreateObject(0UL, NULL, 0UL, NULL);
tfn->C_CopyObject(0UL, 0UL, NULL, 0UL, NULL);
tfn->C_DestroyObject(0UL, 0UL);
tfn->C_GetObjectSize(0UL, 0UL, NULL);
tfn->C_GetAttributeValue(0UL, 0UL, NULL, 0UL);
tfn->C_SetAttributeValue(0UL, 0UL, NULL, 0UL);
tfn->C_FindObjectsInit(0UL, NULL, 0UL);
tfn->C_FindObjects(0UL, NULL, 0UL, NULL);
tfn->C_FindObjectsFinal(0UL);
tfn->C_EncryptInit(0UL, NULL, 0UL);
tfn->C_Encrypt(0UL, NULL, 0UL, NULL, NULL);
tfn->C_EncryptUpdate(0UL, NULL, 0UL, NULL, NULL);
tfn->C_EncryptFinal(0UL, NULL, NULL);
tfn->C_DecryptInit(0UL, NULL, 0UL);
tfn->C_Decrypt(0UL, NULL, 0UL, NULL, NULL);
tfn->C_DecryptUpdate(0UL, NULL, 0UL, NULL, NULL);
tfn->C_DecryptFinal(0UL, NULL, NULL);
tfn->C_DigestInit(0UL, NULL);
tfn->C_Digest(0UL, NULL, 0UL, NULL, 0UL);
tfn->C_DigestUpdate(0UL, NULL, 0UL);
tfn->C_DigestKey(0UL, 0UL);
tfn->C_DigestFinal(0UL, NULL, NULL);
tfn->C_SignInit(0UL, NULL, 0UL);
tfn->C_Sign(0UL, NULL, 0UL, NULL, NULL);
tfn->C_SignUpdate(0UL, NULL, 0UL);
tfn->C_SignFinal(0UL, NULL, NULL);
tfn->C_SignRecoverInit(0UL, NULL, 0UL);
tfn->C_SignRecover(0UL, NULL, 0UL, NULL, NULL);
tfn->C_VerifyInit(0UL, NULL, 0UL);
tfn->C_Verify(0UL, NULL, 0UL, NULL, 0UL);
tfn->C_VerifyUpdate(0UL, NULL, 0UL);
tfn->C_VerifyFinal(0UL, NULL, 0UL);
tfn->C_VerifyRecoverInit(0UL, NULL, 0UL);
tfn->C_VerifyRecover(0UL, NULL, 0UL, NULL, NULL);
tfn->C_DigestEncryptUpdate(0UL, NULL, 0UL, NULL, NULL);
tfn->C_DecryptDigestUpdate(0UL, NULL, 0UL, NULL, NULL);
tfn->C_SignEncryptUpdate(0UL, NULL, 0UL, NULL, NULL);
tfn->C_DecryptVerifyUpdate(0UL, NULL, 0UL, NULL, NULL);
tfn->C_GenerateKey(0UL, NULL, NULL, 0UL, NULL);
tfn->C_GenerateKeyPair(0UL, NULL, NULL, 0UL, NULL, 0UL, NULL, NULL);
tfn->C_WrapKey(0UL, NULL, 0UL, 0UL, NULL, NULL);
tfn->C_UnwrapKey(0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL, NULL);
tfn->C_DeriveKey(0UL, NULL, 0UL, NULL, 0UL, NULL);
tfn->C_SeedRandom(0UL, NULL, 0UL);
tfn->C_GenerateRandom(0UL, NULL, 0UL);
tfn->C_GetFunctionStatus(0UL);
tfn->C_CancelFunction(0UL);
tfn->C_WaitForSlotEvent(0UL, &slot, NULL);
/* Additional PKCS #11 3.0 functions */
tfn->C_GetInterfaceList(NULL, NULL);
tfn->C_GetInterface(NULL, NULL, NULL, 0UL);
tfn->C_LoginUser(0UL, 0UL, NULL, 0UL, NULL, 0UL);
tfn->C_SessionCancel(0UL, 0UL);
tfn->C_MessageEncryptInit(0UL, NULL, 0UL);
tfn->C_EncryptMessage(0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL);
tfn->C_EncryptMessageBegin(0UL, NULL, 0UL, NULL, 0UL);
tfn->C_EncryptMessageNext(0UL, NULL, 0UL, NULL, 0UL, NULL, NULL, 0UL);
tfn->C_MessageEncryptFinal(0UL);
tfn->C_MessageDecryptInit(0UL, NULL, 0UL);
tfn->C_DecryptMessage(0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL);
tfn->C_DecryptMessageBegin(0UL, NULL, 0UL, NULL, 0UL);
tfn->C_DecryptMessageNext(0UL, NULL, 0UL, NULL, 0UL, NULL, NULL, 0UL);
tfn->C_MessageDecryptFinal(0UL);
tfn->C_MessageSignInit(0UL, NULL, 0UL);
tfn->C_SignMessage(0UL, NULL, 0UL, NULL, 0UL, NULL, NULL);
tfn->C_SignMessageBegin(0UL, NULL, 0UL);
tfn->C_SignMessageNext(0UL, NULL, 0UL, NULL, 0UL, NULL, NULL);
tfn->C_MessageSignFinal(0UL);
tfn->C_MessageVerifyInit(0UL, NULL, 0UL);
tfn->C_VerifyMessage(0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL);
tfn->C_VerifyMessageBegin(0UL, NULL, 0UL);
tfn->C_VerifyMessageNext(0UL, NULL, 0UL, NULL, 0UL, NULL, 0UL);
tfn->C_MessageVerifyFinal(0UL);
testcase_pass("C_GetInterface works.\n");
rc = 0;
ret:
return rc;
}
static int get_interface_list_test(void)
{
CK_INTERFACE *il = NULL;
CK_ULONG nmemb = 0UL, i;
CK_VERSION *version;
CK_RV rv;
int rc = -1;
testcase_new_assertion();
rv = funcs3->C_GetInterfaceList(NULL, NULL);
if (rv != CKR_ARGUMENTS_BAD) {
testcase_fail("C_GetInterfaceList returned %s.\n", p11_get_ckr(rv));
goto ret;
}
rv = funcs3->C_GetInterfaceList(NULL, &nmemb);
if (rv != CKR_OK) {
testcase_fail("C_GetInterfaceList returned %s.\n", p11_get_ckr(rv));
goto ret;
}
if (nmemb == 0) {
testcase_fail("C_GetInterfaceList interface list has"
" %lu elements.\n", nmemb);
goto ret;
}
il = calloc(nmemb, sizeof(*il));
if (il == NULL) {
testcase_error("calloc failed.\n");
goto ret;
}
nmemb--;
rv = funcs3->C_GetInterfaceList(il, &nmemb);
if (rv != CKR_BUFFER_TOO_SMALL) {
testcase_fail("C_GetInterfaceList returned %s.\n", p11_get_ckr(rv));
goto ret;
}
rv = funcs3->C_GetInterfaceList(il, &nmemb);
if (rv != CKR_OK) {
testcase_fail("C_GetInterfaceList returned %s.\n", p11_get_ckr(rv));
goto ret;
}
for (i = 0UL; i < nmemb; i++) {
if (strncmp((char *)il[i].pInterfaceName,
"PKCS 11", strlen("PKCS 11")) != 0
&& strncmp((char *)il[i].pInterfaceName,
"Vendor ", strlen("Vendor ")) != 0) {
testcase_fail("Invalid interface name.\n");
goto ret;
}
if (il[i].pFunctionList == NULL) {
testcase_fail("%s", "Interface with NULL function list.\n");
goto ret;
}
if ((il[i].flags & ~CKF_INTERFACE_FORK_SAFE) != 0) {
testcase_fail("Interface with unknown flags: 0x%016lx.\n",
il[i].flags);
goto ret;
}
version = (CK_VERSION *)il[i].pFunctionList;
printf("Interface %lu:\n", i);
printf("pInterfaceName %s\n", il[i].pInterfaceName);
printf("pFunctionList version %u.%u\n",
version->major, version->minor);
printf("flags 0x%016lx\n", il[i].flags);
}
testcase_pass("C_GetInterfaceList works.\n");
rc = 0;
ret:
free(il);
return rc;
}
int main(void)
{
int rc = -1;
testcase_setup(0);
if (do_GetFunctionList() != TRUE) {
testcase_error("%s", "do_GetFunctionList() failed.\n");
goto ret;
}
rc = get_interface_list_test();
if (rc)
goto ret;
rc = get_interface_test();
ret:
testcase_print_result();
/* make sure we return non-zero if rc is non-zero */
return ((rc == 0) || (rc % 256) ? (int)rc : -1);
}