17c478bd9Sstevel@tonic-gate /*
2*c54c769dSwillf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate #include <etypes.h>
77c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
87c478bd9Sstevel@tonic-gate #include <security/pkcs11.h>
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate /*
117c478bd9Sstevel@tonic-gate  * get_algo
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * This routine provides a mapping from Kerberos encryption
147c478bd9Sstevel@tonic-gate  * and hash types to PKCS#11 encryption and hash types.
157c478bd9Sstevel@tonic-gate  */
167c478bd9Sstevel@tonic-gate CK_RV
get_algo(krb5_enctype etype,KRB5_MECH_TO_PKCS * algos)177c478bd9Sstevel@tonic-gate get_algo(krb5_enctype etype, KRB5_MECH_TO_PKCS *algos)
187c478bd9Sstevel@tonic-gate {
197c478bd9Sstevel@tonic-gate 	switch (etype) {
207c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_CRC:
217c478bd9Sstevel@tonic-gate 			algos->enc_algo = CKM_DES_CBC;
227c478bd9Sstevel@tonic-gate 			algos->hash_algo = 0;
237c478bd9Sstevel@tonic-gate 			algos->str2key_algo = 0;
247c478bd9Sstevel@tonic-gate 			algos->flags = USE_ENCR;
257c478bd9Sstevel@tonic-gate 			return (CKR_OK);
267c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_MD5:
277c478bd9Sstevel@tonic-gate 			algos->enc_algo = CKM_DES_CBC;
287c478bd9Sstevel@tonic-gate 			algos->hash_algo = CKM_MD5;
297c478bd9Sstevel@tonic-gate 			algos->str2key_algo = 0;
307c478bd9Sstevel@tonic-gate 			algos->flags = USE_ENCR | USE_HASH;
317c478bd9Sstevel@tonic-gate 			return (CKR_OK);
327c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_RAW:
337c478bd9Sstevel@tonic-gate 			algos->enc_algo = CKM_DES_CBC;
347c478bd9Sstevel@tonic-gate 			algos->hash_algo = 0;
357c478bd9Sstevel@tonic-gate 			algos->str2key_algo = 0;
367c478bd9Sstevel@tonic-gate 			algos->flags = USE_ENCR;
377c478bd9Sstevel@tonic-gate 			return (CKR_OK);
387c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES_HMAC_SHA1:
397c478bd9Sstevel@tonic-gate 			algos->enc_algo = CKM_DES_CBC;
407c478bd9Sstevel@tonic-gate 			algos->hash_algo = CKM_SHA_1_HMAC;
417c478bd9Sstevel@tonic-gate 			algos->str2key_algo = 0;
427c478bd9Sstevel@tonic-gate 			algos->flags = USE_ENCR | USE_HASH;
437c478bd9Sstevel@tonic-gate 			return (CKR_OK);
447c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES3_CBC_SHA1:
457c478bd9Sstevel@tonic-gate 			algos->enc_algo = CKM_DES3_CBC;
467c478bd9Sstevel@tonic-gate 			algos->hash_algo = CKM_SHA_1_HMAC;
477c478bd9Sstevel@tonic-gate 			algos->str2key_algo = 0;
487c478bd9Sstevel@tonic-gate 			algos->flags = USE_ENCR | USE_HASH;
497c478bd9Sstevel@tonic-gate 			return (CKR_OK);
507c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES3_CBC_RAW:
517c478bd9Sstevel@tonic-gate 			algos->enc_algo = CKM_DES3_CBC;
527c478bd9Sstevel@tonic-gate 			algos->hash_algo = 0;
537c478bd9Sstevel@tonic-gate 			algos->str2key_algo = 0;
547c478bd9Sstevel@tonic-gate 			algos->flags = USE_ENCR;
557c478bd9Sstevel@tonic-gate 			return (CKR_OK);
567c478bd9Sstevel@tonic-gate 		case ENCTYPE_ARCFOUR_HMAC:
577c478bd9Sstevel@tonic-gate 		case ENCTYPE_ARCFOUR_HMAC_EXP:
587c478bd9Sstevel@tonic-gate 			algos->enc_algo = CKM_RC4;
597c478bd9Sstevel@tonic-gate 			algos->hash_algo = CKM_MD5_HMAC;
607c478bd9Sstevel@tonic-gate 			algos->str2key_algo = 0;
617c478bd9Sstevel@tonic-gate 			algos->flags = USE_ENCR;
627c478bd9Sstevel@tonic-gate 			return (CKR_OK);
637c478bd9Sstevel@tonic-gate 		case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
647c478bd9Sstevel@tonic-gate 		case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
65*c54c769dSwillf 			algos->enc_algo = CKM_AES_CBC;
667c478bd9Sstevel@tonic-gate 			algos->hash_algo = CKM_SHA_1_HMAC;
677c478bd9Sstevel@tonic-gate 			algos->str2key_algo = CKM_PKCS5_PBKD2;
687c478bd9Sstevel@tonic-gate 			algos->flags = USE_ENCR;
697c478bd9Sstevel@tonic-gate 			return (CKR_OK);
707c478bd9Sstevel@tonic-gate 	}
717c478bd9Sstevel@tonic-gate 	return (CKR_MECHANISM_INVALID);
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  * get_key_type
767c478bd9Sstevel@tonic-gate  *
777c478bd9Sstevel@tonic-gate  * map Kerberos key types to PKCS#11 key type values.
787c478bd9Sstevel@tonic-gate  */
797c478bd9Sstevel@tonic-gate CK_RV
get_key_type(krb5_enctype etype,CK_KEY_TYPE * keyType)807c478bd9Sstevel@tonic-gate get_key_type(krb5_enctype etype, CK_KEY_TYPE *keyType)
817c478bd9Sstevel@tonic-gate {
827c478bd9Sstevel@tonic-gate 	switch (etype) {
837c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_CRC:
847c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_MD5:
857c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_RAW:
867c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES_HMAC_SHA1:
877c478bd9Sstevel@tonic-gate 			*keyType = CKK_DES;
887c478bd9Sstevel@tonic-gate 			return (CKR_OK);
897c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES3_CBC_SHA1:
907c478bd9Sstevel@tonic-gate 		case ENCTYPE_DES3_CBC_RAW:
917c478bd9Sstevel@tonic-gate 			*keyType = CKK_DES3;
927c478bd9Sstevel@tonic-gate 			return (CKR_OK);
937c478bd9Sstevel@tonic-gate 		case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
947c478bd9Sstevel@tonic-gate 		case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
957c478bd9Sstevel@tonic-gate 			*keyType = CKK_AES;
967c478bd9Sstevel@tonic-gate 			return (CKR_OK);
977c478bd9Sstevel@tonic-gate 		case ENCTYPE_ARCFOUR_HMAC:
987c478bd9Sstevel@tonic-gate 		case ENCTYPE_ARCFOUR_HMAC_EXP:
997c478bd9Sstevel@tonic-gate 			*keyType = CKK_RC4;
1007c478bd9Sstevel@tonic-gate 			return (CKR_OK);
1017c478bd9Sstevel@tonic-gate 	}
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	/* There's no appropriate error.  Just return the general one */
1047c478bd9Sstevel@tonic-gate 	return (CKR_GENERAL_ERROR);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * slot_supports_krb5
1097c478bd9Sstevel@tonic-gate  *
1107c478bd9Sstevel@tonic-gate  * Determine whether the PKCS#11 "slot" supports the necessary
1117c478bd9Sstevel@tonic-gate  * crypto needed for Kerberos functionality.
1127c478bd9Sstevel@tonic-gate  *
1137c478bd9Sstevel@tonic-gate  * Return values:
1147c478bd9Sstevel@tonic-gate  * TRUE = The given slot is OK for Kerberos
1157c478bd9Sstevel@tonic-gate  * FALSE = Not ok, try something else.
1167c478bd9Sstevel@tonic-gate  */
1177c478bd9Sstevel@tonic-gate krb5_error_code
slot_supports_krb5(CK_SLOT_ID_PTR slotid)1187c478bd9Sstevel@tonic-gate slot_supports_krb5(CK_SLOT_ID_PTR slotid)
1197c478bd9Sstevel@tonic-gate {
1207c478bd9Sstevel@tonic-gate 	int i;
1217c478bd9Sstevel@tonic-gate 	CK_MECHANISM_INFO info;
1227c478bd9Sstevel@tonic-gate 	CK_RV rv;
1237c478bd9Sstevel@tonic-gate 	int enctypes_found = 0;
1247c478bd9Sstevel@tonic-gate 	KRB5_MECH_TO_PKCS algos;
1257c478bd9Sstevel@tonic-gate 	krb5_enctype tempenctype;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	for (i = 0; i < krb5_enctypes_length; i++) {
1287c478bd9Sstevel@tonic-gate 		tempenctype = krb5_enctypes_list[i].etype;
1297c478bd9Sstevel@tonic-gate 		if ((rv = get_algo(tempenctype, &algos)) != CKR_OK) {
1307c478bd9Sstevel@tonic-gate 			KRB5_LOG0(KRB5_ERR, "Failed to get algorithm.");
1317c478bd9Sstevel@tonic-gate 			/*
1327c478bd9Sstevel@tonic-gate 			 * If the algorithm is not available, disable
1337c478bd9Sstevel@tonic-gate 			 * this enctype so kerberos doesn't try to use it
1347c478bd9Sstevel@tonic-gate 			 * again.
1357c478bd9Sstevel@tonic-gate 			 */
1367c478bd9Sstevel@tonic-gate 			krb5_enctypes_list[i].etype = -1;
1377c478bd9Sstevel@tonic-gate 			krb5_enctypes_list[i].in_string = "<unsupported>";
1387c478bd9Sstevel@tonic-gate 			krb5_enctypes_list[i].out_string = "<unsupported>";
1397c478bd9Sstevel@tonic-gate 			continue;
1407c478bd9Sstevel@tonic-gate 		}
1417c478bd9Sstevel@tonic-gate 		if (ENC_DEFINED(algos)) {
1427c478bd9Sstevel@tonic-gate 			size_t keysize, keylength;
1437c478bd9Sstevel@tonic-gate 			rv = C_GetMechanismInfo(*slotid, algos.enc_algo, &info);
1447c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
1457c478bd9Sstevel@tonic-gate 				KRB5_LOG1(KRB5_ERR, "C_GetMechanismInfo failed "
1467c478bd9Sstevel@tonic-gate 				    "for encr algorith %s: 0x%x\n",
1477c478bd9Sstevel@tonic-gate 				    krb5_enctypes_list[i].in_string,
1487c478bd9Sstevel@tonic-gate 				    rv);
1497c478bd9Sstevel@tonic-gate 				return (FALSE);
1507c478bd9Sstevel@tonic-gate 			}
1517c478bd9Sstevel@tonic-gate 			/*
1527c478bd9Sstevel@tonic-gate 			 * If the encryption algorithm is supported,
1537c478bd9Sstevel@tonic-gate 			 * make sure it supports the correct key sizes.
1547c478bd9Sstevel@tonic-gate 			 * If not, disable this enctype and continue.
1557c478bd9Sstevel@tonic-gate 			 */
156505d05c7Sgtb 			keysize = krb5_enctypes_list[i].enc->keybytes;
157505d05c7Sgtb 			keylength = krb5_enctypes_list[i].enc->keylength;
158505d05c7Sgtb 
1597c478bd9Sstevel@tonic-gate 			if (keylength > info.ulMaxKeySize) {
1607c478bd9Sstevel@tonic-gate 				krb5_enctypes_list[i].etype = -1;
1617c478bd9Sstevel@tonic-gate 				krb5_enctypes_list[i].in_string =
1627c478bd9Sstevel@tonic-gate 					"<unsupported>";
1637c478bd9Sstevel@tonic-gate 				krb5_enctypes_list[i].out_string =
1647c478bd9Sstevel@tonic-gate 					"<unsupported>";
1657c478bd9Sstevel@tonic-gate 				continue;
1667c478bd9Sstevel@tonic-gate 			}
1677c478bd9Sstevel@tonic-gate 			if (!(info.flags & (CKF_ENCRYPT|CKF_RNG)))
1687c478bd9Sstevel@tonic-gate 				return (FALSE);
1697c478bd9Sstevel@tonic-gate 		}
1707c478bd9Sstevel@tonic-gate 		if (HASH_DEFINED(algos)) {
1717c478bd9Sstevel@tonic-gate 			rv = C_GetMechanismInfo(*slotid, algos.hash_algo,
1727c478bd9Sstevel@tonic-gate 			    &info);
1737c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
1747c478bd9Sstevel@tonic-gate 				KRB5_LOG1(KRB5_ERR, "C_GetMechanismInfo failed "
1757c478bd9Sstevel@tonic-gate 				    "for hash algorithm %s: 0x%x\n",
1767c478bd9Sstevel@tonic-gate 				    krb5_enctypes_list[i].in_string,
1777c478bd9Sstevel@tonic-gate 				    rv);
1787c478bd9Sstevel@tonic-gate 				return (FALSE);
1797c478bd9Sstevel@tonic-gate 			}
1807c478bd9Sstevel@tonic-gate 			if (!(info.flags & (CKF_DIGEST|CKF_SIGN|CKF_RNG)))
1817c478bd9Sstevel@tonic-gate 				return (FALSE);
1827c478bd9Sstevel@tonic-gate 		}
1837c478bd9Sstevel@tonic-gate 		if (algos.str2key_algo != 0) {
1847c478bd9Sstevel@tonic-gate 			rv = C_GetMechanismInfo(*slotid, algos.str2key_algo,
1857c478bd9Sstevel@tonic-gate 			    &info);
1867c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
1877c478bd9Sstevel@tonic-gate 				KRB5_LOG(KRB5_ERR, "C_GetMechanismInfo failed "
1887c478bd9Sstevel@tonic-gate 				    "for str2key algorithm: 0x%x\n", rv);
1897c478bd9Sstevel@tonic-gate 				return (FALSE);
1907c478bd9Sstevel@tonic-gate 			}
1917c478bd9Sstevel@tonic-gate 		}
1927c478bd9Sstevel@tonic-gate 		enctypes_found++;
1937c478bd9Sstevel@tonic-gate 	}
1947c478bd9Sstevel@tonic-gate 	/*
1957c478bd9Sstevel@tonic-gate 	 * If NO enctypes were found to be supported, return FALSE.
1967c478bd9Sstevel@tonic-gate 	 */
1977c478bd9Sstevel@tonic-gate 	if (!enctypes_found) {
1987c478bd9Sstevel@tonic-gate 		KRB5_LOG0(KRB5_ERR,
1997c478bd9Sstevel@tonic-gate 			"No crypto support available from PKCS#11.");
2007c478bd9Sstevel@tonic-gate 		return (FALSE);
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 	return (TRUE);
2037c478bd9Sstevel@tonic-gate }
204