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