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 /* privrsa [-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 char label[16];
149
150 static CK_BBOOL truevalue = TRUE;
151 static CK_BBOOL falsevalue = FALSE;
152
153 int
main(int argc,char * argv[])154 main(int argc, char *argv[]) {
155 isc_result_t result;
156 CK_RV rv;
157 CK_SLOT_ID slot = 0;
158 CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
159 CK_OBJECT_HANDLE *hKey;
160 CK_OBJECT_CLASS kClass = CKO_PRIVATE_KEY;
161 CK_KEY_TYPE kType = CKK_RSA;
162 CK_ATTRIBUTE kTemplate[] = {
163 { CKA_CLASS, &kClass, (CK_ULONG)sizeof(kClass) },
164 { CKA_KEY_TYPE, &kType, (CK_ULONG)sizeof(kType) },
165 { CKA_TOKEN, &falsevalue, (CK_ULONG)sizeof(falsevalue) },
166 { CKA_PRIVATE, &truevalue, (CK_ULONG)sizeof(truevalue) },
167 { CKA_LABEL, (CK_BYTE_PTR)label, (CK_ULONG)sizeof(label) },
168 { CKA_SIGN, &truevalue, (CK_ULONG)sizeof(truevalue) },
169 { CKA_MODULUS, modulus, (CK_ULONG)sizeof(modulus) },
170 { CKA_PUBLIC_EXPONENT, pubexp, (CK_ULONG)sizeof(pubexp) },
171 { CKA_PRIVATE_EXPONENT, privexp, (CK_ULONG)sizeof(privexp) },
172 { CKA_PRIME_1, prime1, (CK_ULONG)sizeof(prime1) },
173 { CKA_PRIME_2, prime2, (CK_ULONG)sizeof(prime2) },
174 { CKA_EXPONENT_1, exp_1, (CK_ULONG)sizeof(exp_1) },
175 { CKA_EXPONENT_2, exp_2, (CK_ULONG)sizeof(exp_2) },
176 { CKA_COEFFICIENT, coeff, (CK_ULONG)sizeof(coeff) }
177 };
178 pk11_context_t pctx;
179 pk11_optype_t op_type = OP_RSA;
180 char *lib_name = NULL;
181 char *pin = NULL;
182 int error = 0;
183 int c, errflg = 0;
184 int ontoken = 0;
185 unsigned int count = 1000;
186 unsigned int i;
187 struct timespec starttime;
188 struct timespec endtime;
189
190 while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
191 switch (c) {
192 case 'm':
193 lib_name = isc_commandline_argument;
194 break;
195 case 's':
196 slot = atoi(isc_commandline_argument);
197 op_type = OP_ANY;
198 break;
199 case 'p':
200 pin = isc_commandline_argument;
201 break;
202 case 't':
203 ontoken = 1;
204 break;
205 case 'n':
206 count = atoi(isc_commandline_argument);
207 break;
208 case ':':
209 fprintf(stderr, "Option -%c requires an operand\n",
210 isc_commandline_option);
211 errflg++;
212 break;
213 case '?':
214 default:
215 fprintf(stderr, "Unrecognised option: -%c\n",
216 isc_commandline_option);
217 errflg++;
218 }
219 }
220
221 if (errflg) {
222 fprintf(stderr, "Usage:\n");
223 fprintf(stderr, "\tprivrsa [-m module] [-s slot] [-p pin] "
224 "[-t] [-n count]\n");
225 exit(1);
226 }
227
228 pk11_result_register();
229
230 /* Allocate handles */
231 hKey = (CK_SESSION_HANDLE *)malloc(count * sizeof(CK_SESSION_HANDLE));
232 if (hKey == NULL) {
233 perror("malloc");
234 exit(1);
235 }
236 for (i = 0; i < count; i++)
237 hKey[i] = CK_INVALID_HANDLE;
238
239 /* Initialize the CRYPTOKI library */
240 if (lib_name != NULL) {
241 pk11_set_lib_name(lib_name);
242 }
243
244 if (pin == NULL) {
245 pin = getpass("Enter Pin: ");
246 }
247
248 result = pk11_get_session(&pctx, op_type, false, true, true,
249 (const char *)pin, slot);
250 if ((result != ISC_R_SUCCESS) && (result != PK11_R_NORANDOMSERVICE) &&
251 (result != PK11_R_NODIGESTSERVICE) &&
252 (result != PK11_R_NOAESSERVICE))
253 {
254 fprintf(stderr, "Error initializing PKCS#11: %s\n",
255 isc_result_totext(result));
256 free(hKey);
257 exit(1);
258 }
259
260 if (pin != NULL) {
261 memset(pin, 0, strlen((char *)pin));
262 }
263
264 hSession = pctx.session;
265
266 if (ontoken) {
267 kTemplate[2].pValue = &truevalue;
268 }
269
270 if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
271 perror("clock_gettime(start)");
272 goto exit_objects;
273 }
274
275 for (i = 0; i < count; i++) {
276 (void)snprintf(label, sizeof(label), "obj%u", i);
277 kTemplate[4].ulValueLen = strlen(label);
278 rv = pkcs_C_CreateObject(hSession, kTemplate, 14, &hKey[i]);
279 if (rv != CKR_OK) {
280 fprintf(stderr, "C_CreateObject[%u]: Error = 0x%.8lX\n",
281 i, rv);
282 error = 1;
283 if (i == 0) {
284 goto exit_objects;
285 }
286 break;
287 }
288 }
289
290 if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
291 perror("clock_gettime(end)");
292 goto exit_objects;
293 }
294
295 endtime.tv_sec -= starttime.tv_sec;
296 endtime.tv_nsec -= starttime.tv_nsec;
297 while (endtime.tv_nsec < 0) {
298 endtime.tv_sec -= 1;
299 endtime.tv_nsec += 1000000000;
300 }
301 printf("%u private RSA keys in %ld.%09lds\n", i, endtime.tv_sec,
302 endtime.tv_nsec);
303 if (i > 0) {
304 printf("%g private RSA keys/s\n",
305 1024 * i /
306 ((double)endtime.tv_sec +
307 (double)endtime.tv_nsec / 1000000000.));
308 }
309
310 exit_objects:
311 for (i = 0; i < count; i++) {
312 /* Destroy objects */
313 if (hKey[i] == CK_INVALID_HANDLE) {
314 continue;
315 }
316 rv = pkcs_C_DestroyObject(hSession, hKey[i]);
317 if ((rv != CKR_OK) && !errflg) {
318 fprintf(stderr,
319 "C_DestroyObject[%u]: Error = 0x%.8lX\n", i,
320 rv);
321 errflg = 1;
322 }
323 }
324
325 free(hKey);
326
327 pk11_return_session(&pctx);
328 (void)pk11_finalize();
329
330 exit(error);
331 }
332