1178825Sdfr/*
2233294Sstas * Copyright (c) 2006 - 2008 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5178825Sdfr *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9178825Sdfr *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
20178825Sdfr *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34178825Sdfr#include "hx_locl.h"
35178825Sdfr#include "pkcs11.h"
36178825Sdfr#include <err.h>
37178825Sdfr
38178825Sdfrstatic CK_FUNCTION_LIST_PTR func;
39178825Sdfr
40178825Sdfr
41178825Sdfrstatic CK_RV
42233294Sstasfind_object(CK_SESSION_HANDLE session,
43178825Sdfr	    char *id,
44233294Sstas	    CK_OBJECT_CLASS key_class,
45178825Sdfr	    CK_OBJECT_HANDLE_PTR object)
46178825Sdfr{
47178825Sdfr    CK_ULONG object_count;
48178825Sdfr    CK_RV ret;
49178825Sdfr    CK_ATTRIBUTE search_data[] = {
50178825Sdfr	{CKA_ID, id, 0 },
51178825Sdfr	{CKA_CLASS, &key_class, sizeof(key_class)}
52178825Sdfr    };
53178825Sdfr    CK_ULONG num_search_data = sizeof(search_data)/sizeof(search_data[0]);
54178825Sdfr
55178825Sdfr    search_data[0].ulValueLen = strlen(id);
56178825Sdfr
57178825Sdfr    ret = (*func->C_FindObjectsInit)(session, search_data, num_search_data);
58178825Sdfr    if (ret != CKR_OK)
59178825Sdfr	return ret;
60178825Sdfr
61178825Sdfr    ret = (*func->C_FindObjects)(session, object, 1, &object_count);
62178825Sdfr    if (ret != CKR_OK)
63178825Sdfr	return ret;
64178825Sdfr    if (object_count == 0) {
65178825Sdfr	printf("found no object\n");
66178825Sdfr	return 1;
67178825Sdfr    }
68178825Sdfr
69178825Sdfr    ret = (*func->C_FindObjectsFinal)(session);
70178825Sdfr    if (ret != CKR_OK)
71178825Sdfr	return ret;
72178825Sdfr
73178825Sdfr    return CKR_OK;
74178825Sdfr}
75178825Sdfr
76178825Sdfrstatic char *sighash = "hej";
77178825Sdfrstatic char signature[1024];
78178825Sdfr
79178825Sdfr
80178825Sdfrint
81178825Sdfrmain(int argc, char **argv)
82178825Sdfr{
83178825Sdfr    CK_SLOT_ID_PTR slot_ids;
84178825Sdfr    CK_SLOT_ID slot;
85178825Sdfr    CK_ULONG num_slots;
86178825Sdfr    CK_RV ret;
87178825Sdfr    CK_SLOT_INFO slot_info;
88178825Sdfr    CK_TOKEN_INFO token_info;
89178825Sdfr    CK_SESSION_HANDLE session;
90178825Sdfr    CK_OBJECT_HANDLE public, private;
91178825Sdfr
92178825Sdfr    ret = C_GetFunctionList(&func);
93178825Sdfr    if (ret != CKR_OK)
94178825Sdfr	errx(1, "C_GetFunctionList failed: %d", (int)ret);
95178825Sdfr
96178825Sdfr    (*func->C_Initialize)(NULL_PTR);
97178825Sdfr
98178825Sdfr    ret = (*func->C_GetSlotList)(FALSE, NULL, &num_slots);
99178825Sdfr    if (ret != CKR_OK)
100178825Sdfr	errx(1, "C_GetSlotList1 failed: %d", (int)ret);
101178825Sdfr
102178825Sdfr    if (num_slots == 0)
103178825Sdfr	errx(1, "no slots");
104178825Sdfr
105178825Sdfr    if ((slot_ids = calloc(1, num_slots * sizeof(*slot_ids))) == NULL)
106178825Sdfr	err(1, "alloc slots failed");
107178825Sdfr
108178825Sdfr    ret = (*func->C_GetSlotList)(FALSE, slot_ids, &num_slots);
109178825Sdfr    if (ret != CKR_OK)
110178825Sdfr	errx(1, "C_GetSlotList2 failed: %d", (int)ret);
111178825Sdfr
112178825Sdfr    slot = slot_ids[0];
113178825Sdfr    free(slot_ids);
114178825Sdfr
115178825Sdfr    ret = (*func->C_GetSlotInfo)(slot, &slot_info);
116178825Sdfr    if (ret)
117178825Sdfr	errx(1, "C_GetSlotInfo failed: %d", (int)ret);
118178825Sdfr
119178825Sdfr    if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0)
120178825Sdfr	errx(1, "no token present");
121178825Sdfr
122233294Sstas    ret = (*func->C_OpenSession)(slot, CKF_SERIAL_SESSION,
123178825Sdfr				 NULL, NULL, &session);
124178825Sdfr    if (ret != CKR_OK)
125178825Sdfr	errx(1, "C_OpenSession failed: %d", (int)ret);
126233294Sstas
127178825Sdfr    ret = (*func->C_GetTokenInfo)(slot, &token_info);
128178825Sdfr    if (ret)
129178825Sdfr	errx(1, "C_GetTokenInfo1 failed: %d", (int)ret);
130178825Sdfr
131178825Sdfr    if (token_info.flags & CKF_LOGIN_REQUIRED) {
132178825Sdfr	ret = (*func->C_Login)(session, CKU_USER,
133178825Sdfr			       (unsigned char*)"foobar", 6);
134178825Sdfr	if (ret != CKR_OK)
135178825Sdfr	    errx(1, "C_Login failed: %d", (int)ret);
136178825Sdfr    }
137178825Sdfr
138178825Sdfr    ret = (*func->C_GetTokenInfo)(slot, &token_info);
139178825Sdfr    if (ret)
140178825Sdfr	errx(1, "C_GetTokenInfo2 failed: %d", (int)ret);
141178825Sdfr
142178825Sdfr    if (token_info.flags & CKF_LOGIN_REQUIRED)
143178825Sdfr	errx(1, "login required, even after C_Login");
144178825Sdfr
145178825Sdfr    ret = find_object(session, "cert", CKO_PUBLIC_KEY, &public);
146178825Sdfr    if (ret != CKR_OK)
147178825Sdfr	errx(1, "find cert failed: %d", (int)ret);
148178825Sdfr    ret = find_object(session, "cert", CKO_PRIVATE_KEY, &private);
149178825Sdfr    if (ret != CKR_OK)
150178825Sdfr	errx(1, "find private key failed: %d", (int)ret);
151178825Sdfr
152178825Sdfr    {
153178825Sdfr	CK_ULONG ck_sigsize;
154178825Sdfr	CK_MECHANISM mechanism;
155178825Sdfr
156178825Sdfr	memset(&mechanism, 0, sizeof(mechanism));
157178825Sdfr	mechanism.mechanism = CKM_RSA_PKCS;
158178825Sdfr
159178825Sdfr	ret = (*func->C_SignInit)(session, &mechanism, private);
160178825Sdfr	if (ret != CKR_OK)
161178825Sdfr	    return 1;
162233294Sstas
163178825Sdfr	ck_sigsize = sizeof(signature);
164178825Sdfr	ret = (*func->C_Sign)(session, (CK_BYTE *)sighash, strlen(sighash),
165178825Sdfr			      (CK_BYTE *)signature, &ck_sigsize);
166178825Sdfr	if (ret != CKR_OK) {
167178825Sdfr	    printf("C_Sign failed with: %d\n", (int)ret);
168178825Sdfr	    return 1;
169178825Sdfr	}
170178825Sdfr
171178825Sdfr	ret = (*func->C_VerifyInit)(session, &mechanism, public);
172178825Sdfr	if (ret != CKR_OK)
173178825Sdfr	    return 1;
174178825Sdfr
175233294Sstas	ret = (*func->C_Verify)(session, (CK_BYTE *)signature, ck_sigsize,
176178825Sdfr				(CK_BYTE *)sighash, strlen(sighash));
177178825Sdfr	if (ret != CKR_OK) {
178178825Sdfr	    printf("message: %d\n", (int)ret);
179178825Sdfr	    return 1;
180178825Sdfr	}
181178825Sdfr    }
182178825Sdfr
183178825Sdfr#if 0
184178825Sdfr    {
185178825Sdfr	CK_ULONG ck_sigsize, outsize;
186178825Sdfr	CK_MECHANISM mechanism;
187178825Sdfr	char outdata[1024];
188178825Sdfr
189178825Sdfr	memset(&mechanism, 0, sizeof(mechanism));
190178825Sdfr	mechanism.mechanism = CKM_RSA_PKCS;
191178825Sdfr
192178825Sdfr	ret = (*func->C_EncryptInit)(session, &mechanism, public);
193178825Sdfr	if (ret != CKR_OK)
194178825Sdfr	    return 1;
195233294Sstas
196178825Sdfr	ck_sigsize = sizeof(signature);
197178825Sdfr	ret = (*func->C_Encrypt)(session, (CK_BYTE *)sighash, strlen(sighash),
198178825Sdfr				 (CK_BYTE *)signature, &ck_sigsize);
199178825Sdfr	if (ret != CKR_OK) {
200178825Sdfr	    printf("message: %d\n", (int)ret);
201178825Sdfr	    return 1;
202178825Sdfr	}
203178825Sdfr
204178825Sdfr	ret = (*func->C_DecryptInit)(session, &mechanism, private);
205178825Sdfr	if (ret != CKR_OK)
206178825Sdfr	    return 1;
207178825Sdfr
208178825Sdfr	outsize = sizeof(outdata);
209233294Sstas	ret = (*func->C_Decrypt)(session, (CK_BYTE *)signature, ck_sigsize,
210178825Sdfr				 (CK_BYTE *)outdata, &outsize);
211178825Sdfr	if (ret != CKR_OK) {
212178825Sdfr	    printf("message: %d\n", (int)ret);
213178825Sdfr	    return 1;
214178825Sdfr	}
215178825Sdfr
216233294Sstas	if (ct_memcmp(sighash, outdata, strlen(sighash)) != 0)
217178825Sdfr	    return 1;
218178825Sdfr    }
219178825Sdfr#endif
220178825Sdfr
221178825Sdfr    ret = (*func->C_CloseSession)(session);
222178825Sdfr    if (ret != CKR_OK)
223178825Sdfr	return 1;
224178825Sdfr
225178825Sdfr    (*func->C_Finalize)(NULL_PTR);
226178825Sdfr
227178825Sdfr    return 0;
228178825Sdfr}
229