|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* COPYRIGHT (c) International Business Machines Corp. 2003-2017
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* This program is provided under the terms of the Common Public License,
|
|
Packit |
8681c6 |
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
Packit |
8681c6 |
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
Packit |
8681c6 |
* found in the file LICENSE file or at
|
|
Packit |
8681c6 |
* https://opensource.org/licenses/cpl1.0.php
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* openCryptoki testcase
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* Mar 14, 2003
|
|
Packit |
8681c6 |
* Kent Yoder <yoder1@us.ibm.com>
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include <stdio.h>
|
|
Packit |
8681c6 |
#include <stdlib.h>
|
|
Packit |
8681c6 |
#include <string.h>
|
|
Packit |
8681c6 |
#include <dlfcn.h>
|
|
Packit |
8681c6 |
#include <sys/types.h>
|
|
Packit |
8681c6 |
#include <sys/stat.h>
|
|
Packit |
8681c6 |
#include <unistd.h>
|
|
Packit |
8681c6 |
#include <fcntl.h>
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include "pkcs11types.h"
|
|
Packit |
8681c6 |
#include "regress.h"
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#define AES_KEY_SIZE_128 16
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int clean_up(void);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_SLOT_ID slot_id;
|
|
Packit |
8681c6 |
CK_SESSION_HANDLE sess;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* do_HW_Feature_Seatch Test:
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* 1. Create 5 objects, 3 of which are HW_FEATURE objects (2 of them are
|
|
Packit |
8681c6 |
* monotonic counters).
|
|
Packit |
8681c6 |
* 2. Search for objects using a template that does not have its
|
|
Packit |
8681c6 |
* HW_FEATURE attribute set.
|
|
Packit |
8681c6 |
* 3. Result should be that the other 2 objects are returned, and
|
|
Packit |
8681c6 |
* not the HW_FEATURE objects.
|
|
Packit |
8681c6 |
* 4. Search for objects using a template that does have its
|
|
Packit |
8681c6 |
* HW_FEATURE attribute set.
|
|
Packit |
8681c6 |
* 5. Result should be that the only hardware feature objects that are not
|
|
Packit |
8681c6 |
* monotonic counters should be returned.
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
int do_HW_Feature_Search(void)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
unsigned int i = 0;
|
|
Packit |
8681c6 |
CK_RV rc = 0;
|
|
Packit |
8681c6 |
CK_ULONG find_count = 0;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_BBOOL false = FALSE;
|
|
Packit |
8681c6 |
CK_BBOOL true = TRUE;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// A counter object
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS counter1_class = CKO_HW_FEATURE;
|
|
Packit |
8681c6 |
CK_HW_FEATURE_TYPE feature1_type = CKH_MONOTONIC_COUNTER;
|
|
Packit |
8681c6 |
CK_UTF8CHAR counter1_label[] = "Monotonic counter";
|
|
Packit |
8681c6 |
CK_CHAR counter1_value[16] = {0};
|
|
Packit |
8681c6 |
CK_ATTRIBUTE counter1_template[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &counter1_class, sizeof(counter1_class)},
|
|
Packit |
8681c6 |
{CKA_HW_FEATURE_TYPE, &feature1_type, sizeof(feature1_type)},
|
|
Packit |
8681c6 |
{CKA_LABEL, counter1_label, sizeof(counter1_label) - 1},
|
|
Packit |
8681c6 |
{CKA_VALUE, counter1_value, sizeof(counter1_value)},
|
|
Packit |
8681c6 |
{CKA_RESET_ON_INIT, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_HAS_RESET, &false, sizeof(false)}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Another counter object
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS counter2_class = CKO_HW_FEATURE;
|
|
Packit |
8681c6 |
CK_HW_FEATURE_TYPE feature2_type = CKH_MONOTONIC_COUNTER;
|
|
Packit |
8681c6 |
CK_UTF8CHAR counter2_label[] = "Monotonic counter";
|
|
Packit |
8681c6 |
CK_CHAR counter2_value[16] = {0};
|
|
Packit |
8681c6 |
CK_ATTRIBUTE counter2_template[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &counter2_class, sizeof(counter2_class)},
|
|
Packit |
8681c6 |
{CKA_HW_FEATURE_TYPE, &feature2_type, sizeof(feature2_type)},
|
|
Packit |
8681c6 |
{CKA_LABEL, counter2_label, sizeof(counter2_label) - 1},
|
|
Packit |
8681c6 |
{CKA_VALUE, counter2_value, sizeof(counter2_value)},
|
|
Packit |
8681c6 |
{CKA_RESET_ON_INIT, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_HAS_RESET, &false, sizeof(false)}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// A clock object
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS clock_class = CKO_HW_FEATURE;
|
|
Packit |
8681c6 |
CK_HW_FEATURE_TYPE clock_type = CKH_CLOCK;
|
|
Packit |
8681c6 |
CK_UTF8CHAR clock_label[] = "Clock";
|
|
Packit |
8681c6 |
CK_CHAR clock_value[16] = {0};
|
|
Packit |
8681c6 |
CK_ATTRIBUTE clock_template[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &clock_class, sizeof(clock_class)},
|
|
Packit |
8681c6 |
{CKA_HW_FEATURE_TYPE, &clock_type, sizeof(clock_type)},
|
|
Packit |
8681c6 |
{CKA_LABEL, clock_label, sizeof(clock_label) - 1},
|
|
Packit |
8681c6 |
{CKA_VALUE, clock_value, sizeof(clock_value)}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// A data object
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS obj1_class = CKO_DATA;
|
|
Packit |
8681c6 |
CK_UTF8CHAR obj1_label[] = "Object 1";
|
|
Packit |
8681c6 |
CK_BYTE obj1_data[] = "Object 1's data";
|
|
Packit |
8681c6 |
CK_ATTRIBUTE obj1_template[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &obj1_class, sizeof(obj1_class)},
|
|
Packit |
8681c6 |
{CKA_TOKEN, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_LABEL, obj1_label, sizeof(obj1_label) - 1},
|
|
Packit |
8681c6 |
{CKA_VALUE, obj1_data, sizeof(obj1_data)}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// A secret key object
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS obj2_class = CKO_SECRET_KEY;
|
|
Packit |
8681c6 |
CK_KEY_TYPE obj2_type = CKK_AES;
|
|
Packit |
8681c6 |
CK_UTF8CHAR obj2_label[] = "Object 2";
|
|
Packit |
8681c6 |
CK_BYTE obj2_data[AES_KEY_SIZE_128] = {0};
|
|
Packit |
8681c6 |
CK_ATTRIBUTE obj2_template[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &obj2_class, sizeof(obj2_class)},
|
|
Packit |
8681c6 |
{CKA_TOKEN, &true, sizeof(true)},
|
|
Packit |
8681c6 |
{CKA_KEY_TYPE, &obj2_type, sizeof(obj2_type)},
|
|
Packit |
8681c6 |
{CKA_LABEL, obj2_label, sizeof(obj2_label) - 1},
|
|
Packit |
8681c6 |
{CKA_VALUE, obj2_data, sizeof(obj2_data)}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE h_counter1 = 0,
|
|
Packit |
8681c6 |
h_counter2 = 0, h_clock = 0, h_obj1 = 0, h_obj2 = 0,
|
|
Packit |
8681c6 |
obj_list[10] = {0};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE find_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &counter1_class, sizeof(counter1_class)}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Create the 5 test objects */
|
|
Packit |
8681c6 |
rc = funcs->C_CreateObject(sess, obj1_template, 4, &h_obj1);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error("C_CreateObject #1", rc);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_CreateObject(sess, obj2_template, 5, &h_obj2);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error("C_CreateObject #2", rc);
|
|
Packit |
8681c6 |
goto destroy_1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_CreateObject(sess, counter1_template, 6, &h_counter1);
|
|
Packit |
8681c6 |
if (rc != CKR_ATTRIBUTE_READ_ONLY) {
|
|
Packit |
8681c6 |
show_error("C_CreateObject #3", rc);
|
|
Packit |
8681c6 |
goto destroy_2;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_CreateObject(sess, counter2_template, 6, &h_counter2);
|
|
Packit |
8681c6 |
if (rc != CKR_ATTRIBUTE_READ_ONLY) {
|
|
Packit |
8681c6 |
show_error("C_CreateObject #4", rc);
|
|
Packit |
8681c6 |
goto destroy_3;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_CreateObject(sess, clock_template, 4, &h_clock);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error("C_CreateObject #5", rc);
|
|
Packit |
8681c6 |
goto destroy_4;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Search for the 2 objects w/o HW_FEATURE set
|
|
Packit |
8681c6 |
* A NULL template here should return all objects in v2.01, but
|
|
Packit |
8681c6 |
* in v2.11, it should return all objects *except* HW_FEATURE
|
|
Packit |
8681c6 |
* objects.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
rc = funcs->C_FindObjectsInit(sess, NULL, 0);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error(" C_FindObjectsInit #1", rc);
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_FindObjects(sess, obj_list, 10, &find_count);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error(" C_FindObjects #1", rc);
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* So, we created 5 objects before here, and then searched with a NULL
|
|
Packit |
8681c6 |
* template, so that should return all objects except our hardware
|
|
Packit |
8681c6 |
* feature object.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
if (find_count != 2) {
|
|
Packit |
8681c6 |
printf("%s:%d ERROR: C_FindObjects #1 should have found 2 objects!\n"
|
|
Packit |
8681c6 |
" It found %ld objects\n", __FILE__, __LINE__,
|
|
Packit |
8681c6 |
find_count);
|
|
Packit |
8681c6 |
rc = -1;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (obj_list[0] != h_obj1 && obj_list[0] != h_obj2) {
|
|
Packit |
8681c6 |
printf("%s:%d ERROR: C_FindObjects #1 found the wrong objects!\n",
|
|
Packit |
8681c6 |
__FILE__, __LINE__);
|
|
Packit |
8681c6 |
rc = -1;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (obj_list[1] != h_obj1 && obj_list[1] != h_obj2) {
|
|
Packit |
8681c6 |
printf("%s:%d ERROR: C_FindObjects #1 found the wrong objects!\n",
|
|
Packit |
8681c6 |
__FILE__, __LINE__);
|
|
Packit |
8681c6 |
rc = -1;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_FindObjectsFinal(sess);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error(" C_FindObjectsFinal #1", rc);
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Now find the hardware feature objects (should find only 1 since monotonic
|
|
Packit |
8681c6 |
* counters are read-only
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
rc = funcs->C_FindObjectsInit(sess, find_tmpl, 1);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error(" C_FindObjectsInit #2", rc);
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_FindObjects(sess, obj_list, 10, &find_count);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error(" C_FindObjects #2", rc);
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (find_count != 1) {
|
|
Packit |
8681c6 |
printf("%s:%d ERROR: C_FindObjects #2 should have found 1 object!\n"
|
|
Packit |
8681c6 |
" It found %ld objects\n", __FILE__, __LINE__,
|
|
Packit |
8681c6 |
find_count);
|
|
Packit |
8681c6 |
funcs->C_FindObjectsFinal(sess);
|
|
Packit |
8681c6 |
rc = -1;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Make sure we got the right ones */
|
|
Packit |
8681c6 |
for (i = 0; i < find_count; i++) {
|
|
Packit |
8681c6 |
if (obj_list[i] != h_counter1 &&
|
|
Packit |
8681c6 |
obj_list[i] != h_counter2 && obj_list[i] != h_clock) {
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
printf("%s:%d ERROR: C_FindObjects #2 found the wrong\n"
|
|
Packit |
8681c6 |
" objects!", __FILE__, __LINE__);
|
|
Packit |
8681c6 |
rc = -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_FindObjectsFinal(sess);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error(" C_FindObjectsFinal #2", rc);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
/* Destroy the created objects, don't clobber the rc */
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(sess, h_clock);
|
|
Packit |
8681c6 |
destroy_4:
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(sess, h_counter2);
|
|
Packit |
8681c6 |
destroy_3:
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(sess, h_counter1);
|
|
Packit |
8681c6 |
destroy_2:
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(sess, h_obj2);
|
|
Packit |
8681c6 |
destroy_1:
|
|
Packit |
8681c6 |
funcs->C_DestroyObject(sess, h_obj1);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int main(int argc, char **argv)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
int i;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
CK_C_INITIALIZE_ARGS initialize_args;
|
|
Packit |
8681c6 |
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
|
|
Packit |
8681c6 |
CK_ULONG user_pin_len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Set default slot to 0 */
|
|
Packit |
8681c6 |
slot_id = 0;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Parse the command line */
|
|
Packit |
8681c6 |
for (i = 1; i < argc; i++) {
|
|
Packit |
8681c6 |
if (strncmp(argv[i], "-slot", 5) == 0) {
|
|
Packit |
8681c6 |
slot_id = atoi(argv[i + 1]);
|
|
Packit |
8681c6 |
i++;
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
printf("Using slot %ld...\n\n", slot_id);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!do_GetFunctionList())
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* There will be no multi-threaded Cryptoki access in this app */
|
|
Packit |
8681c6 |
memset(&initialize_args, 0, sizeof(initialize_args));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_Initialize(&initialize_args);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error("C_Initialize", rc);
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_OpenSession(slot_id,
|
|
Packit |
8681c6 |
(CKF_SERIAL_SESSION | CKF_RW_SESSION),
|
|
Packit |
8681c6 |
NULL_PTR, NULL_PTR, &sess;;
|
|
Packit |
8681c6 |
/* Open a session with the token */
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error("C_OpenSession #1", rc);
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (get_user_pin(user_pin))
|
|
Packit |
8681c6 |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
user_pin_len = (CK_ULONG) strlen((char *) user_pin);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Login correctly
|
|
Packit |
8681c6 |
rc = funcs->C_Login(sess, CKU_USER, user_pin, user_pin_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
show_error("C_Login #1", rc);
|
|
Packit |
8681c6 |
goto session_close;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
printf("do_HW_Feature_Search...\n");
|
|
Packit |
8681c6 |
rc = do_HW_Feature_Search();
|
|
Packit |
8681c6 |
if (rc)
|
|
Packit |
8681c6 |
goto logout;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
printf("Hardware Feature tests succeeded.\n");
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
logout:
|
|
Packit |
8681c6 |
rc = funcs->C_Logout(sess);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
show_error("C_Logout #1", rc);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
session_close:
|
|
Packit |
8681c6 |
rc = funcs->C_CloseSession(sess);
|
|
Packit |
8681c6 |
/* Close the session */
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
show_error("C_CloseSession", rc);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
/* Call C_Finalize and dlclose the library */
|
|
Packit |
8681c6 |
return clean_up();
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int clean_up(void)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_RV rc = 0;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_Finalize(NULL);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
show_error("C_Finalize", rc);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|