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