1 /*
2 * COPYRIGHT (c) International Business Machines Corp. 2003-2017
3 *
4 * This program is provided under the terms of the Common Public License,
5 * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
6 * software constitutes recipient's acceptance of CPL-1.0 terms which can be
7 * found in the file LICENSE file or at
8 * https://opensource.org/licenses/cpl1.0.php
9 */
10
11 /*
12 * openCryptoki testcase
13 *
14 * Mar 14, 2003
15 * Kent Yoder <yoder1@us.ibm.com>
16 *
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <dlfcn.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27
28 #include "pkcs11types.h"
29 #include "regress.h"
30
31 #define AES_KEY_SIZE_128 16
32
33 int do_GetFunctionList(void);
34 int clean_up(void);
35
36 CK_SLOT_ID slot_id;
37 CK_FUNCTION_LIST *funcs;
38 CK_SESSION_HANDLE sess;
39
40 /*
41 * do_HW_Feature_Seatch Test:
42 *
43 * 1. Create 5 objects, 3 of which are HW_FEATURE objects (2 of them are
44 * monotonic counters).
45 * 2. Search for objects using a template that does not have its
46 * HW_FEATURE attribute set.
47 * 3. Result should be that the other 2 objects are returned, and
48 * not the HW_FEATURE objects.
49 * 4. Search for objects using a template that does have its
50 * HW_FEATURE attribute set.
51 * 5. Result should be that the only hardware feature objects that are not
52 * monotonic counters should be returned.
53 *
54 */
do_HW_Feature_Search(void)55 int do_HW_Feature_Search(void)
56 {
57 unsigned int i = 0;
58 CK_RV rc = 0;
59 CK_ULONG find_count = 0;
60
61 CK_BBOOL false = FALSE;
62 CK_BBOOL true = TRUE;
63
64 // A counter object
65 CK_OBJECT_CLASS counter1_class = CKO_HW_FEATURE;
66 CK_HW_FEATURE_TYPE feature1_type = CKH_MONOTONIC_COUNTER;
67 CK_UTF8CHAR counter1_label[] = "Monotonic counter";
68 CK_CHAR counter1_value[16] = {0};
69 CK_ATTRIBUTE counter1_template[] = {
70 {CKA_CLASS, &counter1_class, sizeof(counter1_class)},
71 {CKA_HW_FEATURE_TYPE, &feature1_type, sizeof(feature1_type)},
72 {CKA_LABEL, counter1_label, sizeof(counter1_label) - 1},
73 {CKA_VALUE, counter1_value, sizeof(counter1_value)},
74 {CKA_RESET_ON_INIT, &true, sizeof(true)},
75 {CKA_HAS_RESET, &false, sizeof(false)}
76 };
77
78 // Another counter object
79 CK_OBJECT_CLASS counter2_class = CKO_HW_FEATURE;
80 CK_HW_FEATURE_TYPE feature2_type = CKH_MONOTONIC_COUNTER;
81 CK_UTF8CHAR counter2_label[] = "Monotonic counter";
82 CK_CHAR counter2_value[16] = {0};
83 CK_ATTRIBUTE counter2_template[] = {
84 {CKA_CLASS, &counter2_class, sizeof(counter2_class)},
85 {CKA_HW_FEATURE_TYPE, &feature2_type, sizeof(feature2_type)},
86 {CKA_LABEL, counter2_label, sizeof(counter2_label) - 1},
87 {CKA_VALUE, counter2_value, sizeof(counter2_value)},
88 {CKA_RESET_ON_INIT, &true, sizeof(true)},
89 {CKA_HAS_RESET, &false, sizeof(false)}
90 };
91
92 // A clock object
93 CK_OBJECT_CLASS clock_class = CKO_HW_FEATURE;
94 CK_HW_FEATURE_TYPE clock_type = CKH_CLOCK;
95 CK_UTF8CHAR clock_label[] = "Clock";
96 CK_CHAR clock_value[16] = {0};
97 CK_ATTRIBUTE clock_template[] = {
98 {CKA_CLASS, &clock_class, sizeof(clock_class)},
99 {CKA_HW_FEATURE_TYPE, &clock_type, sizeof(clock_type)},
100 {CKA_LABEL, clock_label, sizeof(clock_label) - 1},
101 {CKA_VALUE, clock_value, sizeof(clock_value)}
102 };
103
104 // A data object
105 CK_OBJECT_CLASS obj1_class = CKO_DATA;
106 CK_UTF8CHAR obj1_label[] = "Object 1";
107 CK_BYTE obj1_data[] = "Object 1's data";
108 CK_ATTRIBUTE obj1_template[] = {
109 {CKA_CLASS, &obj1_class, sizeof(obj1_class)},
110 {CKA_TOKEN, &true, sizeof(true)},
111 {CKA_LABEL, obj1_label, sizeof(obj1_label) - 1},
112 {CKA_VALUE, obj1_data, sizeof(obj1_data)}
113 };
114
115 // A secret key object
116 CK_OBJECT_CLASS obj2_class = CKO_SECRET_KEY;
117 CK_KEY_TYPE obj2_type = CKK_AES;
118 CK_UTF8CHAR obj2_label[] = "Object 2";
119 CK_BYTE obj2_data[AES_KEY_SIZE_128] = {0};
120 CK_ATTRIBUTE obj2_template[] = {
121 {CKA_CLASS, &obj2_class, sizeof(obj2_class)},
122 {CKA_TOKEN, &true, sizeof(true)},
123 {CKA_KEY_TYPE, &obj2_type, sizeof(obj2_type)},
124 {CKA_LABEL, obj2_label, sizeof(obj2_label) - 1},
125 {CKA_VALUE, obj2_data, sizeof(obj2_data)}
126 };
127
128 CK_OBJECT_HANDLE h_counter1 = 0,
129 h_counter2 = 0, h_clock = 0, h_obj1 = 0, h_obj2 = 0,
130 obj_list[10] = {0};
131
132 CK_ATTRIBUTE find_tmpl[] = {
133 {CKA_CLASS, &counter1_class, sizeof(counter1_class)}
134 };
135
136 /* Create the 5 test objects */
137 rc = funcs->C_CreateObject(sess, obj1_template, 4, &h_obj1);
138 if (rc != CKR_OK) {
139 show_error("C_CreateObject #1", rc);
140 return rc;
141 }
142
143 rc = funcs->C_CreateObject(sess, obj2_template, 5, &h_obj2);
144 if (rc != CKR_OK) {
145 show_error("C_CreateObject #2", rc);
146 goto destroy_1;
147 }
148
149 rc = funcs->C_CreateObject(sess, counter1_template, 6, &h_counter1);
150 if (rc != CKR_ATTRIBUTE_READ_ONLY) {
151 show_error("C_CreateObject #3", rc);
152 goto destroy_2;
153 }
154
155 rc = funcs->C_CreateObject(sess, counter2_template, 6, &h_counter2);
156 if (rc != CKR_ATTRIBUTE_READ_ONLY) {
157 show_error("C_CreateObject #4", rc);
158 goto destroy_3;
159 }
160
161 rc = funcs->C_CreateObject(sess, clock_template, 4, &h_clock);
162 if (rc != CKR_OK) {
163 show_error("C_CreateObject #5", rc);
164 goto destroy_4;
165 }
166
167
168 /* Search for the 2 objects w/o HW_FEATURE set
169 * A NULL template here should return all objects in v2.01, but
170 * in v2.11, it should return all objects *except* HW_FEATURE
171 * objects.
172 */
173 rc = funcs->C_FindObjectsInit(sess, NULL, 0);
174 if (rc != CKR_OK) {
175 show_error(" C_FindObjectsInit #1", rc);
176 goto done;
177 }
178
179 rc = funcs->C_FindObjects(sess, obj_list, 10, &find_count);
180 if (rc != CKR_OK) {
181 show_error(" C_FindObjects #1", rc);
182 goto done;
183 }
184
185 /* So, we created 5 objects before here, and then searched with a NULL
186 * template, so that should return all objects except our hardware
187 * feature object.
188 */
189 if (find_count != 2) {
190 printf("%s:%d ERROR: C_FindObjects #1 should have found 2 objects!\n"
191 " It found %ld objects\n", __FILE__, __LINE__,
192 find_count);
193 rc = -1;
194 goto done;
195 }
196
197 if (obj_list[0] != h_obj1 && obj_list[0] != h_obj2) {
198 printf("%s:%d ERROR: C_FindObjects #1 found the wrong objects!\n",
199 __FILE__, __LINE__);
200 rc = -1;
201 goto done;
202 }
203
204 if (obj_list[1] != h_obj1 && obj_list[1] != h_obj2) {
205 printf("%s:%d ERROR: C_FindObjects #1 found the wrong objects!\n",
206 __FILE__, __LINE__);
207 rc = -1;
208 goto done;
209 }
210
211 rc = funcs->C_FindObjectsFinal(sess);
212 if (rc != CKR_OK) {
213 show_error(" C_FindObjectsFinal #1", rc);
214 goto done;
215 }
216
217
218 /* Now find the hardware feature objects (should find only 1 since monotonic
219 * counters are read-only
220 */
221 rc = funcs->C_FindObjectsInit(sess, find_tmpl, 1);
222 if (rc != CKR_OK) {
223 show_error(" C_FindObjectsInit #2", rc);
224 goto done;
225 }
226
227 rc = funcs->C_FindObjects(sess, obj_list, 10, &find_count);
228 if (rc != CKR_OK) {
229 show_error(" C_FindObjects #2", rc);
230 goto done;
231 }
232
233 if (find_count != 1) {
234 printf("%s:%d ERROR: C_FindObjects #2 should have found 1 object!\n"
235 " It found %ld objects\n", __FILE__, __LINE__,
236 find_count);
237 funcs->C_FindObjectsFinal(sess);
238 rc = -1;
239 goto done;
240 }
241
242 /* Make sure we got the right ones */
243 for (i = 0; i < find_count; i++) {
244 if (obj_list[i] != h_counter1 &&
245 obj_list[i] != h_counter2 && obj_list[i] != h_clock) {
246
247 printf("%s:%d ERROR: C_FindObjects #2 found the wrong\n"
248 " objects!", __FILE__, __LINE__);
249 rc = -1;
250 }
251 }
252
253 rc = funcs->C_FindObjectsFinal(sess);
254 if (rc != CKR_OK) {
255 show_error(" C_FindObjectsFinal #2", rc);
256 }
257
258 done:
259 /* Destroy the created objects, don't clobber the rc */
260 funcs->C_DestroyObject(sess, h_clock);
261 destroy_4:
262 funcs->C_DestroyObject(sess, h_counter2);
263 destroy_3:
264 funcs->C_DestroyObject(sess, h_counter1);
265 destroy_2:
266 funcs->C_DestroyObject(sess, h_obj2);
267 destroy_1:
268 funcs->C_DestroyObject(sess, h_obj1);
269
270 return rc;
271 }
272
main(int argc,char ** argv)273 int main(int argc, char **argv)
274 {
275 int i;
276 CK_RV rc;
277 CK_C_INITIALIZE_ARGS initialize_args;
278 CK_BYTE user_pin[PKCS11_MAX_PIN_LEN];
279 CK_ULONG user_pin_len;
280
281 /* Set default slot to 0 */
282 slot_id = 0;
283
284 /* Parse the command line */
285 for (i = 1; i < argc; i++) {
286 if (strncmp(argv[i], "-slot", 5) == 0) {
287 slot_id = atoi(argv[i + 1]);
288 i++;
289 break;
290 }
291 }
292
293 printf("Using slot %ld...\n\n", slot_id);
294
295 if (!do_GetFunctionList())
296 return -1;
297
298 /* There will be no multi-threaded Cryptoki access in this app */
299 memset(&initialize_args, 0, sizeof(initialize_args));
300
301 rc = funcs->C_Initialize(&initialize_args);
302 if (rc != CKR_OK) {
303 show_error("C_Initialize", rc);
304 return -1;
305 }
306
307 rc = funcs->C_OpenSession(slot_id,
308 (CKF_SERIAL_SESSION | CKF_RW_SESSION),
309 NULL_PTR, NULL_PTR, &sess);
310 /* Open a session with the token */
311 if (rc != CKR_OK) {
312 show_error("C_OpenSession #1", rc);
313 goto done;
314 }
315
316 if (get_user_pin(user_pin))
317 return CKR_FUNCTION_FAILED;
318
319 user_pin_len = (CK_ULONG) strlen((char *) user_pin);
320
321 // Login correctly
322 rc = funcs->C_Login(sess, CKU_USER, user_pin, user_pin_len);
323 if (rc != CKR_OK) {
324 show_error("C_Login #1", rc);
325 goto session_close;
326 }
327
328 printf("do_HW_Feature_Search...\n");
329 rc = do_HW_Feature_Search();
330 if (rc)
331 goto logout;
332
333 printf("Hardware Feature tests succeeded.\n");
334
335 logout:
336 rc = funcs->C_Logout(sess);
337 if (rc != CKR_OK)
338 show_error("C_Logout #1", rc);
339
340 session_close:
341 rc = funcs->C_CloseSession(sess);
342 /* Close the session */
343 if (rc != CKR_OK)
344 show_error("C_CloseSession", rc);
345
346 done:
347 /* Call C_Finalize and dlclose the library */
348 return clean_up();
349 }
350
clean_up(void)351 int clean_up(void)
352 {
353 CK_RV rc = 0;
354
355 rc = funcs->C_Finalize(NULL);
356 if (rc != CKR_OK)
357 show_error("C_Finalize", rc);
358
359 return rc;
360 }
361