#include <etypes.h>
#include <security/cryptoki.h>
#include <security/pkcs11.h>
CK_RV
get_algo(krb5_enctype etype, KRB5_MECH_TO_PKCS *algos)
{
switch (etype) {
case ENCTYPE_DES_CBC_CRC:
algos->enc_algo = CKM_DES_CBC;
algos->hash_algo = 0;
algos->str2key_algo = 0;
algos->flags = USE_ENCR;
return (CKR_OK);
case ENCTYPE_DES_CBC_MD5:
algos->enc_algo = CKM_DES_CBC;
algos->hash_algo = CKM_MD5;
algos->str2key_algo = 0;
algos->flags = USE_ENCR | USE_HASH;
return (CKR_OK);
case ENCTYPE_DES_CBC_RAW:
algos->enc_algo = CKM_DES_CBC;
algos->hash_algo = 0;
algos->str2key_algo = 0;
algos->flags = USE_ENCR;
return (CKR_OK);
case ENCTYPE_DES_HMAC_SHA1:
algos->enc_algo = CKM_DES_CBC;
algos->hash_algo = CKM_SHA_1_HMAC;
algos->str2key_algo = 0;
algos->flags = USE_ENCR | USE_HASH;
return (CKR_OK);
case ENCTYPE_DES3_CBC_SHA1:
algos->enc_algo = CKM_DES3_CBC;
algos->hash_algo = CKM_SHA_1_HMAC;
algos->str2key_algo = 0;
algos->flags = USE_ENCR | USE_HASH;
return (CKR_OK);
case ENCTYPE_DES3_CBC_RAW:
algos->enc_algo = CKM_DES3_CBC;
algos->hash_algo = 0;
algos->str2key_algo = 0;
algos->flags = USE_ENCR;
return (CKR_OK);
case ENCTYPE_ARCFOUR_HMAC:
case ENCTYPE_ARCFOUR_HMAC_EXP:
algos->enc_algo = CKM_RC4;
algos->hash_algo = CKM_MD5_HMAC;
algos->str2key_algo = 0;
algos->flags = USE_ENCR;
return (CKR_OK);
case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
algos->enc_algo = CKM_AES_CBC;
algos->hash_algo = CKM_SHA_1_HMAC;
algos->str2key_algo = CKM_PKCS5_PBKD2;
algos->flags = USE_ENCR;
return (CKR_OK);
}
return (CKR_MECHANISM_INVALID);
}
CK_RV
get_key_type(krb5_enctype etype, CK_KEY_TYPE *keyType)
{
switch (etype) {
case ENCTYPE_DES_CBC_CRC:
case ENCTYPE_DES_CBC_MD5:
case ENCTYPE_DES_CBC_RAW:
case ENCTYPE_DES_HMAC_SHA1:
*keyType = CKK_DES;
return (CKR_OK);
case ENCTYPE_DES3_CBC_SHA1:
case ENCTYPE_DES3_CBC_RAW:
*keyType = CKK_DES3;
return (CKR_OK);
case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
*keyType = CKK_AES;
return (CKR_OK);
case ENCTYPE_ARCFOUR_HMAC:
case ENCTYPE_ARCFOUR_HMAC_EXP:
*keyType = CKK_RC4;
return (CKR_OK);
}
return (CKR_GENERAL_ERROR);
}
krb5_error_code
slot_supports_krb5(CK_SLOT_ID_PTR slotid)
{
int i;
CK_MECHANISM_INFO info;
CK_RV rv;
int enctypes_found = 0;
KRB5_MECH_TO_PKCS algos;
krb5_enctype tempenctype;
for (i = 0; i < krb5_enctypes_length; i++) {
tempenctype = krb5_enctypes_list[i].etype;
if ((rv = get_algo(tempenctype, &algos)) != CKR_OK) {
KRB5_LOG0(KRB5_ERR, "Failed to get algorithm.");
krb5_enctypes_list[i].etype = -1;
krb5_enctypes_list[i].in_string = "<unsupported>";
krb5_enctypes_list[i].out_string = "<unsupported>";
continue;
}
if (ENC_DEFINED(algos)) {
size_t keysize, keylength;
rv = C_GetMechanismInfo(*slotid, algos.enc_algo, &info);
if (rv != CKR_OK) {
KRB5_LOG1(KRB5_ERR, "C_GetMechanismInfo failed "
"for encr algorith %s: 0x%x\n",
krb5_enctypes_list[i].in_string,
rv);
return (FALSE);
}
keysize = krb5_enctypes_list[i].enc->keybytes;
keylength = krb5_enctypes_list[i].enc->keylength;
if (keylength > info.ulMaxKeySize) {
krb5_enctypes_list[i].etype = -1;
krb5_enctypes_list[i].in_string =
"<unsupported>";
krb5_enctypes_list[i].out_string =
"<unsupported>";
continue;
}
if (!(info.flags & (CKF_ENCRYPT|CKF_RNG)))
return (FALSE);
}
if (HASH_DEFINED(algos)) {
rv = C_GetMechanismInfo(*slotid, algos.hash_algo,
&info);
if (rv != CKR_OK) {
KRB5_LOG1(KRB5_ERR, "C_GetMechanismInfo failed "
"for hash algorithm %s: 0x%x\n",
krb5_enctypes_list[i].in_string,
rv);
return (FALSE);
}
if (!(info.flags & (CKF_DIGEST|CKF_SIGN|CKF_RNG)))
return (FALSE);
}
if (algos.str2key_algo != 0) {
rv = C_GetMechanismInfo(*slotid, algos.str2key_algo,
&info);
if (rv != CKR_OK) {
KRB5_LOG(KRB5_ERR, "C_GetMechanismInfo failed "
"for str2key algorithm: 0x%x\n", rv);
return (FALSE);
}
}
enctypes_found++;
}
if (!enctypes_found) {
KRB5_LOG0(KRB5_ERR,
"No crypto support available from PKCS#11.");
return (FALSE);
}
return (TRUE);
}