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