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