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