From 7f0166ab123d54e2229b78261371e10d93cd2b4c Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 13 Aug 2020 18:44:50 +0200 Subject: [PATCH] p11test: Basic test for C_GetInterface API from PKCS#11 3.0 --- src/tests/p11test/Makefile.am | 3 +- src/tests/p11test/p11test.c | 4 + src/tests/p11test/p11test_case_interface.c | 134 +++++++++++++++++++++ src/tests/p11test/p11test_case_interface.h | 25 ++++ src/tests/p11test/p11test_loader.c | 2 +- 5 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 src/tests/p11test/p11test_case_interface.c create mode 100644 src/tests/p11test/p11test_case_interface.h diff --git a/src/tests/p11test/Makefile.am b/src/tests/p11test/Makefile.am index b8c3db64..f7cc67e3 100644 --- a/src/tests/p11test/Makefile.am +++ b/src/tests/p11test/Makefile.am @@ -14,7 +14,7 @@ noinst_HEADERS = p11test_loader.h p11test_case_common.h \ p11test_case_mechs.h p11test_case_ec_sign.h \ p11test_case_usage.h p11test_case_wait.h \ p11test_case_pss_oaep.h p11test_helpers.h \ - p11test_case_ec_derive.h \ + p11test_case_ec_derive.h p11test_case_interface.h \ p11test_common.h AM_CPPFLAGS = -I$(top_srcdir)/src @@ -29,6 +29,7 @@ p11test_SOURCES = p11test.c p11test_loader.c \ p11test_case_usage.c \ p11test_case_wait.c \ p11test_case_pss_oaep.c \ + p11test_case_interface.c \ p11test_helpers.c p11test_CFLAGS = -DNDEBUG $(CMOCKA_CFLAGS) p11test_LDADD = $(OPTIONAL_OPENSSL_LIBS) $(CMOCKA_LIBS) diff --git a/src/tests/p11test/p11test.c b/src/tests/p11test/p11test.c index a16282cb..457a7b63 100644 --- a/src/tests/p11test/p11test.c +++ b/src/tests/p11test/p11test.c @@ -31,6 +31,7 @@ #include "p11test_case_mechs.h" #include "p11test_case_wait.h" #include "p11test_case_pss_oaep.h" +#include "p11test_case_interface.h" #define DEFAULT_P11LIB "../../pkcs11/.libs/opensc-pkcs11.so" @@ -62,6 +63,9 @@ int main(int argc, char** argv) { cmocka_unit_test_setup_teardown(supported_mechanisms_test, token_setup, token_cleanup), + /* Check the PKCS #11 3.0 Interface to access new functions */ + cmocka_unit_test(interface_test), + /* Complex readonly test of all objects on the card */ cmocka_unit_test_setup_teardown(readonly_tests, user_login_setup, after_test_cleanup), diff --git a/src/tests/p11test/p11test_case_interface.c b/src/tests/p11test/p11test_case_interface.c new file mode 100644 index 00000000..d0ca59b5 --- /dev/null +++ b/src/tests/p11test/p11test_case_interface.c @@ -0,0 +1,134 @@ +/* + * p11test_case_interface.c: Test new PKCS #11 3.0 interface + * + * Copyright (C) 2020 Red Hat, Inc. + * + * Author: Jakub Jelen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "p11test_case_interface.h" +#include + +extern void *pkcs11_so; + +void interface_test(void **state) +{ + token_info_t *info = (token_info_t *) *state; + CK_RV (*C_GetInterfaceList)(CK_INTERFACE_PTR, CK_ULONG_PTR) = NULL; + CK_RV (*C_GetInterface)(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS) = NULL; + CK_RV rv; + CK_ULONG count = 0; + CK_INTERFACE *interfaces = NULL; + CK_INTERFACE_PTR interface; + CK_VERSION version; + unsigned int i; + + P11TEST_START(info); + + C_GetInterfaceList = (CK_RV (*)(CK_INTERFACE_PTR, CK_ULONG_PTR)) dlsym(pkcs11_so, "C_GetInterfaceList"); + if (C_GetInterfaceList == NULL) { + /* If the library does not have this function, it is probably not PKCS #11 3.0 */ + P11TEST_SKIP(info); + } + /* If we have C_GetInterfaceList, we should have also C_GetInterface */ + C_GetInterface = (CK_RV (*)(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS)) + dlsym(pkcs11_so, "C_GetInterface"); + assert_non_null(C_GetInterface); + + /* Invalid arguments */ + rv = C_GetInterfaceList(NULL, NULL); + assert_int_equal(rv, CKR_ARGUMENTS_BAD); + + /* Get the count of interfaces */ + rv = C_GetInterfaceList(NULL, &count); + assert_int_equal(rv, CKR_OK); + /* XXX assuming two interfaces, PKCS#11 3.0 and 2.20 */ + assert_int_equal(count, 2); + + interfaces = malloc(count * sizeof(CK_INTERFACE)); + assert_non_null(interfaces); + + /* Now get the actual interfaces */ + rv = C_GetInterfaceList(interfaces, &count); + assert_int_equal(rv, CKR_OK); + for (i = 0; i < count; i++) { + printf("interface '%s' version %d.%d funcs %p flags 0x%lu\n", + interfaces[i].pInterfaceName, + ((CK_VERSION *)interfaces[i].pFunctionList)->major, + ((CK_VERSION *)interfaces[i].pFunctionList)->minor, + interfaces[i].pFunctionList, + interfaces[i].flags); + } + assert_string_equal(interfaces[0].pInterfaceName, "PKCS 11"); + assert_int_equal(((CK_VERSION *)interfaces[0].pFunctionList)->major, 3); + assert_int_equal(((CK_VERSION *)interfaces[0].pFunctionList)->minor, 0); + assert_int_equal(interfaces[0].flags, 0); + assert_string_equal(interfaces[1].pInterfaceName, "PKCS 11"); + assert_int_equal(((CK_VERSION *)interfaces[1].pFunctionList)->major, 2); + assert_int_equal(((CK_VERSION *)interfaces[1].pFunctionList)->minor, 20); + assert_int_equal(interfaces[1].flags, 0); + + /* GetInterface with NULL name should give us default PKCS 11 one */ + rv = C_GetInterface(NULL, NULL, &interface, 0); + assert_int_equal(rv, CKR_OK); + assert_string_equal(interface->pInterfaceName, "PKCS 11"); + assert_int_equal(((CK_VERSION *)interface->pFunctionList)->major, 3); + assert_int_equal(((CK_VERSION *)interface->pFunctionList)->minor, 0); + assert_int_equal(interface->flags, 0); + /* The function list should be the same */ + assert_ptr_equal(interfaces[0].pFunctionList, interface->pFunctionList); + + /* GetInterface with explicit 3.0 version */ + version.major = 3; + version.minor = 0; + rv = C_GetInterface((unsigned char *)"PKCS 11", &version, &interface, 0); + assert_int_equal(rv, CKR_OK); + assert_string_equal(interface->pInterfaceName, "PKCS 11"); + assert_int_equal(((CK_VERSION *)interface->pFunctionList)->major, 3); + assert_int_equal(((CK_VERSION *)interface->pFunctionList)->minor, 0); + assert_int_equal(interface->flags, 0); + /* The function list should be the same */ + assert_ptr_equal(interfaces[0].pFunctionList, interface->pFunctionList); + + /* GetInterface with explicit 2.20 version */ + version.major = 2; + version.minor = 20; + rv = C_GetInterface((unsigned char *)"PKCS 11", &version, &interface, 0); + assert_int_equal(rv, CKR_OK); + assert_string_equal(interface->pInterfaceName, "PKCS 11"); + assert_int_equal(((CK_VERSION *)interface->pFunctionList)->major, 2); + assert_int_equal(((CK_VERSION *)interface->pFunctionList)->minor, 20); + assert_int_equal(interface->flags, 0); + /* The function list should be the same here too */ + assert_ptr_equal(interfaces[1].pFunctionList, interface->pFunctionList); + + /* GetInterface with unknown interface */ + rv = C_GetInterface((unsigned char *)"PKCS 11 other", NULL, &interface, 0); + assert_int_equal(rv, CKR_ARGUMENTS_BAD); + + /* GetInterface with wrong version */ + version.major = 2; + version.minor = 50; + rv = C_GetInterface((unsigned char *)"PKCS 11", &version, &interface, 0); + assert_int_equal(rv, CKR_ARGUMENTS_BAD); + + /* GetInterface with unknown flags */ + rv = C_GetInterface((unsigned char *)"PKCS 11", NULL, &interface, 2); + assert_int_equal(rv, CKR_ARGUMENTS_BAD); + free(interfaces); + + P11TEST_PASS(info); +} diff --git a/src/tests/p11test/p11test_case_interface.h b/src/tests/p11test/p11test_case_interface.h new file mode 100644 index 00000000..59ebe1f4 --- /dev/null +++ b/src/tests/p11test/p11test_case_interface.h @@ -0,0 +1,25 @@ +/* + * p11test_case_interface.h: Test new PKCS #11 3.0 interface + * + * Copyright (C) 2020 Red Hat, Inc. + * + * Author: Jakub Jelen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "p11test_case_common.h" + +void interface_test(void **state); + diff --git a/src/tests/p11test/p11test_loader.c b/src/tests/p11test/p11test_loader.c index 6dc2236c..107266a5 100644 --- a/src/tests/p11test/p11test_loader.c +++ b/src/tests/p11test/p11test_loader.c @@ -22,7 +22,7 @@ #include "p11test_loader.h" -static void *pkcs11_so; +void *pkcs11_so; int get_slot_with_card(token_info_t * info) {