1 /*
2  * COPYRIGHT (c) International Business Machines Corp. 2010-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 /* File: sess_perf.c */
12 
13 #include <windows.h>
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <memory.h>
19 
20 #include "pkcs11types.h"
21 #include "regress.h"
22 #include "defs.h"
23 
24 #define DATALEN 1024
25 CK_BYTE DATA[DATALEN];
26 CK_BYTE DUMP[DATALEN];
27 
28 typedef struct _context_table {
29     CK_SESSION_HANDLE hsess;
30     CK_OBJECT_HANDLE hkey;
31 } context_table_t;
32 
dump_session_info(CK_SESSION_INFO * info)33 void dump_session_info(CK_SESSION_INFO * info)
34 {
35     printf("   CK_SESSION_INFO:\n");
36     printf("      slotID:         %ld\n", info->slotID);
37     printf("      state:          ");
38     switch (info->state) {
39     case CKS_RO_PUBLIC_SESSION:
40         printf("CKS_RO_PUBLIC_SESSION\n");
41         break;
42     case CKS_RW_PUBLIC_SESSION:
43         printf("CKS_RW_PUBLIC_SESSION\n");
44         break;
45     case CKS_RO_USER_FUNCTIONS:
46         printf("CKS_RO_USER_FUNCTIONS\n");
47         break;
48     case CKS_RW_USER_FUNCTIONS:
49         printf("CKS_RW_USER_FUNCTIONS\n");
50         break;
51     case CKS_RW_SO_FUNCTIONS:
52         printf("CKS_RW_SO_FUNCTIONS\n");
53         break;
54     }
55     printf("      flags:          %p\n", (void *) info->flags);
56     printf("      ulDeviceError:  %ld\n", info->ulDeviceError);
57 }
58 
create_des_encrypt_context(CK_SESSION_HANDLE_PTR hsess,CK_OBJECT_HANDLE_PTR hkey)59 int create_des_encrypt_context(CK_SESSION_HANDLE_PTR hsess,
60                                CK_OBJECT_HANDLE_PTR hkey)
61 {
62     CK_SLOT_ID slot_id;
63     CK_FLAGS flags;
64     CK_RV rc;
65     CK_MECHANISM mech;
66     CK_ULONG key_len = 16;
67     CK_ATTRIBUTE tkey = { CKA_VALUE_LEN, &key_len, sizeof(CK_ULONG) };
68 
69     /* create session */
70     slot_id = SLOT_ID;
71     flags = CKF_SERIAL_SESSION; // read-only session
72 
73     rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, hsess);
74     if (rc != CKR_OK) {
75         show_error("   C_OpenSession #1", rc);
76         return FALSE;
77     }
78 
79     /* generate key in this specific session */
80     mech.mechanism = CKM_AES_KEY_GEN;
81     mech.ulParameterLen = 0;
82     mech.pParameter = NULL;
83 
84     rc = funcs->C_GenerateKey(*hsess, &mech, &tkey, 1, hkey);
85     if (rc != CKR_OK) {
86         show_error("   C_GenerateKey #1", rc);
87         return FALSE;
88     }
89 
90     /* Get Random for Initialization Vector */
91     mech.mechanism = CKM_AES_CBC;
92     mech.ulParameterLen = 16;
93     mech.pParameter = "1234567890123456";
94 
95     /* Create encryption context using this session and key */
96     rc = funcs->C_EncryptInit(*hsess, &mech, *hkey);
97     if (rc != CKR_OK) {
98         show_error("   C_EncryptInit #1", rc);
99         return FALSE;
100     }
101 
102     return TRUE;
103 }
104 
encrypt_DATA(CK_SESSION_HANDLE hsess,CK_OBJECT_HANDLE hkey,CK_ULONG blocklen)105 int encrypt_DATA(CK_SESSION_HANDLE hsess, CK_OBJECT_HANDLE hkey,
106                  CK_ULONG blocklen)
107 {
108     CK_RV rc;
109     CK_ULONG outlen = 16;
110     unsigned long int i;
111 
112     UNUSED(hkey);
113 
114     for (i = 0; i < DATALEN; i += outlen) {
115         rc = funcs->C_EncryptUpdate(hsess, (CK_BYTE_PTR) (DATA + i), blocklen,
116                                     (CK_BYTE_PTR) (DUMP + i), &outlen);
117         if (rc != CKR_OK) {
118             show_error("C_Encrypt #1", rc);
119             return FALSE;
120         }
121     }
122 
123     return TRUE;
124 }
125 
126 
finalize_des_encrypt_context(CK_SESSION_HANDLE hsess)127 int finalize_des_encrypt_context(CK_SESSION_HANDLE hsess)
128 {
129     CK_RV rc;
130     CK_ULONG outlen = DATALEN;
131 
132     rc = funcs->C_EncryptFinal(hsess, DUMP, &outlen);
133     if (rc != CKR_OK) {
134         show_error("C_EncryptFinal#1", rc);
135         return FALSE;
136     }
137 
138     rc = funcs->C_CloseSession(hsess);
139     if (rc != CKR_OK) {
140         show_error("C_CloseSession #1", rc);
141         return FALSE;
142     }
143 
144     return TRUE;
145 }
146 
close_all_sess(void)147 int close_all_sess(void)
148 {
149     CK_SLOT_ID slot_id;
150     CK_RV rc;
151 
152     slot_id = SLOT_ID;
153 
154     rc = funcs->C_CloseAllSessions(slot_id);
155     if (rc != CKR_OK) {
156         show_error("C_CloseAllSessions #1", rc);
157         return FALSE;
158     }
159 
160     return TRUE;
161 }
162 
do_SessionPerformance(unsigned int count)163 int do_SessionPerformance(unsigned int count)
164 {
165     SYSTEMTIME t1, t2;
166     int rc;
167     unsigned int i;
168     context_table_t *t = NULL;
169 
170     if (count == 0) {
171         show_error("do_SessionPerformance: zero session count", (CK_RV) 0);
172         return FALSE;
173     }
174 
175     t = (context_table_t *) calloc(count, sizeof(context_table_t));
176     if (t == NULL) {
177         show_error("do_SessionPerformance: insuficient memory", (CK_RV) 0);
178         return FALSE;
179     }
180 
181     /* create encryption contexts */
182     for (i = 0; i < count; i++) {
183         rc = create_des_encrypt_context(&(t[i].hsess), &(t[i].hkey));
184         if (rc == FALSE) {
185             show_error("create_aes_encrypt_context", (CK_RV) 0);
186             goto ret;
187         }
188     }
189 
190     /* Time encrypt operation in the first and last session */
191     GetSystemTime(&t1);
192     rc = encrypt_DATA(t[0].hsess, t[0].hkey, 16);
193     if (rc == FALSE) {
194         show_error("encrypt_DATA #1", (CK_RV) 0);
195         goto ret;
196     }
197 
198     rc = encrypt_DATA(t[count - 1].hsess, t[count - 1].hkey, 16);
199     if (rc == FALSE) {
200         show_error("encrypt_DATA #2", (CK_RV) 0);
201         goto ret;
202     }
203     GetSystemTime(&t2);
204     process_time(t1, t2);
205 
206     for (i = 0; i < count; i++) {
207         rc = finalize_des_encrypt_context(t[i].hsess);
208         if (rc == FALSE) {
209             show_error("finalize_aes_encrypt_context", (CK_RV) 0);
210             goto ret;
211         }
212     }
213 
214     rc = TRUE;
215 ret:
216     if (t != NULL)
217         free(t);
218     return rc;
219 }
220 
main(int argc,char ** argv)221 int main(int argc, char **argv)
222 {
223     CK_C_INITIALIZE_ARGS cinit_args;
224     int rc, i;
225 
226 
227     rc = do_ParseArgs(argc, argv);
228     if (rc != 1)
229         return rc;
230 
231     printf("Using slot #%lu...\n\n", SLOT_ID);
232     printf("With option: no_init: %d\n", no_init);
233 
234     rc = do_GetFunctionList();
235     if (!rc) {
236         PRINT_ERR("ERROR do_GetFunctionList() Failed , rc = 0x%0x\n", rc);
237         return rc;
238     }
239 
240     memset(&cinit_args, 0x0, sizeof(cinit_args));
241     cinit_args.flags = CKF_OS_LOCKING_OK;
242 
243     // SAB Add calls to ALL functions before the C_Initialize gets hit
244 
245     funcs->C_Initialize(&cinit_args);
246 
247     {
248         CK_SESSION_HANDLE hsess = 0;
249 
250         rc = funcs->C_GetFunctionStatus(hsess);
251         if (rc != CKR_FUNCTION_NOT_PARALLEL)
252             return rc;
253 
254         rc = funcs->C_CancelFunction(hsess);
255         if (rc != CKR_FUNCTION_NOT_PARALLEL)
256             return rc;
257 
258     }
259 
260     for (i = 100; i < 50000; i = 1.2 * i) {
261         printf("timing do_SessionPerformance(%d)\n", i);
262         do_SessionPerformance(i);
263     }
264 
265     return 0;
266 }
267