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