1/*
2 * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
11 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
14 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/*
18 * Portions copyright (c) 2008 Nominet UK.  All rights reserved.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 *    notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 *    notice, this list of conditions and the following disclaimer in the
27 *    documentation and/or other materials provided with the distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
30 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
31 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
34 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
38 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41/* $Id: pkcs11-destroy.c,v 1.8 2010/01/13 21:19:52 fdupont Exp $ */
42
43/* pkcs11-destroy [-m module] [-s $slot] [-i $id | -l $label] [-p $pin] */
44
45/*! \file */
46
47#include <config.h>
48
49#include <stdio.h>
50#include <stdlib.h>
51#include <fcntl.h>
52#include <errno.h>
53#include <string.h>
54#include <sys/types.h>
55#include "cryptoki.h"
56
57#ifdef WIN32
58#define sleep(x)	Sleep(x)
59#include "win32.c"
60#else
61#ifndef FORCE_STATIC_PROVIDER
62#include "unix.c"
63#endif
64#endif
65
66#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
67#define getpassphrase(x)	getpass(x)
68#endif
69
70int
71main(int argc, char *argv[])
72{
73	CK_RV rv;
74	CK_SLOT_ID slot = 0;
75	CK_SESSION_HANDLE hSession;
76	CK_UTF8CHAR *pin = NULL;
77	CK_BYTE attr_id[2];
78	CK_OBJECT_HANDLE akey[50];
79	char *label = NULL;
80	int error = 0;
81	unsigned int id = 0, i = 0;
82	int c, errflg = 0;
83	CK_ULONG ulObjectCount;
84	CK_ATTRIBUTE search_template[] = {
85		{CKA_ID, &attr_id, sizeof(attr_id)}
86	};
87	char *pk11_provider;
88	unsigned int j, len;
89	extern char *optarg;
90	extern int optopt;
91
92	pk11_provider = getenv("PKCS11_PROVIDER");
93	if (pk11_provider != NULL)
94		pk11_libname = pk11_provider;
95
96	while ((c = getopt(argc, argv, ":m:s:i:l:p:")) != -1) {
97		switch (c) {
98		case 'm':
99			pk11_libname = optarg;
100			break;
101		case 's':
102			slot = atoi(optarg);
103			break;
104		case 'i':
105			id = atoi(optarg);
106			id &= 0xffff;
107			break;
108		case 'l':
109			label = optarg;
110			break;
111		case 'p':
112			pin = (CK_UTF8CHAR *)optarg;
113			break;
114		case ':':
115			fprintf(stderr,
116				"Option -%c requires an operand\n",
117				optopt);
118			errflg++;
119			break;
120		case '?':
121		default:
122			fprintf(stderr, "Unrecognised option: -%c\n", optopt);
123			errflg++;
124		}
125	}
126
127	if (errflg || (id && (label != NULL))) {
128		fprintf(stderr, "Usage:\n");
129		fprintf(stderr, "\tpkcs11-destroy [-m module] [-s slot] "
130				"[-i id | -l label] [-p pin]\n");
131		exit(1);
132	}
133
134	if (id) {
135		printf("id %i\n", id);
136		attr_id[0] = (id >> 8) & 0xff;
137		attr_id[1] = id & 0xff;
138	} else if (label) {
139		printf("label %s\n", label);
140		search_template[0].type = CKA_LABEL;
141		search_template[0].pValue = label;
142		search_template[0].ulValueLen = strlen(label);
143	}
144
145	/* Initialize the CRYPTOKI library */
146	rv = C_Initialize(NULL_PTR);
147	if (rv != CKR_OK) {
148		if (rv == 0xfe)
149			fprintf(stderr,
150				"Can't load or link module \"%s\"\n",
151				pk11_libname);
152		else
153			fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv);
154		exit(1);
155	}
156
157	/* Open a session on the slot found */
158	rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION,
159			   NULL_PTR, NULL_PTR, &hSession);
160	if (rv != CKR_OK) {
161		fprintf(stderr, "C_OpenSession: Error = 0x%.8lX\n", rv);
162		error = 1;
163		goto exit_program;
164	}
165
166	if (pin == NULL)
167		pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
168
169	/* Login to the Token (Keystore) */
170	rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin));
171	memset(pin, 0, strlen((char *)pin));
172	if (rv != CKR_OK) {
173		fprintf(stderr, "C_Login: Error = 0x%.8lX\n", rv);
174		error = 1;
175		goto exit_session;
176	}
177
178	rv = C_FindObjectsInit(hSession, search_template,
179		   ((id != 0) || (label != NULL)) ? 1 : 0);
180
181	if (rv != CKR_OK) {
182		fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv);
183		error = 1;
184		goto exit_session;
185	}
186
187	rv = C_FindObjects(hSession, akey, 50, &ulObjectCount);
188	if (rv != CKR_OK) {
189		fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv);
190		error = 1;
191		goto exit_search;
192	}
193
194	for (i = 0; i < ulObjectCount; i++) {
195		CK_OBJECT_CLASS oclass = 0;
196		CK_BYTE labelbuf[64 + 1];
197		CK_BYTE idbuf[64];
198		CK_ATTRIBUTE attr_template[] = {
199			{CKA_CLASS, &oclass, sizeof(oclass)},
200			{CKA_LABEL, labelbuf, sizeof(labelbuf) - 1},
201			{CKA_ID, idbuf, sizeof(idbuf)}
202		};
203
204		memset(labelbuf, 0, sizeof(labelbuf));
205		memset(idbuf, 0, sizeof(idbuf));
206
207		rv = C_GetAttributeValue(hSession, akey[i], attr_template, 3);
208		if (rv != CKR_OK) {
209			fprintf(stderr,
210				"C_GetAttributeValue[%u]: rv = 0x%.8lX\n",
211				i, rv);
212			error = 1;
213			goto exit_search;
214		}
215		len = attr_template[2].ulValueLen;
216		printf("object[%u]: class %lu label '%s' id[%lu] ",
217		       i, oclass, labelbuf, attr_template[2].ulValueLen);
218		if (len > 4)
219			len = 4;
220		if (len > 0)
221			printf("0x");
222		for (j = 0; j < len; j++)
223			printf("%02x", idbuf[j]);
224		if (attr_template[2].ulValueLen > len)
225			printf("...\n");
226		else
227			printf("\n");
228	}
229
230	/* give a chance to kill this */
231	printf("sleeping 5 seconds...\n");
232	sleep(5);
233
234	for (i = 0; i < ulObjectCount; i++) {
235		rv = C_DestroyObject(hSession, akey[i]);
236		if (rv != CKR_OK) {
237			fprintf(stderr,
238				"C_DestroyObject[%u]: rv = 0x%.8lX\n",
239				i, rv);
240			error = 1;
241		}
242	}
243
244 exit_search:
245	rv = C_FindObjectsFinal(hSession);
246	if (rv != CKR_OK) {
247		fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv);
248		error = 1;
249	}
250
251 exit_session:
252	(void)C_CloseSession(hSession);
253
254 exit_program:
255	(void)C_Finalize(NULL_PTR);
256
257	exit(error);
258}
259