xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/crypto/pkcs11slot.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 #include <etypes.h>
9 #include <security/cryptoki.h>
10 #include <security/pkcs11.h>
11 
12 /*
13  * get_algo
14  *
15  * This routine provides a mapping from Kerberos encryption
16  * and hash types to PKCS#11 encryption and hash types.
17  */
18 CK_RV
19 get_algo(krb5_enctype etype, KRB5_MECH_TO_PKCS *algos)
20 {
21 	switch (etype) {
22 		case ENCTYPE_DES_CBC_CRC:
23 			algos->enc_algo = CKM_DES_CBC;
24 			algos->hash_algo = 0;
25 			algos->str2key_algo = 0;
26 			algos->flags = USE_ENCR;
27 			return (CKR_OK);
28 		case ENCTYPE_DES_CBC_MD5:
29 			algos->enc_algo = CKM_DES_CBC;
30 			algos->hash_algo = CKM_MD5;
31 			algos->str2key_algo = 0;
32 			algos->flags = USE_ENCR | USE_HASH;
33 			return (CKR_OK);
34 		case ENCTYPE_DES_CBC_RAW:
35 			algos->enc_algo = CKM_DES_CBC;
36 			algos->hash_algo = 0;
37 			algos->str2key_algo = 0;
38 			algos->flags = USE_ENCR;
39 			return (CKR_OK);
40 		case ENCTYPE_DES_HMAC_SHA1:
41 			algos->enc_algo = CKM_DES_CBC;
42 			algos->hash_algo = CKM_SHA_1_HMAC;
43 			algos->str2key_algo = 0;
44 			algos->flags = USE_ENCR | USE_HASH;
45 			return (CKR_OK);
46 		case ENCTYPE_DES3_CBC_SHA1:
47 			algos->enc_algo = CKM_DES3_CBC;
48 			algos->hash_algo = CKM_SHA_1_HMAC;
49 			algos->str2key_algo = 0;
50 			algos->flags = USE_ENCR | USE_HASH;
51 			return (CKR_OK);
52 		case ENCTYPE_DES3_CBC_RAW:
53 			algos->enc_algo = CKM_DES3_CBC;
54 			algos->hash_algo = 0;
55 			algos->str2key_algo = 0;
56 			algos->flags = USE_ENCR;
57 			return (CKR_OK);
58 		case ENCTYPE_ARCFOUR_HMAC:
59 		case ENCTYPE_ARCFOUR_HMAC_EXP:
60 			algos->enc_algo = CKM_RC4;
61 			algos->hash_algo = CKM_MD5_HMAC;
62 			algos->str2key_algo = 0;
63 			algos->flags = USE_ENCR;
64 			return (CKR_OK);
65 		case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
66 		case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
67 			algos->enc_algo = CKM_AES_ECB;
68 			algos->hash_algo = CKM_SHA_1_HMAC;
69 			algos->str2key_algo = CKM_PKCS5_PBKD2;
70 			algos->flags = USE_ENCR;
71 			return (CKR_OK);
72 	}
73 	return (CKR_MECHANISM_INVALID);
74 }
75 
76 /*
77  * get_key_type
78  *
79  * map Kerberos key types to PKCS#11 key type values.
80  */
81 CK_RV
82 get_key_type(krb5_enctype etype, CK_KEY_TYPE *keyType)
83 {
84 	switch (etype) {
85 		case ENCTYPE_DES_CBC_CRC:
86 		case ENCTYPE_DES_CBC_MD5:
87 		case ENCTYPE_DES_CBC_RAW:
88 		case ENCTYPE_DES_HMAC_SHA1:
89 			*keyType = CKK_DES;
90 			return (CKR_OK);
91 		case ENCTYPE_DES3_CBC_SHA1:
92 		case ENCTYPE_DES3_CBC_RAW:
93 			*keyType = CKK_DES3;
94 			return (CKR_OK);
95 		case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
96 		case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
97 			*keyType = CKK_AES;
98 			return (CKR_OK);
99 		case ENCTYPE_ARCFOUR_HMAC:
100 		case ENCTYPE_ARCFOUR_HMAC_EXP:
101 			*keyType = CKK_RC4;
102 			return (CKR_OK);
103 	}
104 
105 	/* There's no appropriate error.  Just return the general one */
106 	return (CKR_GENERAL_ERROR);
107 }
108 
109 /*
110  * slot_supports_krb5
111  *
112  * Determine whether the PKCS#11 "slot" supports the necessary
113  * crypto needed for Kerberos functionality.
114  *
115  * Return values:
116  * TRUE = The given slot is OK for Kerberos
117  * FALSE = Not ok, try something else.
118  */
119 krb5_error_code
120 slot_supports_krb5(CK_SLOT_ID_PTR slotid)
121 {
122 	int i;
123 	CK_MECHANISM_INFO info;
124 	CK_RV rv;
125 	int enctypes_found = 0;
126 	KRB5_MECH_TO_PKCS algos;
127 	krb5_enctype tempenctype;
128 
129 	for (i = 0; i < krb5_enctypes_length; i++) {
130 		tempenctype = krb5_enctypes_list[i].etype;
131 		if ((rv = get_algo(tempenctype, &algos)) != CKR_OK) {
132 			KRB5_LOG0(KRB5_ERR, "Failed to get algorithm.");
133 			/*
134 			 * If the algorithm is not available, disable
135 			 * this enctype so kerberos doesn't try to use it
136 			 * again.
137 			 */
138 			krb5_enctypes_list[i].etype = -1;
139 			krb5_enctypes_list[i].in_string = "<unsupported>";
140 			krb5_enctypes_list[i].out_string = "<unsupported>";
141 			continue;
142 		}
143 		if (ENC_DEFINED(algos)) {
144 			size_t keysize, keylength;
145 			rv = C_GetMechanismInfo(*slotid, algos.enc_algo, &info);
146 			if (rv != CKR_OK) {
147 				KRB5_LOG1(KRB5_ERR, "C_GetMechanismInfo failed "
148 				    "for encr algorith %s: 0x%x\n",
149 				    krb5_enctypes_list[i].in_string,
150 				    rv);
151 				return (FALSE);
152 			}
153 			/*
154 			 * If the encryption algorithm is supported,
155 			 * make sure it supports the correct key sizes.
156 			 * If not, disable this enctype and continue.
157 			 */
158 			krb5_enctypes_list[i].enc->keysize(&keysize,
159 				&keylength);
160 			if (keylength > info.ulMaxKeySize) {
161 				krb5_enctypes_list[i].etype = -1;
162 				krb5_enctypes_list[i].in_string =
163 					"<unsupported>";
164 				krb5_enctypes_list[i].out_string =
165 					"<unsupported>";
166 				continue;
167 			}
168 			if (!(info.flags & (CKF_ENCRYPT|CKF_RNG)))
169 				return (FALSE);
170 		}
171 		if (HASH_DEFINED(algos)) {
172 			rv = C_GetMechanismInfo(*slotid, algos.hash_algo,
173 			    &info);
174 			if (rv != CKR_OK) {
175 				KRB5_LOG1(KRB5_ERR, "C_GetMechanismInfo failed "
176 				    "for hash algorithm %s: 0x%x\n",
177 				    krb5_enctypes_list[i].in_string,
178 				    rv);
179 				return (FALSE);
180 			}
181 			if (!(info.flags & (CKF_DIGEST|CKF_SIGN|CKF_RNG)))
182 				return (FALSE);
183 		}
184 		if (algos.str2key_algo != 0) {
185 			rv = C_GetMechanismInfo(*slotid, algos.str2key_algo,
186 			    &info);
187 			if (rv != CKR_OK) {
188 				KRB5_LOG(KRB5_ERR, "C_GetMechanismInfo failed "
189 				    "for str2key algorithm: 0x%x\n", rv);
190 				return (FALSE);
191 			}
192 		}
193 		enctypes_found++;
194 	}
195 	/*
196 	 * If NO enctypes were found to be supported, return FALSE.
197 	 */
198 	if (!enctypes_found) {
199 		KRB5_LOG0(KRB5_ERR,
200 			"No crypto support available from PKCS#11.");
201 		return (FALSE);
202 	}
203 	return (TRUE);
204 }
205