TclPKCS11

Check-in [fcc22c8809]
Login

Check-in [fcc22c8809]

Overview
Comment:Updated to use pragma pack on Win32 fixing issues experienced with C_GetFunctionList returning unusable data Updated to unload all active PKCS#11 modules on exit
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: fcc22c8809a0898782acc77219826aa370a89a82edd892fc4bcd206249419a7d
User & Date: rkeene on 2010-10-11 13:41:19
Other Links: manifest | tags
Context
2010-10-11
13:54
Changed session management functions to use an active flag rather than a special session value check-in: 250660270e user: rkeene tags: trunk
13:41
Updated to use pragma pack on Win32 fixing issues experienced with C_GetFunctionList returning unusable data Updated to unload all active PKCS#11 modules on exit check-in: fcc22c8809 user: rkeene tags: trunk
04:59
Updated to close session if we get a CKR_DEVICE_REMOVED on logout Win32-specific PKCS#11 definitions created Updated to retrieve function pointers using lookups rather than C_GetFunctionList on Win32 since ActivClient doesn't seem to return valid function pointers... Updated to return fake PKCS#11 error "MAYBE_LOGIN" if we are unable to find any private key objects Updated to try C_Encrypt for encryption before trying C_Sign. Updated to unpad (PKCS 1.5 mode 1 only) input when encrypting since some drivers require the input to be unpadded Minor cleanup Updated test driver to support logging in if MAYBE_LOGIN is recieved check-in: 85de7abf4c user: rkeene tags: trunk
Changes

Modified tclpkcs11.c from [f5446da071] to [671cc071b5].

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







-
-
-
-
-
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+

+

+
+
+
+








#if 10 * TCL_MAJOR_VERSION + TCL_MINOR_VERSION >= 86
#  define TCL_INCLUDES_LOADFILE 1
#endif

/* PKCS#11 Definitions for the local platform */
#ifndef _WIN32
#define CK_PTR *
#define CK_DECLARE_FUNCTION(rv, func) rv func
#define CK_DECLARE_FUNCTION_POINTER(rv, func) rv (CK_PTR func)
#define CK_CALLBACK_FUNCTION(rv, func) rv (CK_PTR func)
#define CK_NULL_PTR ((void *) 0)
#  define CK_PTR *
#  define CK_DECLARE_FUNCTION(rv, func) rv func
#  define CK_DECLARE_FUNCTION_POINTER(rv, func) rv (CK_PTR func)
#  define CK_CALLBACK_FUNCTION(rv, func) rv (CK_PTR func)
#  define CK_NULL_PTR ((void *) 0)
#else
#define CK_PTR *
#define CK_DECLARE_FUNCTION(rv, func) rv __declspec(dllimport) func
#define CK_DECLARE_FUNCTION_POINTER(rv, func) rv __declspec(dllimport) (CK_PTR func)
#define CK_CALLBACK_FUNCTION(rv, func) rv (CK_PTR func)
#define CK_NULL_PTR ((void *) 0)
#  define CK_PTR *
#  define CK_DECLARE_FUNCTION(rv, func) rv __declspec(dllimport) func
#  define CK_DECLARE_FUNCTION_POINTER(rv, func) rv __declspec(dllimport) (CK_PTR func)
#  define CK_CALLBACK_FUNCTION(rv, func) rv (CK_PTR func)
#  define CK_NULL_PTR ((void *) 0)
#  pragma pack(push, cryptoki, 1)
#endif

#include "pkcs11.h"

#ifdef _WIN32
#  pragma pack(pop, cryptoki)
#endif

struct tclpkcs11_interpdata {
	/* Handle Hash Table */
	Tcl_HashTable handles;
	unsigned long handles_idx;
};

486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
492
493
494
495
496
497
498

499
500
501
502
503
504
505
506







-
+







	const char *pathname;
	Tcl_HashEntry *tcl_handle_entry;
	Tcl_Obj *tcl_handle;
	void *handle;
	int is_new_entry;

	CK_C_INITIALIZE_ARGS initargs;
	CK_RV (CK_PTR getFuncList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList);
	CK_C_GetFunctionList getFuncList;
	CK_FUNCTION_LIST_PTR pkcs11_function_list = NULL;
	CK_RV chk_rv;

	if (!cd) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid clientdata\n", -1));

		return(TCL_ERROR);
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
529
530
531
532
533
534
535

536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554




















































































































































555
556
557
558
559
560
561







-



















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	getFuncList = tclpkcs11_int_lookup_sym(handle, "C_GetFunctionList");
	if (!getFuncList) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to locate C_GetFunctionList symbol in PKCS#11 module", -1));

		return(TCL_ERROR);
	}

#ifndef _WIN32
	chk_rv = getFuncList(&pkcs11_function_list);
	if (chk_rv != CKR_OK) {
		Tcl_SetObjResult(interp, tclpkcs11_pkcs11_error(chk_rv));

		return(TCL_ERROR);
	}

	if (!pkcs11_function_list) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned invalid data", -1));

		return(TCL_ERROR);
	}

	if (!pkcs11_function_list->C_Initialize) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data", -1));

		return(TCL_ERROR);
	}

#else
	/*
	 * Retreiving the functions from C_GetFunctionList does not seem to be
	 *reliable on Win32
	 */
	pkcs11_function_list = (CK_FUNCTION_LIST_PTR) ckalloc(sizeof(*pkcs11_function_list));

	pkcs11_function_list->C_CloseSession = tclpkcs11_int_lookup_sym(handle, "C_CloseSession");
	if (pkcs11_function_list->C_CloseSession == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_CloseSession)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_Decrypt = tclpkcs11_int_lookup_sym(handle, "C_Decrypt");
	if (pkcs11_function_list->C_Decrypt == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_Decrypt)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_DecryptFinal = tclpkcs11_int_lookup_sym(handle, "C_DecryptFinal");
	if (pkcs11_function_list->C_DecryptFinal == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_DecryptFinal)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_DecryptInit = tclpkcs11_int_lookup_sym(handle, "C_DecryptInit");
	if (pkcs11_function_list->C_DecryptInit == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_DecryptInit)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_Encrypt = tclpkcs11_int_lookup_sym(handle, "C_Encrypt");
	if (pkcs11_function_list->C_Encrypt == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_Encrypt)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_EncryptInit = tclpkcs11_int_lookup_sym(handle, "C_EncryptInit");
	if (pkcs11_function_list->C_EncryptInit == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_EncryptInit)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_Finalize = tclpkcs11_int_lookup_sym(handle, "C_Finalize");
	if (pkcs11_function_list->C_Finalize == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_Finalize)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_FindObjects = tclpkcs11_int_lookup_sym(handle, "C_FindObjects");
	if (pkcs11_function_list->C_FindObjects == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_FindObjects)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_FindObjectsFinal = tclpkcs11_int_lookup_sym(handle, "C_FindObjectsFinal");
	if (pkcs11_function_list->C_FindObjectsFinal == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_FindObjectsFinal)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_FindObjectsInit = tclpkcs11_int_lookup_sym(handle, "C_FindObjectsInit");
	if (pkcs11_function_list->C_FindObjectsInit == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_FindObjectsInit)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_GetAttributeValue = tclpkcs11_int_lookup_sym(handle, "C_GetAttributeValue");
	if (pkcs11_function_list->C_GetAttributeValue == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_GetAttributeValue)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_GetSlotInfo = tclpkcs11_int_lookup_sym(handle, "C_GetSlotInfo");
	if (pkcs11_function_list->C_GetSlotInfo == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_GetSlotInfo)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_GetSlotList = tclpkcs11_int_lookup_sym(handle, "C_GetSlotList");
	if (pkcs11_function_list->C_GetSlotList == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_GetSlotList)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_GetTokenInfo = tclpkcs11_int_lookup_sym(handle, "C_GetTokenInfo");
	if (pkcs11_function_list->C_GetTokenInfo == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_GetTokenInfo)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_Initialize = tclpkcs11_int_lookup_sym(handle, "C_Initialize");
	if (pkcs11_function_list->C_Initialize == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_Initialize)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_Login = tclpkcs11_int_lookup_sym(handle, "C_Login");
	if (pkcs11_function_list->C_Login == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_Login)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_Logout = tclpkcs11_int_lookup_sym(handle, "C_Logout");
	if (pkcs11_function_list->C_Logout == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_Logout)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_OpenSession = tclpkcs11_int_lookup_sym(handle, "C_OpenSession");
	if (pkcs11_function_list->C_OpenSession == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_OpenSession)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_Sign = tclpkcs11_int_lookup_sym(handle, "C_Sign");
	if (pkcs11_function_list->C_Sign == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_Sign)", -1));

		return(TCL_ERROR);
	}

	pkcs11_function_list->C_SignInit = tclpkcs11_int_lookup_sym(handle, "C_SignInit");
	if (pkcs11_function_list->C_SignInit == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("C_GetFunctionList returned incomplete data (missing C_SignInit)", -1));

		return(TCL_ERROR);
	}
#endif

	initargs.CreateMutex = tclpkcs11_create_mutex;
	initargs.DestroyMutex = tclpkcs11_destroy_mutex;
	initargs.LockMutex = tclpkcs11_lock_mutex;
	initargs.UnlockMutex = tclpkcs11_unlock_mutex;
	initargs.flags = 0;
	initargs.LibraryFlags = NULL;
	initargs.pReserved = NULL;
1673
1674
1675
1676
1677
1678
1679


































1680
1681
1682
1683
1684
1685
1686
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







MODULE_SCOPE int tclpkcs11_encrypt(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	return(tclpkcs11_perform_pki(1, cd, interp, objc, objv));
}

MODULE_SCOPE int tclpkcs11_decrypt(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	return(tclpkcs11_perform_pki(0, cd, interp, objc, objv));
}

MODULE_SCOPE void tclpkcs11_unloadall(ClientData cd) {
	struct tclpkcs11_interpdata *interpdata;
	struct tclpkcs11_handle *handle;
	Tcl_HashEntry *tcl_handle_entry;
	Tcl_HashSearch search;

	if (!cd) {
		return;
	}

	interpdata = (struct tclpkcs11_interpdata *) cd;

	for (
		tcl_handle_entry = Tcl_FirstHashEntry(&interpdata->handles, &search);
		tcl_handle_entry;
		tcl_handle_entry = Tcl_NextHashEntry(&search)
	) {

		handle = (struct tclpkcs11_handle *) Tcl_GetHashValue(tcl_handle_entry);

		if (handle->pkcs11 && handle->pkcs11->C_Finalize) {
			handle->pkcs11->C_Finalize(NULL);
		}

		tclpkcs11_int_unload_module(handle->base);

		ckfree((char *) handle);

	}

	return;
}


/*
 * Tcl Loadable Module Initialization
 */
int Tclpkcs11_Init(Tcl_Interp *interp) {
	struct tclpkcs11_interpdata *interpdata;
	Tcl_Command tclCreatComm_ret;
1745
1746
1747
1748
1749
1750
1751



1752
1753
1754
1755
1756
1757
1758
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652







+
+
+







		return(TCL_ERROR);
	}

	tclCreatComm_ret = Tcl_CreateObjCommand(interp, "pki::pkcs11::decrypt", tclpkcs11_decrypt, interpdata, NULL);
	if (!tclCreatComm_ret) {
		return(TCL_ERROR);
	}

	/* Create an exit handler to unload and close all PKCS#11 modules */
	Tcl_CreateExitHandler(tclpkcs11_unloadall, interpdata);

	/* Register PKI handlers */
	Tcl_ObjSetVar2(interp,
	               Tcl_NewStringObj("pki::handlers", -1),
	               Tcl_NewStringObj("pkcs11", -1),
	               Tcl_NewStringObj("::pki::pkcs11::encrypt ::pki::pkcs11::decrypt", -1),
	               TCL_GLOBAL_ONLY