summaryrefslogtreecommitdiff
path: root/ckcapi.h
blob: ddb9d753cd58eb35bfba3d23292383464e9e744e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/* 
 * Copyright (C) 2007 Nate Nielsen
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifndef CKCAPI_H
#define CKCAPI_H

/* --------------------------------------------------------------------
 * 
 * Session = CkCapiSession
 * - A PKCS#11 Session 
 * 
 * Objects = CkCapiObject
 * - There's a global list of objects in ckcapi-object.c indexed by 
 *   object handle. 
 * - The object itself has no attributes or cached data, but knows how 
 *   to load data when needed. 
 * - Each object has a unique key which guarantees we don't load the 
 *   same object twice with two different object handles.
 * 
 * Object Data = CkCapiObjectData
 * - Object Data is owned by the Session
 * - Loaded data and/or attributes for an object. 
 */

#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x400
#include <windows.h>
#include <wincrypt.h>

#define CRYPTOKI_EXPORTS
#include "pkcs11/cryptoki.h"

#include "ckcapi-util.h"

struct _CkCapiObject;
struct _CkCapiObjectData;
struct _CkCapiSession;

typedef struct _CkCapiObject CkCapiObject;
typedef struct _CkCapiObjectData CkCapiObjectData;
typedef struct _CkCapiSession CkCapiSession;


/* ------------------------------------------------------------------ 
 * ckcapi-object.c
 */

/* A function to get an attribute from ObjectData */
typedef CK_RV (*CkCapiGetAttribute)(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr);

/* A function to free some data */
typedef void (*CkCapiRelease)(void* data);

/* Object data functions */
typedef struct _CkCapiObjectDataVtable
{
	CkCapiGetAttribute get_bool;
	CkCapiGetAttribute get_ulong;
	CkCapiGetAttribute get_bytes;
	CkCapiGetAttribute get_date;
	CkCapiRelease release;
}
CkCapiObjectDataVtable;

/* 
 * Base class for object data. Different types of 
 * objects extend this with more detailed data 
 */
struct _CkCapiObjectData
{
	CK_OBJECT_HANDLE object;
	const CkCapiObjectDataVtable* data_funcs;
};

/* Match object data against all the given match attributes */
CK_BBOOL			ckcapi_object_data_match		(CkCapiObjectData* objdata, 
													 CK_ATTRIBUTE_PTR matches, CK_ULONG count);

/* Match a single attribute against object data */
CK_BBOOL			ckcapi_object_data_match_attr	(CkCapiObjectData* objdata, 
													 CK_ATTRIBUTE_PTR match);

/* Get a bunch of attributes from object data */
CK_RV				ckcapi_object_data_get_attrs	(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attrs, 
													 CK_ULONG count);

/* A function to load data for an object */
typedef CK_RV (*CkCapiLoadData)(CkCapiSession* sess, struct _CkCapiObject* obj, 
								CkCapiObjectData** objdata);

/* Object functions */
typedef struct _CkCapiObjectVtable
{
	CkCapiLoadData load_data;
	CkCapiRelease release;
}
CkCapiObjectVtable;

/* Represents a object we've seen */
struct _CkCapiObject
{
	CK_OBJECT_HANDLE id;
	const CkCapiObjectVtable* obj_funcs;
	void* unique_key;
	size_t unique_len;
};

/* Debug print something about an object */
#define DBGO(obj, msg) \
	ckcapi_debug("O%d: %s", (obj) ? (obj)->id : 0, (msg))
#define DBGOD(objdata, msg) \
	ckcapi_debug("O%d: %s", (objdata) ? (objdata)->obj : 0, (msg))

/* Get the number of the maximum object handle currently in memory */
CK_OBJECT_HANDLE	ckcapi_object_get_max_handle	(void);

/* Lookup an object for a given object handle */
CkCapiObject*		ckcapi_object_lookup			(CkCapiSession* sess, CK_OBJECT_HANDLE obj);

/* Register a new object, a handle will be assigned to obj->id */
CK_RV				ckcapi_object_register			(CkCapiSession* sess, CkCapiObject* obj);

/* Clear all objects. Only done when finalizing */
void				ckcapi_object_clear_all			(void);

/* 
 * Each object has a unique key which guarantees that we're 
 * not loading the same objects over and over again. 
 * Usually these are contiguous members of a struct. These 
 * macros help calculate the address and length of such a 
 * unique key 
 */

/* The unique key starts at the address of the starting struct member */
#define UNIQUE_KEY_AT(obj, mem)	\
	(void*)(&((obj->mem)))

/* Calculates key length between first and last struct members */
#define UNIQUE_KEY_LEN(obj, first, last) \
	UNIQUE_KEY_VAR_LEN(obj, first, last, sizeof(obj->last))

/* Calcs key len between first and a certain num of bytes past last struct member */
#define UNIQUE_KEY_VAR_LEN(obj, first, last, len) \
	((((char*)&((obj->last))) - ((char*)&((obj->first)))) + (len))

/* Used internally to have a unique id for different object types */
enum
{
	OBJECT_CERT =	 1,
	OBJECT_BUILTIN = 2,
	OBJECT_TRUST =	 3
};

/* ------------------------------------------------------------------ 
 * cryptoki-capi-session.c
 */

/* For operation_type in CkCapiSession */
enum
{
	OPERATION_NONE = 0,
	OPERATION_FIND = 1,
};

/* Callback to cancel a current operation */
typedef void (*CkCapiSessionCancel) (struct _CkCapiSession* sess);

/* Represents an open session */
typedef struct _CkCapiSession 
{
	CK_ULONG id;                    /* Unique ID for this session */
	int in_call;					/* Whether this session is use in PKCS#11 function */

	int operation_type;				/* Whether an operation is happening or not */
	void* operation_data;			/* Data for this operation */
	CkCapiSessionCancel operation_cancel;	/* Callback to cancel operation when necessary */

	CkCapiHash* object_data;

	CK_NOTIFY notify_callback;      /* Application specified callback */
	CK_VOID_PTR user_data;          /* Argument for above */

	int refs;                       /* Reference count */
	HANDLE mutex;					/* Mutex for protecting this structure */
} 
CkCapiSession;

/* Debug print something related to a session */
#define DBGS(sess, msg) \
	ckcapi_debug("S%d: %s", (sess) ? (sess)->id : 0, (msg))

/* Create a session */
CkCapiSession*	ckcapi_session_create			(void);

/* Destroy a session */
void			ckcapi_session_destroy			(CkCapiSession* sess);

/* Register a new session */
CK_RV			ckcapi_session_register			(CkCapiSession* sess);

/* Get a session from a handle, and lock it */
CK_RV			ckcapi_session_get_lock_ref		(CK_ULONG id, int remove, 
												 CkCapiSession **sess);

/* Unlock and unreference a session */
void			ckcapi_session_unref_unlock		(CkCapiSession* sess);

/* Close all sessions */
void			ckcapi_session_close_all		(void);



/* Start a find operation on a session */
CK_RV			ckcapi_session_find_init		(CkCapiSession* sess, 
												 CK_ATTRIBUTE_PTR templ, 
												 CK_ULONG count);

/* Return results from a find operation */
CK_RV			ckcapi_session_find				(CkCapiSession* sess, 
												 CK_OBJECT_HANDLE_PTR objects, 
												 CK_ULONG max_object_count, 
												 CK_ULONG_PTR object_count);

/* End a find operation */
CK_RV			ckcapi_session_find_final		(CkCapiSession* sess);




/* Get object data for an object */
CK_RV			ckcapi_session_get_object_data		(CkCapiSession* sess, 
													 CkCapiObject* obj, 
													 CkCapiObjectData** objdata);

/* Get object data for an object handle */
CK_RV			ckcapi_session_get_object_data_for	(CkCapiSession* sess, 
													 CK_OBJECT_HANDLE hand, 
													 CkCapiObjectData** objdata);

/* Set object data for an object */
void			ckcapi_session_take_object_data		(CkCapiSession* sess, 
													 CkCapiObject* obj, 
													 CkCapiObjectData* objdata);

/* Clear object data for an object */
void			ckcapi_session_clear_object_data	(CkCapiSession* sess, 
													 CkCapiObject* obj);

/* Enumerate object data for all objects */
typedef	void	(*CkCapiEnumObjectData)				(CkCapiSession* sess, 
													 CkCapiObject* obj, 
													 CkCapiObjectData* data, 
													 void* arg);
void			ckcapi_session_enum_object_data		(CkCapiSession* sess, 
													 CkCapiEnumObjectData enum_func, 
													 void* arg);



/* -------------------------------------------------------------------
 * ckcapi-cert.c
 */

/* Find certificates matching criteria */
CK_RV			ckcapi_cert_find					(CkCapiSession* sess, CK_OBJECT_CLASS cls, 
													 CK_ATTRIBUTE_PTR match,  CK_ULONG count, 
													 CkCapiArray* arr);


/* Called by trust stuff */
CK_RV			ckcapi_cert_certificate_get_bytes		(PCCERT_CONTEXT cert, 
														 CK_ATTRIBUTE_PTR attr);
PCCERT_CONTEXT	ckcapi_cert_object_data_get_certificate	(CkCapiObjectData* objdata);


/* -------------------------------------------------------------------
 * ckcapi-builtin.c
 */

/* Find builtin objects matching criteria */
CK_RV				ckcapi_builtin_find				(CkCapiSession* sess, CK_OBJECT_CLASS cls, 
													 CK_ATTRIBUTE_PTR match, CK_ULONG count, 
													 CkCapiArray* arr);

/* -------------------------------------------------------------------
 * ckcapi-trust.c
 */

/* Find trust objects matching criteria */
CK_RV				ckcapi_trust_find				(CkCapiSession* sess, CK_OBJECT_CLASS cls, 
													 CK_ATTRIBUTE_PTR match, CK_ULONG count, 
													 CkCapiArray* arr);

/* ------------------------------------------------------------------
 * cryptoki-capi.c
 * 
 * Module helper and logging functions.
 */

#define DBG(args) \
	ckcapi_debug args

void		ckcapi_debug			(const char* msg, ...);

/* 
 * Protect global data with these.
 */
void		ckcapi_lock_global		(void);
void		ckcapi_unlock_global	(void);

/*
 * Convert a GetLastError() windows error to a 
 * PKCS#11 return code. 
 */
CK_RV		ckcapi_winerr_to_ckr	(DWORD werr);

/* 
 * This stores data in the output buffer with appropriate 
 * PKCS#11 codes when the buffer is too short, or the caller
 * just wants to know the length, etc.
 */
CK_RV		ckcapi_return_data		(CK_VOID_PTR dst, CK_ULONG_PTR dlen, 
									 CK_VOID_PTR src, DWORD slen);


/* ------------------------------------------------------------------ */

#ifndef ASSERT
#include "assert.h"
#define ASSERT assert
#endif

/* Represents 'any' class in searches */
#define CKO_ANY CK_INVALID_HANDLE


#endif /* CRYPTOKI_CAPI_H */