xref: /onnv-gate/usr/src/lib/gss_mechs/mech_krb5/crypto/pkcs11slot.c (revision 4248:1af110a94693)
10Sstevel@tonic-gate /*
2*4248Swillf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
70Sstevel@tonic-gate 
80Sstevel@tonic-gate #include <etypes.h>
90Sstevel@tonic-gate #include <security/cryptoki.h>
100Sstevel@tonic-gate #include <security/pkcs11.h>
110Sstevel@tonic-gate 
120Sstevel@tonic-gate /*
130Sstevel@tonic-gate  * get_algo
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  * This routine provides a mapping from Kerberos encryption
160Sstevel@tonic-gate  * and hash types to PKCS#11 encryption and hash types.
170Sstevel@tonic-gate  */
180Sstevel@tonic-gate CK_RV
get_algo(krb5_enctype etype,KRB5_MECH_TO_PKCS * algos)190Sstevel@tonic-gate get_algo(krb5_enctype etype, KRB5_MECH_TO_PKCS *algos)
200Sstevel@tonic-gate {
210Sstevel@tonic-gate 	switch (etype) {
220Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_CRC:
230Sstevel@tonic-gate 			algos->enc_algo = CKM_DES_CBC;
240Sstevel@tonic-gate 			algos->hash_algo = 0;
250Sstevel@tonic-gate 			algos->str2key_algo = 0;
260Sstevel@tonic-gate 			algos->flags = USE_ENCR;
270Sstevel@tonic-gate 			return (CKR_OK);
280Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_MD5:
290Sstevel@tonic-gate 			algos->enc_algo = CKM_DES_CBC;
300Sstevel@tonic-gate 			algos->hash_algo = CKM_MD5;
310Sstevel@tonic-gate 			algos->str2key_algo = 0;
320Sstevel@tonic-gate 			algos->flags = USE_ENCR | USE_HASH;
330Sstevel@tonic-gate 			return (CKR_OK);
340Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_RAW:
350Sstevel@tonic-gate 			algos->enc_algo = CKM_DES_CBC;
360Sstevel@tonic-gate 			algos->hash_algo = 0;
370Sstevel@tonic-gate 			algos->str2key_algo = 0;
380Sstevel@tonic-gate 			algos->flags = USE_ENCR;
390Sstevel@tonic-gate 			return (CKR_OK);
400Sstevel@tonic-gate 		case ENCTYPE_DES_HMAC_SHA1:
410Sstevel@tonic-gate 			algos->enc_algo = CKM_DES_CBC;
420Sstevel@tonic-gate 			algos->hash_algo = CKM_SHA_1_HMAC;
430Sstevel@tonic-gate 			algos->str2key_algo = 0;
440Sstevel@tonic-gate 			algos->flags = USE_ENCR | USE_HASH;
450Sstevel@tonic-gate 			return (CKR_OK);
460Sstevel@tonic-gate 		case ENCTYPE_DES3_CBC_SHA1:
470Sstevel@tonic-gate 			algos->enc_algo = CKM_DES3_CBC;
480Sstevel@tonic-gate 			algos->hash_algo = CKM_SHA_1_HMAC;
490Sstevel@tonic-gate 			algos->str2key_algo = 0;
500Sstevel@tonic-gate 			algos->flags = USE_ENCR | USE_HASH;
510Sstevel@tonic-gate 			return (CKR_OK);
520Sstevel@tonic-gate 		case ENCTYPE_DES3_CBC_RAW:
530Sstevel@tonic-gate 			algos->enc_algo = CKM_DES3_CBC;
540Sstevel@tonic-gate 			algos->hash_algo = 0;
550Sstevel@tonic-gate 			algos->str2key_algo = 0;
560Sstevel@tonic-gate 			algos->flags = USE_ENCR;
570Sstevel@tonic-gate 			return (CKR_OK);
580Sstevel@tonic-gate 		case ENCTYPE_ARCFOUR_HMAC:
590Sstevel@tonic-gate 		case ENCTYPE_ARCFOUR_HMAC_EXP:
600Sstevel@tonic-gate 			algos->enc_algo = CKM_RC4;
610Sstevel@tonic-gate 			algos->hash_algo = CKM_MD5_HMAC;
620Sstevel@tonic-gate 			algos->str2key_algo = 0;
630Sstevel@tonic-gate 			algos->flags = USE_ENCR;
640Sstevel@tonic-gate 			return (CKR_OK);
650Sstevel@tonic-gate 		case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
660Sstevel@tonic-gate 		case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
67*4248Swillf 			algos->enc_algo = CKM_AES_CBC;
680Sstevel@tonic-gate 			algos->hash_algo = CKM_SHA_1_HMAC;
690Sstevel@tonic-gate 			algos->str2key_algo = CKM_PKCS5_PBKD2;
700Sstevel@tonic-gate 			algos->flags = USE_ENCR;
710Sstevel@tonic-gate 			return (CKR_OK);
720Sstevel@tonic-gate 	}
730Sstevel@tonic-gate 	return (CKR_MECHANISM_INVALID);
740Sstevel@tonic-gate }
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate  * get_key_type
780Sstevel@tonic-gate  *
790Sstevel@tonic-gate  * map Kerberos key types to PKCS#11 key type values.
800Sstevel@tonic-gate  */
810Sstevel@tonic-gate CK_RV
get_key_type(krb5_enctype etype,CK_KEY_TYPE * keyType)820Sstevel@tonic-gate get_key_type(krb5_enctype etype, CK_KEY_TYPE *keyType)
830Sstevel@tonic-gate {
840Sstevel@tonic-gate 	switch (etype) {
850Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_CRC:
860Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_MD5:
870Sstevel@tonic-gate 		case ENCTYPE_DES_CBC_RAW:
880Sstevel@tonic-gate 		case ENCTYPE_DES_HMAC_SHA1:
890Sstevel@tonic-gate 			*keyType = CKK_DES;
900Sstevel@tonic-gate 			return (CKR_OK);
910Sstevel@tonic-gate 		case ENCTYPE_DES3_CBC_SHA1:
920Sstevel@tonic-gate 		case ENCTYPE_DES3_CBC_RAW:
930Sstevel@tonic-gate 			*keyType = CKK_DES3;
940Sstevel@tonic-gate 			return (CKR_OK);
950Sstevel@tonic-gate 		case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
960Sstevel@tonic-gate 		case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
970Sstevel@tonic-gate 			*keyType = CKK_AES;
980Sstevel@tonic-gate 			return (CKR_OK);
990Sstevel@tonic-gate 		case ENCTYPE_ARCFOUR_HMAC:
1000Sstevel@tonic-gate 		case ENCTYPE_ARCFOUR_HMAC_EXP:
1010Sstevel@tonic-gate 			*keyType = CKK_RC4;
1020Sstevel@tonic-gate 			return (CKR_OK);
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	/* There's no appropriate error.  Just return the general one */
1060Sstevel@tonic-gate 	return (CKR_GENERAL_ERROR);
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate /*
1100Sstevel@tonic-gate  * slot_supports_krb5
1110Sstevel@tonic-gate  *
1120Sstevel@tonic-gate  * Determine whether the PKCS#11 "slot" supports the necessary
1130Sstevel@tonic-gate  * crypto needed for Kerberos functionality.
1140Sstevel@tonic-gate  *
1150Sstevel@tonic-gate  * Return values:
1160Sstevel@tonic-gate  * TRUE = The given slot is OK for Kerberos
1170Sstevel@tonic-gate  * FALSE = Not ok, try something else.
1180Sstevel@tonic-gate  */
1190Sstevel@tonic-gate krb5_error_code
slot_supports_krb5(CK_SLOT_ID_PTR slotid)1200Sstevel@tonic-gate slot_supports_krb5(CK_SLOT_ID_PTR slotid)
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate 	int i;
1230Sstevel@tonic-gate 	CK_MECHANISM_INFO info;
1240Sstevel@tonic-gate 	CK_RV rv;
1250Sstevel@tonic-gate 	int enctypes_found = 0;
1260Sstevel@tonic-gate 	KRB5_MECH_TO_PKCS algos;
1270Sstevel@tonic-gate 	krb5_enctype tempenctype;
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	for (i = 0; i < krb5_enctypes_length; i++) {
1300Sstevel@tonic-gate 		tempenctype = krb5_enctypes_list[i].etype;
1310Sstevel@tonic-gate 		if ((rv = get_algo(tempenctype, &algos)) != CKR_OK) {
1320Sstevel@tonic-gate 			KRB5_LOG0(KRB5_ERR, "Failed to get algorithm.");
1330Sstevel@tonic-gate 			/*
1340Sstevel@tonic-gate 			 * If the algorithm is not available, disable
1350Sstevel@tonic-gate 			 * this enctype so kerberos doesn't try to use it
1360Sstevel@tonic-gate 			 * again.
1370Sstevel@tonic-gate 			 */
1380Sstevel@tonic-gate 			krb5_enctypes_list[i].etype = -1;
1390Sstevel@tonic-gate 			krb5_enctypes_list[i].in_string = "<unsupported>";
1400Sstevel@tonic-gate 			krb5_enctypes_list[i].out_string = "<unsupported>";
1410Sstevel@tonic-gate 			continue;
1420Sstevel@tonic-gate 		}
1430Sstevel@tonic-gate 		if (ENC_DEFINED(algos)) {
1440Sstevel@tonic-gate 			size_t keysize, keylength;
1450Sstevel@tonic-gate 			rv = C_GetMechanismInfo(*slotid, algos.enc_algo, &info);
1460Sstevel@tonic-gate 			if (rv != CKR_OK) {
1470Sstevel@tonic-gate 				KRB5_LOG1(KRB5_ERR, "C_GetMechanismInfo failed "
1480Sstevel@tonic-gate 				    "for encr algorith %s: 0x%x\n",
1490Sstevel@tonic-gate 				    krb5_enctypes_list[i].in_string,
1500Sstevel@tonic-gate 				    rv);
1510Sstevel@tonic-gate 				return (FALSE);
1520Sstevel@tonic-gate 			}
1530Sstevel@tonic-gate 			/*
1540Sstevel@tonic-gate 			 * If the encryption algorithm is supported,
1550Sstevel@tonic-gate 			 * make sure it supports the correct key sizes.
1560Sstevel@tonic-gate 			 * If not, disable this enctype and continue.
1570Sstevel@tonic-gate 			 */
158781Sgtb 			keysize = krb5_enctypes_list[i].enc->keybytes;
159781Sgtb 			keylength = krb5_enctypes_list[i].enc->keylength;
160781Sgtb 
1610Sstevel@tonic-gate 			if (keylength > info.ulMaxKeySize) {
1620Sstevel@tonic-gate 				krb5_enctypes_list[i].etype = -1;
1630Sstevel@tonic-gate 				krb5_enctypes_list[i].in_string =
1640Sstevel@tonic-gate 					"<unsupported>";
1650Sstevel@tonic-gate 				krb5_enctypes_list[i].out_string =
1660Sstevel@tonic-gate 					"<unsupported>";
1670Sstevel@tonic-gate 				continue;
1680Sstevel@tonic-gate 			}
1690Sstevel@tonic-gate 			if (!(info.flags & (CKF_ENCRYPT|CKF_RNG)))
1700Sstevel@tonic-gate 				return (FALSE);
1710Sstevel@tonic-gate 		}
1720Sstevel@tonic-gate 		if (HASH_DEFINED(algos)) {
1730Sstevel@tonic-gate 			rv = C_GetMechanismInfo(*slotid, algos.hash_algo,
1740Sstevel@tonic-gate 			    &info);
1750Sstevel@tonic-gate 			if (rv != CKR_OK) {
1760Sstevel@tonic-gate 				KRB5_LOG1(KRB5_ERR, "C_GetMechanismInfo failed "
1770Sstevel@tonic-gate 				    "for hash algorithm %s: 0x%x\n",
1780Sstevel@tonic-gate 				    krb5_enctypes_list[i].in_string,
1790Sstevel@tonic-gate 				    rv);
1800Sstevel@tonic-gate 				return (FALSE);
1810Sstevel@tonic-gate 			}
1820Sstevel@tonic-gate 			if (!(info.flags & (CKF_DIGEST|CKF_SIGN|CKF_RNG)))
1830Sstevel@tonic-gate 				return (FALSE);
1840Sstevel@tonic-gate 		}
1850Sstevel@tonic-gate 		if (algos.str2key_algo != 0) {
1860Sstevel@tonic-gate 			rv = C_GetMechanismInfo(*slotid, algos.str2key_algo,
1870Sstevel@tonic-gate 			    &info);
1880Sstevel@tonic-gate 			if (rv != CKR_OK) {
1890Sstevel@tonic-gate 				KRB5_LOG(KRB5_ERR, "C_GetMechanismInfo failed "
1900Sstevel@tonic-gate 				    "for str2key algorithm: 0x%x\n", rv);
1910Sstevel@tonic-gate 				return (FALSE);
1920Sstevel@tonic-gate 			}
1930Sstevel@tonic-gate 		}
1940Sstevel@tonic-gate 		enctypes_found++;
1950Sstevel@tonic-gate 	}
1960Sstevel@tonic-gate 	/*
1970Sstevel@tonic-gate 	 * If NO enctypes were found to be supported, return FALSE.
1980Sstevel@tonic-gate 	 */
1990Sstevel@tonic-gate 	if (!enctypes_found) {
2000Sstevel@tonic-gate 		KRB5_LOG0(KRB5_ERR,
2010Sstevel@tonic-gate 			"No crypto support available from PKCS#11.");
2020Sstevel@tonic-gate 		return (FALSE);
2030Sstevel@tonic-gate 	}
2040Sstevel@tonic-gate 	return (TRUE);
2050Sstevel@tonic-gate }
206