1*c0b5d9fbSchristos /*	$NetBSD: create.c,v 1.7 2022/09/23 12:15:23 christos Exp $	*/
2e2b1b9c0Schristos 
3e2b1b9c0Schristos /*
4e2b1b9c0Schristos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5e2b1b9c0Schristos  *
6*c0b5d9fbSchristos  * SPDX-License-Identifier: MPL-2.0
7*c0b5d9fbSchristos  *
8e2b1b9c0Schristos  * This Source Code Form is subject to the terms of the Mozilla Public
9e2b1b9c0Schristos  * License, v. 2.0.  If a copy of the MPL was not distributed with this
1073584a28Schristos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11e2b1b9c0Schristos  *
12e2b1b9c0Schristos  * See the COPYRIGHT file distributed with this work for additional
13e2b1b9c0Schristos  * information regarding copyright ownership.
14e2b1b9c0Schristos  */
15e2b1b9c0Schristos 
16e2b1b9c0Schristos /*
17e2b1b9c0Schristos  * Portions copyright (c) 2008 Nominet UK.  All rights reserved.
18e2b1b9c0Schristos  *
19e2b1b9c0Schristos  * Redistribution and use in source and binary forms, with or without
20e2b1b9c0Schristos  * modification, are permitted provided that the following conditions
21e2b1b9c0Schristos  * are met:
22e2b1b9c0Schristos  * 1. Redistributions of source code must retain the above copyright
23e2b1b9c0Schristos  *    notice, this list of conditions and the following disclaimer.
24e2b1b9c0Schristos  * 2. Redistributions in binary form must reproduce the above copyright
25e2b1b9c0Schristos  *    notice, this list of conditions and the following disclaimer in the
26e2b1b9c0Schristos  *    documentation and/or other materials provided with the distribution.
27e2b1b9c0Schristos  *
28e2b1b9c0Schristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
29e2b1b9c0Schristos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
30e2b1b9c0Schristos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31e2b1b9c0Schristos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
32e2b1b9c0Schristos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33e2b1b9c0Schristos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34e2b1b9c0Schristos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35e2b1b9c0Schristos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36e2b1b9c0Schristos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37e2b1b9c0Schristos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38e2b1b9c0Schristos  */
39e2b1b9c0Schristos 
40e2b1b9c0Schristos /* create [-m module] [-s $slot] [-p pin] [-t] [-n count] */
41e2b1b9c0Schristos 
42e2b1b9c0Schristos /*! \file */
43e2b1b9c0Schristos 
44f2e20987Schristos #include <inttypes.h>
459742fdb4Schristos #include <stdio.h>
46e2b1b9c0Schristos #include <stdlib.h>
47e2b1b9c0Schristos #include <string.h>
48e2b1b9c0Schristos #include <time.h>
49e2b1b9c0Schristos #include <unistd.h>
50e2b1b9c0Schristos 
51e2b1b9c0Schristos #include <isc/commandline.h>
52e2b1b9c0Schristos #include <isc/print.h>
53e2b1b9c0Schristos #include <isc/result.h>
54e2b1b9c0Schristos #include <isc/types.h>
55e2b1b9c0Schristos #include <isc/util.h>
56e2b1b9c0Schristos 
57e2b1b9c0Schristos #include <pk11/pk11.h>
58e2b1b9c0Schristos #include <pk11/result.h>
59e2b1b9c0Schristos 
60e2b1b9c0Schristos #ifndef HAVE_CLOCK_GETTIME
61e2b1b9c0Schristos 
62e2b1b9c0Schristos #include <sys/time.h>
63e2b1b9c0Schristos 
64e2b1b9c0Schristos #ifndef CLOCK_REALTIME
65e2b1b9c0Schristos #define CLOCK_REALTIME 0
669742fdb4Schristos #endif /* ifndef CLOCK_REALTIME */
67e2b1b9c0Schristos 
68e2b1b9c0Schristos static int
699742fdb4Schristos clock_gettime(int32_t id, struct timespec *tp);
709742fdb4Schristos 
719742fdb4Schristos static int
clock_gettime(int32_t id,struct timespec * tp)729742fdb4Schristos clock_gettime(int32_t id, struct timespec *tp) {
73e2b1b9c0Schristos 	struct timeval tv;
74e2b1b9c0Schristos 	int result;
75e2b1b9c0Schristos 
76e2b1b9c0Schristos 	UNUSED(id);
77e2b1b9c0Schristos 
78e2b1b9c0Schristos 	result = gettimeofday(&tv, NULL);
7955ba2b39Schristos 	if (result == 0) {
80e2b1b9c0Schristos 		tp->tv_sec = tv.tv_sec;
81e2b1b9c0Schristos 		tp->tv_nsec = (long)tv.tv_usec * 1000;
8255ba2b39Schristos 	}
83e2b1b9c0Schristos 	return (result);
84e2b1b9c0Schristos }
859742fdb4Schristos #endif /* ifndef HAVE_CLOCK_GETTIME */
86e2b1b9c0Schristos 
87e2b1b9c0Schristos CK_BYTE buf[1024];
88e2b1b9c0Schristos char label[16];
89e2b1b9c0Schristos 
90e2b1b9c0Schristos static CK_BBOOL truevalue = TRUE;
91e2b1b9c0Schristos static CK_BBOOL falsevalue = FALSE;
92e2b1b9c0Schristos 
93e2b1b9c0Schristos int
main(int argc,char * argv[])94e2b1b9c0Schristos main(int argc, char *argv[]) {
95e2b1b9c0Schristos 	isc_result_t result;
96e2b1b9c0Schristos 	CK_RV rv;
97e2b1b9c0Schristos 	CK_SLOT_ID slot = 0;
98e2b1b9c0Schristos 	CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
99e2b1b9c0Schristos 	CK_OBJECT_HANDLE *hKey;
100e2b1b9c0Schristos 	CK_OBJECT_CLASS kClass = CKO_DATA;
101e2b1b9c0Schristos 	CK_ULONG len = sizeof(buf);
1029742fdb4Schristos 	CK_ATTRIBUTE kTemplate[] = {
103e2b1b9c0Schristos 		{ CKA_CLASS, &kClass, (CK_ULONG)sizeof(kClass) },
104e2b1b9c0Schristos 		{ CKA_TOKEN, &falsevalue, (CK_ULONG)sizeof(falsevalue) },
105e2b1b9c0Schristos 		{ CKA_PRIVATE, &falsevalue, (CK_ULONG)sizeof(falsevalue) },
106e2b1b9c0Schristos 		{ CKA_LABEL, (CK_BYTE_PTR)label, (CK_ULONG)sizeof(label) },
107e2b1b9c0Schristos 		{ CKA_VALUE, buf, (CK_ULONG)sizeof(buf) }
108e2b1b9c0Schristos 	};
109e2b1b9c0Schristos 	pk11_context_t pctx;
110e2b1b9c0Schristos 	char *lib_name = NULL;
111e2b1b9c0Schristos 	char *pin = NULL;
112e2b1b9c0Schristos 	int error = 0;
113e2b1b9c0Schristos 	int c, errflg = 0;
114e2b1b9c0Schristos 	int ontoken = 0;
115e2b1b9c0Schristos 	unsigned int count = 1000;
116e2b1b9c0Schristos 	unsigned int i;
117e2b1b9c0Schristos 	struct timespec starttime;
118e2b1b9c0Schristos 	struct timespec endtime;
119e2b1b9c0Schristos 
120e2b1b9c0Schristos 	while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
121e2b1b9c0Schristos 		switch (c) {
122e2b1b9c0Schristos 		case 'm':
123e2b1b9c0Schristos 			lib_name = isc_commandline_argument;
124e2b1b9c0Schristos 			break;
125e2b1b9c0Schristos 		case 's':
126e2b1b9c0Schristos 			slot = atoi(isc_commandline_argument);
127e2b1b9c0Schristos 			break;
128e2b1b9c0Schristos 		case 't':
129e2b1b9c0Schristos 			ontoken = 1;
130e2b1b9c0Schristos 			break;
131e2b1b9c0Schristos 		case 'p':
132e2b1b9c0Schristos 			pin = isc_commandline_argument;
133e2b1b9c0Schristos 			break;
134e2b1b9c0Schristos 		case 'n':
135e2b1b9c0Schristos 			count = atoi(isc_commandline_argument);
136e2b1b9c0Schristos 			break;
137e2b1b9c0Schristos 		case ':':
1389742fdb4Schristos 			fprintf(stderr, "Option -%c requires an operand\n",
139e2b1b9c0Schristos 				isc_commandline_option);
140e2b1b9c0Schristos 			errflg++;
141e2b1b9c0Schristos 			break;
142e2b1b9c0Schristos 		case '?':
143e2b1b9c0Schristos 		default:
144e2b1b9c0Schristos 			fprintf(stderr, "Unrecognised option: -%c\n",
145e2b1b9c0Schristos 				isc_commandline_option);
146e2b1b9c0Schristos 			errflg++;
147e2b1b9c0Schristos 		}
148e2b1b9c0Schristos 	}
149e2b1b9c0Schristos 
150e2b1b9c0Schristos 	if (errflg) {
151e2b1b9c0Schristos 		fprintf(stderr, "Usage:\n");
1529742fdb4Schristos 		fprintf(stderr, "\tcreate [-m module] [-s slot] [-t] [-n "
1539742fdb4Schristos 				"count]\n");
154e2b1b9c0Schristos 		exit(1);
155e2b1b9c0Schristos 	}
156e2b1b9c0Schristos 
157e2b1b9c0Schristos 	pk11_result_register();
158e2b1b9c0Schristos 
1599742fdb4Schristos 	/* Allocate handles */
1609742fdb4Schristos 	hKey = (CK_SESSION_HANDLE *)malloc(count * sizeof(CK_SESSION_HANDLE));
161e2b1b9c0Schristos 	if (hKey == NULL) {
162e2b1b9c0Schristos 		perror("malloc");
163e2b1b9c0Schristos 		exit(1);
164e2b1b9c0Schristos 	}
165*c0b5d9fbSchristos 	for (i = 0; i < count; i++) {
166e2b1b9c0Schristos 		hKey[i] = CK_INVALID_HANDLE;
167*c0b5d9fbSchristos 	}
168e2b1b9c0Schristos 
169e2b1b9c0Schristos 	/* Initialize the CRYPTOKI library */
1709742fdb4Schristos 	if (lib_name != NULL) {
171e2b1b9c0Schristos 		pk11_set_lib_name(lib_name);
1729742fdb4Schristos 	}
173e2b1b9c0Schristos 
1749742fdb4Schristos 	if (pin == NULL) {
175f2e20987Schristos 		pin = getpass("Enter Pin: ");
1769742fdb4Schristos 	}
177e2b1b9c0Schristos 
1789742fdb4Schristos 	result = pk11_get_session(&pctx, OP_ANY, true, true, true,
1799742fdb4Schristos 				  (const char *)pin, slot);
1809742fdb4Schristos 	if ((result != ISC_R_SUCCESS) && (result != PK11_R_NORANDOMSERVICE) &&
181e2b1b9c0Schristos 	    (result != PK11_R_NODIGESTSERVICE) &&
1829742fdb4Schristos 	    (result != PK11_R_NOAESSERVICE))
1839742fdb4Schristos 	{
184e2b1b9c0Schristos 		fprintf(stderr, "Error initializing PKCS#11: %s\n",
185e2b1b9c0Schristos 			isc_result_totext(result));
186e2b1b9c0Schristos 		exit(1);
187e2b1b9c0Schristos 	}
188e2b1b9c0Schristos 
1899742fdb4Schristos 	if (pin != NULL) {
190e2b1b9c0Schristos 		memset(pin, 0, strlen((char *)pin));
1919742fdb4Schristos 	}
192e2b1b9c0Schristos 
193e2b1b9c0Schristos 	hSession = pctx.session;
194e2b1b9c0Schristos 
195e2b1b9c0Schristos 	/* Randomize the buffer */
196e2b1b9c0Schristos 	rv = pkcs_C_GenerateRandom(hSession, buf, len);
197e2b1b9c0Schristos 	if (rv != CKR_OK) {
198e2b1b9c0Schristos 		fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
199e2b1b9c0Schristos 		goto exit_objects;
200e2b1b9c0Schristos 	}
201e2b1b9c0Schristos 
2029742fdb4Schristos 	if (ontoken) {
203e2b1b9c0Schristos 		kTemplate[1].pValue = &truevalue;
2049742fdb4Schristos 	}
205e2b1b9c0Schristos 
206e2b1b9c0Schristos 	if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
207e2b1b9c0Schristos 		perror("clock_gettime(start)");
208e2b1b9c0Schristos 		goto exit_objects;
209e2b1b9c0Schristos 	}
210e2b1b9c0Schristos 
211e2b1b9c0Schristos 	for (i = 0; i < count; i++) {
212e2b1b9c0Schristos 		(void)snprintf(label, sizeof(label), "obj%u", i);
213e2b1b9c0Schristos 		kTemplate[3].ulValueLen = strlen(label);
214e2b1b9c0Schristos 		rv = pkcs_C_CreateObject(hSession, kTemplate, 5, &hKey[i]);
215e2b1b9c0Schristos 		if (rv != CKR_OK) {
2169742fdb4Schristos 			fprintf(stderr, "C_CreateObject[%u]: Error = 0x%.8lX\n",
217e2b1b9c0Schristos 				i, rv);
218e2b1b9c0Schristos 			error = 1;
2199742fdb4Schristos 			if (i == 0) {
220e2b1b9c0Schristos 				goto exit_objects;
2219742fdb4Schristos 			}
222e2b1b9c0Schristos 			break;
223e2b1b9c0Schristos 		}
224e2b1b9c0Schristos 	}
225e2b1b9c0Schristos 
226e2b1b9c0Schristos 	if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
227e2b1b9c0Schristos 		perror("clock_gettime(end)");
228e2b1b9c0Schristos 		goto exit_objects;
229e2b1b9c0Schristos 	}
230e2b1b9c0Schristos 
231e2b1b9c0Schristos 	endtime.tv_sec -= starttime.tv_sec;
232e2b1b9c0Schristos 	endtime.tv_nsec -= starttime.tv_nsec;
233e2b1b9c0Schristos 	while (endtime.tv_nsec < 0) {
234e2b1b9c0Schristos 		endtime.tv_sec -= 1;
235e2b1b9c0Schristos 		endtime.tv_nsec += 1000000000;
236e2b1b9c0Schristos 	}
2379742fdb4Schristos 	printf("%u created objects in %ld.%09lds\n", i, endtime.tv_sec,
2389742fdb4Schristos 	       endtime.tv_nsec);
2399742fdb4Schristos 	if (i > 0) {
240e2b1b9c0Schristos 		printf("%g created objects/s\n",
2419742fdb4Schristos 		       1024 * i /
2429742fdb4Schristos 			       ((double)endtime.tv_sec +
243e2b1b9c0Schristos 				(double)endtime.tv_nsec / 1000000000.));
2449742fdb4Schristos 	}
245e2b1b9c0Schristos 
246e2b1b9c0Schristos exit_objects:
247e2b1b9c0Schristos 	for (i = 0; i < count; i++) {
248e2b1b9c0Schristos 		/* Destroy objects */
2499742fdb4Schristos 		if (hKey[i] == CK_INVALID_HANDLE) {
250e2b1b9c0Schristos 			continue;
2519742fdb4Schristos 		}
252e2b1b9c0Schristos 		rv = pkcs_C_DestroyObject(hSession, hKey[i]);
253e2b1b9c0Schristos 		if ((rv != CKR_OK) && !errflg) {
254e2b1b9c0Schristos 			fprintf(stderr,
2559742fdb4Schristos 				"C_DestroyObject[%u]: Error = 0x%.8lX\n", i,
2569742fdb4Schristos 				rv);
257e2b1b9c0Schristos 			errflg = 1;
258e2b1b9c0Schristos 		}
259e2b1b9c0Schristos 	}
260e2b1b9c0Schristos 
261e2b1b9c0Schristos 	free(hKey);
262e2b1b9c0Schristos 	pk11_return_session(&pctx);
263e2b1b9c0Schristos 	(void)pk11_finalize();
264e2b1b9c0Schristos 
265e2b1b9c0Schristos 	exit(error);
266e2b1b9c0Schristos }
267