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 https://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 /* signrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
37 
38 /*! \file */
39 
40 #include <config.h>
41 
42 #include <stdio.h>
43 #include <inttypes.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 #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
59 #define getpassphrase(x)	getpass(x)
60 #endif
61 
62 #ifndef HAVE_CLOCK_GETTIME
63 
64 #include <sys/time.h>
65 
66 #ifndef CLOCK_REALTIME
67 #define CLOCK_REALTIME 0
68 #endif
69 
70 static int clock_gettime(int32_t id, struct timespec *tp);
71 
72 static int
clock_gettime(int32_t id,struct timespec * tp)73 clock_gettime(int32_t id, struct timespec *tp)
74 {
75 	struct timeval tv;
76 	int result;
77 
78 	UNUSED(id);
79 
80 	result = gettimeofday(&tv, NULL);
81 	if (result == 0) {
82 		tp->tv_sec = tv.tv_sec;
83 		tp->tv_nsec = (long) tv.tv_usec * 1000;
84 	}
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 pubexp[] = { 0x01, 0x00, 0x01 };
109 CK_BYTE privexp[] = {
110 	0x00, 0xae, 0x02, 0xf1, 0x47, 0xa8, 0x07, 0x02,
111 	0xb8, 0xf1, 0xd6, 0x92, 0x03, 0xee, 0x50, 0x33,
112 	0xab, 0x67, 0x9e, 0x3b, 0xb1, 0x57, 0xc7, 0x3e,
113 	0xc4, 0x86, 0x46, 0x61, 0xf1, 0xf8, 0xb6, 0x63,
114 	0x9f, 0x91, 0xe6, 0x3f, 0x44, 0xb8, 0x77, 0x1b,
115 	0xbe, 0x4c, 0x3c, 0xb8, 0x9f, 0xf7, 0x45, 0x7d,
116 	0xbf, 0x4f, 0xef, 0x3b, 0xcc, 0xda, 0x1a, 0x4e,
117 	0x34, 0xa8, 0x40, 0xea, 0x51, 0x72, 0x8a, 0xea,
118 	0x47, 0x06, 0x04, 0xd0, 0x62, 0x31, 0xa0, 0x6c,
119 	0x09, 0x60, 0xf9, 0xc7, 0x95, 0x88, 0x4a, 0xd7,
120 	0x19, 0xce, 0x89, 0x08, 0x87, 0x14, 0xef, 0xcc,
121 	0x0a, 0xef, 0x72, 0xb9, 0x21, 0xf5, 0xf0, 0xcd,
122 	0x6d, 0xe5, 0xfa, 0x15, 0x7f, 0xae, 0x33, 0x9f,
123 	0x26, 0xac, 0x2e, 0x52, 0x02, 0x07, 0xfb, 0x1d,
124 	0x4b, 0xec, 0x9a, 0x6b, 0x3b, 0x26, 0x1f, 0x52,
125 	0xfc, 0x47, 0xf8, 0x66, 0x33, 0xfa, 0x50, 0x6c,
126 	0x41
127 };
128 CK_BYTE prime1[] = {
129 	0x00, 0xe8, 0x98, 0xeb, 0xa1, 0xf0, 0xce, 0xde,
130 	0xc2, 0x74, 0x01, 0x18, 0x2b, 0xd3, 0x8f, 0x58,
131 	0xcd, 0xe9, 0x8e, 0x97, 0xbe, 0xfe, 0xe8, 0x6f,
132 	0xd6, 0x0c, 0x0a, 0x47, 0xf8, 0x56, 0x84, 0x36,
133 	0x15, 0xe6, 0x75, 0x1c, 0x69, 0x48, 0x8b, 0xf5,
134 	0x0f, 0x84, 0xd2, 0x60, 0x8b, 0xa2, 0x2a, 0xa1,
135 	0xeb, 0xed, 0xbe, 0x2d, 0xe9, 0x41, 0x0b, 0xed,
136 	0x17, 0x7c, 0xd3, 0xa6, 0x35, 0x6e, 0xa6, 0xd8,
137 	0x21
138 };
139 CK_BYTE prime2[] = {
140 	0x00, 0xca, 0x15, 0x6a, 0x43, 0x5e, 0x83, 0xc9,
141 	0x09, 0xeb, 0x14, 0x1e, 0x46, 0x46, 0x97, 0xfa,
142 	0xfa, 0x3c, 0x61, 0x7e, 0xc1, 0xf8, 0x8c, 0x5e,
143 	0xcb, 0xbf, 0xe4, 0xb9, 0x78, 0x7f, 0x4f, 0xab,
144 	0x82, 0x15, 0x53, 0xaa, 0x04, 0xee, 0x11, 0x21,
145 	0x2e, 0x23, 0x08, 0xa0, 0x14, 0x6d, 0x3a, 0x88,
146 	0xe6, 0xf8, 0xbe, 0x61, 0x38, 0x99, 0xca, 0x36,
147 	0x0d, 0x3e, 0x42, 0x0f, 0x63, 0x4d, 0x73, 0xf0,
148 	0xdf
149 };
150 CK_BYTE exp_1[] = {
151 	0x66, 0x2d, 0xb7, 0x65, 0xbe, 0x99, 0xc2, 0x35,
152 	0xfe, 0x2b, 0xf4, 0xe8, 0x5b, 0xd9, 0xdf, 0x13,
153 	0x26, 0x04, 0xe4, 0x18, 0x9d, 0x76, 0x92, 0x9a,
154 	0x9f, 0x53, 0x6c, 0xe6, 0x65, 0x6b, 0x53, 0x2f,
155 	0x2f, 0xbc, 0x46, 0xac, 0xe1, 0x97, 0xca, 0x21,
156 	0xf5, 0x21, 0x4e, 0x14, 0x49, 0x3b, 0x1d, 0x42,
157 	0xbd, 0x80, 0x0c, 0x3f, 0x29, 0xba, 0x09, 0x7f,
158 	0x85, 0xf0, 0x9c, 0x55, 0x60, 0xb4, 0x9e, 0xc1
159 };
160 CK_BYTE exp_2[] = {
161 	0x00, 0x87, 0x22, 0x74, 0xf1, 0xe2, 0x15, 0x3c,
162 	0x6d, 0xde, 0x7e, 0x90, 0x94, 0x2c, 0x06, 0xdb,
163 	0xb5, 0x54, 0x85, 0x59, 0xcf, 0x7a, 0x56, 0xdb,
164 	0xd9, 0x62, 0x54, 0x20, 0x56, 0xdc, 0xc3, 0xb9,
165 	0x0b, 0xff, 0x18, 0xf8, 0x7b, 0xdd, 0x7b, 0x24,
166 	0xf6, 0x06, 0x45, 0x71, 0x4e, 0xd7, 0x90, 0x2a,
167 	0x16, 0x52, 0x46, 0x75, 0x1a, 0xf5, 0x74, 0x8c,
168 	0x5a, 0xa4, 0xc4, 0x66, 0x27, 0xe0, 0x96, 0x64,
169 	0x7f
170 };
171 CK_BYTE coeff[] = {
172 	0x00, 0xd0, 0x1f, 0xb3, 0x47, 0x40, 0x93, 0x8b,
173 	0x99, 0xd7, 0xb5, 0xc6, 0x09, 0x82, 0x65, 0x94,
174 	0x9d, 0x56, 0x0a, 0x05, 0x55, 0x7d, 0x93, 0x04,
175 	0xa4, 0x26, 0xee, 0x42, 0x86, 0xa3, 0xf1, 0xd5,
176 	0x7a, 0x42, 0x84, 0x3c, 0x21, 0x96, 0x9a, 0xd9,
177 	0x36, 0xd4, 0x62, 0x01, 0xb0, 0x8b, 0x77, 0xe5,
178 	0xcc, 0x1b, 0xd2, 0x12, 0xd2, 0x9c, 0x89, 0x67,
179 	0x0c, 0x00, 0x09, 0x56, 0x8c, 0x33, 0x57, 0xf9,
180 	0x8c
181 };
182 
183 CK_BYTE buf[1024];
184 CK_BYTE sig[128];
185 
186 static CK_BBOOL truevalue = TRUE;
187 static CK_BBOOL falsevalue = FALSE;
188 
189 int
main(int argc,char * argv[])190 main(int argc, char *argv[]) {
191 	isc_result_t result;
192 	CK_RV rv;
193 	CK_SLOT_ID slot = 0;
194 	CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
195 	CK_ULONG len;
196 	CK_ULONG slen;
197 	CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
198 	CK_OBJECT_CLASS kClass = CKO_PRIVATE_KEY;
199 	CK_KEY_TYPE kType = CKK_RSA;
200 	CK_ATTRIBUTE kTemplate[] =
201 	{
202 		{ CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
203 		{ CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
204 		{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
205 		{ CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) },
206 		{ CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
207 		{ CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
208 		{ CKA_PUBLIC_EXPONENT, pubexp, (CK_ULONG) sizeof(pubexp) },
209 		{ CKA_PRIVATE_EXPONENT, privexp, (CK_ULONG) sizeof(privexp) },
210 		{ CKA_PRIME_1, prime1, (CK_ULONG) sizeof(prime1) },
211 		{ CKA_PRIME_2, prime2, (CK_ULONG) sizeof(prime2) },
212 		{ CKA_EXPONENT_1, exp_1, (CK_ULONG) sizeof(exp_1) },
213 		{ CKA_EXPONENT_2, exp_2, (CK_ULONG) sizeof(exp_2) },
214 		{ CKA_COEFFICIENT, coeff, (CK_ULONG) sizeof(coeff) }
215 	};
216 	CK_MECHANISM mech = { CKM_SHA1_RSA_PKCS, NULL, 0 };
217 	pk11_context_t pctx;
218 	pk11_optype_t op_type = OP_RSA;
219 	char *lib_name = NULL;
220 	char *pin = NULL;
221 	int error = 0;
222 	int c, errflg = 0;
223 	int ontoken  = 0;
224 	unsigned int count = 1000;
225 	unsigned int i;
226 	struct timespec starttime;
227 	struct timespec endtime;
228 
229 	while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
230 		switch (c) {
231 		case 'm':
232 			lib_name = isc_commandline_argument;
233 			break;
234 		case 's':
235 			slot = atoi(isc_commandline_argument);
236 			op_type = OP_ANY;
237 			break;
238 		case 'p':
239 			pin = isc_commandline_argument;
240 			break;
241 		case 't':
242 			ontoken = 1;
243 			break;
244 		case 'n':
245 			count = atoi(isc_commandline_argument);
246 			break;
247 		case ':':
248 			fprintf(stderr,
249 				"Option -%c requires an operand\n",
250 				isc_commandline_option);
251 			errflg++;
252 			break;
253 		case '?':
254 		default:
255 			fprintf(stderr, "Unrecognised option: -%c\n",
256 				isc_commandline_option);
257 			errflg++;
258 		}
259 	}
260 
261 	if (errflg) {
262 		fprintf(stderr, "Usage:\n");
263 		fprintf(stderr,
264 			"\tsign [-m module] [-s slot] [-p pin] "
265 			"[-t] [-n count]\n");
266 		exit(1);
267 	}
268 
269 	pk11_result_register();
270 
271 	/* Initialize the CRYPTOKI library */
272 	if (lib_name != NULL)
273 		pk11_set_lib_name(lib_name);
274 
275 	if (pin == NULL)
276 		pin = getpassphrase("Enter Pin: ");
277 
278 	result = pk11_get_session(&pctx, op_type, false, true,
279 				  true, (const char *) pin, slot);
280 	if ((result != ISC_R_SUCCESS) &&
281 	    (result != PK11_R_NORANDOMSERVICE) &&
282 	    (result != PK11_R_NODIGESTSERVICE) &&
283 	    (result != PK11_R_NOAESSERVICE)) {
284 		fprintf(stderr, "Error initializing PKCS#11: %s\n",
285 			isc_result_totext(result));
286 		exit(1);
287 	}
288 
289 	if (pin != NULL)
290 		memset(pin, 0, strlen((char *)pin));
291 
292 	hSession = pctx.session;
293 
294 	/* Create the private RSA key */
295 	if (ontoken)
296 		kTemplate[2].pValue = &truevalue;
297 
298 	rv = pkcs_C_CreateObject(hSession, kTemplate, 13, &hKey);
299 	if (rv != CKR_OK) {
300 		fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv);
301 		goto exit_key;
302 	}
303 
304 	/* Randomize the buffer */
305 	len = (CK_ULONG) sizeof(buf);
306 	rv = pkcs_C_GenerateRandom(hSession, buf, len);
307 	if (rv != CKR_OK) {
308 		fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
309 		goto exit_key;
310 	}
311 
312 	if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
313 		perror("clock_gettime(start)");
314 		goto exit_key;
315 	}
316 
317 	for (i = 0; i < count; i++) {
318 		/* Initialize Sign */
319 		rv = pkcs_C_SignInit(hSession, &mech, hKey);
320 		if (rv != CKR_OK) {
321 			fprintf(stderr,
322 				"C_SignInit[%u]: Error = 0x%.8lX\n",
323 				i, rv);
324 			error = 1;
325 			break;
326 		}
327 
328 		/* Perform Sign */
329 		slen = (CK_ULONG) sizeof(sig);
330 		rv = pkcs_C_Sign(hSession, buf, len, sig, &slen);
331 		if (rv != CKR_OK) {
332 			fprintf(stderr,
333 				"C_Sign[%u]: Error = 0x%.8lX\n",
334 				i, rv);
335 			error = 1;
336 			break;
337 		}
338 	}
339 
340 	if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
341 		perror("clock_gettime(end)");
342 		goto exit_key;
343 	}
344 
345 	endtime.tv_sec -= starttime.tv_sec;
346 	endtime.tv_nsec -= starttime.tv_nsec;
347 	while (endtime.tv_nsec < 0) {
348 		endtime.tv_sec -= 1;
349 		endtime.tv_nsec += 1000000000;
350 	}
351 	printf("%u RSA signs in %ld.%09lds\n", i,
352 	       endtime.tv_sec, endtime.tv_nsec);
353 	if (i > 0)
354 		printf("%g RSA signs/s\n",
355 		       1024 * i / ((double) endtime.tv_sec +
356 				   (double) endtime.tv_nsec / 1000000000.));
357 
358     exit_key:
359 	if (hKey != CK_INVALID_HANDLE) {
360 		rv = pkcs_C_DestroyObject(hSession, hKey);
361 		if (rv != CKR_OK)
362 			fprintf(stderr,
363 				"C_DestroyObject: Error = 0x%.8lX\n",
364 				rv);
365 	}
366 
367 	pk11_return_session(&pctx);
368 	(void) pk11_finalize();
369 
370 	exit(error);
371 }
372