1 /*	$NetBSD: verify.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 /* verify [-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 exponent[] = { 0x01, 0x00, 0x01 };
108 
109 CK_BYTE buf[1024];
110 CK_BYTE sig[128];
111 
112 static CK_BBOOL truevalue = TRUE;
113 static CK_BBOOL falsevalue = FALSE;
114 
115 int
116 main(int argc, char *argv[]) {
117 	isc_result_t result;
118 	CK_RV rv;
119 	CK_SLOT_ID slot = 0;
120 	CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
121 	CK_ULONG len;
122 	CK_ULONG slen;
123 	CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
124 	CK_OBJECT_CLASS kClass = CKO_PUBLIC_KEY;
125 	CK_KEY_TYPE kType = CKK_RSA;
126 	CK_ATTRIBUTE kTemplate[] =
127 	{
128 		{ CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
129 		{ CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
130 		{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
131 		{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
132 		{ CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
133 		{ CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
134 		{ CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) }
135 	};
136 	CK_MECHANISM mech = { CKM_SHA1_RSA_PKCS, NULL, 0 };
137 	pk11_context_t pctx;
138 	pk11_optype_t op_type = OP_RSA;
139 	char *lib_name = NULL;
140 	char *pin = NULL;
141 	int error = 0;
142 	int c, errflg = 0;
143 	int ontoken  = 0;
144 	unsigned int count = 1000;
145 	unsigned int i;
146 	struct timespec starttime;
147 	struct timespec endtime;
148 
149 	while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
150 		switch (c) {
151 		case 'm':
152 			lib_name = isc_commandline_argument;
153 			break;
154 		case 's':
155 			slot = atoi(isc_commandline_argument);
156 			op_type = OP_ANY;
157 			break;
158 		case 'p':
159 			pin = isc_commandline_argument;
160 			break;
161 		case 't':
162 			ontoken = 1;
163 			break;
164 		case 'n':
165 			count = atoi(isc_commandline_argument);
166 			break;
167 		case ':':
168 			fprintf(stderr,
169 				"Option -%c requires an operand\n",
170 				isc_commandline_option);
171 			errflg++;
172 			break;
173 		case '?':
174 		default:
175 			fprintf(stderr, "Unrecognised option: -%c\n",
176 				isc_commandline_option);
177 			errflg++;
178 		}
179 	}
180 
181 	if (errflg) {
182 		fprintf(stderr, "Usage:\n");
183 		fprintf(stderr,
184 			"\tverify [-m module] [-s slot] [-p pin] "
185 			"[-t] [-n count]\n");
186 		exit(1);
187 	}
188 
189 	pk11_result_register();
190 
191 	/* Initialize the CRYPTOKI library */
192 	if (lib_name != NULL)
193 		pk11_set_lib_name(lib_name);
194 
195 	if (pin == NULL)
196 		pin = getpassphrase("Enter Pin: ");
197 
198 	result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE,
199 				  ISC_TRUE, (const char *) pin, slot);
200 	if ((result != ISC_R_SUCCESS) &&
201 	    (result != PK11_R_NORANDOMSERVICE) &&
202 	    (result != PK11_R_NODIGESTSERVICE) &&
203 	    (result != PK11_R_NOAESSERVICE)) {
204 		fprintf(stderr, "Error initializing PKCS#11: %s\n",
205 			isc_result_totext(result));
206 		exit(1);
207 	}
208 
209 	if (pin != NULL)
210 		memset(pin, 0, strlen((char *)pin));
211 
212 	hSession = pctx.session;
213 
214 	/* Create the private RSA key */
215 	if (ontoken)
216 		kTemplate[2].pValue = &truevalue;
217 
218 	rv = pkcs_C_CreateObject(hSession, kTemplate, 7, &hKey);
219 	if (rv != CKR_OK) {
220 		fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv);
221 		error = 1;
222 		goto exit_key;
223 	}
224 
225 	/* Randomize the buffer */
226 	len = (CK_ULONG) sizeof(buf);
227 	rv = pkcs_C_GenerateRandom(hSession, buf, len);
228 	if (rv != CKR_OK) {
229 		fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
230 		goto exit_key;
231 	}
232 
233 	if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
234 		perror("clock_gettime(start)");
235 		goto exit_key;
236 	}
237 
238 	for (i = 0; i < count; i++) {
239 		/* Initialize Verify */
240 		rv = pkcs_C_VerifyInit(hSession, &mech, hKey);
241 		if (rv != CKR_OK) {
242 			fprintf(stderr,
243 				"C_VerifyInit[%u]: Error = 0x%.8lX\n",
244 				i, rv);
245 			error = 1;
246 			break;
247 		}
248 
249 		/* Perform Verify */
250 		slen = (CK_ULONG) sizeof(sig);
251 		rv = pkcs_C_Verify(hSession, buf, len, sig, slen);
252 		if ((rv != CKR_OK) && (rv != CKR_SIGNATURE_INVALID)) {
253 			fprintf(stderr,
254 				"C_Verify[%u]: Error = 0x%.8lX\n",
255 				i, rv);
256 			error = 1;
257 			break;
258 		}
259 	}
260 
261 	if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
262 		perror("clock_gettime(end)");
263 		goto exit_key;
264 	}
265 
266 	endtime.tv_sec -= starttime.tv_sec;
267 	endtime.tv_nsec -= starttime.tv_nsec;
268 	while (endtime.tv_nsec < 0) {
269 		endtime.tv_sec -= 1;
270 		endtime.tv_nsec += 1000000000;
271 	}
272 	printf("%u RSA verify in %ld.%09lds\n", i,
273 	       endtime.tv_sec, endtime.tv_nsec);
274 	if (i > 0)
275 		printf("%g RSA verify/s\n",
276 		       1024 * i / ((double) endtime.tv_sec +
277 				   (double) endtime.tv_nsec / 1000000000.));
278 
279     exit_key:
280 	if (hKey != CK_INVALID_HANDLE) {
281 		rv = pkcs_C_DestroyObject(hSession, hKey);
282 		if (rv != CKR_OK) {
283 			fprintf(stderr,
284 				"C_DestroyObject: Error = 0x%.8lX\n",
285 				rv);
286 			errflg = 1;
287 		}
288 	}
289 
290 	pk11_return_session(&pctx);
291 	(void) pk11_finalize();
292 
293 	exit(error);
294 }
295