1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * SPDX-License-Identifier: MPL-2.0
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*
15 * Portions copyright (c) 2008 Nominet UK. All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 /* signrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
39
40 /*! \file */
41
42 #include <inttypes.h>
43 #include <stdio.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 #ifndef HAVE_CLOCK_GETTIME
59
60 #include <sys/time.h>
61
62 #ifndef CLOCK_REALTIME
63 #define CLOCK_REALTIME 0
64 #endif /* ifndef CLOCK_REALTIME */
65
66 static int
67 clock_gettime(int32_t id, struct timespec *tp);
68
69 static int
clock_gettime(int32_t id,struct timespec * tp)70 clock_gettime(int32_t id, struct timespec *tp) {
71 struct timeval tv;
72 int result;
73
74 UNUSED(id);
75
76 result = gettimeofday(&tv, NULL);
77 if (result == 0) {
78 tp->tv_sec = tv.tv_sec;
79 tp->tv_nsec = (long)tv.tv_usec * 1000;
80 }
81 return (result);
82 }
83 #endif /* ifndef HAVE_CLOCK_GETTIME */
84
85 CK_BYTE modulus[] = {
86 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99, 0x44, 0x82, 0x20, 0x78,
87 0x43, 0x7f, 0x5f, 0x3b, 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90,
88 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f, 0x16, 0x1c, 0x56, 0xf8,
89 0xc1, 0x06, 0x2f, 0x96, 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5,
90 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b, 0x9f, 0xdc, 0x36, 0xcb,
91 0xad, 0x56, 0xf4, 0xbd, 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08,
92 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79, 0xca, 0x4e, 0x72, 0xeb,
93 0xfb, 0x2c, 0xf1, 0x45, 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7,
94 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd, 0x49, 0xdd, 0x8a, 0x3c,
95 0x3c, 0xf7, 0xa1, 0x5d, 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f,
96 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34, 0xbf
97 };
98 CK_BYTE pubexp[] = { 0x01, 0x00, 0x01 };
99 CK_BYTE privexp[] = {
100 0x00, 0xae, 0x02, 0xf1, 0x47, 0xa8, 0x07, 0x02, 0xb8, 0xf1, 0xd6, 0x92,
101 0x03, 0xee, 0x50, 0x33, 0xab, 0x67, 0x9e, 0x3b, 0xb1, 0x57, 0xc7, 0x3e,
102 0xc4, 0x86, 0x46, 0x61, 0xf1, 0xf8, 0xb6, 0x63, 0x9f, 0x91, 0xe6, 0x3f,
103 0x44, 0xb8, 0x77, 0x1b, 0xbe, 0x4c, 0x3c, 0xb8, 0x9f, 0xf7, 0x45, 0x7d,
104 0xbf, 0x4f, 0xef, 0x3b, 0xcc, 0xda, 0x1a, 0x4e, 0x34, 0xa8, 0x40, 0xea,
105 0x51, 0x72, 0x8a, 0xea, 0x47, 0x06, 0x04, 0xd0, 0x62, 0x31, 0xa0, 0x6c,
106 0x09, 0x60, 0xf9, 0xc7, 0x95, 0x88, 0x4a, 0xd7, 0x19, 0xce, 0x89, 0x08,
107 0x87, 0x14, 0xef, 0xcc, 0x0a, 0xef, 0x72, 0xb9, 0x21, 0xf5, 0xf0, 0xcd,
108 0x6d, 0xe5, 0xfa, 0x15, 0x7f, 0xae, 0x33, 0x9f, 0x26, 0xac, 0x2e, 0x52,
109 0x02, 0x07, 0xfb, 0x1d, 0x4b, 0xec, 0x9a, 0x6b, 0x3b, 0x26, 0x1f, 0x52,
110 0xfc, 0x47, 0xf8, 0x66, 0x33, 0xfa, 0x50, 0x6c, 0x41
111 };
112 CK_BYTE prime1[] = { 0x00, 0xe8, 0x98, 0xeb, 0xa1, 0xf0, 0xce, 0xde, 0xc2, 0x74,
113 0x01, 0x18, 0x2b, 0xd3, 0x8f, 0x58, 0xcd, 0xe9, 0x8e, 0x97,
114 0xbe, 0xfe, 0xe8, 0x6f, 0xd6, 0x0c, 0x0a, 0x47, 0xf8, 0x56,
115 0x84, 0x36, 0x15, 0xe6, 0x75, 0x1c, 0x69, 0x48, 0x8b, 0xf5,
116 0x0f, 0x84, 0xd2, 0x60, 0x8b, 0xa2, 0x2a, 0xa1, 0xeb, 0xed,
117 0xbe, 0x2d, 0xe9, 0x41, 0x0b, 0xed, 0x17, 0x7c, 0xd3, 0xa6,
118 0x35, 0x6e, 0xa6, 0xd8, 0x21 };
119 CK_BYTE prime2[] = { 0x00, 0xca, 0x15, 0x6a, 0x43, 0x5e, 0x83, 0xc9, 0x09, 0xeb,
120 0x14, 0x1e, 0x46, 0x46, 0x97, 0xfa, 0xfa, 0x3c, 0x61, 0x7e,
121 0xc1, 0xf8, 0x8c, 0x5e, 0xcb, 0xbf, 0xe4, 0xb9, 0x78, 0x7f,
122 0x4f, 0xab, 0x82, 0x15, 0x53, 0xaa, 0x04, 0xee, 0x11, 0x21,
123 0x2e, 0x23, 0x08, 0xa0, 0x14, 0x6d, 0x3a, 0x88, 0xe6, 0xf8,
124 0xbe, 0x61, 0x38, 0x99, 0xca, 0x36, 0x0d, 0x3e, 0x42, 0x0f,
125 0x63, 0x4d, 0x73, 0xf0, 0xdf };
126 CK_BYTE exp_1[] = { 0x66, 0x2d, 0xb7, 0x65, 0xbe, 0x99, 0xc2, 0x35, 0xfe, 0x2b,
127 0xf4, 0xe8, 0x5b, 0xd9, 0xdf, 0x13, 0x26, 0x04, 0xe4, 0x18,
128 0x9d, 0x76, 0x92, 0x9a, 0x9f, 0x53, 0x6c, 0xe6, 0x65, 0x6b,
129 0x53, 0x2f, 0x2f, 0xbc, 0x46, 0xac, 0xe1, 0x97, 0xca, 0x21,
130 0xf5, 0x21, 0x4e, 0x14, 0x49, 0x3b, 0x1d, 0x42, 0xbd, 0x80,
131 0x0c, 0x3f, 0x29, 0xba, 0x09, 0x7f, 0x85, 0xf0, 0x9c, 0x55,
132 0x60, 0xb4, 0x9e, 0xc1 };
133 CK_BYTE exp_2[] = { 0x00, 0x87, 0x22, 0x74, 0xf1, 0xe2, 0x15, 0x3c, 0x6d, 0xde,
134 0x7e, 0x90, 0x94, 0x2c, 0x06, 0xdb, 0xb5, 0x54, 0x85, 0x59,
135 0xcf, 0x7a, 0x56, 0xdb, 0xd9, 0x62, 0x54, 0x20, 0x56, 0xdc,
136 0xc3, 0xb9, 0x0b, 0xff, 0x18, 0xf8, 0x7b, 0xdd, 0x7b, 0x24,
137 0xf6, 0x06, 0x45, 0x71, 0x4e, 0xd7, 0x90, 0x2a, 0x16, 0x52,
138 0x46, 0x75, 0x1a, 0xf5, 0x74, 0x8c, 0x5a, 0xa4, 0xc4, 0x66,
139 0x27, 0xe0, 0x96, 0x64, 0x7f };
140 CK_BYTE coeff[] = { 0x00, 0xd0, 0x1f, 0xb3, 0x47, 0x40, 0x93, 0x8b, 0x99, 0xd7,
141 0xb5, 0xc6, 0x09, 0x82, 0x65, 0x94, 0x9d, 0x56, 0x0a, 0x05,
142 0x55, 0x7d, 0x93, 0x04, 0xa4, 0x26, 0xee, 0x42, 0x86, 0xa3,
143 0xf1, 0xd5, 0x7a, 0x42, 0x84, 0x3c, 0x21, 0x96, 0x9a, 0xd9,
144 0x36, 0xd4, 0x62, 0x01, 0xb0, 0x8b, 0x77, 0xe5, 0xcc, 0x1b,
145 0xd2, 0x12, 0xd2, 0x9c, 0x89, 0x67, 0x0c, 0x00, 0x09, 0x56,
146 0x8c, 0x33, 0x57, 0xf9, 0x8c };
147
148 CK_BYTE buf[1024];
149 CK_BYTE sig[128];
150
151 static CK_BBOOL truevalue = TRUE;
152 static CK_BBOOL falsevalue = FALSE;
153
154 int
main(int argc,char * argv[])155 main(int argc, char *argv[]) {
156 isc_result_t result;
157 CK_RV rv;
158 CK_SLOT_ID slot = 0;
159 CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
160 CK_ULONG len;
161 CK_ULONG slen;
162 CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
163 CK_OBJECT_CLASS kClass = CKO_PRIVATE_KEY;
164 CK_KEY_TYPE kType = CKK_RSA;
165 CK_ATTRIBUTE kTemplate[] = {
166 { CKA_CLASS, &kClass, (CK_ULONG)sizeof(kClass) },
167 { CKA_KEY_TYPE, &kType, (CK_ULONG)sizeof(kType) },
168 { CKA_TOKEN, &falsevalue, (CK_ULONG)sizeof(falsevalue) },
169 { CKA_PRIVATE, &truevalue, (CK_ULONG)sizeof(truevalue) },
170 { CKA_SIGN, &truevalue, (CK_ULONG)sizeof(truevalue) },
171 { CKA_MODULUS, modulus, (CK_ULONG)sizeof(modulus) },
172 { CKA_PUBLIC_EXPONENT, pubexp, (CK_ULONG)sizeof(pubexp) },
173 { CKA_PRIVATE_EXPONENT, privexp, (CK_ULONG)sizeof(privexp) },
174 { CKA_PRIME_1, prime1, (CK_ULONG)sizeof(prime1) },
175 { CKA_PRIME_2, prime2, (CK_ULONG)sizeof(prime2) },
176 { CKA_EXPONENT_1, exp_1, (CK_ULONG)sizeof(exp_1) },
177 { CKA_EXPONENT_2, exp_2, (CK_ULONG)sizeof(exp_2) },
178 { CKA_COEFFICIENT, coeff, (CK_ULONG)sizeof(coeff) }
179 };
180 CK_MECHANISM mech = { CKM_SHA1_RSA_PKCS, NULL, 0 };
181 pk11_context_t pctx;
182 pk11_optype_t op_type = OP_RSA;
183 char *lib_name = NULL;
184 char *pin = NULL;
185 int error = 0;
186 int c, errflg = 0;
187 int ontoken = 0;
188 unsigned int count = 1000;
189 unsigned int i;
190 struct timespec starttime;
191 struct timespec endtime;
192
193 while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
194 switch (c) {
195 case 'm':
196 lib_name = isc_commandline_argument;
197 break;
198 case 's':
199 slot = atoi(isc_commandline_argument);
200 op_type = OP_ANY;
201 break;
202 case 'p':
203 pin = isc_commandline_argument;
204 break;
205 case 't':
206 ontoken = 1;
207 break;
208 case 'n':
209 count = atoi(isc_commandline_argument);
210 break;
211 case ':':
212 fprintf(stderr, "Option -%c requires an operand\n",
213 isc_commandline_option);
214 errflg++;
215 break;
216 case '?':
217 default:
218 fprintf(stderr, "Unrecognised option: -%c\n",
219 isc_commandline_option);
220 errflg++;
221 }
222 }
223
224 if (errflg) {
225 fprintf(stderr, "Usage:\n");
226 fprintf(stderr, "\tsign [-m module] [-s slot] [-p pin] "
227 "[-t] [-n count]\n");
228 exit(1);
229 }
230
231 pk11_result_register();
232
233 /* Initialize the CRYPTOKI library */
234 if (lib_name != NULL) {
235 pk11_set_lib_name(lib_name);
236 }
237
238 if (pin == NULL) {
239 pin = getpass("Enter Pin: ");
240 }
241
242 result = pk11_get_session(&pctx, op_type, false, true, true,
243 (const char *)pin, slot);
244 if ((result != ISC_R_SUCCESS) && (result != PK11_R_NORANDOMSERVICE) &&
245 (result != PK11_R_NODIGESTSERVICE) &&
246 (result != PK11_R_NOAESSERVICE))
247 {
248 fprintf(stderr, "Error initializing PKCS#11: %s\n",
249 isc_result_totext(result));
250 exit(1);
251 }
252
253 if (pin != NULL) {
254 memset(pin, 0, strlen((char *)pin));
255 }
256
257 hSession = pctx.session;
258
259 /* Create the private RSA key */
260 if (ontoken) {
261 kTemplate[2].pValue = &truevalue;
262 }
263
264 rv = pkcs_C_CreateObject(hSession, kTemplate, 13, &hKey);
265 if (rv != CKR_OK) {
266 fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv);
267 goto exit_key;
268 }
269
270 /* Randomize the buffer */
271 len = (CK_ULONG)sizeof(buf);
272 rv = pkcs_C_GenerateRandom(hSession, buf, len);
273 if (rv != CKR_OK) {
274 fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
275 goto exit_key;
276 }
277
278 if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
279 perror("clock_gettime(start)");
280 goto exit_key;
281 }
282
283 for (i = 0; i < count; i++) {
284 /* Initialize Sign */
285 rv = pkcs_C_SignInit(hSession, &mech, hKey);
286 if (rv != CKR_OK) {
287 fprintf(stderr, "C_SignInit[%u]: Error = 0x%.8lX\n", i,
288 rv);
289 error = 1;
290 break;
291 }
292
293 /* Perform Sign */
294 slen = (CK_ULONG)sizeof(sig);
295 rv = pkcs_C_Sign(hSession, buf, len, sig, &slen);
296 if (rv != CKR_OK) {
297 fprintf(stderr, "C_Sign[%u]: Error = 0x%.8lX\n", i, rv);
298 error = 1;
299 break;
300 }
301 }
302
303 if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
304 perror("clock_gettime(end)");
305 goto exit_key;
306 }
307
308 endtime.tv_sec -= starttime.tv_sec;
309 endtime.tv_nsec -= starttime.tv_nsec;
310 while (endtime.tv_nsec < 0) {
311 endtime.tv_sec -= 1;
312 endtime.tv_nsec += 1000000000;
313 }
314 printf("%u RSA signs in %ld.%09lds\n", i, endtime.tv_sec,
315 endtime.tv_nsec);
316 if (i > 0) {
317 printf("%g RSA signs/s\n",
318 1024 * i /
319 ((double)endtime.tv_sec +
320 (double)endtime.tv_nsec / 1000000000.));
321 }
322
323 exit_key:
324 if (hKey != CK_INVALID_HANDLE) {
325 rv = pkcs_C_DestroyObject(hSession, hKey);
326 if (rv != CKR_OK) {
327 fprintf(stderr, "C_DestroyObject: Error = 0x%.8lX\n",
328 rv);
329 }
330 }
331
332 pk11_return_session(&pctx);
333 (void)pk11_finalize();
334
335 exit(error);
336 }
337