1 /* 2 * Copyright 2007 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_CBC; 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 keysize = krb5_enctypes_list[i].enc->keybytes; 159 keylength = krb5_enctypes_list[i].enc->keylength; 160 161 if (keylength > info.ulMaxKeySize) { 162 krb5_enctypes_list[i].etype = -1; 163 krb5_enctypes_list[i].in_string = 164 "<unsupported>"; 165 krb5_enctypes_list[i].out_string = 166 "<unsupported>"; 167 continue; 168 } 169 if (!(info.flags & (CKF_ENCRYPT|CKF_RNG))) 170 return (FALSE); 171 } 172 if (HASH_DEFINED(algos)) { 173 rv = C_GetMechanismInfo(*slotid, algos.hash_algo, 174 &info); 175 if (rv != CKR_OK) { 176 KRB5_LOG1(KRB5_ERR, "C_GetMechanismInfo failed " 177 "for hash algorithm %s: 0x%x\n", 178 krb5_enctypes_list[i].in_string, 179 rv); 180 return (FALSE); 181 } 182 if (!(info.flags & (CKF_DIGEST|CKF_SIGN|CKF_RNG))) 183 return (FALSE); 184 } 185 if (algos.str2key_algo != 0) { 186 rv = C_GetMechanismInfo(*slotid, algos.str2key_algo, 187 &info); 188 if (rv != CKR_OK) { 189 KRB5_LOG(KRB5_ERR, "C_GetMechanismInfo failed " 190 "for str2key algorithm: 0x%x\n", rv); 191 return (FALSE); 192 } 193 } 194 enctypes_found++; 195 } 196 /* 197 * If NO enctypes were found to be supported, return FALSE. 198 */ 199 if (!enctypes_found) { 200 KRB5_LOG0(KRB5_ERR, 201 "No crypto support available from PKCS#11."); 202 return (FALSE); 203 } 204 return (TRUE); 205 } 206