xref: /minix3/external/bsd/bind/dist/bin/tests/pkcs11/benchmarks/genrsa.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1 /*	$NetBSD: genrsa.c,v 1.1.1.4 2014/12/10 03:34:28 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Portions copyright (c) 2008 Nominet UK.  All rights reserved.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the above copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
35  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  */
42 
43 /* Id */
44 
45 /* genrsa [-m module] [-s $slot] [-p pin] [-t] [-b bits] [-n count] */
46 
47 /*! \file */
48 
49 #include <config.h>
50 
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <time.h>
55 #include <unistd.h>
56 
57 #include <isc/commandline.h>
58 #include <isc/result.h>
59 #include <isc/types.h>
60 
61 #include <pk11/pk11.h>
62 #include <pk11/result.h>
63 
64 #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
65 #define getpassphrase(x)	getpass(x)
66 #endif
67 
68 #ifndef HAVE_CLOCK_GETTIME
69 #ifndef CLOCK_REALTIME
70 #define CLOCK_REALTIME 0
71 #endif
72 
73 int
clock_gettime(int32_t id,struct timespec * tp)74 clock_gettime(int32_t id, struct timespec *tp)
75 {
76 	struct timeval tv;
77 	int result;
78 
79 	result = gettimeofday(&tv, NULL);
80 	if (result)
81 		return (result);
82 	tp->tv_sec = tv.tv_sec;
83 	tp->tv_nsec = (long) tv.tv_usec * 1000;
84 	return (result);
85 }
86 #endif
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_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 };
98 	CK_OBJECT_HANDLE *pubKey;
99 	CK_OBJECT_HANDLE *privKey;
100 	CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
101 	CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
102 	CK_KEY_TYPE kType = CKK_RSA;
103 	CK_ULONG bits = 1024;
104 	CK_BYTE exponent[] = { 0x01, 0x00, 0x01 };
105 	CK_ATTRIBUTE pubTemplate[] =
106 	{
107 		{ CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
108 		{ CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
109 		{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
110 		{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
111 		{ CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
112 		{ CKA_MODULUS_BITS, &bits, (CK_ULONG) sizeof(bits) },
113 		{ CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) }
114 	};
115 	CK_ATTRIBUTE privTemplate[] =
116 	{
117 		{ CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
118 		{ CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
119 		{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
120 		{ CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) },
121 		{ CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
122 	};
123 	pk11_context_t pctx;
124 	pk11_optype_t op_type = OP_RSA;
125 	char *lib_name = NULL;
126 	char *pin = NULL;
127 	int error = 0;
128 	int c, errflg = 0;
129 	int ontoken  = 0;
130 	unsigned int count = 1000;
131 	unsigned int i;
132 	struct timespec starttime;
133 	struct timespec endtime;
134 
135 	while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tb:n:")) != -1) {
136 		switch (c) {
137 		case 'm':
138 			lib_name = isc_commandline_argument;
139 			break;
140 		case 's':
141 			slot = atoi(isc_commandline_argument);
142 			op_type = OP_ANY;
143 			break;
144 		case 'p':
145 			pin = isc_commandline_argument;
146 			break;
147 		case 't':
148 			ontoken = 1;
149 			break;
150 		case 'b':
151 			bits = (CK_ULONG)atoi(isc_commandline_argument);
152 			break;
153 		case 'n':
154 			count = atoi(isc_commandline_argument);
155 			break;
156 		case ':':
157 			fprintf(stderr,
158 				"Option -%c requires an operand\n",
159 				isc_commandline_option);
160 			errflg++;
161 			break;
162 		case '?':
163 		default:
164 			fprintf(stderr, "Unrecognised option: -%c\n",
165 				isc_commandline_option);
166 			errflg++;
167 		}
168 	}
169 
170 	if (errflg) {
171 		fprintf(stderr, "Usage:\n");
172 		fprintf(stderr,
173 			"\tgenrsa [-m module] [-s slot] [-p pin] "
174 			"[-t] [-b bits] [-n count]\n");
175 		exit(1);
176 	}
177 
178 	pk11_result_register();
179 
180 	/* Allocate hanles */
181 	pubKey = (CK_SESSION_HANDLE *)
182 		malloc(count * sizeof(CK_SESSION_HANDLE));
183 	if (pubKey == NULL) {
184 		perror("malloc");
185 		exit(1);
186 	}
187 	privKey = (CK_SESSION_HANDLE *)
188 		malloc(count * sizeof(CK_SESSION_HANDLE));
189 	if (privKey == NULL) {
190 		free(pubKey);
191 		perror("malloc");
192 		exit(1);
193 	}
194 	for (i = 0; i < count; i++) {
195 		pubKey[i] = CK_INVALID_HANDLE;
196 		privKey[i] = CK_INVALID_HANDLE;
197 	}
198 
199 	/* Initialize the CRYPTOKI library */
200 	if (lib_name != NULL)
201 		pk11_set_lib_name(lib_name);
202 
203 	if (pin == NULL)
204 		pin = getpassphrase("Enter Pin: ");
205 
206 	result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE,
207 				  ISC_TRUE, (const char *) pin, slot);
208 	if ((result != ISC_R_SUCCESS) &&
209 	    (result != PK11_R_NORANDOMSERVICE) &&
210 	    (result != PK11_R_NODIGESTSERVICE) &&
211 	    (result != PK11_R_NOAESSERVICE)) {
212 		fprintf(stderr, "Error initializing PKCS#11: %s\n",
213 			isc_result_totext(result));
214 		exit(1);
215 	}
216 
217 	if (pin != NULL)
218 		memset(pin, 0, strlen((char *)pin));
219 
220 	hSession = pctx.session;
221 
222 	if (ontoken) {
223 		pubTemplate[2].pValue = &truevalue;
224 		privTemplate[2].pValue = &truevalue;
225 	}
226 
227 	if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
228 		perror("clock_gettime(start)");
229 		goto exit_keys;
230 	}
231 
232 	for (i = 0; i < count; i++) {
233 		rv = pkcs_C_GenerateKeyPair(hSession, &mech,
234 				       pubTemplate, 7,
235 				       privTemplate, 5,
236 				       &pubKey[i], &privKey[i]);
237 		if (rv != CKR_OK) {
238 			fprintf(stderr,
239 				"C_GenerateKeyPair[%u]: Error = 0x%.8lX\n",
240 				i, rv);
241 			error = 1;
242 			if (i == 0)
243 				goto exit_keys;
244 			break;
245 		}
246 	}
247 
248 	if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
249 		perror("clock_gettime(end)");
250 		goto exit_keys;
251 	}
252 
253 	endtime.tv_sec -= starttime.tv_sec;
254 	endtime.tv_nsec -= starttime.tv_nsec;
255 	while (endtime.tv_nsec < 0) {
256 		endtime.tv_sec -= 1;
257 		endtime.tv_nsec += 1000000000;
258 	}
259 	printf("%u generated RSA in %ld.%09lds\n", i,
260 	       endtime.tv_sec, endtime.tv_nsec);
261 	if (i > 0)
262 		printf("%g generated RSA/s\n",
263 		       1024 * i / ((double) endtime.tv_sec +
264 				   (double) endtime.tv_nsec / 1000000000.));
265 
266     exit_keys:
267 	for (i = 0; i < count; i++) {
268 		/* Destroy keys */
269 		if (pubKey[i] == CK_INVALID_HANDLE)
270 			goto destroy_priv;
271 		rv = pkcs_C_DestroyObject(hSession, pubKey[i]);
272 		if ((rv != CKR_OK) && !errflg) {
273 			fprintf(stderr,
274 				"C_DestroyObject[pub%u]: Error = 0x%.8lX\n",
275 				i, rv);
276 			errflg = 1;
277 		}
278 	    destroy_priv:
279 		if (privKey[i] == CK_INVALID_HANDLE)
280 			continue;
281 		rv = pkcs_C_DestroyObject(hSession, privKey[i]);
282 		if ((rv != CKR_OK) && !errflg) {
283 			fprintf(stderr,
284 				"C_DestroyObject[priv%u]: Error = 0x%.8lX\n",
285 				i, rv);
286 			errflg = 1;
287 		}
288 	}
289 
290 	free(pubKey);
291 	free(privKey);
292 
293 	pk11_return_session(&pctx);
294 	(void) pk11_finalize();
295 
296 	exit(error);
297 }
298