1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) The PHP Group                                          |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Author: Guillaume Amringer                                           |
16    +----------------------------------------------------------------------+
17 */
18 
19 #include "pkcs11int.h"
20 
21 zend_class_entry *ce_Pkcs11_Module;
22 static zend_object_handlers pkcs11_handlers;
23 
24 
25 ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 1)
26     ZEND_ARG_TYPE_INFO(0, modulePath, IS_STRING, 0)
27 ZEND_END_ARG_INFO()
28 
29 ZEND_BEGIN_ARG_INFO_EX(arginfo_getInfo, 0, 0, 0)
30 ZEND_END_ARG_INFO()
31 
32 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GetInfo, 0, 0, 1)
33     ZEND_ARG_TYPE_INFO(1, pInfo, IS_ARRAY, 1)
34 ZEND_END_ARG_INFO()
35 
36 ZEND_BEGIN_ARG_INFO_EX(arginfo_getSlots, 0, 0, 0)
37 ZEND_END_ARG_INFO()
38 
39 ZEND_BEGIN_ARG_INFO_EX(arginfo_getSlotList, 0, 0, 0)
40 ZEND_END_ARG_INFO()
41 
42 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GetSlotList, 0, 0, 2)
43     ZEND_ARG_TYPE_INFO(0, tokenPresent, _IS_BOOL, 0)
44     ZEND_ARG_TYPE_INFO(1, pSlotList, IS_ARRAY, 1)
45 ZEND_END_ARG_INFO()
46 
47 ZEND_BEGIN_ARG_INFO_EX(arginfo_getSlotInfo, 0, 0, 1)
48     ZEND_ARG_TYPE_INFO(0, slotId, IS_LONG, 0)
49 ZEND_END_ARG_INFO()
50 
51 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GetSlotInfo, 0, 0, 2)
52     ZEND_ARG_TYPE_INFO(0, slotId, IS_LONG, 0)
53     ZEND_ARG_TYPE_INFO(1, pInfo, IS_ARRAY, 1)
54 ZEND_END_ARG_INFO()
55 
56 ZEND_BEGIN_ARG_INFO_EX(arginfo_getTokenInfo, 0, 0, 1)
57     ZEND_ARG_TYPE_INFO(0, slotId, IS_LONG, 0)
58 ZEND_END_ARG_INFO()
59 
60 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GetTokenInfo, 0, 0, 2)
61     ZEND_ARG_TYPE_INFO(0, slotId, IS_LONG, 0)
62     ZEND_ARG_TYPE_INFO(1, pInfo, IS_ARRAY, 1)
63 ZEND_END_ARG_INFO()
64 
65 ZEND_BEGIN_ARG_INFO_EX(arginfo_getMechanismList, 0, 0, 1)
66     ZEND_ARG_TYPE_INFO(0, slotId, IS_LONG, 0)
67 ZEND_END_ARG_INFO()
68 
69 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GetMechanismList, 0, 0, 2)
70     ZEND_ARG_TYPE_INFO(0, slotId, IS_LONG, 0)
71     ZEND_ARG_TYPE_INFO(1, pMechanismList, IS_ARRAY, 1)
72 ZEND_END_ARG_INFO()
73 
74 ZEND_BEGIN_ARG_INFO_EX(arginfo_getMechanismInfo, 0, 0, 2)
75     ZEND_ARG_TYPE_INFO(0, slotId, IS_LONG, 0)
76     ZEND_ARG_TYPE_INFO(0, mechanismId, IS_LONG, 0)
77 ZEND_END_ARG_INFO()
78 
79 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GetMechanismInfo, 0, 0, 3)
80     ZEND_ARG_TYPE_INFO(0, slotId, IS_LONG, 0)
81     ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0)
82     ZEND_ARG_TYPE_INFO(1, pInfo, IS_ARRAY, 1)
83 ZEND_END_ARG_INFO()
84 
85 ZEND_BEGIN_ARG_INFO_EX(arginfo_initToken, 0, 0, 3)
86     ZEND_ARG_TYPE_INFO(0, slotid, IS_LONG, 0)
87     ZEND_ARG_TYPE_INFO(0, label, IS_STRING, 0)
88     ZEND_ARG_TYPE_INFO(0, sopin, IS_STRING, 0)
89 ZEND_END_ARG_INFO()
90 
91 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_InitToken, 0, 0, 3)
92     ZEND_ARG_TYPE_INFO(0, slotid, IS_LONG, 0)
93     ZEND_ARG_TYPE_INFO(0, label, IS_STRING, 0)
94     ZEND_ARG_TYPE_INFO(0, sopin, IS_STRING, 0)
95 ZEND_END_ARG_INFO()
96 
97 ZEND_BEGIN_ARG_INFO_EX(arginfo_openSession, 0, 0, 1)
98     ZEND_ARG_TYPE_INFO(0, slotid, IS_LONG, 0)
99     ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
100     ZEND_ARG_TYPE_INFO(0, application, IS_STRING, 1)
101     ZEND_ARG_TYPE_INFO(0, notify, IS_CALLABLE, 1)
102 ZEND_END_ARG_INFO()
103 
104 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_OpenSession, 0, 0, 5)
105     ZEND_ARG_TYPE_INFO(0, slotID, IS_LONG, 0)
106     ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
107     ZEND_ARG_TYPE_INFO(0, pApplication, IS_STRING, 1)
108     ZEND_ARG_TYPE_INFO(0, notify, IS_CALLABLE, 1)
109     ZEND_ARG_OBJ_INFO(1, hSession, Pkcs11\\Session, 1)
110 ZEND_END_ARG_INFO()
111 
112 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_WaitForSlotEvent, 0, 0, 2)
113     ZEND_ARG_TYPE_INFO(0, php_flags, IS_LONG, 1)
114     ZEND_ARG_TYPE_INFO(1, php_slotID, IS_LONG, 1)
115 ZEND_END_ARG_INFO()
116 
117 
118 ZEND_BEGIN_ARG_INFO_EX(arginfo_waitForSlotEvent, 0, 0, 1)
119     ZEND_ARG_TYPE_INFO(0, php_flags, IS_LONG, 1)
120 ZEND_END_ARG_INFO()
121 
122 
123 PHP_METHOD(Module, __construct) {
124     char *module_path;
125     size_t module_path_len;
126 
127     ZEND_PARSE_PARAMETERS_START(1, 1)
128         Z_PARAM_PATH(module_path, module_path_len)
129     ZEND_PARSE_PARAMETERS_END();
130 
131 
132     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
133 
134     if (objval->initialised) {
135         zend_throw_exception(zend_ce_exception, "Already initialised PKCS11 module", 0);
136         return;
137     }
138 
139     CK_RV rv;
140 
141     char* dlerror_str;
142     objval->pkcs11module = dlopen(module_path, RTLD_NOW);
143 
144     dlerror_str = dlerror();
145     if (dlerror_str != NULL) {
146         general_error("Unable to initialise PKCS11 module", dlerror_str);
147         return;
148     }
149 
150     CK_C_GetFunctionList C_GetFunctionList = dlsym(objval->pkcs11module, "C_GetFunctionList");
151     dlerror_str = dlerror();
152     if (dlerror_str != NULL) {
153         general_error("Unable to initialise PKCS11 module", dlerror_str);
154         return;
155     }
156 
157     rv = C_GetFunctionList(&objval->functionList);
158     if (rv != CKR_OK) {
159         pkcs11_error(rv, "Unable to retrieve function list");
160         return;
161     }
162 
163     rv = objval->functionList->C_Initialize(NULL);
164     if (rv != CKR_OK) {
165         pkcs11_error(rv, "Unable to initialise token");
166         return;
167     }
168 
169     objval->initialised = true;
170 }
171 
172 
173 CK_RV php_C_GetInfo(pkcs11_object *objval, zval *retval) {
174 
175     CK_RV rv;
176     CK_INFO info;
177 
178     rv = objval->functionList->C_GetInfo(&info);
179     if (rv != CKR_OK) {
180         return rv;
181     }
182 
183     zval cryptokiversion;
184     array_init(&cryptokiversion);
185     add_assoc_long(&cryptokiversion, "major", info.cryptokiVersion.major);
186     add_assoc_long(&cryptokiversion, "minor", info.cryptokiVersion.minor);
187 
188     zval libversion;
189     array_init(&libversion);
190     add_assoc_long(&libversion, "major", info.libraryVersion.major);
191     add_assoc_long(&libversion, "minor", info.libraryVersion.minor);
192 
193     array_init(retval);
194     add_assoc_zval(retval, "cryptokiVersion", &cryptokiversion);
195     add_assoc_stringl(retval, "manufacturerID", info.manufacturerID, sizeof(info.manufacturerID));
196     add_assoc_stringl(retval, "libraryDescription", info.libraryDescription, sizeof(info.libraryDescription));
197     add_assoc_zval(retval, "libraryVersion", &libversion);
198 
199     return rv;
200 }
201 
202 /* {{{ proto array Pkcs11\Module::getInfo(void)
203    Return the session cookie parameters */
204 PHP_METHOD(Module, getInfo) {
205     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
206 
207     ZEND_PARSE_PARAMETERS_NONE();
208 
209     if (!objval->initialised) {
210         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
211         return;
212     }
213 
214     CK_RV rv = php_C_GetInfo(objval, return_value);
215     if (rv != CKR_OK) {
216         pkcs11_error(rv, "Unable to get information from token");
217     }
218 }
219 /* }}} */
220 
221 PHP_METHOD(Module, C_GetInfo) {
222     CK_RV rv;
223     zval *pInfo;
224     zval retval;
225 
226     ZEND_PARSE_PARAMETERS_START(1, 1)
227         Z_PARAM_ZVAL(pInfo)
228     ZEND_PARSE_PARAMETERS_END();
229 
230     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
231 
232     if (!objval->initialised) {
233         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
234         return;
235     }
236 
237     rv = php_C_GetInfo(objval, &retval);
238 
239     ZEND_TRY_ASSIGN_REF_VALUE(pInfo, &retval);
240 
241     RETURN_LONG(rv);
242 }
243 
244 CK_RV php_C_GetSlotList(pkcs11_object *objval, zend_bool tokenPresent, zval *retval) {
245 
246     CK_RV rv;
247     CK_ULONG ulSlotCount;
248     CK_SLOT_ID_PTR pSlotList;
249 
250     rv = objval->functionList->C_GetSlotList((CK_BBOOL)tokenPresent, NULL_PTR, &ulSlotCount);
251     if (rv != CKR_OK) {
252         return rv;
253     }
254 
255     pSlotList = (CK_SLOT_ID_PTR) ecalloc(ulSlotCount, sizeof(CK_SLOT_ID));
256     rv = objval->functionList->C_GetSlotList((CK_BBOOL)tokenPresent, pSlotList, &ulSlotCount);
257     if (rv != CKR_OK) {
258         efree(pSlotList);
259         return rv;
260     }
261 
262     array_init(retval);
263     for (CK_SLOT_ID i=0; i<ulSlotCount; i++) {
264         add_next_index_long(retval, pSlotList[i]);
265     }
266 
267     efree(pSlotList);
268 
269     return rv;
270 }
271 
272 PHP_METHOD(Module, getSlots) {
273     CK_RV rv;
274     CK_ULONG ulSlotCount;
275     CK_SLOT_ID_PTR pSlotList;
276     CK_SLOT_INFO slotInfo;
277 
278     ZEND_PARSE_PARAMETERS_NONE();
279 
280     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
281 
282     if (!objval->initialised) {
283         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
284         return;
285     }
286 
287     rv = objval->functionList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
288     if (rv != CKR_OK) {
289         pkcs11_error(rv, "Unable to get slot list from token");
290         return;
291     }
292 
293     pSlotList = (CK_SLOT_ID_PTR) ecalloc(ulSlotCount, sizeof(CK_SLOT_ID));
294     rv = objval->functionList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
295     if (rv != CKR_OK) {
296         efree(pSlotList);
297         pkcs11_error(rv, "Unable to get slot list from token");
298         return;
299     }
300 
301     zval slotObj;
302     array_init(return_value);
303     for (CK_SLOT_ID i=0; i<ulSlotCount; i++) {
304         rv = objval->functionList->C_GetSlotInfo(pSlotList[i], &slotInfo);
305         if (rv != CKR_OK) {
306             pkcs11_error(rv, "Unable to get slot info from token");
307             return;
308         }
309 
310         array_init(&slotObj);
311         add_assoc_long(&slotObj, "id", pSlotList[i]);
312         add_assoc_stringl(&slotObj, "slotDescription", slotInfo.slotDescription, sizeof(slotInfo.slotDescription));
313         add_index_zval(return_value, pSlotList[i], &slotObj);
314     }
315     efree(pSlotList);
316 }
317 
318 PHP_METHOD(Module, getSlotList) {
319 
320     ZEND_PARSE_PARAMETERS_NONE();
321 
322     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
323 
324     if (!objval->initialised) {
325         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
326         return;
327     }
328 
329     CK_RV rv = php_C_GetSlotList(objval, false, return_value);
330     if (rv != CKR_OK) {
331         pkcs11_error(rv, "Unable to get slot list from token");
332     }
333 }
334 
335 PHP_METHOD(Module, C_GetSlotList) {
336     CK_RV rv;
337     zend_bool tokenPresent;
338     zval *pSlotList;
339     zval retval;
340 
341     ZEND_PARSE_PARAMETERS_START(2, 2)
342         Z_PARAM_BOOL(tokenPresent)
343         Z_PARAM_ZVAL(pSlotList)
344     ZEND_PARSE_PARAMETERS_END();
345 
346     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
347 
348     if (!objval->initialised) {
349         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
350         return;
351     }
352 
353     rv = php_C_GetSlotList(objval, tokenPresent, &retval);
354 
355     ZEND_TRY_ASSIGN_REF_VALUE(pSlotList, &retval);
356 
357     RETURN_LONG(rv);
358 }
359 
360 
361 CK_RV php_C_GetSlotInfo(pkcs11_object *objval, zend_long slotId, zval *retval) {
362 
363     CK_RV rv;
364     CK_SLOT_INFO slotInfo;
365 
366     rv = objval->functionList->C_GetSlotInfo((CK_SLOT_ID)slotId, &slotInfo);
367     if (rv != CKR_OK) {
368         return rv;
369     }
370 
371     array_init(retval);
372     add_assoc_long(retval, "id", (CK_SLOT_ID)slotId);
373     add_assoc_stringl(retval, "description", slotInfo.slotDescription, 64);
374     add_assoc_stringl(retval, "manufacturerID", slotInfo.manufacturerID, sizeof(slotInfo.manufacturerID));
375     add_assoc_long(retval, "flags", slotInfo.flags);
376 
377     zval hardwareVersion;
378     array_init(&hardwareVersion);
379     add_assoc_long(&hardwareVersion, "major", slotInfo.hardwareVersion.major);
380     add_assoc_long(&hardwareVersion, "minor", slotInfo.hardwareVersion.minor);
381     add_assoc_zval(retval, "hardwareVersion", &hardwareVersion);
382 
383     zval firmwareVersion;
384     array_init(&firmwareVersion);
385     add_assoc_long(&firmwareVersion, "major", slotInfo.firmwareVersion.major);
386     add_assoc_long(&firmwareVersion, "minor", slotInfo.firmwareVersion.minor);
387     add_assoc_zval(retval, "firmwareVersion", &firmwareVersion);
388 
389     return rv;
390 }
391 
392 PHP_METHOD(Module, getSlotInfo) {
393 
394     zend_long slotId;
395 
396     ZEND_PARSE_PARAMETERS_START(1, 1)
397         Z_PARAM_LONG(slotId)
398     ZEND_PARSE_PARAMETERS_END();
399 
400     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
401 
402     if (!objval->initialised) {
403         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
404         return;
405     }
406 
407 
408     CK_RV rv = php_C_GetSlotInfo(objval, slotId, return_value);
409     if (rv != CKR_OK) {
410         pkcs11_error(rv, "Unable to get slot info from token");
411     }
412 }
413 
414 PHP_METHOD(Module, C_GetSlotInfo) {
415     CK_RV rv;
416     zend_long slotId;
417     zval *pInfo;
418     zval retval;
419 
420     ZEND_PARSE_PARAMETERS_START(2, 2)
421         Z_PARAM_LONG(slotId)
422         Z_PARAM_ZVAL(pInfo)
423     ZEND_PARSE_PARAMETERS_END();
424 
425     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
426 
427     if (!objval->initialised) {
428         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
429         return;
430     }
431 
432     rv = php_C_GetSlotInfo(objval, slotId, &retval);
433 
434     ZEND_TRY_ASSIGN_REF_VALUE(pInfo, &retval);
435 
436     RETURN_LONG(rv);
437 }
438 
439 
440 CK_RV php_C_GetTokenInfo(pkcs11_object *objval, CK_SLOT_ID slotId, zval *retval) {
441 
442     CK_RV rv;
443     CK_TOKEN_INFO tokenInfo = {};
444 
445     rv = objval->functionList->C_GetTokenInfo((CK_SLOT_ID)slotId, &tokenInfo);
446     if (rv != CKR_OK) {
447         return rv;
448     }
449 
450     array_init(retval);
451     add_assoc_stringl(retval, "label", tokenInfo.label, sizeof(tokenInfo.label));
452     add_assoc_stringl(retval, "manufacturerID", tokenInfo.manufacturerID, sizeof(tokenInfo.manufacturerID));
453     add_assoc_stringl(retval, "model", tokenInfo.model, sizeof(tokenInfo.model));
454     add_assoc_stringl(retval, "serialNumber", tokenInfo.serialNumber, sizeof(tokenInfo.serialNumber));
455 
456     add_assoc_long(retval, "flags", tokenInfo.flags);
457 
458     add_assoc_long(retval, "ulMaxSessionCount", tokenInfo.ulMaxSessionCount);
459     add_assoc_long(retval, "ulSessionCount", tokenInfo.ulSessionCount);
460     add_assoc_long(retval, "ulMaxRwSessionCount", tokenInfo.ulMaxRwSessionCount);
461     add_assoc_long(retval, "ulRwSessionCount", tokenInfo.ulRwSessionCount);
462     add_assoc_long(retval, "ulMaxPinLen", tokenInfo.ulMaxPinLen);
463     add_assoc_long(retval, "ulMinPinLen", tokenInfo.ulMinPinLen);
464     add_assoc_long(retval, "ulTotalPublicMemory", tokenInfo.ulTotalPublicMemory);
465     add_assoc_long(retval, "ulFreePublicMemory", tokenInfo.ulFreePublicMemory);
466     add_assoc_long(retval, "ulTotalPrivateMemory", tokenInfo.ulTotalPrivateMemory);
467     add_assoc_long(retval, "ulFreePrivateMemory", tokenInfo.ulFreePrivateMemory);
468 
469     zval hardwareVersion;
470     array_init(&hardwareVersion);
471     add_assoc_long(&hardwareVersion, "major", tokenInfo.hardwareVersion.major);
472     add_assoc_long(&hardwareVersion, "minor", tokenInfo.hardwareVersion.minor);
473     add_assoc_zval(retval, "hardwareVersion", &hardwareVersion);
474 
475     zval firmwareVersion;
476     array_init(&firmwareVersion);
477     add_assoc_long(&firmwareVersion, "major", tokenInfo.firmwareVersion.major);
478     add_assoc_long(&firmwareVersion, "minor", tokenInfo.firmwareVersion.minor);
479     add_assoc_zval(retval, "firmwareVersion", &firmwareVersion);
480 
481     add_assoc_stringl(retval, "utcTime", tokenInfo.utcTime, sizeof(tokenInfo.utcTime));
482 
483     return rv;
484 }
485 
486 PHP_METHOD(Module, getTokenInfo) {
487 
488     zend_long slotId;
489 
490     ZEND_PARSE_PARAMETERS_START(1, 1)
491         Z_PARAM_LONG(slotId)
492     ZEND_PARSE_PARAMETERS_END();
493 
494     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
495 
496     if (!objval->initialised) {
497         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
498         return;
499     }
500 
501     CK_RV rv = php_C_GetTokenInfo(objval, slotId, return_value);
502     if (rv != CKR_OK) {
503         pkcs11_error(rv, "Unable to get slot info from token");
504     }
505 }
506 
507 PHP_METHOD(Module, C_GetTokenInfo) {
508     CK_RV rv;
509     zend_long slotId;
510     zval *pInfo;
511     zval retval;
512 
513     ZEND_PARSE_PARAMETERS_START(2, 2)
514         Z_PARAM_LONG(slotId)
515         Z_PARAM_ZVAL(pInfo)
516     ZEND_PARSE_PARAMETERS_END();
517 
518     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
519 
520     if (!objval->initialised) {
521         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
522         return;
523     }
524 
525     rv = php_C_GetTokenInfo(objval, slotId, &retval);
526 
527     ZEND_TRY_ASSIGN_REF_VALUE(pInfo, &retval);
528 
529     RETURN_LONG(rv);
530 }
531 
532 
533 CK_RV php_C_GetMechanismList(pkcs11_object *objval, zend_long slotId, zval *retval) {
534 
535     CK_RV rv;
536 
537     CK_ULONG ulMechanismCount;
538     rv = objval->functionList->C_GetMechanismList((CK_SLOT_ID)slotId, NULL_PTR, &ulMechanismCount);
539     if (rv != CKR_OK) {
540         return rv;
541     }
542 
543     CK_MECHANISM_TYPE_PTR pMechanismList = (CK_MECHANISM_TYPE_PTR) ecalloc(ulMechanismCount, sizeof(CK_MECHANISM_TYPE));
544     rv = objval->functionList->C_GetMechanismList((CK_SLOT_ID)slotId, pMechanismList, &ulMechanismCount);
545     if (rv != CKR_OK) {
546         efree(pMechanismList);
547         return rv;
548     }
549 
550     CK_SLOT_ID i;
551     array_init(retval);
552     for (i=0; i<ulMechanismCount; i++) {
553         add_next_index_long(retval, pMechanismList[i]);
554     }
555     efree(pMechanismList);
556 
557     return rv;
558 }
559 
560 PHP_METHOD(Module, getMechanismList) {
561 
562     zend_long slotId;
563 
564     ZEND_PARSE_PARAMETERS_START(1, 1)
565         Z_PARAM_LONG(slotId)
566     ZEND_PARSE_PARAMETERS_END();
567 
568 
569     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
570 
571     if (!objval->initialised) {
572         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
573         return;
574     }
575 
576     CK_RV rv = php_C_GetMechanismList(objval, slotId, return_value);
577     if (rv != CKR_OK) {
578         pkcs11_error(rv, "Unable to get mechanism list from token");
579     }
580 }
581 
582 PHP_METHOD(Module, C_GetMechanismList) {
583     CK_RV rv;
584     zend_long slotId;
585     zval *pMechanismList;
586     zval retval;
587 
588     ZEND_PARSE_PARAMETERS_START(2, 2)
589         Z_PARAM_LONG(slotId)
590         Z_PARAM_ZVAL(pMechanismList)
591     ZEND_PARSE_PARAMETERS_END();
592 
593     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
594 
595     if (!objval->initialised) {
596         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
597         return;
598     }
599 
600     rv = php_C_GetMechanismList(objval, slotId, &retval);
601 
602     ZEND_TRY_ASSIGN_REF_VALUE(pMechanismList, &retval);
603 
604     RETURN_LONG(rv);
605 }
606 
607 
608 CK_RV php_C_GetMechanismInfo(pkcs11_object *objval, zend_long slotId, zend_long mechanismId, zval *retval) {
609 
610     CK_MECHANISM_INFO mechanismInfo = {};
611 
612     CK_RV rv = objval->functionList->C_GetMechanismInfo((CK_SLOT_ID)slotId, (CK_MECHANISM_TYPE)mechanismId, &mechanismInfo);
613     if (rv != CKR_OK) {
614         return rv;
615     }
616 
617     array_init(retval);
618     add_assoc_long(retval, "ulMinKeySize", mechanismInfo.ulMinKeySize);
619     add_assoc_long(retval, "ulMaxKeySize", mechanismInfo.ulMaxKeySize);
620     add_assoc_long(retval, "flags", mechanismInfo.flags);
621 
622     return rv;
623 }
624 
625 PHP_METHOD(Module, getMechanismInfo) {
626 
627     zend_long slotId;
628     zend_long mechanismId;
629 
630     ZEND_PARSE_PARAMETERS_START(2, 2)
631         Z_PARAM_LONG(slotId)
632         Z_PARAM_LONG(mechanismId)
633     ZEND_PARSE_PARAMETERS_END();
634 
635     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
636 
637     if (!objval->initialised) {
638         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
639         return;
640     }
641 
642     CK_RV rv = php_C_GetMechanismInfo(objval, slotId, mechanismId, return_value);
643     if (rv != CKR_OK) {
644         pkcs11_error(rv, "Unable to get mechanism info");
645     }
646 }
647 
648 PHP_METHOD(Module, C_GetMechanismInfo) {
649     CK_RV rv;
650     zend_long slotId;
651     zend_long type;
652     zval *pInfo;
653     zval retval;
654 
655     ZEND_PARSE_PARAMETERS_START(3, 3)
656         Z_PARAM_LONG(slotId)
657         Z_PARAM_LONG(type)
658         Z_PARAM_ZVAL(pInfo)
659     ZEND_PARSE_PARAMETERS_END();
660 
661     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
662 
663     if (!objval->initialised) {
664         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
665         return;
666     }
667 
668     rv = php_C_GetMechanismInfo(objval, slotId, type, &retval);
669 
670     ZEND_TRY_ASSIGN_REF_VALUE(pInfo, &retval);
671 
672     RETURN_LONG(rv);
673 }
674 
675 
676 CK_RV php_C_InitToken(pkcs11_object *objval, zend_long slotId, zend_string *label, zend_string *sopin, zval *retval) {
677 
678     CK_MECHANISM_INFO mechanismInfo;
679     CK_RV rv = objval->functionList->C_InitToken((CK_SLOT_ID)slotId, (CK_UTF8CHAR_PTR)sopin, ZSTR_LEN(sopin), (CK_UTF8CHAR_PTR)label);
680     if (rv != CKR_OK) {
681         return rv;
682     }
683 
684     return rv;
685 }
686 
687 PHP_METHOD(Module, initToken) {
688     zend_string    *label_str;
689     zend_string    *sopin_str;
690     zend_long      slotid;
691 
692     ZEND_PARSE_PARAMETERS_START(3, 3)
693         Z_PARAM_LONG(slotid)
694         Z_PARAM_STR(label_str)
695         Z_PARAM_STR(sopin_str)
696     ZEND_PARSE_PARAMETERS_END();
697 
698     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
699 
700     if (!objval->initialised) {
701         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
702         return;
703     }
704 
705     CK_RV rv = php_C_InitToken(objval, slotid, label_str, sopin_str, return_value);
706     if (rv != CKR_OK) {
707         pkcs11_error(rv, "Unable to initialise token");
708     }
709 }
710 
711 PHP_METHOD(Module, C_InitToken) {
712     zend_string    *label_str;
713     zend_string    *sopin_str;
714     zend_long      slotid;
715 
716     ZEND_PARSE_PARAMETERS_START(3, 3)
717         Z_PARAM_LONG(slotid)
718         Z_PARAM_STR(label_str)
719         Z_PARAM_STR(sopin_str)
720     ZEND_PARSE_PARAMETERS_END();
721 
722     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
723 
724     if (!objval->initialised) {
725         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
726         return;
727     }
728 
729     CK_RV rv = php_C_InitToken(objval, slotid, label_str, sopin_str, return_value);
730 
731     RETURN_LONG(rv);
732 }
733 
734 PHP_METHOD(Module, openSession) {
735     CK_RV rv;
736 
737     zend_long      slotid;
738     zend_long      flags = 0;
739     zend_string    *application;
740     zend_fcall_info php_fciNotify;
741     zend_fcall_info_cache fciNotify_cache;
742 
743     ZEND_PARSE_PARAMETERS_START(1, 4)
744         Z_PARAM_LONG(slotid)
745         Z_PARAM_OPTIONAL
746         Z_PARAM_LONG(flags)
747         Z_PARAM_STR(application)
748         Z_PARAM_FUNC(php_fciNotify, fciNotify_cache)
749     ZEND_PARSE_PARAMETERS_END();
750 
751     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
752 
753     if (!objval->initialised) {
754         zend_throw_exception(zend_ce_exception, "Uninitialised PKCS11 module", 0);
755         return;
756     }
757 
758     pkcs11_session_object* session_obj;
759 
760     object_init_ex(return_value, ce_Pkcs11_Session);
761     session_obj = Z_PKCS11_SESSION_P(return_value);
762     session_obj->pkcs11 = objval;
763     GC_ADDREF(&objval->std);
764 
765     CK_SESSION_HANDLE phSession;
766     rv = objval->functionList->C_OpenSession(slotid, CKF_SERIAL_SESSION | flags, NULL_PTR, NULL_PTR, &phSession);
767     if (rv != CKR_OK) {
768         pkcs11_error(rv, "Unable to open session");
769         return;
770     }
771     session_obj->session = phSession;
772     session_obj->slotID = slotid;
773 }
774 
775 PHP_METHOD(Module, waitForSlotEvent) {
776     CK_RV rv;
777     CK_SLOT_ID slotID;
778 
779     zend_long php_flags;
780 
781     ZEND_PARSE_PARAMETERS_START(1, 1)
782         Z_PARAM_LONG(php_flags)
783     ZEND_PARSE_PARAMETERS_END();
784 
785     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
786 
787     rv = objval->functionList->C_WaitForSlotEvent((CK_FLAGS)php_flags, &slotID, NULL_PTR);
788 
789     if (rv == CKR_OK) {
790         RETURN_LONG(slotID);
791     }
792 
793     if (rv == CKR_NO_EVENT) {
794         RETURN_NULL();
795     }
796 
797     pkcs11_error(rv, "Error waiting for events");
798 }
799 
800 /*
801  * fabric (__construct like) of a \Session thru a ref parameter
802  */
803 PHP_METHOD(Module, C_OpenSession) {
804     CK_RV rv;
805 
806     zend_long      php_slotID;
807     zend_long      php_flags;
808     zend_string    *php_pApplication = NULL;
809     zend_fcall_info php_fciNotify;
810     zend_fcall_info_cache fciNotify_cache;
811     zval           *php_hSession;
812 
813     ZEND_PARSE_PARAMETERS_START(5, 5)
814         Z_PARAM_LONG(php_slotID)
815         Z_PARAM_LONG(php_flags)
816     	Z_PARAM_STR_EX(php_pApplication, 1, 0)
817     	Z_PARAM_FUNC_EX(php_fciNotify, fciNotify_cache, 1, 0)
818     	Z_PARAM_ZVAL(php_hSession)
819     ZEND_PARSE_PARAMETERS_END();
820 	//Z_PARAM_OBJECT_EX(php_hSession, 1, 0)
821 	//Z_PARAM_OBJECT_OF_CLASS_EX(php_hSession, ce_Pkcs11_Session, 1, 0)
822 
823     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
824 
825     if (((CK_FLAGS)php_flags) &
826          (CKF_RW_SESSION || CKF_SERIAL_SESSION)) {
827         ; /* nope */
828     } else {
829         ; /* nope */
830     }
831 
832     pkcs11_session_object* session_objval;
833 
834     zval zvhSession = {};
835     object_init_ex(&zvhSession, ce_Pkcs11_Session);
836     session_objval = Z_PKCS11_SESSION_P(&zvhSession);
837     session_objval->pkcs11 = objval;
838     GC_ADDREF(&objval->std); /* session is refering the pkcs11 module */
839 
840     CK_SESSION_HANDLE hSession = 0;
841     if (ZEND_NUM_ARGS() > 4)
842         rv = objval->functionList->C_OpenSession((CK_SLOT_ID)php_slotID, php_flags, NULL_PTR, NULL_PTR, &hSession); /* TODO: add callbacks */
843     else
844         rv = objval->functionList->C_OpenSession((CK_SLOT_ID)php_slotID, php_flags, NULL_PTR, NULL_PTR, &hSession); /* TODO: add callbacks */
845     session_objval->session = hSession;
846     if (rv != CKR_OK) {
847         RETURN_LONG(rv);
848     }
849 
850     session_objval->slotID = php_slotID;
851 
852     ZEND_TRY_ASSIGN_REF_VALUE(php_hSession, &zvhSession);
853 
854     RETURN_LONG(rv);
855 }
856 
857 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_CloseSession, 0, 0, 1)
858     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
859 ZEND_END_ARG_INFO()
860 
861 PHP_METHOD(Module, C_CloseSession) {
862     CK_RV rv;
863 
864     zval *php_session;
865 
866     ZEND_PARSE_PARAMETERS_START(1, 1)
867         Z_PARAM_OBJECT_OF_CLASS(php_session, ce_Pkcs11_Session)
868     ZEND_PARSE_PARAMETERS_END();
869 
870     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
871     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(php_session);
872 
873     rv = sessionobjval->pkcs11->functionList->C_CloseSession(sessionobjval->session);
874     // TBC GC_DELREF(&objval->std); /* session is refering the pkcs11 module */
875     sessionobjval->session = 0;
876 
877     RETURN_LONG(rv);
878 }
879 
880 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GetSessionInfo, 0, 0, 1)
881     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
882     ZEND_ARG_TYPE_INFO(1, pInfo, IS_ARRAY, 1)
883 ZEND_END_ARG_INFO()
884 
885 PHP_METHOD(Module, C_GetSessionInfo) {
886     CK_RV rv;
887 
888     zval *session;
889     zval *pInfo;
890     zval retval;
891 
892     ZEND_PARSE_PARAMETERS_START(2, 2)
893         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
894         Z_PARAM_ZVAL(pInfo)
895     ZEND_PARSE_PARAMETERS_END();
896 
897     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
898 
899     rv = php_C_GetSessionInfo(sessionobjval, &retval);
900 
901     ZEND_TRY_ASSIGN_REF_VALUE(pInfo, &retval);
902 
903     RETURN_LONG(rv);
904 }
905 
906 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GenerateRandom, 0, 0, 1)
907     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
908     ZEND_ARG_TYPE_INFO(0, RandomLen, IS_LONG, 0)
909     ZEND_ARG_TYPE_INFO(1, pRandomData, IS_STRING, 1)
910 ZEND_END_ARG_INFO()
911 
912 PHP_METHOD(Module, C_GenerateRandom) {
913     CK_RV rv;
914 
915     zval *php_session;
916     zend_long php_RandomLen = 0;
917     zval *pRandomData;
918     zval retval;
919 
920     ZEND_PARSE_PARAMETERS_START(3, 3)
921         Z_PARAM_OBJECT_OF_CLASS(php_session, ce_Pkcs11_Session)
922         Z_PARAM_LONG(php_RandomLen)
923         Z_PARAM_ZVAL(pRandomData)
924     ZEND_PARSE_PARAMETERS_END();
925 
926     pkcs11_session_object *objval = Z_PKCS11_SESSION_P(php_session);
927     rv = php_C_GenerateRandom(objval, php_RandomLen, &retval);
928 
929     ZEND_TRY_ASSIGN_REF_VALUE(pRandomData, &retval);
930 
931     RETURN_LONG(rv);
932 }
933 
934 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_SeedRandom, 0, 0, 1)
935     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
936     ZEND_ARG_TYPE_INFO(0, Seed, IS_STRING, 0)
937 ZEND_END_ARG_INFO()
938 
939 PHP_METHOD(Module, C_SeedRandom) {
940     CK_RV rv;
941 
942     zval *php_session;
943     zend_string *php_pSeed = NULL;
944     zval retval;
945 
946     ZEND_PARSE_PARAMETERS_START(2, 2)
947         Z_PARAM_OBJECT_OF_CLASS(php_session, ce_Pkcs11_Session)
948         Z_PARAM_STR(php_pSeed)
949     ZEND_PARSE_PARAMETERS_END();
950 
951     pkcs11_session_object *objval = Z_PKCS11_SESSION_P(php_session);
952     rv = php_C_SeedRandom(objval, php_pSeed);
953 
954     RETURN_LONG(rv);
955 }
956 
957 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_Login, 0, 0, 3)
958     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
959     ZEND_ARG_TYPE_INFO(0, loginType, IS_LONG, 0)
960     ZEND_ARG_TYPE_INFO(0, pin, IS_STRING, 0)
961 ZEND_END_ARG_INFO()
962 
963 PHP_METHOD(Module, C_Login) {
964     CK_RV rv;
965 
966     zval *session;
967     zend_long userType;
968     zend_string *pin;
969 
970     ZEND_PARSE_PARAMETERS_START(3, 3)
971         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
972         Z_PARAM_LONG(userType)
973         Z_PARAM_STR(pin)
974     ZEND_PARSE_PARAMETERS_END();
975 
976     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
977     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
978 
979     rv = objval->functionList->C_Login(sessionobjval->session, userType, ZSTR_VAL(pin), ZSTR_LEN(pin));
980 
981     RETURN_LONG(rv);
982 }
983 
984 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_Logout, 0, 0, 1)
985     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
986 ZEND_END_ARG_INFO()
987 
988 PHP_METHOD(Module, C_Logout) {
989     CK_RV rv;
990 
991     zval *session;
992 
993     ZEND_PARSE_PARAMETERS_START(1, 1)
994         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
995     ZEND_PARSE_PARAMETERS_END();
996 
997     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
998     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
999 
1000     rv = objval->functionList->C_Logout(sessionobjval->session);
1001 
1002     RETURN_LONG(rv);
1003 }
1004 
1005 PHP_METHOD(Module, C_WaitForSlotEvent) {
1006     CK_RV rv;
1007     CK_SLOT_ID slotID;
1008 
1009     zend_long php_flags;
1010     zval *php_slotID = NULL;
1011 
1012     ZEND_PARSE_PARAMETERS_START(2, 2)
1013         Z_PARAM_LONG(php_flags)
1014         Z_PARAM_ZVAL(php_slotID)
1015     ZEND_PARSE_PARAMETERS_END();
1016 
1017     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1018 
1019     rv = objval->functionList->C_WaitForSlotEvent((CK_FLAGS)php_flags, &slotID, NULL_PTR);
1020 
1021     if (rv == CKR_OK) {
1022         zval zva;
1023         ZVAL_LONG(&zva, slotID);
1024         ZEND_TRY_ASSIGN_REF_VALUE(php_slotID, &zva);
1025     }
1026 
1027     RETURN_LONG(rv);
1028 }
1029 
1030 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_SetPIN, 0, 0, 3)
1031     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1032     ZEND_ARG_TYPE_INFO(0, oldPin, IS_STRING, 0)
1033     ZEND_ARG_TYPE_INFO(0, newPin, IS_STRING, 0)
1034 ZEND_END_ARG_INFO()
1035 
1036 PHP_METHOD(Module, C_SetPIN) {
1037     CK_RV rv;
1038 
1039     zval *session;
1040     zend_string *oldPin;
1041     zend_string *newPin;
1042 
1043     ZEND_PARSE_PARAMETERS_START(3, 3)
1044         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1045         Z_PARAM_STR(oldPin)
1046         Z_PARAM_STR(newPin)
1047     ZEND_PARSE_PARAMETERS_END();
1048 
1049     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1050     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1051 
1052     rv = objval->functionList->C_SetPIN(
1053         sessionobjval->session,
1054         ZSTR_VAL(oldPin),
1055         ZSTR_LEN(oldPin),
1056         ZSTR_VAL(newPin),
1057         ZSTR_LEN(newPin)
1058     );
1059 
1060     RETURN_LONG(rv);
1061 }
1062 
1063 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_InitPIN, 0, 0, 2)
1064     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1065     ZEND_ARG_TYPE_INFO(0, newPin, IS_STRING, 0)
1066 ZEND_END_ARG_INFO()
1067 
1068 PHP_METHOD(Module, C_InitPIN) {
1069     CK_RV rv;
1070 
1071     zval *session;
1072     zend_string *newPin;
1073 
1074     ZEND_PARSE_PARAMETERS_START(2, 2)
1075         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1076         Z_PARAM_STR(newPin)
1077     ZEND_PARSE_PARAMETERS_END();
1078 
1079     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1080     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1081 
1082     rv = objval->functionList->C_InitPIN(
1083         sessionobjval->session,
1084         ZSTR_VAL(newPin),
1085         ZSTR_LEN(newPin)
1086     );
1087 
1088     RETURN_LONG(rv);
1089 }
1090 
1091 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GenerateKey, 0, 0, 3)
1092     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1093     ZEND_ARG_OBJ_INFO(0, mechanism, Pkcs11\\Mechanism, 0)
1094     ZEND_ARG_TYPE_INFO(0, template, IS_ARRAY, 0)
1095     ZEND_ARG_OBJ_INFO(1, phKey, IS_LONG, 1)
1096 ZEND_END_ARG_INFO()
1097 
1098 PHP_METHOD(Module, C_GenerateKey) {
1099     CK_RV rv;
1100 
1101     zval *session;
1102     zval *mechanism;
1103     HashTable *template;
1104     zval *phKey;
1105     zval retval;
1106 
1107     ZEND_PARSE_PARAMETERS_START(4, 4)
1108         Z_PARAM_ZVAL(session)
1109         Z_PARAM_ZVAL(mechanism)
1110         Z_PARAM_ARRAY_HT(template)
1111         Z_PARAM_ZVAL(phKey)
1112     ZEND_PARSE_PARAMETERS_END();
1113 
1114     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1115     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1116 
1117     rv = php_C_GenerateKey(sessionobjval, mechanism, template, &retval);
1118 
1119     pkcs11_key_object* key_obj = Z_PKCS11_KEY_P(&retval);
1120 
1121     zval zva;
1122     ZVAL_LONG(&zva, key_obj->key);
1123     ZEND_TRY_ASSIGN_REF_VALUE(phKey, &zva);
1124 
1125     RETURN_LONG(rv);
1126 }
1127 
1128 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GenerateKeyPair, 0, 0, 4)
1129     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1130     ZEND_ARG_OBJ_INFO(0, mechanism, Pkcs11\\Mechanism, 0)
1131     ZEND_ARG_TYPE_INFO(0, pkTemplate, IS_ARRAY, 0)
1132     ZEND_ARG_TYPE_INFO(0, skTemplate, IS_ARRAY, 0)
1133     ZEND_ARG_OBJ_INFO(1, phPublicKey, Pkcs11\\Key, 1)
1134     ZEND_ARG_OBJ_INFO(1, phPrivateKey, Pkcs11\\Key, 1)
1135 ZEND_END_ARG_INFO()
1136 
1137 PHP_METHOD(Module, C_GenerateKeyPair) {
1138     CK_RV rv;
1139 
1140     zval *session;
1141     zval *mechanism;
1142     HashTable *pkTemplate;
1143     HashTable *skTemplate;
1144     zval *phPublicKey;
1145     zval *phPrivateKey;
1146     zval retvalpk;
1147     zval retvalsk;
1148 
1149     ZEND_PARSE_PARAMETERS_START(6, 6)
1150         Z_PARAM_ZVAL(session)
1151         Z_PARAM_ZVAL(mechanism)
1152         Z_PARAM_ARRAY_HT(pkTemplate)
1153         Z_PARAM_ARRAY_HT(skTemplate)
1154         Z_PARAM_ZVAL(phPublicKey)
1155         Z_PARAM_ZVAL(phPrivateKey)
1156     ZEND_PARSE_PARAMETERS_END();
1157 
1158     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1159     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1160 
1161     rv = php_C_GenerateKeyPair(sessionobjval, mechanism, pkTemplate, skTemplate, &retvalpk, &retvalsk);
1162 
1163     if (rv != CKR_OK)
1164         goto fini;
1165 
1166     ZEND_TRY_ASSIGN_REF_VALUE(phPublicKey, &retvalpk);
1167     ZEND_TRY_ASSIGN_REF_VALUE(phPrivateKey, &retvalsk);
1168 
1169 fini:
1170     RETURN_LONG(rv);
1171 }
1172 
1173 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_DigestInit, 0, 0, 2)
1174     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1175     ZEND_ARG_OBJ_INFO(0, mechanism, Pkcs11\\Mechanism, 0)
1176 ZEND_END_ARG_INFO()
1177 
1178 PHP_METHOD(Module, C_DigestInit) {
1179     CK_RV rv;
1180 
1181     zval *session;
1182     zval *mechanism;
1183 
1184     ZEND_PARSE_PARAMETERS_START(2, 2)
1185         Z_PARAM_ZVAL(session)
1186         Z_PARAM_ZVAL(mechanism)
1187     ZEND_PARSE_PARAMETERS_END();
1188 
1189     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1190     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1191 
1192     pkcs11_mechanism_object *mechanismObjval = Z_PKCS11_MECHANISM_P(mechanism);
1193 
1194     rv = sessionobjval->pkcs11->functionList->C_DigestInit(
1195         sessionobjval->session,
1196         &mechanismObjval->mechanism
1197     );
1198 
1199     RETURN_LONG(rv);
1200 }
1201 
1202 
1203 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_Digest, 0, 0, 3)
1204     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1205     ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0)
1206     ZEND_ARG_TYPE_INFO(1, digest, IS_STRING, 1)
1207 ZEND_END_ARG_INFO()
1208 
1209 PHP_METHOD(Module, C_Digest) {
1210     CK_RV rv;
1211 
1212     zval *session;
1213     zend_string *data;
1214     zval *php_digest = NULL;
1215 
1216     ZEND_PARSE_PARAMETERS_START(3, 3)
1217         Z_PARAM_ZVAL(session)
1218         Z_PARAM_STR(data)
1219         Z_PARAM_ZVAL(php_digest)
1220     ZEND_PARSE_PARAMETERS_END();
1221 
1222     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1223     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1224 
1225     CK_ULONG digestLen;
1226     rv = sessionobjval->pkcs11->functionList->C_Digest(
1227         sessionobjval->session,
1228         ZSTR_VAL(data),
1229         ZSTR_LEN(data),
1230         NULL_PTR,
1231         &digestLen
1232     );
1233     if (rv != CKR_OK) {
1234         pkcs11_error(rv, "Unable to digest");
1235         return;
1236     }
1237 
1238     CK_BYTE_PTR digest = ecalloc(digestLen, sizeof(CK_BYTE));
1239     rv = sessionobjval->pkcs11->functionList->C_Digest(
1240         sessionobjval->session,
1241         ZSTR_VAL(data),
1242         ZSTR_LEN(data),
1243         digest,
1244         &digestLen
1245     );
1246 
1247     if (rv != CKR_OK)
1248         goto fini;
1249 
1250     zval retval;
1251     ZVAL_STRINGL(&retval, digest, digestLen);
1252     efree(digest);
1253 
1254     ZEND_TRY_ASSIGN_REF_VALUE(php_digest, &retval);
1255 
1256 fini:
1257     RETURN_LONG(rv);
1258 }
1259 
1260 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_DigestUpdate, 0, 0, 2)
1261     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1262     ZEND_ARG_TYPE_INFO(0, part, IS_STRING, 0)
1263 ZEND_END_ARG_INFO()
1264 
1265 PHP_METHOD(Module, C_DigestUpdate) {
1266     CK_RV rv;
1267 
1268     zval *session;
1269     zend_string *part;
1270 
1271     ZEND_PARSE_PARAMETERS_START(2, 2)
1272         Z_PARAM_ZVAL(session)
1273         Z_PARAM_STR(part)
1274     ZEND_PARSE_PARAMETERS_END();
1275 
1276     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1277     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1278 
1279     rv = sessionobjval->pkcs11->functionList->C_DigestUpdate(
1280         sessionobjval->session,
1281         ZSTR_VAL(part),
1282         ZSTR_LEN(part)
1283     );
1284 
1285     RETURN_LONG(rv);
1286 }
1287 
1288 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_DigestKey, 0, 0, 2)
1289     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1290     ZEND_ARG_OBJ_INFO(0, key, Pkcs11\\Key, 0)
1291 ZEND_END_ARG_INFO()
1292 
1293 PHP_METHOD(Module, C_DigestKey) {
1294     CK_RV rv;
1295 
1296     zval *session;
1297     zval *key;
1298 
1299     ZEND_PARSE_PARAMETERS_START(2, 2)
1300         Z_PARAM_ZVAL(session)
1301         Z_PARAM_ZVAL(key)
1302     ZEND_PARSE_PARAMETERS_END();
1303 
1304     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1305     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1306     pkcs11_key_object *keyobjval = Z_PKCS11_KEY_P(key);
1307 
1308     rv = sessionobjval->pkcs11->functionList->C_DigestKey(
1309         sessionobjval->session,
1310         keyobjval->key
1311     );
1312 
1313     RETURN_LONG(rv);
1314 }
1315 
1316 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_DigestFinal, 0, 0, 2)
1317     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1318     ZEND_ARG_TYPE_INFO(1, digest, IS_STRING, 1)
1319 ZEND_END_ARG_INFO()
1320 
1321 PHP_METHOD(Module, C_DigestFinal) {
1322     CK_RV rv;
1323 
1324     zval *session;
1325     zval *php_digest = NULL;
1326 
1327     ZEND_PARSE_PARAMETERS_START(2, 2)
1328         Z_PARAM_ZVAL(session)
1329         Z_PARAM_ZVAL(php_digest)
1330     ZEND_PARSE_PARAMETERS_END();
1331 
1332     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1333     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1334 
1335     CK_ULONG digestLen;
1336     rv = sessionobjval->pkcs11->functionList->C_DigestFinal(
1337         sessionobjval->session,
1338         NULL_PTR,
1339         &digestLen
1340     );
1341     if (rv != CKR_OK) {
1342         pkcs11_error(rv, "Unable to finalize digest");
1343         return;
1344     }
1345 
1346     CK_BYTE_PTR digest = ecalloc(digestLen, sizeof(CK_BYTE));
1347     rv = sessionobjval->pkcs11->functionList->C_DigestFinal(
1348         sessionobjval->session,
1349         digest,
1350         &digestLen
1351     );
1352 
1353     if (rv != CKR_OK)
1354         goto fini;
1355 
1356     zval retval;
1357     ZVAL_STRINGL(&retval, digest, digestLen);
1358     efree(digest);
1359 
1360     ZEND_TRY_ASSIGN_REF_VALUE(php_digest, &retval);
1361 
1362 fini:
1363     RETURN_LONG(rv);
1364 }
1365 
1366 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_SignInit, 0, 0, 3)
1367     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1368     ZEND_ARG_OBJ_INFO(0, mechanism, Pkcs11\\Mechanism, 0)
1369     ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0)
1370 ZEND_END_ARG_INFO()
1371 
1372 PHP_METHOD(Module, C_SignInit) {
1373     CK_RV rv;
1374     CK_OBJECT_HANDLE hKey;
1375 
1376     zval *mechanism;
1377     zend_long key;
1378     zval *session;
1379 
1380     ZEND_PARSE_PARAMETERS_START(3, 3)
1381         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1382         Z_PARAM_OBJECT_OF_CLASS(mechanism, ce_Pkcs11_Mechanism)
1383         Z_PARAM_LONG(key)
1384     ZEND_PARSE_PARAMETERS_END();
1385 
1386     pkcs11_mechanism_object * const oMechanism = Z_PKCS11_MECHANISM_P(mechanism);
1387 
1388     if (oMechanism->mechanism.mechanism == 0) {
1389         zend_throw_exception(zend_ce_exception, "Invalid mechanism", 0);
1390         return ;
1391     }
1392 
1393     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1394     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1395 
1396     hKey = (CK_OBJECT_HANDLE)key;
1397 
1398     rv = objval->functionList->C_SignInit(sessionobjval->session, &oMechanism->mechanism, hKey);
1399 
1400     RETURN_LONG(rv);
1401 }
1402 
1403 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_Sign, 0, 0, 3)
1404     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1405     ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0)
1406     ZEND_ARG_TYPE_INFO(1, signature, IS_STRING, 1)
1407 ZEND_END_ARG_INFO()
1408 
1409 PHP_METHOD(Module, C_Sign) {
1410     CK_RV rv;
1411     CK_BYTE_PTR pData;
1412     CK_ULONG ulDataLen;
1413     CK_BYTE_PTR pSignature = NULL;
1414     CK_ULONG ulSignatureLen = 0;
1415 
1416     zval *session;
1417     zend_string *data = NULL;
1418     zval *signature = NULL;
1419 
1420     ZEND_PARSE_PARAMETERS_START(3, 3)
1421         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1422         Z_PARAM_STR(data)
1423         Z_PARAM_ZVAL(signature)
1424     ZEND_PARSE_PARAMETERS_END();
1425 
1426     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1427     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1428 
1429     pData = (CK_BYTE_PTR)ZSTR_VAL(data);
1430     ulDataLen = (CK_ULONG)ZSTR_LEN(data);
1431 
1432     /* first, get the length of the Signature */
1433     rv = objval->functionList->C_Sign(sessionobjval->session, pData, ulDataLen, NULL, &ulSignatureLen);
1434     if (rv != CKR_OK) {
1435         RETURN_LONG(rv);
1436         return ;
1437     }
1438 
1439     pSignature = ecalloc(sizeof(*pSignature), ulSignatureLen);
1440 
1441     rv = objval->functionList->C_Sign(sessionobjval->session, pData, ulDataLen, pSignature, &ulSignatureLen);
1442 
1443     if (rv != CKR_OK)
1444         goto fini;
1445 
1446     zval retval;
1447     ZVAL_STRINGL(&retval, (char *)pSignature, ulSignatureLen);
1448 
1449     ZEND_TRY_ASSIGN_REF_VALUE(signature, &retval);
1450 
1451 fini:
1452     efree(pSignature);
1453     RETURN_LONG(rv);
1454 }
1455 
1456 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_VerifyInit, 0, 0, 3)
1457     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1458     ZEND_ARG_OBJ_INFO(0, mechanism, Pkcs11\\Mechanism, 0)
1459     ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0)
1460 ZEND_END_ARG_INFO()
1461 
1462 PHP_METHOD(Module, C_VerifyInit) {
1463     CK_RV rv;
1464     CK_OBJECT_HANDLE hKey;
1465 
1466     zval *mechanism;
1467     zend_long key;
1468     zval *session;
1469 
1470     ZEND_PARSE_PARAMETERS_START(3, 3)
1471         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1472         Z_PARAM_OBJECT_OF_CLASS(mechanism, ce_Pkcs11_Mechanism)
1473         Z_PARAM_LONG(key)
1474     ZEND_PARSE_PARAMETERS_END();
1475 
1476     pkcs11_mechanism_object * const oMechanism = Z_PKCS11_MECHANISM_P(mechanism);
1477 
1478     if (oMechanism->mechanism.mechanism == 0) {
1479         zend_throw_exception(zend_ce_exception, "Invalid mechanism", 0);
1480         return ;
1481     }
1482 
1483     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1484     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1485 
1486     hKey = (CK_OBJECT_HANDLE)key;
1487 
1488     rv = objval->functionList->C_VerifyInit(sessionobjval->session, &oMechanism->mechanism, hKey);
1489 
1490     RETURN_LONG(rv);
1491 }
1492 
1493 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_Verify, 0, 0, 3)
1494     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1495     ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0)
1496     ZEND_ARG_TYPE_INFO(0, signature, IS_STRING, 0)
1497 ZEND_END_ARG_INFO()
1498 
1499 PHP_METHOD(Module, C_Verify) {
1500     CK_RV rv;
1501     CK_BYTE_PTR pData;
1502     CK_ULONG ulDataLen;
1503     CK_BYTE_PTR pSignature = NULL;
1504     CK_ULONG ulSignatureLen = 0;
1505 
1506     zval *session;
1507     zend_string *data = NULL;
1508     zend_string *signature = NULL;
1509 
1510     ZEND_PARSE_PARAMETERS_START(3, 3)
1511         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1512         Z_PARAM_STR(data)
1513         Z_PARAM_STR(signature)
1514     ZEND_PARSE_PARAMETERS_END();
1515 
1516     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1517     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1518 
1519     pData = (CK_BYTE_PTR)ZSTR_VAL(data);
1520     ulDataLen = (CK_ULONG)ZSTR_LEN(data);
1521     pSignature = (CK_BYTE_PTR)ZSTR_VAL(signature);
1522     ulSignatureLen = (CK_ULONG)ZSTR_LEN(signature);
1523 
1524     rv = objval->functionList->C_Verify(sessionobjval->session, pData, ulDataLen, pSignature, ulSignatureLen);
1525 
1526     RETURN_LONG(rv);
1527 }
1528 
1529 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_EncryptInit, 0, 0, 3)
1530     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1531     ZEND_ARG_OBJ_INFO(0, mechanism, Pkcs11\\Mechanism, 0)
1532     ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0)
1533 ZEND_END_ARG_INFO()
1534 
1535 PHP_METHOD(Module, C_EncryptInit) {
1536     CK_RV rv;
1537     CK_OBJECT_HANDLE hKey;
1538 
1539     zval *mechanism;
1540     zend_long key;
1541     zval *session;
1542 
1543     ZEND_PARSE_PARAMETERS_START(3, 3)
1544         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1545         Z_PARAM_OBJECT_OF_CLASS(mechanism, ce_Pkcs11_Mechanism)
1546         Z_PARAM_LONG(key)
1547     ZEND_PARSE_PARAMETERS_END();
1548 
1549     pkcs11_mechanism_object * const oMechanism = Z_PKCS11_MECHANISM_P(mechanism);
1550 
1551     if (oMechanism->mechanism.mechanism == 0) {
1552         zend_throw_exception(zend_ce_exception, "Invalid mechanism", 0);
1553         return ;
1554     }
1555 
1556     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1557     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1558 
1559     hKey = (CK_OBJECT_HANDLE)key;
1560 
1561     rv = objval->functionList->C_EncryptInit(sessionobjval->session, &oMechanism->mechanism, hKey);
1562 
1563     RETURN_LONG(rv);
1564 }
1565 
1566 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_Encrypt, 0, 0, 3)
1567     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1568     ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0)
1569     ZEND_ARG_TYPE_INFO(1, encryptedData, IS_STRING, 1)
1570 ZEND_END_ARG_INFO()
1571 
1572 PHP_METHOD(Module, C_Encrypt) {
1573     CK_RV rv;
1574     CK_BYTE_PTR pData;
1575     CK_ULONG ulDataLen;
1576     CK_BYTE_PTR pEncryptedData = NULL;
1577     CK_ULONG ulEncryptedDataLen = 0;
1578 
1579     zval *session;
1580     zend_string *data = NULL;
1581     zval *encryptedData = NULL;
1582 
1583     ZEND_PARSE_PARAMETERS_START(3, 3)
1584         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1585         Z_PARAM_STR(data)
1586         Z_PARAM_ZVAL(encryptedData)
1587     ZEND_PARSE_PARAMETERS_END();
1588 
1589     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1590     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1591 
1592     pData = (CK_BYTE_PTR)ZSTR_VAL(data);
1593     ulDataLen = (CK_ULONG)ZSTR_LEN(data);
1594 
1595     rv = objval->functionList->C_Encrypt(sessionobjval->session, pData, ulDataLen, NULL, &ulEncryptedDataLen);
1596     if (rv != CKR_OK) {
1597         RETURN_LONG(rv);
1598         return ;
1599     }
1600 
1601     pEncryptedData = ecalloc(sizeof(*pEncryptedData), ulEncryptedDataLen);
1602 
1603     rv = objval->functionList->C_Encrypt(sessionobjval->session, pData, ulDataLen, pEncryptedData, &ulEncryptedDataLen);
1604 
1605     if (rv != CKR_OK)
1606         goto fini;
1607 
1608     zval retval;
1609     ZVAL_STRINGL(&retval, (char *)pEncryptedData, ulEncryptedDataLen);
1610 
1611     ZEND_TRY_ASSIGN_REF_VALUE(encryptedData, &retval);
1612 
1613 fini:
1614     efree(pEncryptedData);
1615     RETURN_LONG(rv);
1616 }
1617 
1618 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_DecryptInit, 0, 0, 3)
1619     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1620     ZEND_ARG_OBJ_INFO(0, mechanism, Pkcs11\\Mechanism, 0)
1621     ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0)
1622 ZEND_END_ARG_INFO()
1623 
1624 PHP_METHOD(Module, C_DecryptInit) {
1625     CK_RV rv;
1626     CK_OBJECT_HANDLE hKey;
1627 
1628     zval *mechanism;
1629     zend_long key;
1630     zval *session;
1631 
1632     ZEND_PARSE_PARAMETERS_START(3, 3)
1633         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1634         Z_PARAM_OBJECT_OF_CLASS(mechanism, ce_Pkcs11_Mechanism)
1635         Z_PARAM_LONG(key)
1636     ZEND_PARSE_PARAMETERS_END();
1637 
1638     pkcs11_mechanism_object * const oMechanism = Z_PKCS11_MECHANISM_P(mechanism);
1639 
1640     if (oMechanism->mechanism.mechanism == 0) {
1641         zend_throw_exception(zend_ce_exception, "Invalid mechanism", 0);
1642         return ;
1643     }
1644 
1645     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1646     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1647 
1648     hKey = (CK_OBJECT_HANDLE)key;
1649 
1650     rv = objval->functionList->C_DecryptInit(sessionobjval->session, &oMechanism->mechanism, hKey);
1651 
1652     RETURN_LONG(rv);
1653 }
1654 
1655 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_Decrypt, 0, 0, 3)
1656     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1657     ZEND_ARG_TYPE_INFO(0, encryptedData, IS_STRING, 0)
1658     ZEND_ARG_TYPE_INFO(1, data, IS_STRING, 1)
1659 ZEND_END_ARG_INFO()
1660 
1661 PHP_METHOD(Module, C_Decrypt) {
1662     CK_RV rv;
1663     CK_BYTE_PTR pEncryptedData;
1664     CK_ULONG ulEncryptedDataLen;
1665     CK_BYTE_PTR pData = NULL;
1666     CK_ULONG ulDataLen = 0;
1667 
1668     zval *session;
1669     zend_string *encryptedData = NULL;
1670     zval *data = NULL;
1671 
1672     ZEND_PARSE_PARAMETERS_START(3, 3)
1673         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1674         Z_PARAM_STR(encryptedData)
1675         Z_PARAM_ZVAL(data)
1676     ZEND_PARSE_PARAMETERS_END();
1677 
1678     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1679     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1680 
1681     pEncryptedData = (CK_BYTE_PTR)ZSTR_VAL(encryptedData);
1682     ulEncryptedDataLen = (CK_ULONG)ZSTR_LEN(encryptedData);
1683 
1684     rv = objval->functionList->C_Decrypt(sessionobjval->session, pEncryptedData, ulEncryptedDataLen, NULL, &ulDataLen);
1685     if (rv != CKR_OK) {
1686         RETURN_LONG(rv);
1687         return ;
1688     }
1689 
1690     pData = ecalloc(sizeof(*pData), ulDataLen);
1691 
1692     rv = objval->functionList->C_Decrypt(sessionobjval->session, pEncryptedData, ulEncryptedDataLen, pData, &ulDataLen);
1693 
1694     if (rv != CKR_OK)
1695         goto fini;
1696 
1697     zval retval;
1698     ZVAL_STRINGL(&retval, (char *)pData, ulDataLen);
1699 
1700     ZEND_TRY_ASSIGN_REF_VALUE(data, &retval);
1701 
1702 fini:
1703     efree(pEncryptedData);
1704     RETURN_LONG(rv);
1705 }
1706 
1707 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_Wrap, 0, 0, 5)
1708     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1709     ZEND_ARG_OBJ_INFO(0, mechanism, Pkcs11\\Mechanism, 0)
1710     ZEND_ARG_TYPE_INFO(0, keyId, IS_LONG, 0)
1711     ZEND_ARG_TYPE_INFO(0, targetKeyId, IS_LONG, 0)
1712     ZEND_ARG_TYPE_INFO(1, ciphertext, IS_STRING, 1)
1713 ZEND_END_ARG_INFO()
1714 
1715 PHP_METHOD(Module, C_Wrap) {
1716     CK_RV rv;
1717 
1718     zval *session;
1719     zval *mechanism;
1720     zend_long key;
1721     zend_long targetKey;
1722     zval *ciphertext = NULL;
1723 
1724     ZEND_PARSE_PARAMETERS_START(5, 5)
1725         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1726         Z_PARAM_OBJECT_OF_CLASS(mechanism, ce_Pkcs11_Mechanism)
1727         Z_PARAM_LONG(key)
1728         Z_PARAM_LONG(targetKey)
1729         Z_PARAM_ZVAL(ciphertext)
1730     ZEND_PARSE_PARAMETERS_END();
1731 
1732     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1733     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1734     pkcs11_mechanism_object *mechanismobjval = Z_PKCS11_MECHANISM_P(mechanism);
1735 
1736     if (mechanismobjval->mechanism.mechanism == 0) {
1737         zend_throw_exception(zend_ce_exception, "Invalid mechanism", 0);
1738         return ;
1739     }
1740 
1741     CK_OBJECT_HANDLE hKey = (CK_OBJECT_HANDLE)key;
1742     CK_OBJECT_HANDLE hTargetKey = (CK_OBJECT_HANDLE)targetKey;
1743 
1744     CK_ULONG ciphertextLen;
1745     rv = objval->functionList->C_WrapKey(
1746         sessionobjval->session,
1747         &mechanismobjval->mechanism,
1748         hKey,
1749         hTargetKey,
1750         NULL_PTR,
1751         &ciphertextLen
1752     );
1753 
1754     if (rv != CKR_OK) {
1755         RETURN_LONG(rv);
1756     }
1757 
1758     CK_BYTE_PTR hCiphertext = ecalloc(ciphertextLen, sizeof(CK_BYTE));
1759     if (hCiphertext == NULL) {
1760         RETURN_LONG(CKR_HOST_MEMORY);
1761     }
1762 
1763     rv = objval->functionList->C_WrapKey(
1764         sessionobjval->session,
1765         &mechanismobjval->mechanism,
1766         hKey,
1767         hTargetKey,
1768         hCiphertext,
1769         &ciphertextLen
1770     );
1771     if (rv != CKR_OK) {
1772         efree(hCiphertext);
1773         pkcs11_error(rv, "Unable to wrap");
1774         return;
1775     }
1776 
1777     zval retval;
1778     ZVAL_STRINGL(&retval, (char *)hCiphertext, ciphertextLen);
1779     ZEND_TRY_ASSIGN_REF_VALUE(ciphertext, &retval);
1780 
1781     efree(hCiphertext);
1782     RETURN_LONG(rv);
1783 }
1784 
1785 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_Unwrap, 0, 0, 6)
1786     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1787     ZEND_ARG_OBJ_INFO(0, mechanism, Pkcs11\\Mechanism, 0)
1788     ZEND_ARG_TYPE_INFO(0, keyId, IS_LONG, 0)
1789     ZEND_ARG_TYPE_INFO(0, encryptedData, IS_STRING, 0)
1790     ZEND_ARG_TYPE_INFO(0, template, IS_ARRAY, 0)
1791     ZEND_ARG_TYPE_INFO(1, keyId, IS_LONG, 1)
1792 ZEND_END_ARG_INFO()
1793 
1794 PHP_METHOD(Module, C_Unwrap) {
1795     CK_RV rv;
1796 
1797     zval *session;
1798     zval *mechanism;
1799     zend_long key;
1800     zend_string *ciphertext;
1801     HashTable *template;
1802     zval *wkeyid = NULL;
1803 
1804     ZEND_PARSE_PARAMETERS_START(6, 6)
1805         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1806         Z_PARAM_OBJECT_OF_CLASS(mechanism, ce_Pkcs11_Mechanism)
1807         Z_PARAM_LONG(key)
1808         Z_PARAM_STR(ciphertext)
1809         Z_PARAM_ARRAY_HT(template)
1810         Z_PARAM_ZVAL(wkeyid)
1811     ZEND_PARSE_PARAMETERS_END();
1812 
1813     int templateItemCount;
1814     CK_ATTRIBUTE_PTR templateObj;
1815     parseTemplate(&template, &templateObj, &templateItemCount);
1816 
1817     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1818     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1819     pkcs11_mechanism_object *mechanismobjval = Z_PKCS11_MECHANISM_P(mechanism);
1820 
1821     if (mechanismobjval->mechanism.mechanism == 0) {
1822         freeTemplate(templateObj);
1823         zend_throw_exception(zend_ce_exception, "Invalid mechanism", 0);
1824         return ;
1825     }
1826 
1827     CK_OBJECT_HANDLE hKey = (CK_OBJECT_HANDLE)key;
1828     CK_OBJECT_HANDLE hUnwrappedKey;
1829 
1830     rv = objval->functionList->C_UnwrapKey(
1831         sessionobjval->session,
1832         &mechanismobjval->mechanism,
1833         hKey,
1834         ZSTR_VAL(ciphertext),
1835         ZSTR_LEN(ciphertext),
1836         templateObj,
1837         templateItemCount,
1838         &hUnwrappedKey
1839     );
1840     freeTemplate(templateObj);
1841 
1842     if (rv != CKR_OK) {
1843         RETURN_LONG(rv);
1844     }
1845 
1846     zval zva;
1847     ZVAL_LONG(&zva, hUnwrappedKey);
1848     ZEND_TRY_ASSIGN_REF_VALUE(wkeyid, &zva);
1849 
1850     RETURN_LONG(rv);
1851 }
1852 
1853 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_CreateObject, 0, 0, 3)
1854     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1855     ZEND_ARG_TYPE_INFO(0, template, IS_ARRAY, 0)
1856     ZEND_ARG_OBJ_INFO(1, phObject, Pkcs11\\P11Object, 1)
1857 ZEND_END_ARG_INFO()
1858 
1859 
1860 PHP_METHOD(Module, C_CreateObject) {
1861     CK_RV rv;
1862 
1863     zval *session;
1864     zval *phObject;
1865     HashTable *template;
1866     zval retval;
1867 
1868     ZEND_PARSE_PARAMETERS_START(3, 3)
1869         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1870         Z_PARAM_ARRAY_HT(template)
1871         Z_PARAM_ZVAL(phObject)
1872     ZEND_PARSE_PARAMETERS_END();
1873 
1874     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1875     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1876 
1877     rv = php_C_CreateObject(sessionobjval, template, &retval);
1878 
1879     ZEND_TRY_ASSIGN_REF_VALUE(phObject, &retval);
1880 
1881     RETURN_LONG(rv);
1882 }
1883 
1884 static int AssertAttributeCKA(const CK_ATTRIBUTE_PTR pAttribute) {
1885     switch(pAttribute->type) {
1886         case CKA_KEY_TYPE:
1887             return !(pAttribute->ulValueLen == sizeof(CK_KEY_TYPE));
1888         case CKA_CLASS:
1889             return !(pAttribute->ulValueLen == sizeof(CK_OBJECT_CLASS));
1890         case CKA_CERTIFICATE_TYPE:
1891             return !(pAttribute->ulValueLen == sizeof(CK_CERTIFICATE_TYPE));
1892         case CKA_TOKEN:
1893         case CKA_PRIVATE:
1894         case CKA_TRUSTED:
1895         case CKA_SENSITIVE:
1896         case CKA_ENCRYPT:
1897         case CKA_DECRYPT:
1898         case CKA_WRAP:
1899         case CKA_UNWRAP:
1900         case CKA_SIGN:
1901         case CKA_SIGN_RECOVER:
1902         case CKA_VERIFY:
1903         case CKA_VERIFY_RECOVER:
1904         case CKA_DERIVE:
1905         case CKA_EXTRACTABLE:
1906         case CKA_LOCAL:
1907         case CKA_NEVER_EXTRACTABLE:
1908         case CKA_ALWAYS_SENSITIVE:
1909         case CKA_ALWAYS_AUTHENTICATE:
1910         case CKA_WRAP_WITH_TRUSTED:
1911         case CKA_RESET_ON_INIT:
1912         case CKA_HAS_RESET:
1913         case CKA_COLOR:
1914             return !(pAttribute->ulValueLen == sizeof(CK_BBOOL));
1915         case CKA_CERTIFICATE_CATEGORY:
1916         case CKA_JAVA_MIDP_SECURITY_DOMAIN:
1917         case CKA_MODULUS_BITS:
1918         case CKA_PRIME_BITS:
1919         case CKA_SUB_PRIME_BITS:
1920         case CKA_VALUE_BITS:
1921         case CKA_VALUE_LEN:
1922         case CKA_PIXEL_X:
1923         case CKA_PIXEL_Y:
1924         case CKA_RESOLUTION:
1925         case CKA_CHAR_ROWS:
1926         case CKA_CHAR_COLUMNS:
1927         case CKA_BITS_PER_PIXEL:
1928             return !(pAttribute->ulValueLen == sizeof(CK_ULONG));
1929         case CKA_VALUE:
1930         case CKA_OBJECT_ID:
1931         case CKA_SERIAL_NUMBER:
1932         case CKA_ATTR_TYPES:
1933         case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
1934         case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
1935         case CKA_CHECK_VALUE:
1936         case CKA_ECDSA_PARAMS:
1937         case CKA_LABEL:
1938         case CKA_EC_POINT:
1939         case CKA_REQUIRED_CMS_ATTRIBUTES:
1940         case CKA_DEFAULT_CMS_ATTRIBUTES:
1941         case CKA_SUPPORTED_CMS_ATTRIBUTES:
1942         case CKA_ID:
1943         case CKA_APPLICATION:
1944         case CKA_URL:
1945         case CKA_CHAR_SETS:
1946         case CKA_ENCODING_METHODS:
1947         case CKA_MIME_TYPES:
1948         default: /* TBD */
1949             return 0; /* any length */
1950     }
1951     return 0;
1952 }
1953 
1954 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_FindObjectsInit, 0, 0, 2)
1955     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1956     ZEND_ARG_TYPE_INFO(0, template, IS_ARRAY, 0)
1957 ZEND_END_ARG_INFO()
1958 
1959 PHP_METHOD(Module, C_FindObjectsInit) {
1960     CK_RV rv;
1961 
1962     zval *session;
1963     HashTable *template = NULL; /* PHP array */
1964 
1965     CK_ULONG ulCount = 0; /* number of attributes in the search template */
1966     CK_ATTRIBUTE_PTR pTemplate = NULL;
1967 
1968     ZEND_PARSE_PARAMETERS_START(1, 2)
1969         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
1970         Z_PARAM_OPTIONAL
1971         Z_PARAM_ARRAY_HT(template)
1972     ZEND_PARSE_PARAMETERS_END();
1973 
1974     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
1975     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
1976 
1977     if (template)
1978         parseTemplate(&template, &pTemplate, (int *)&ulCount);
1979 
1980     for(int i = 0; i < ulCount; i++) {
1981         if (AssertAttributeCKA(&pTemplate[i])) {
1982             zend_throw_exception(zend_ce_exception, "sizeof('value') invalid for requested type", 0);
1983             freeTemplate(pTemplate);
1984             return ;
1985         }
1986     }
1987 
1988     rv = objval->functionList->C_FindObjectsInit(sessionobjval->session, pTemplate, ulCount);
1989     if (pTemplate)
1990         freeTemplate(pTemplate);
1991 
1992     RETURN_LONG(rv);
1993 }
1994 
1995 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_FindObjects, 0, 0, 2)
1996     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
1997     ZEND_ARG_TYPE_INFO(1, Objects, IS_ARRAY, 1)
1998     ZEND_ARG_TYPE_INFO(0, MaxObjectCount, IS_LONG, 0) // Default 32
1999 ZEND_END_ARG_INFO()
2000 
2001 PHP_METHOD(Module, C_FindObjects) {
2002     CK_RV rv;
2003     CK_OBJECT_HANDLE_PTR phObject = NULL;
2004     CK_ULONG ulMaxObjectCount = 32; /* default is a batch of 32 */
2005     CK_ULONG ulObjectCount;
2006 
2007     zval *session;
2008     zend_long MaxObjectCount = ulMaxObjectCount;
2009     zval *Objects;
2010 
2011     ZEND_PARSE_PARAMETERS_START(2, 3)
2012         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
2013         Z_PARAM_ZVAL(Objects)
2014         Z_PARAM_OPTIONAL
2015         Z_PARAM_LONG(MaxObjectCount)
2016     ZEND_PARSE_PARAMETERS_END();
2017 
2018     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
2019     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
2020 
2021     if (MaxObjectCount < 1) {
2022         zend_throw_exception(zend_ce_exception, "Invalid MaxObjectCount argument", 0);
2023         return ;
2024     }
2025     ulMaxObjectCount = (CK_ULONG)MaxObjectCount;
2026 
2027     phObject = (CK_OBJECT_HANDLE_PTR)ecalloc(sizeof(*phObject), ulMaxObjectCount);
2028 
2029     rv = objval->functionList->C_FindObjects(sessionobjval->session,
2030                                              phObject, ulMaxObjectCount, &ulObjectCount);
2031 
2032     zval O;
2033     array_init(&O);
2034     for(CK_ULONG i = 0; i < ulObjectCount; i++)
2035         add_next_index_long(&O, phObject[i]);
2036 
2037     ZEND_TRY_ASSIGN_REF_VALUE(Objects, &O);
2038 
2039     efree(phObject);
2040 
2041     RETURN_LONG(rv);
2042 }
2043 
2044 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_FindObjectsFinal, 0, 0, 1)
2045     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
2046 ZEND_END_ARG_INFO()
2047 
2048 PHP_METHOD(Module, C_FindObjectsFinal) {
2049     CK_RV rv;
2050 
2051     zval *session;
2052 
2053     ZEND_PARSE_PARAMETERS_START(1, 1)
2054         Z_PARAM_ZVAL(session)
2055     ZEND_PARSE_PARAMETERS_END();
2056 
2057     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
2058     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
2059 
2060     rv = objval->functionList->C_FindObjectsFinal(sessionobjval->session);
2061 
2062     RETURN_LONG(rv);
2063 }
2064 
2065 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_GetAttributeValue, 0, 0, 3)
2066     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
2067     ZEND_ARG_TYPE_INFO(0, object, IS_LONG, 0)
2068     ZEND_ARG_TYPE_INFO(1, template, IS_ARRAY, 0)
2069 ZEND_END_ARG_INFO()
2070 
2071 PHP_METHOD(Module, C_GetAttributeValue) {
2072     CK_RV rv = 0;
2073     CK_OBJECT_HANDLE hObject;
2074     CK_ATTRIBUTE_PTR pTemplate = NULL;
2075     CK_ULONG ulCount = 0;
2076 
2077     char **infos = NULL;
2078 
2079     zval *session;
2080     zend_long object;
2081     HashTable *template = NULL; /* PHP array */
2082 
2083     ZEND_PARSE_PARAMETERS_START(3, 3)
2084         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
2085         Z_PARAM_LONG(object)
2086         Z_PARAM_ARRAY_HT_EX2(template, 0, 1 /* deref*/, 0) // &$template is a reference
2087     ZEND_PARSE_PARAMETERS_END();
2088 
2089     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
2090     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
2091 
2092     hObject = (CK_OBJECT_HANDLE)object;
2093 
2094     parseTemplate(&template, &pTemplate, (int *)&ulCount);
2095 
2096     if (ulCount < 1) {
2097         zend_throw_exception(zend_ce_exception, "Invalid Template size", 0);
2098         freeTemplate(pTemplate);
2099         return ;
2100     }
2101 
2102     /* first step: fetch the length of each entry */
2103     rv = objval->functionList->C_GetAttributeValue(sessionobjval->session,
2104                                                    hObject, pTemplate, ulCount);
2105     /*
2106      * Note that the error codes CKR_ATTRIBUTE_SENSITIVE, CKR_ATTRIBUTE_TYPE_INVALID,
2107      * and CKR_BUFFER_TOO_SMALL do not denote true errors for C_GetAttributeValue.
2108      * If a call to C_GetAttributeValue returns any of these three values, then the
2109      * call MUST nonetheless have processed every attribute in the template supplied
2110      * to C_GetAttributeValue.
2111      * Each attribute in the template whose value can be returned by the call to
2112      * C_GetAttributeValue will be returned by the call to C_GetAttributeValue.
2113      */
2114     switch(rv) {
2115         case CKR_ATTRIBUTE_SENSITIVE:
2116         case CKR_ATTRIBUTE_TYPE_INVALID: /* one of the requested attributed does not exist */
2117         case CKR_BUFFER_TOO_SMALL:
2118         case CKR_OK:
2119             break; /* ok */
2120         default:
2121             pkcs11_error(rv, "C_GetAttributeValue(), get size");
2122             freeTemplate(pTemplate);
2123             return ;
2124     }
2125 
2126     for (CK_ULONG k = 0; k < ulCount; k++) {
2127         if ((pTemplate[k].ulValueLen == CK_UNAVAILABLE_INFORMATION) ||
2128             (pTemplate[k].ulValueLen < 1))
2129             continue;
2130         pTemplate[k].pValue = (CK_BYTE_PTR)ecalloc(1, pTemplate[k].ulValueLen);
2131     }
2132 
2133     /* fetch the content */
2134     rv = objval->functionList->C_GetAttributeValue(sessionobjval->session,
2135                                                    hObject, pTemplate, ulCount);
2136     /*
2137      * Note that the error codes CKR_ATTRIBUTE_SENSITIVE, CKR_ATTRIBUTE_TYPE_INVALID,
2138      * and CKR_BUFFER_TOO_SMALL do not denote true errors for C_GetAttributeValue.
2139      * If a call to C_GetAttributeValue returns any of these three values, then the
2140      * call MUST nonetheless have processed every attribute in the template supplied
2141      * to C_GetAttributeValue.
2142      * Each attribute in the template whose value can be returned by the call to
2143      * C_GetAttributeValue will be returned by the call to C_GetAttributeValue.
2144      */
2145     switch(rv) {
2146         case CKR_ATTRIBUTE_SENSITIVE:
2147         case CKR_ATTRIBUTE_TYPE_INVALID: /* one of the requested attributed does not exist */
2148         case CKR_BUFFER_TOO_SMALL:
2149         case CKR_OK:
2150             break; /* ok */
2151         default:
2152             goto fini; /* free pTemplate, pTemplate[x].pValue */
2153             RETURN_LONG(rv); // placeholder, will be performed into the fini section
2154     }
2155 
2156     for(CK_ULONG k = 0; k < ulCount; k++) {
2157         zval zva;
2158         zval tmp;
2159 
2160         switch(pTemplate[k].ulValueLen) {
2161           case CK_UNAVAILABLE_INFORMATION:
2162             zend_hash_index_del(template, pTemplate[k].type);
2163           break;
2164           case 0:
2165             ZVAL_NULL(&tmp);
2166             zend_hash_index_update(template, pTemplate[k].type, &tmp);
2167           break;
2168           default:
2169             /* add_index_stringl(&template, k, pTemplate[k].pValue, pTemplate[k].ulValueLen); */
2170             ZVAL_STRINGL(&tmp, pTemplate[k].pValue, pTemplate[k].ulValueLen);
2171             zend_hash_index_update(template, pTemplate[k].type, &tmp);
2172           break;
2173         }
2174     }
2175 
2176 fini: /* memory free section */
2177     for(CK_ULONG k = 0; k < ulCount; k++) {
2178         if ((pTemplate[k].ulValueLen == CK_UNAVAILABLE_INFORMATION) ||
2179             (pTemplate[k].ulValueLen < 1)) {
2180             continue;
2181         }
2182         efree(pTemplate[k].pValue);
2183     }
2184 
2185     freeTemplate(pTemplate);
2186 
2187     RETURN_LONG(rv);
2188 }
2189 
2190 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_CopyObject, 0, 0, 4)
2191     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
2192     ZEND_ARG_OBJ_INFO(0, object, Pkcs11\\P11Object, 0)
2193     ZEND_ARG_TYPE_INFO(0, template, IS_ARRAY, 0)
2194     ZEND_ARG_OBJ_INFO(1, phNewObject, Pkcs11\\P11Object, 1)
2195 ZEND_END_ARG_INFO()
2196 
2197 PHP_METHOD(Module, C_CopyObject) {
2198     CK_RV rv;
2199 
2200     zval *session;
2201     zval *object;
2202     zval *phNewObject;
2203     HashTable *template;
2204     zval retval;
2205 
2206     ZEND_PARSE_PARAMETERS_START(4, 4)
2207         Z_PARAM_OBJECT_OF_CLASS(session, ce_Pkcs11_Session)
2208         Z_PARAM_OBJECT_OF_CLASS(object, ce_Pkcs11_P11Object)
2209         Z_PARAM_ARRAY_HT(template)
2210         Z_PARAM_ZVAL(phNewObject)
2211     ZEND_PARSE_PARAMETERS_END();
2212 
2213     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
2214     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
2215 
2216     rv = php_C_CopyObject(sessionobjval, object, template, &retval);
2217 
2218     ZEND_TRY_ASSIGN_REF_VALUE(phNewObject, &retval);
2219 
2220     RETURN_LONG(rv);
2221 }
2222 
2223 
2224 ZEND_BEGIN_ARG_INFO_EX(arginfo_C_DestroyObject, 0, 0, 2)
2225     ZEND_ARG_OBJ_INFO(0, session, Pkcs11\\Session, 0)
2226     ZEND_ARG_OBJ_INFO(0, object, Pkcs11\\P11Object, 0)
2227 ZEND_END_ARG_INFO()
2228 
2229 PHP_METHOD(Module, C_DestroyObject) {
2230     CK_RV rv;
2231 
2232     zval *session;
2233     zval *object;
2234 
2235     ZEND_PARSE_PARAMETERS_START(2, 2)
2236         Z_PARAM_ZVAL(session)
2237         Z_PARAM_ZVAL(object)
2238     ZEND_PARSE_PARAMETERS_END();
2239 
2240     pkcs11_object *objval = Z_PKCS11_P(ZEND_THIS);
2241     pkcs11_session_object *sessionobjval = Z_PKCS11_SESSION_P(session);
2242 
2243     rv = php_C_DestroyObject(sessionobjval, object);
2244 
2245     RETURN_LONG(rv);
2246 }
2247 
2248 void pkcs11_shutdown(pkcs11_object *obj) {
2249     // called before the pkcs11_object is freed
2250     if (obj->functionList != NULL) {
2251         obj->functionList->C_Finalize(NULL_PTR);
2252         obj->functionList = NULL;
2253     }
2254 
2255     if (obj->pkcs11module != NULL) {
2256         dlclose(obj->pkcs11module);
2257     }
2258 }
2259 
2260 
2261 static zend_function_entry module_class_functions[] = {
2262     PHP_ME(Module, __construct,      arginfo___construct,      ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
2263     PHP_ME(Module, getInfo,          arginfo_getInfo,          ZEND_ACC_PUBLIC)
2264     PHP_ME(Module, getSlots,         arginfo_getSlots,         ZEND_ACC_PUBLIC)
2265     PHP_ME(Module, getSlotList,      arginfo_getSlotList,      ZEND_ACC_PUBLIC)
2266     PHP_ME(Module, getSlotInfo,      arginfo_getSlotInfo,      ZEND_ACC_PUBLIC)
2267     PHP_ME(Module, getTokenInfo,     arginfo_getTokenInfo,     ZEND_ACC_PUBLIC)
2268     PHP_ME(Module, getMechanismList, arginfo_getMechanismList, ZEND_ACC_PUBLIC)
2269     PHP_ME(Module, getMechanismInfo, arginfo_getMechanismInfo, ZEND_ACC_PUBLIC)
2270     PHP_ME(Module, initToken,        arginfo_initToken,        ZEND_ACC_PUBLIC)
2271     PHP_ME(Module, openSession,      arginfo_openSession,      ZEND_ACC_PUBLIC)
2272     PHP_ME(Module, waitForSlotEvent, arginfo_waitForSlotEvent, ZEND_ACC_PUBLIC)
2273 
2274     PHP_ME(Module, C_GetInfo,          arginfo_C_GetInfo,          ZEND_ACC_PUBLIC)
2275     PHP_ME(Module, C_GetSlotList,      arginfo_C_GetSlotList,      ZEND_ACC_PUBLIC)
2276     PHP_ME(Module, C_GetSlotInfo,      arginfo_C_GetSlotInfo,      ZEND_ACC_PUBLIC)
2277     PHP_ME(Module, C_GetTokenInfo,     arginfo_C_GetTokenInfo,     ZEND_ACC_PUBLIC)
2278     PHP_ME(Module, C_GetMechanismList, arginfo_C_GetMechanismList, ZEND_ACC_PUBLIC)
2279     PHP_ME(Module, C_GetMechanismInfo, arginfo_C_GetMechanismInfo, ZEND_ACC_PUBLIC)
2280     PHP_ME(Module, C_InitToken,        arginfo_C_InitToken,        ZEND_ACC_PUBLIC)
2281     PHP_ME(Module, C_SetPIN,           arginfo_C_SetPIN,           ZEND_ACC_PUBLIC)
2282     PHP_ME(Module, C_InitPIN,          arginfo_C_InitPIN,          ZEND_ACC_PUBLIC)
2283     PHP_ME(Module, C_OpenSession,      arginfo_C_OpenSession,      ZEND_ACC_PUBLIC)
2284     PHP_ME(Module, C_CloseSession,     arginfo_C_CloseSession,     ZEND_ACC_PUBLIC)
2285     PHP_ME(Module, C_GetSessionInfo,   arginfo_C_GetSessionInfo,   ZEND_ACC_PUBLIC)
2286     PHP_ME(Module, C_Login,            arginfo_C_Login,            ZEND_ACC_PUBLIC)
2287     PHP_ME(Module, C_Logout,           arginfo_C_Logout,           ZEND_ACC_PUBLIC)
2288     PHP_ME(Module, C_WaitForSlotEvent, arginfo_C_WaitForSlotEvent, ZEND_ACC_PUBLIC)
2289 
2290     PHP_ME(Module, C_GenerateKey,             arginfo_C_GenerateKey,             ZEND_ACC_PUBLIC)
2291     PHP_ME(Module, C_GenerateKeyPair,         arginfo_C_GenerateKeyPair,         ZEND_ACC_PUBLIC)
2292     PHP_ME(Module, C_DigestInit,              arginfo_C_DigestInit,              ZEND_ACC_PUBLIC)
2293     PHP_ME(Module, C_Digest,                  arginfo_C_Digest,                  ZEND_ACC_PUBLIC)
2294     PHP_ME(Module, C_DigestUpdate,            arginfo_C_DigestUpdate,            ZEND_ACC_PUBLIC)
2295     PHP_ME(Module, C_DigestKey,               arginfo_C_DigestKey,               ZEND_ACC_PUBLIC)
2296     PHP_ME(Module, C_DigestFinal,             arginfo_C_DigestFinal,             ZEND_ACC_PUBLIC)
2297 
2298     PHP_ME(Module, C_SignInit,                arginfo_C_SignInit,                ZEND_ACC_PUBLIC)
2299     PHP_ME(Module, C_Sign,                    arginfo_C_Sign,                    ZEND_ACC_PUBLIC)
2300 
2301     PHP_ME(Module, C_VerifyInit,              arginfo_C_VerifyInit,              ZEND_ACC_PUBLIC)
2302     PHP_ME(Module, C_Verify,                  arginfo_C_Verify,                  ZEND_ACC_PUBLIC)
2303 
2304     PHP_ME(Module, C_EncryptInit,             arginfo_C_EncryptInit,             ZEND_ACC_PUBLIC)
2305     PHP_ME(Module, C_Encrypt,                 arginfo_C_Encrypt,                 ZEND_ACC_PUBLIC)
2306     PHP_ME(Module, C_DecryptInit,             arginfo_C_DecryptInit,             ZEND_ACC_PUBLIC)
2307     PHP_ME(Module, C_Decrypt,                 arginfo_C_Decrypt,                 ZEND_ACC_PUBLIC)
2308 
2309     PHP_ME(Module, C_Wrap,                    arginfo_C_Wrap,                    ZEND_ACC_PUBLIC)
2310     PHP_ME(Module, C_Unwrap,                  arginfo_C_Unwrap,                  ZEND_ACC_PUBLIC)
2311 
2312     PHP_ME(Module, C_GenerateRandom,          arginfo_C_GenerateRandom,          ZEND_ACC_PUBLIC)
2313     PHP_ME(Module, C_SeedRandom,              arginfo_C_SeedRandom,              ZEND_ACC_PUBLIC)
2314 
2315     PHP_ME(Module, C_CreateObject,            arginfo_C_CreateObject,            ZEND_ACC_PUBLIC)
2316     PHP_ME(Module, C_FindObjectsInit,         arginfo_C_FindObjectsInit,         ZEND_ACC_PUBLIC)
2317     PHP_ME(Module, C_FindObjects,             arginfo_C_FindObjects,             ZEND_ACC_PUBLIC)
2318     PHP_ME(Module, C_FindObjectsFinal,        arginfo_C_FindObjectsFinal,        ZEND_ACC_PUBLIC)
2319     PHP_ME(Module, C_GetAttributeValue,       arginfo_C_GetAttributeValue,       ZEND_ACC_PUBLIC)
2320     PHP_ME(Module, C_CopyObject,              arginfo_C_CopyObject,              ZEND_ACC_PUBLIC)
2321     PHP_ME(Module, C_DestroyObject,           arginfo_C_DestroyObject,           ZEND_ACC_PUBLIC)
2322 
2323     PHP_FE_END
2324 };
2325 
2326 
2327 DEFINE_MAGIC_FUNCS(pkcs11, module, Module)
2328