1 /*	$NetBSD: pubrsa.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 /* pubrsa [-m module] [-s $slot] [-p pin] [-t] [-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/print.h>
59 #include <isc/result.h>
60 #include <isc/types.h>
61 
62 #include <pk11/pk11.h>
63 #include <pk11/result.h>
64 
65 #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
66 #define getpassphrase(x)	getpass(x)
67 #endif
68 
69 #ifndef HAVE_CLOCK_GETTIME
70 #ifndef CLOCK_REALTIME
71 #define CLOCK_REALTIME 0
72 #endif
73 
74 int
clock_gettime(int32_t id,struct timespec * tp)75 clock_gettime(int32_t id, struct timespec *tp)
76 {
77 	struct timeval tv;
78 	int result;
79 
80 	result = gettimeofday(&tv, NULL);
81 	if (result)
82 		return (result);
83 	tp->tv_sec = tv.tv_sec;
84 	tp->tv_nsec = (long) tv.tv_usec * 1000;
85 	return (result);
86 }
87 #endif
88 
89 CK_BYTE modulus[] = {
90 	0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99,
91 	0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b,
92 	0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90,
93 	0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f,
94 	0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96,
95 	0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5,
96 	0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b,
97 	0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd,
98 	0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08,
99 	0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79,
100 	0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45,
101 	0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7,
102 	0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd,
103 	0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d,
104 	0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f,
105 	0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34,
106 	0xbf
107 };
108 CK_BYTE exponent[] = { 0x01, 0x00, 0x01 };
109 
110 char label[16];
111 
112 static CK_BBOOL truevalue = TRUE;
113 static CK_BBOOL falsevalue = FALSE;
114 
115 int
main(int argc,char * argv[])116 main(int argc, char *argv[]) {
117 	isc_result_t result;
118 	CK_RV rv;
119 	CK_SLOT_ID slot = 0;
120 	CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
121 	CK_OBJECT_HANDLE *hKey;
122 	CK_OBJECT_CLASS kClass = CKO_PUBLIC_KEY;
123 	CK_KEY_TYPE kType = CKK_RSA;
124 	CK_ATTRIBUTE kTemplate[] =
125 	{
126 		{ CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
127 		{ CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
128 		{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
129 		{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
130 		{ CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) },
131 		{ CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
132 		{ CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
133 		{ CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) }
134 	};
135 	pk11_context_t pctx;
136 	pk11_optype_t op_type = OP_RSA;
137 	char *lib_name = NULL;
138 	char *pin = NULL;
139 	int error = 0;
140 	int c, errflg = 0;
141 	int ontoken  = 0;
142 	unsigned int count = 1000;
143 	unsigned int i;
144 	struct timespec starttime;
145 	struct timespec endtime;
146 
147 	while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
148 		switch (c) {
149 		case 'm':
150 			lib_name = isc_commandline_argument;
151 			break;
152 		case 's':
153 			slot = atoi(isc_commandline_argument);
154 			op_type = OP_ANY;
155 			break;
156 		case 'p':
157 			pin = isc_commandline_argument;
158 			break;
159 		case 't':
160 			ontoken = 1;
161 			break;
162 		case 'n':
163 			count = atoi(isc_commandline_argument);
164 			break;
165 		case ':':
166 			fprintf(stderr,
167 				"Option -%c requires an operand\n",
168 				isc_commandline_option);
169 			errflg++;
170 			break;
171 		case '?':
172 		default:
173 			fprintf(stderr, "Unrecognised option: -%c\n",
174 				isc_commandline_option);
175 			errflg++;
176 		}
177 	}
178 
179 	if (errflg) {
180 		fprintf(stderr, "Usage:\n");
181 		fprintf(stderr,
182 			"\tpubrsa [-m module] [-s slot] [-p pin] "
183 			"[-t] [-n count]\n");
184 		exit(1);
185 	}
186 
187 	pk11_result_register();
188 
189 	/* Allocate hanles */
190 	hKey = (CK_SESSION_HANDLE *)
191 		malloc(count * sizeof(CK_SESSION_HANDLE));
192 	if (hKey == NULL) {
193 		perror("malloc");
194 		exit(1);
195 	}
196 	for (i = 0; i < count; i++)
197 		hKey[i] = CK_INVALID_HANDLE;
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 		free(hKey);
215 		exit(1);
216 	}
217 
218 	if (pin != NULL)
219 		memset(pin, 0, strlen((char *)pin));
220 
221 	hSession = pctx.session;
222 
223 	if (ontoken)
224 		kTemplate[2].pValue = &truevalue;
225 
226 	if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
227 		perror("clock_gettime(start)");
228 		goto exit_objects;
229 	}
230 
231 	for (i = 0; i < count; i++) {
232 		(void) snprintf(label, sizeof(label), "obj%u", i);
233 		kTemplate[4].ulValueLen = strlen(label);
234 		rv = pkcs_C_CreateObject(hSession, kTemplate, 8, &hKey[i]);
235 		if (rv != CKR_OK) {
236 			fprintf(stderr,
237 				"C_CreateObject[%u]: Error = 0x%.8lX\n",
238 				i, rv);
239 			error = 1;
240 			if (i == 0)
241 				goto exit_objects;
242 			break;
243 		}
244 	}
245 
246 	if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
247 		perror("clock_gettime(end)");
248 		goto exit_objects;
249 	}
250 
251 	endtime.tv_sec -= starttime.tv_sec;
252 	endtime.tv_nsec -= starttime.tv_nsec;
253 	while (endtime.tv_nsec < 0) {
254 		endtime.tv_sec -= 1;
255 		endtime.tv_nsec += 1000000000;
256 	}
257 	printf("%u public RSA keys in %ld.%09lds\n", i,
258 	       endtime.tv_sec, endtime.tv_nsec);
259 	if (i > 0)
260 		printf("%g public RSA keys/s\n",
261 		       1024 * i / ((double) endtime.tv_sec +
262 				   (double) endtime.tv_nsec / 1000000000.));
263 
264     exit_objects:
265 	for (i = 0; i < count; i++) {
266 		/* Destroy objects */
267 		if (hKey[i] == CK_INVALID_HANDLE)
268 			continue;
269 		rv = pkcs_C_DestroyObject(hSession, hKey[i]);
270 		if ((rv != CKR_OK) && !errflg) {
271 			fprintf(stderr,
272 				"C_DestroyObject[%u]: Error = 0x%.8lX\n",
273 				i, rv);
274 			errflg = 1;
275 		}
276 	}
277 
278 	free(hKey);
279 
280 	pk11_return_session(&pctx);
281 	(void) pk11_finalize();
282 
283 	exit(error);
284 }
285