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