1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * SPDX-License-Identifier: MPL-2.0
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*
15 * Portions copyright (c) 2008 Nominet UK. All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 /* create [-m module] [-s $slot] [-p pin] [-t] [-n count] */
39
40 /*! \file */
41
42 #include <inttypes.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <time.h>
47 #include <unistd.h>
48
49 #include <isc/commandline.h>
50 #include <isc/print.h>
51 #include <isc/result.h>
52 #include <isc/types.h>
53 #include <isc/util.h>
54
55 #include <pk11/pk11.h>
56 #include <pk11/result.h>
57
58 #ifndef HAVE_CLOCK_GETTIME
59
60 #include <sys/time.h>
61
62 #ifndef CLOCK_REALTIME
63 #define CLOCK_REALTIME 0
64 #endif /* ifndef CLOCK_REALTIME */
65
66 static int
67 clock_gettime(int32_t id, struct timespec *tp);
68
69 static int
clock_gettime(int32_t id,struct timespec * tp)70 clock_gettime(int32_t id, struct timespec *tp) {
71 struct timeval tv;
72 int result;
73
74 UNUSED(id);
75
76 result = gettimeofday(&tv, NULL);
77 if (result == 0) {
78 tp->tv_sec = tv.tv_sec;
79 tp->tv_nsec = (long)tv.tv_usec * 1000;
80 }
81 return (result);
82 }
83 #endif /* ifndef HAVE_CLOCK_GETTIME */
84
85 CK_BYTE buf[1024];
86 char label[16];
87
88 static CK_BBOOL truevalue = TRUE;
89 static CK_BBOOL falsevalue = FALSE;
90
91 int
main(int argc,char * argv[])92 main(int argc, char *argv[]) {
93 isc_result_t result;
94 CK_RV rv;
95 CK_SLOT_ID slot = 0;
96 CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
97 CK_OBJECT_HANDLE *hKey;
98 CK_OBJECT_CLASS kClass = CKO_DATA;
99 CK_ULONG len = sizeof(buf);
100 CK_ATTRIBUTE kTemplate[] = {
101 { CKA_CLASS, &kClass, (CK_ULONG)sizeof(kClass) },
102 { CKA_TOKEN, &falsevalue, (CK_ULONG)sizeof(falsevalue) },
103 { CKA_PRIVATE, &falsevalue, (CK_ULONG)sizeof(falsevalue) },
104 { CKA_LABEL, (CK_BYTE_PTR)label, (CK_ULONG)sizeof(label) },
105 { CKA_VALUE, buf, (CK_ULONG)sizeof(buf) }
106 };
107 pk11_context_t pctx;
108 char *lib_name = NULL;
109 char *pin = NULL;
110 int error = 0;
111 int c, errflg = 0;
112 int ontoken = 0;
113 unsigned int count = 1000;
114 unsigned int i;
115 struct timespec starttime;
116 struct timespec endtime;
117
118 while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
119 switch (c) {
120 case 'm':
121 lib_name = isc_commandline_argument;
122 break;
123 case 's':
124 slot = atoi(isc_commandline_argument);
125 break;
126 case 't':
127 ontoken = 1;
128 break;
129 case 'p':
130 pin = isc_commandline_argument;
131 break;
132 case 'n':
133 count = atoi(isc_commandline_argument);
134 break;
135 case ':':
136 fprintf(stderr, "Option -%c requires an operand\n",
137 isc_commandline_option);
138 errflg++;
139 break;
140 case '?':
141 default:
142 fprintf(stderr, "Unrecognised option: -%c\n",
143 isc_commandline_option);
144 errflg++;
145 }
146 }
147
148 if (errflg) {
149 fprintf(stderr, "Usage:\n");
150 fprintf(stderr, "\tcreate [-m module] [-s slot] [-t] [-n "
151 "count]\n");
152 exit(1);
153 }
154
155 pk11_result_register();
156
157 /* Allocate handles */
158 hKey = (CK_SESSION_HANDLE *)malloc(count * sizeof(CK_SESSION_HANDLE));
159 if (hKey == NULL) {
160 perror("malloc");
161 exit(1);
162 }
163 for (i = 0; i < count; i++)
164 hKey[i] = CK_INVALID_HANDLE;
165
166 /* Initialize the CRYPTOKI library */
167 if (lib_name != NULL) {
168 pk11_set_lib_name(lib_name);
169 }
170
171 if (pin == NULL) {
172 pin = getpass("Enter Pin: ");
173 }
174
175 result = pk11_get_session(&pctx, OP_ANY, true, true, true,
176 (const char *)pin, slot);
177 if ((result != ISC_R_SUCCESS) && (result != PK11_R_NORANDOMSERVICE) &&
178 (result != PK11_R_NODIGESTSERVICE) &&
179 (result != PK11_R_NOAESSERVICE))
180 {
181 fprintf(stderr, "Error initializing PKCS#11: %s\n",
182 isc_result_totext(result));
183 exit(1);
184 }
185
186 if (pin != NULL) {
187 memset(pin, 0, strlen((char *)pin));
188 }
189
190 hSession = pctx.session;
191
192 /* Randomize the buffer */
193 rv = pkcs_C_GenerateRandom(hSession, buf, len);
194 if (rv != CKR_OK) {
195 fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
196 goto exit_objects;
197 }
198
199 if (ontoken) {
200 kTemplate[1].pValue = &truevalue;
201 }
202
203 if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
204 perror("clock_gettime(start)");
205 goto exit_objects;
206 }
207
208 for (i = 0; i < count; i++) {
209 (void)snprintf(label, sizeof(label), "obj%u", i);
210 kTemplate[3].ulValueLen = strlen(label);
211 rv = pkcs_C_CreateObject(hSession, kTemplate, 5, &hKey[i]);
212 if (rv != CKR_OK) {
213 fprintf(stderr, "C_CreateObject[%u]: Error = 0x%.8lX\n",
214 i, rv);
215 error = 1;
216 if (i == 0) {
217 goto exit_objects;
218 }
219 break;
220 }
221 }
222
223 if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
224 perror("clock_gettime(end)");
225 goto exit_objects;
226 }
227
228 endtime.tv_sec -= starttime.tv_sec;
229 endtime.tv_nsec -= starttime.tv_nsec;
230 while (endtime.tv_nsec < 0) {
231 endtime.tv_sec -= 1;
232 endtime.tv_nsec += 1000000000;
233 }
234 printf("%u created objects in %ld.%09lds\n", i, endtime.tv_sec,
235 endtime.tv_nsec);
236 if (i > 0) {
237 printf("%g created objects/s\n",
238 1024 * i /
239 ((double)endtime.tv_sec +
240 (double)endtime.tv_nsec / 1000000000.));
241 }
242
243 exit_objects:
244 for (i = 0; i < count; i++) {
245 /* Destroy objects */
246 if (hKey[i] == CK_INVALID_HANDLE) {
247 continue;
248 }
249 rv = pkcs_C_DestroyObject(hSession, hKey[i]);
250 if ((rv != CKR_OK) && !errflg) {
251 fprintf(stderr,
252 "C_DestroyObject[%u]: Error = 0x%.8lX\n", i,
253 rv);
254 errflg = 1;
255 }
256 }
257
258 free(hKey);
259 pk11_return_session(&pctx);
260 (void)pk11_finalize();
261
262 exit(error);
263 }
264