summaryrefslogtreecommitdiff
path: root/ckcapi.h
blob: f166528eec2cf6e5deaa413757f6c28c0c466f20 (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

#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;
};

/* 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))

CK_OBJECT_HANDLE	ckcapi_object_get_max_handle	(void);

CkCapiObject*		ckcapi_object_lookup			(CkCapiSession* sess, CK_OBJECT_HANDLE obj);

CK_RV				ckcapi_object_register			(CkCapiSession* sess, CkCapiObject* obj);

void				ckcapi_object_clear_all			(void);


CK_BBOOL			ckcapi_object_data_match		(CkCapiObjectData* objdata, 
													 CK_ATTRIBUTE_PTR matches, CK_ULONG count);

CK_BBOOL			ckcapi_object_data_match_attr	(CkCapiObjectData* objdata, 
													 CK_ATTRIBUTE_PTR match);

CK_RV				ckcapi_object_data_get_attrs	(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attrs, 
													 CK_ULONG count);

/* 
 * 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,
};

typedef void (*CkCapiSessionCancel) (struct _CkCapiSession* sess);

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;

#define DBGS(sess, msg) \
	ckcapi_debug("S%d: %s", (sess) ? (sess)->id : 0, (msg))

CkCapiSession* ckcapi_session_create(void);
void ckcapi_session_destroy(CkCapiSession* sess);
CK_RV ckcapi_session_register(CkCapiSession* sess);
CK_RV ckcapi_session_get_lock_ref(CK_ULONG id, int remove, CkCapiSession **sess);
void ckcapi_session_unref_unlock(CkCapiSession* sess);
void ckcapi_session_close_all();

CK_RV		ckcapi_session_find_init			(CkCapiSession* sess, CK_ATTRIBUTE_PTR templ, CK_ULONG count);
CK_RV		ckcapi_session_find				(CkCapiSession* sess, CK_OBJECT_HANDLE_PTR objects, 
											 CK_ULONG max_object_count, CK_ULONG_PTR object_count);
CK_RV		ckcapi_session_find_final		(CkCapiSession* sess);

CK_RV		ckcapi_session_get_object_data	(CkCapiSession* sess, CkCapiObject* obj, 
											 CkCapiObjectData** objdata);

CK_RV		ckcapi_session_get_object_data_for		(CkCapiSession* sess, CK_OBJECT_HANDLE hand, 
													 CkCapiObjectData** objdata);

void		ckcapi_session_take_object_data	(CkCapiSession* sess, CkCapiObject* obj, 
											 CkCapiObjectData* objdata);

void		ckcapi_session_clear_object_data	(CkCapiSession* sess, CkCapiObject* obj);

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
 */

CK_RV				ckcapi_cert_find				(CkCapiSession* sess, CK_OBJECT_CLASS cls, 
													 CK_ATTRIBUTE_PTR match,  CK_ULONG count, 
													 CkCapiArray* arr);

CK_RV				ckcapi_cert_find_specific		(CkCapiSession* sess, CK_OBJECT_CLASS cls, 
													 CK_ATTRIBUTE_PTR issuer, CK_ATTRIBUTE_PTR serial, 
													 CK_OBJECT_HANDLE_PTR obj);

/* 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
 */

CK_RV				ckcapi_builtin_find				(CkCapiSession* sess, CK_OBJECT_CLASS cls, 
													 CK_ATTRIBUTE_PTR match, CK_ULONG count, 
													 CkCapiArray* arr);

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

CK_RV				ckcapi_trust_find				(CkCapiSession* sess, CK_OBJECT_CLASS cls, 
													 CK_ATTRIBUTE_PTR match, CK_ULONG count, 
													 CkCapiArray* arr);

CK_RV				ckcapi_trust_find_specific		(CkCapiSession* sess, CK_OBJECT_CLASS cls, 
													 CK_ATTRIBUTE_PTR issuer, CK_ATTRIBUTE_PTR serial, 
													 CK_OBJECT_HANDLE_PTR obj);

/* ------------------------------------------------------------------
 * 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 */