1 /* ****************************************************************************
2 
3  * eID Middleware Project.
4  * Copyright (C) 2014 FedICT.
5  *
6  * This is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License version
8  * 3.0 as published by the Free Software Foundation.
9  *
10  * This software is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this software; if not, see
17  * http://www.gnu.org/licenses/.
18 
19 **************************************************************************** */
20 #ifdef WIN32
21 #include <win32.h>
22 #pragma pack(push, cryptoki, 1)
23 #include "pkcs11.h"
24 #pragma pack(pop, cryptoki)
25 #else
26 #include <unix.h>
27 #include <pkcs11.h>
28 #endif
29 #include <stdio.h>
30 #include <stdlib.h>
31 
32 #include "testlib.h"
33 
34 #define HAS_CKM(ckm, crit_rsa, crit_ecdsa) case ckm: { printf("Found " #ckm "\n"); known_mechs++; if(crit_rsa) rsa_mechs++; if(crit_ecdsa) ecdsa_mechs++; } break;
35 
TEST_FUNC(mechlist)36 TEST_FUNC(mechlist) {
37 	CK_SLOT_ID slot;
38 	CK_ULONG count=0;
39 	CK_MECHANISM_TYPE_PTR mechlist;
40 	CK_ULONG known_mechs = 0;
41 	int rsa_mechs = 0;
42 	int ecdsa_mechs = 0;
43 	unsigned int i;
44 	int ret;
45 	int retval = TEST_RV_OK;
46 	ckrv_mod m_small[] = {
47 		{ CKR_BUFFER_TOO_SMALL, TEST_RV_OK },
48 		{ CKR_OK, TEST_RV_FAIL },
49 	};
50 	ckrv_mod m_p11_ntoken[] = {
51 		{ CKR_TOKEN_NOT_PRESENT, TEST_RV_OK },
52 		{ CKR_FUNCTION_FAILED, TEST_RV_OK },
53 		{ CKR_OK, TEST_RV_FAIL },
54 	};
55 
56 	check_rv_long(C_GetMechanismList(0, NULL_PTR, &count), m_p11_noinit);
57 
58 	check_rv(C_Initialize(NULL_PTR));
59 
60 	if((ret = find_slot(CK_TRUE, &slot)) != TEST_RV_OK) {
61 		check_rv(C_Finalize(NULL_PTR));
62 		return ret;
63 	}
64 
65 	check_rv(C_GetMechanismList(slot, NULL_PTR, &count));
66 	mechlist = malloc(sizeof(CK_MECHANISM_TYPE) * count);
67 	printf("number of mechanisms supported: %lu\n", count);
68 
69 	for(i=0; i<count; i++) {
70 		mechlist[i] = 0xdeadbeef;
71 	}
72 
73 	check_rv(C_GetMechanismList(slot, mechlist, &count));
74 	if(count == 0) {
75 		printf("Token supports no mechanisms!\n");
76 		retval = TEST_RV_FAIL;
77 		goto done;
78 	}
79 
80 	for(i=0; i<count; i++) {
81 		unsigned long temp = i+1;
82 
83 		switch(mechlist[i]) {
84 		HAS_CKM(CKM_RSA_PKCS, 1, 0);
85 		HAS_CKM(CKM_RIPEMD160, 0, 0);
86 		HAS_CKM(CKM_MD5, 0, 0);
87 		HAS_CKM(CKM_SHA_1, 0, 0);
88 		HAS_CKM(CKM_SHA256, 0, 0);
89 		HAS_CKM(CKM_SHA384, 0, 0);
90 		HAS_CKM(CKM_SHA512, 0, 0);
91 		HAS_CKM(CKM_RIPEMD160_RSA_PKCS, 1, 0);
92 		HAS_CKM(CKM_MD5_RSA_PKCS, 1, 0);
93 		HAS_CKM(CKM_SHA1_RSA_PKCS, 1, 0);
94 		HAS_CKM(CKM_SHA1_RSA_PKCS_PSS, 0, 0);
95 		HAS_CKM(CKM_SHA256_RSA_PKCS, 1, 0);
96 		HAS_CKM(CKM_SHA256_RSA_PKCS_PSS, 1, 0);
97 		HAS_CKM(CKM_SHA384_RSA_PKCS, 1, 0);
98 		HAS_CKM(CKM_SHA512_RSA_PKCS, 1, 0);
99 		HAS_CKM(CKM_ECDSA, 0, 1);
100 		HAS_CKM(CKM_ECDSA_SHA1, 0, 0);
101 		HAS_CKM(CKM_ECDSA_SHA256, 0, 1);
102 		HAS_CKM(CKM_ECDSA_SHA384, 0, 1);
103 		HAS_CKM(CKM_ECDSA_SHA512, 0, 1);
104 		case 0xdeadbeef:
105 			printf("E: found uninitialized data\n");
106 			retval = TEST_RV_FAIL;
107 			goto done;
108 		default:
109 			printf("Found unknown mechanism %#08lx\n", mechlist[i]);
110 			break;
111 		}
112 		if(i<(count-1)) {
113 			check_rv_long(C_GetMechanismList(slot, mechlist, &temp), m_small);
114 		} else {
115 			check_rv(C_GetMechanismList(slot, mechlist, &temp));
116 		}
117 	}
118 
119 	if(count == known_mechs) {
120 		printf("INFO: no unknown mechanisms found\n");
121 	} else {
122 		if(count > known_mechs) {
123 			printf("INFO: %lu unknown mechanisms found\n", count - known_mechs);
124 		} else {
125 			fprintf(stderr, "E: something weird happened");
126 			retval = TEST_RV_FAIL;
127 			goto done;
128 		}
129 	}
130 
131 	verbose_assert(count == known_mechs);
132 	verbose_assert(rsa_mechs == 7 || rsa_mechs == 8 || ecdsa_mechs == 4);
133 
134 	check_rv_long(C_GetMechanismList(slot+30, mechlist, &count), m_p11_badslot);
135 
136 	if(have_robot()) {
137 		robot_remove_card();
138 		check_rv_long(C_GetMechanismList(slot, mechlist, &count), m_p11_ntoken);
139 	}
140 
141 	check_rv(C_Finalize(NULL_PTR));
142 
143 done:
144 	free(mechlist);
145 
146 	return retval;
147 }
148