1 /*
2  * p11test_case_interface.c: Test new PKCS #11 3.0 interface
3  *
4  * Copyright (C) 2020 Red Hat, Inc.
5  *
6  * Author: Jakub Jelen <jjelen@redhat.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "p11test_case_interface.h"
23 #include <dlfcn.h>
24 
25 extern void *pkcs11_so;
26 
interface_test(void ** state)27 void interface_test(void **state)
28 {
29 	token_info_t *info = (token_info_t *) *state;
30 	CK_RV (*C_GetInterfaceList)(CK_INTERFACE_PTR, CK_ULONG_PTR) = NULL;
31 	CK_RV (*C_GetInterface)(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS) = NULL;
32 	CK_RV rv;
33 	CK_ULONG count = 0;
34 	CK_INTERFACE *interfaces = NULL;
35 	CK_INTERFACE_PTR interface;
36 	CK_VERSION version;
37 	unsigned int i;
38 
39 	P11TEST_START(info);
40 
41 	C_GetInterfaceList = (CK_RV (*)(CK_INTERFACE_PTR, CK_ULONG_PTR)) dlsym(pkcs11_so, "C_GetInterfaceList");
42 	if (C_GetInterfaceList == NULL) {
43 		/* If the library does not have this function, it is probably not PKCS #11 3.0 */
44 		P11TEST_SKIP(info);
45 	}
46 	/* If we have C_GetInterfaceList, we should have also C_GetInterface */
47 	C_GetInterface = (CK_RV (*)(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS))
48 		dlsym(pkcs11_so, "C_GetInterface");
49 	assert_non_null(C_GetInterface);
50 
51 	/* Invalid arguments */
52 	rv = C_GetInterfaceList(NULL, NULL);
53 	assert_int_equal(rv, CKR_ARGUMENTS_BAD);
54 
55 	/* Get the count of interfaces */
56 	rv = C_GetInterfaceList(NULL, &count);
57 	assert_int_equal(rv, CKR_OK);
58 	/* XXX assuming two interfaces, PKCS#11 3.0 and 2.20 */
59 	assert_int_equal(count, 2);
60 
61 	interfaces = malloc(count * sizeof(CK_INTERFACE));
62 	assert_non_null(interfaces);
63 
64 	/* Now get the actual interfaces */
65 	rv = C_GetInterfaceList(interfaces, &count);
66 	assert_int_equal(rv, CKR_OK);
67 	for (i = 0; i < count; i++) {
68 		printf("interface '%s' version %d.%d funcs %p flags 0x%lu\n",
69 			interfaces[i].pInterfaceName,
70 			((CK_VERSION *)interfaces[i].pFunctionList)->major,
71 			((CK_VERSION *)interfaces[i].pFunctionList)->minor,
72 			interfaces[i].pFunctionList,
73 			interfaces[i].flags);
74 	}
75 	assert_string_equal(interfaces[0].pInterfaceName, "PKCS 11");
76 	assert_int_equal(((CK_VERSION *)interfaces[0].pFunctionList)->major, 3);
77 	assert_int_equal(((CK_VERSION *)interfaces[0].pFunctionList)->minor, 0);
78 	assert_int_equal(interfaces[0].flags, 0);
79 	assert_string_equal(interfaces[1].pInterfaceName, "PKCS 11");
80 	assert_int_equal(((CK_VERSION *)interfaces[1].pFunctionList)->major, 2);
81 	assert_int_equal(((CK_VERSION *)interfaces[1].pFunctionList)->minor, 20);
82 	assert_int_equal(interfaces[1].flags, 0);
83 
84 	/* GetInterface with NULL name should give us default PKCS 11 one */
85 	rv = C_GetInterface(NULL, NULL, &interface, 0);
86 	assert_int_equal(rv, CKR_OK);
87 	assert_string_equal(interface->pInterfaceName, "PKCS 11");
88 	assert_int_equal(((CK_VERSION *)interface->pFunctionList)->major, 3);
89 	assert_int_equal(((CK_VERSION *)interface->pFunctionList)->minor, 0);
90 	assert_int_equal(interface->flags, 0);
91 	/* The function list should be the same */
92 	assert_ptr_equal(interfaces[0].pFunctionList, interface->pFunctionList);
93 
94 	/* GetInterface with explicit 3.0 version */
95 	version.major = 3;
96 	version.minor = 0;
97 	rv = C_GetInterface((unsigned char *)"PKCS 11", &version, &interface, 0);
98 	assert_int_equal(rv, CKR_OK);
99 	assert_string_equal(interface->pInterfaceName, "PKCS 11");
100 	assert_int_equal(((CK_VERSION *)interface->pFunctionList)->major, 3);
101 	assert_int_equal(((CK_VERSION *)interface->pFunctionList)->minor, 0);
102 	assert_int_equal(interface->flags, 0);
103 	/* The function list should be the same */
104 	assert_ptr_equal(interfaces[0].pFunctionList, interface->pFunctionList);
105 
106 	/* GetInterface with explicit 2.20 version */
107 	version.major = 2;
108 	version.minor = 20;
109 	rv = C_GetInterface((unsigned char *)"PKCS 11", &version, &interface, 0);
110 	assert_int_equal(rv, CKR_OK);
111 	assert_string_equal(interface->pInterfaceName, "PKCS 11");
112 	assert_int_equal(((CK_VERSION *)interface->pFunctionList)->major, 2);
113 	assert_int_equal(((CK_VERSION *)interface->pFunctionList)->minor, 20);
114 	assert_int_equal(interface->flags, 0);
115 	/* The function list should be the same here too */
116 	assert_ptr_equal(interfaces[1].pFunctionList, interface->pFunctionList);
117 
118 	/* GetInterface with unknown interface  */
119 	rv = C_GetInterface((unsigned char *)"PKCS 11 other", NULL, &interface, 0);
120 	assert_int_equal(rv, CKR_ARGUMENTS_BAD);
121 
122 	/* GetInterface with wrong version  */
123 	version.major = 2;
124 	version.minor = 50;
125 	rv = C_GetInterface((unsigned char *)"PKCS 11", &version, &interface, 0);
126 	assert_int_equal(rv, CKR_ARGUMENTS_BAD);
127 
128 	/* GetInterface with unknown flags  */
129 	rv = C_GetInterface((unsigned char *)"PKCS 11", NULL, &interface, 2);
130 	assert_int_equal(rv, CKR_ARGUMENTS_BAD);
131 	free(interfaces);
132 
133 	P11TEST_PASS(info);
134 }
135