Home | History | Annotate | Download | only in crypto
      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