#include <k5-int.h>
#include <enc_provider.h>
#define BLOCK_SIZE 16
#ifdef _KERNEL
krb5_error_code
krb5int_aes_encrypt(krb5_context context,
const krb5_keyblock *key, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
{
int ret = 0;
int nblocks, partialamount;
crypto_mechanism_t mech;
char *nlobp, *lobp;
char local_iv_data[BLOCK_SIZE];
krb5_data local_iv;
KRB5_LOG0(KRB5_INFO, "In krb5int_aes_encrypt(kernel): start");
ASSERT(input != NULL);
if (input->length < BLOCK_SIZE)
return (KRB5_BAD_MSIZE);
ASSERT(output != NULL);
ASSERT(input->length == output->length);
ASSERT(key != NULL);
ASSERT(key->key_tmpl != NULL);
ASSERT(key->kef_mt == crypto_mech2id(SUN_CKM_AES_CBC));
if (ivec != NULL) {
if (ivec->data == NULL || ivec->length != BLOCK_SIZE) {
ASSERT(ivec->data != NULL);
ASSERT(ivec->length == BLOCK_SIZE);
KRB5_LOG1(KRB5_ERR, "In krb5int_aes_encrypt: error "
"ivec->data = %p ivec->length = %d",
(void *)ivec->data, ivec->length);
ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
}
nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE;
KRB5_LOG(KRB5_INFO, "nblocks = %d", nblocks);
partialamount = input->length % BLOCK_SIZE;
KRB5_LOG(KRB5_INFO, "partialamount = %d", partialamount);
if (nblocks == 1 || (partialamount == 0)) {
if (ivec != NULL) {
local_iv.data = ivec->data;
local_iv.length = ivec->length;
} else {
bzero(local_iv_data, sizeof (local_iv_data));
local_iv.data = local_iv_data;
local_iv.length = sizeof (local_iv_data);
}
ret = k5_ef_crypto((const char *)input->data,
(char *)output->data,
input->length, (krb5_keyblock *)key,
&local_iv, TRUE);
if (ret != 0) {
KRB5_LOG(KRB5_ERR,
"k5_ef_crypto: error: ret = 0x%08x", ret);
goto cleanup;
}
if (nblocks > 1) {
char tmp[BLOCK_SIZE];
nlobp = (char *)(output->data +
((nblocks - 2) * BLOCK_SIZE));
lobp = (char *)(output->data +
((nblocks - 1) * BLOCK_SIZE));
bcopy(nlobp, tmp, BLOCK_SIZE);
bcopy(lobp, nlobp, BLOCK_SIZE);
bcopy(tmp, lobp, BLOCK_SIZE);
}
} else {
char tmp_pt[BLOCK_SIZE], tmp_ct[BLOCK_SIZE];
struct iovec iovarray_pt[2], iovarray_ct[2];
struct uio uio_pt, uio_ct;
crypto_data_t ct, pt;
bzero(tmp_pt, sizeof (tmp_pt));
pt.cd_format = CRYPTO_DATA_UIO;
pt.cd_offset = 0;
pt.cd_length = nblocks * BLOCK_SIZE;
pt.cd_miscdata = NULL;
bzero(&uio_pt, sizeof (uio_pt));
pt.cd_uio = &uio_pt;
pt.cd_uio->uio_iov = iovarray_pt;
pt.cd_uio->uio_iovcnt = 2;
pt.cd_uio->uio_segflg = UIO_SYSSPACE;
pt.cd_uio->uio_iov[0].iov_base = (char *)input->data;
pt.cd_uio->uio_iov[0].iov_len = input->length - partialamount;
KRB5_LOG(KRB5_INFO, "pt0 iov_len = %d",
(int)pt.cd_uio->uio_iov[0].iov_len);
pt.cd_uio->uio_iov[1].iov_base = tmp_pt;
bcopy(input->data + (input->length - partialamount), tmp_pt,
partialamount);
pt.cd_uio->uio_iov[1].iov_len = BLOCK_SIZE;
ct.cd_format = CRYPTO_DATA_UIO;
ct.cd_offset = 0;
ct.cd_length = nblocks * BLOCK_SIZE;
ct.cd_miscdata = NULL;
bzero(&uio_ct, sizeof (uio_ct));
ct.cd_uio = &uio_ct;
ct.cd_uio->uio_iov = iovarray_ct;
ct.cd_uio->uio_iovcnt = 2;
ct.cd_uio->uio_segflg = UIO_SYSSPACE;
ct.cd_uio->uio_iov[0].iov_base = (char *)output->data;
ct.cd_uio->uio_iov[0].iov_len = output->length - partialamount;
KRB5_LOG(KRB5_INFO, "ct0 iov_len = %d",
(int)ct.cd_uio->uio_iov[0].iov_len);
ct.cd_uio->uio_iov[1].iov_base = tmp_ct;
ct.cd_uio->uio_iov[1].iov_len = BLOCK_SIZE;
mech.cm_type = key->kef_mt;
if (ivec == NULL) {
bzero(local_iv_data, sizeof (local_iv_data));
mech.cm_param = local_iv_data;
mech.cm_param_len = sizeof (local_iv_data);
} else {
mech.cm_param = ivec->data;
mech.cm_param_len = ivec->length;
}
ret = crypto_encrypt(&mech, &pt, (crypto_key_t *)&key->kef_key,
key->key_tmpl, &ct, NULL);
if (ret != CRYPTO_SUCCESS) {
KRB5_LOG(KRB5_ERR,
"crypto_encrypt: error: ret = 0x%08x",
ret);
goto cleanup;
}
nlobp = (char *)(output->data + ((nblocks - 2) * BLOCK_SIZE));
lobp = (char *)(output->data + ((nblocks - 1) * BLOCK_SIZE));
bcopy(nlobp, lobp, partialamount);
bcopy(tmp_ct, nlobp, BLOCK_SIZE);
}
if (nblocks > 1 && ivec)
(void) memcpy(ivec->data, nlobp, BLOCK_SIZE);
cleanup:
if (ret)
bzero(output->data, output->length);
return (ret);
}
#else
krb5_error_code
krb5int_aes_encrypt(krb5_context context,
const krb5_keyblock *key, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
{
krb5_error_code ret = 0;
int nblocks, partialamount;
CK_RV rv;
KRB5_MECH_TO_PKCS algos;
CK_MECHANISM mechanism;
CK_ULONG outlen;
char *nlobp, *lobp;
char tmp_ivec[BLOCK_SIZE];
assert(input != NULL);
if (input->length < BLOCK_SIZE)
return (KRB5_BAD_MSIZE);
assert(output != NULL);
assert(input->length == output->length);
assert(key != NULL);
if (ivec != NULL) {
if (ivec->data == NULL || ivec->length != BLOCK_SIZE) {
assert(ivec->data != NULL);
assert(ivec->length == BLOCK_SIZE);
KRB5_LOG1(KRB5_ERR, "In krb5int_aes_encrypt: error "
"ivec->data = %p ivec->length = %d", ivec->data,
ivec->length);
ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
}
nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE;
KRB5_LOG(KRB5_INFO, "nblocks = %d", nblocks);
partialamount = input->length % BLOCK_SIZE;
KRB5_LOG(KRB5_INFO, "partialamount = %d", partialamount);
rv = get_algo(key->enctype, &algos);
if (rv != CKR_OK)
goto cleanup;
assert(algos.enc_algo == CKM_AES_CBC);
rv = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key);
if (rv != CKR_OK)
goto cleanup;
mechanism.mechanism = algos.enc_algo;
if (ivec == NULL) {
bzero(tmp_ivec, sizeof (tmp_ivec));
mechanism.pParameter = tmp_ivec;
mechanism.ulParameterLen = sizeof (tmp_ivec);
} else {
mechanism.pParameter = ivec->data;
mechanism.ulParameterLen = ivec->length;
}
rv = C_EncryptInit(krb_ctx_hSession(context), &mechanism, key->hKey);
if (rv != CKR_OK) {
KRB5_LOG(KRB5_ERR, "C_EncryptInit failed in "
"krb5int_aes_encrypt: rv = 0x%x", rv);
goto cleanup;
}
if (nblocks == 1 || (partialamount == 0)) {
outlen = output->length;
rv = C_Encrypt(krb_ctx_hSession(context),
(CK_BYTE_PTR)input->data,
input->length,
(CK_BYTE_PTR)output->data,
&outlen);
if (rv != CKR_OK) {
KRB5_LOG(KRB5_ERR, "C_Encrypt failed in "
"krb5int_aes_encrypt: rv = 0x%x", rv);
goto cleanup;
}
assert(output->length == (unsigned int)outlen);
if (nblocks > 1) {
char tmp[BLOCK_SIZE];
nlobp = (char *)(output->data +
((nblocks - 2) * BLOCK_SIZE));
lobp = (char *)(output->data +
((nblocks - 1) * BLOCK_SIZE));
bcopy(nlobp, tmp, BLOCK_SIZE);
bcopy(lobp, nlobp, BLOCK_SIZE);
bcopy(tmp, lobp, BLOCK_SIZE);
}
} else {
char tmp_pt[BLOCK_SIZE], tmp_ct[BLOCK_SIZE];
outlen = input->length - partialamount;
rv = C_EncryptUpdate(krb_ctx_hSession(context),
(CK_BYTE_PTR)input->data,
input->length - partialamount,
(CK_BYTE_PTR)output->data,
&outlen);
if (rv != CKR_OK) {
KRB5_LOG(KRB5_ERR, "C_EncryptUpdate failed in "
"krb5int_aes_encrypt: rv = 0x%x", rv);
goto cleanup;
}
bzero(tmp_pt, sizeof (tmp_pt));
bcopy(input->data + (input->length - partialamount), tmp_pt,
partialamount);
outlen = sizeof (tmp_ct);
rv = C_EncryptUpdate(krb_ctx_hSession(context),
(CK_BYTE_PTR)tmp_pt,
BLOCK_SIZE,
(CK_BYTE_PTR)tmp_ct,
&outlen);
if (rv != CKR_OK) {
KRB5_LOG(KRB5_ERR, "C_Encrypt failed in "
"krb5int_aes_encrypt: rv = 0x%x", rv);
goto cleanup;
}
nlobp = (char *)(output->data + ((nblocks - 2) * BLOCK_SIZE));
lobp = (char *)(output->data + ((nblocks - 1) * BLOCK_SIZE));
bcopy(nlobp, lobp, partialamount);
bcopy(tmp_ct, nlobp, BLOCK_SIZE);
rv = C_EncryptFinal(krb_ctx_hSession(context),
(CK_BYTE_PTR)tmp_ct, &outlen);
if (rv != CKR_OK)
goto cleanup;
}
if (nblocks > 1 && ivec)
(void) memcpy(ivec->data, nlobp, BLOCK_SIZE);
cleanup:
if (rv != CKR_OK)
ret = PKCS_ERR;
if (ret)
bzero(output->data, input->length);
return (ret);
}
#endif
#ifdef _KERNEL
krb5_error_code
krb5int_aes_decrypt(krb5_context context,
const krb5_keyblock *key, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
{
krb5_error_code ret = 0;
int nblocks, partialamount;
char local_iv_data[BLOCK_SIZE];
krb5_data local_iv;
KRB5_LOG0(KRB5_INFO, "In krb5int_aes_decrypt: start");
ASSERT(input != NULL);
if (input->length < BLOCK_SIZE)
return (KRB5_BAD_MSIZE);
ASSERT(output != NULL);
ASSERT(input->length == output->length);
ASSERT(key != NULL);
ASSERT(key->kef_mt == crypto_mech2id(SUN_CKM_AES_CBC));
if (ivec != NULL) {
if (ivec->data == NULL || ivec->length != BLOCK_SIZE) {
ASSERT(ivec->data != NULL);
ASSERT(ivec->length == BLOCK_SIZE);
KRB5_LOG1(KRB5_ERR, "In krb5int_aes_decrypt: error "
"ivec->data = %p ivec->length = %d",
(void *)ivec->data, ivec->length);
ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
}
nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE;
KRB5_LOG(KRB5_INFO, "nblocks = %d", nblocks);
partialamount = input->length % BLOCK_SIZE;
KRB5_LOG(KRB5_INFO, "partialamount = %d", partialamount);
if (ivec != NULL) {
local_iv.data = ivec->data;
local_iv.length = ivec->length;
} else {
bzero(local_iv_data, sizeof (local_iv_data));
local_iv.data = local_iv_data;
local_iv.length = sizeof (local_iv_data);
}
if (nblocks == 1 || (partialamount == 0)) {
char orig_input[BLOCK_SIZE * 2];
char *nlibp, *libp;
if (nblocks > 1) {
char tmp[BLOCK_SIZE];
nlibp = input->data + ((nblocks - 2) * BLOCK_SIZE);
libp = input->data + ((nblocks - 1) * BLOCK_SIZE);
bcopy(nlibp, orig_input, sizeof (orig_input));
bcopy(nlibp, tmp, BLOCK_SIZE);
bcopy(libp, nlibp, BLOCK_SIZE);
bcopy(tmp, libp, BLOCK_SIZE);
}
ret = k5_ef_crypto((const char *)input->data,
(char *)output->data,
input->length, (krb5_keyblock *)key,
&local_iv, FALSE);
if (nblocks > 1) {
bcopy(orig_input, nlibp, sizeof (orig_input));
}
if (ret != 0) {
KRB5_LOG(KRB5_ERR,
"k5_ef_crypto returned error: ret = 0x%08x",
ret);
goto cleanup;
}
} else {
krb5_data tmp_ivec;
char tmp_ivec_data[BLOCK_SIZE], tmp_input_data[BLOCK_SIZE],
tmp_output_data[BLOCK_SIZE];
char *Cn, *Cn_1, *Cn_2;
long length;
Cn = input->data + (input->length - partialamount);
Cn_1 = Cn - BLOCK_SIZE;
Cn_2 = Cn_1 - BLOCK_SIZE;
if (nblocks > 2) {
length = input->length - (BLOCK_SIZE + partialamount);
ret = k5_ef_crypto((const char *)input->data,
output->data, length, (krb5_keyblock *)key,
&local_iv, FALSE);
if (ret != 0) {
KRB5_LOG(KRB5_ERR,
"k5_ef_crypto: error: ret = 0x%08x",
ret);
goto cleanup;
}
}
bzero(tmp_ivec_data, sizeof (tmp_ivec_data));
bcopy(Cn, tmp_ivec_data, partialamount);
tmp_ivec.data = tmp_ivec_data;
tmp_ivec.length = sizeof (tmp_ivec_data);
length = BLOCK_SIZE;
ret = k5_ef_crypto((const char *)Cn_1,
tmp_output_data, length,
(krb5_keyblock *)key, &tmp_ivec, FALSE);
if (ret != 0) {
KRB5_LOG(KRB5_ERR,
"k5_ef_crypto: error: ret = 0x%08x",
ret);
goto cleanup;
}
bcopy(Cn, tmp_input_data, partialamount);
bcopy(tmp_output_data + partialamount,
tmp_input_data + partialamount,
(BLOCK_SIZE - partialamount));
bcopy(tmp_output_data,
output->data + (input->length - partialamount),
partialamount);
if (nblocks > 2) {
tmp_ivec.data = Cn_2;
} else {
bzero(tmp_ivec_data, sizeof (tmp_ivec_data));
}
ret = k5_ef_crypto((const char *)tmp_input_data,
(char *)output->data +
(input->length - (BLOCK_SIZE + partialamount)),
length, (krb5_keyblock *)key,
&tmp_ivec, FALSE);
if (ret != 0) {
KRB5_LOG(KRB5_ERR,
"k5_ef_crypto: error: ret = 0x%08x", ret);
goto cleanup;
}
}
if (nblocks > 1 && ivec) {
(void) memcpy(ivec->data,
input->data + ((nblocks - 2) * BLOCK_SIZE),
BLOCK_SIZE);
}
cleanup:
if (ret)
bzero(output->data, output->length);
return (ret);
}
#else
krb5_error_code
krb5int_aes_decrypt(krb5_context context,
const krb5_keyblock *key, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
{
krb5_error_code ret = 0;
int nblocks, partialamount;
CK_RV rv;
KRB5_MECH_TO_PKCS algos;
CK_MECHANISM mechanism;
CK_ULONG outlen;
char tmp_ivec[BLOCK_SIZE];
assert(input != NULL);
if (input->length < BLOCK_SIZE)
return (KRB5_BAD_MSIZE);
assert(output != NULL);
assert(input->length == output->length);
assert(key != NULL);
if (ivec != NULL) {
if (ivec->data == NULL || ivec->length != BLOCK_SIZE) {
assert(ivec->data != NULL);
assert(ivec->length == BLOCK_SIZE);
KRB5_LOG1(KRB5_ERR, "In krb5int_aes_decrypt: error "
"ivec->data = %p ivec->length = %d", ivec->data,
ivec->length);
ret = KRB5_CRYPTO_INTERNAL;
goto cleanup;
}
}
nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE;
KRB5_LOG(KRB5_INFO, "nblocks = %d", nblocks);
partialamount = input->length % BLOCK_SIZE;
KRB5_LOG(KRB5_INFO, "partialamount = %d", partialamount);
rv = get_algo(key->enctype, &algos);
if (rv != CKR_OK)
goto cleanup;
assert(algos.enc_algo == CKM_AES_CBC);
rv = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key);
if (rv != CKR_OK) {
goto cleanup;
}
mechanism.mechanism = algos.enc_algo;
if (ivec == NULL) {
bzero(tmp_ivec, sizeof (tmp_ivec));
mechanism.pParameter = tmp_ivec;
mechanism.ulParameterLen = sizeof (tmp_ivec);
} else {
mechanism.pParameter = ivec->data;
mechanism.ulParameterLen = ivec->length;
}
if (nblocks == 1 || (partialamount == 0)) {
char orig_input[BLOCK_SIZE * 2];
char *nlibp, *libp;
if (nblocks > 1) {
char tmp[BLOCK_SIZE];
nlibp = input->data + ((nblocks - 2) * BLOCK_SIZE);
libp = input->data + ((nblocks - 1) * BLOCK_SIZE);
bcopy(nlibp, orig_input, sizeof (orig_input));
bcopy(nlibp, tmp, BLOCK_SIZE);
bcopy(libp, nlibp, BLOCK_SIZE);
bcopy(tmp, libp, BLOCK_SIZE);
}
rv = C_DecryptInit(krb_ctx_hSession(context), &mechanism,
key->hKey);
if (rv != CKR_OK) {
KRB5_LOG(KRB5_ERR, "C_DecryptInit failed in "
"krb5int_aes_decrypt: rv = 0x%x", rv);
goto cleanup;
}
outlen = output->length;
rv = C_Decrypt(krb_ctx_hSession(context),
(CK_BYTE_PTR)input->data,
input->length,
(CK_BYTE_PTR)output->data,
&outlen);
if (nblocks > 1) {
bcopy(orig_input, nlibp, sizeof (orig_input));
}
} else {
char tmp_ivec_data[BLOCK_SIZE], tmp_input_data[BLOCK_SIZE],
tmp_output_data[BLOCK_SIZE];
char *Cn, *Cn_1, *Cn_2;
CK_ULONG length;
Cn = input->data + (input->length - partialamount);
Cn_1 = Cn - BLOCK_SIZE;
Cn_2 = Cn_1 - BLOCK_SIZE;
if (nblocks > 2) {
rv = C_DecryptInit(krb_ctx_hSession(context),
&mechanism, key->hKey);
if (rv != CKR_OK) {
KRB5_LOG(KRB5_ERR, "C_DecryptInit failed in "
"krb5int_aes_decrypt: rv = 0x%x", rv);
goto cleanup;
}
length = input->length - (BLOCK_SIZE + partialamount);
outlen = length;
rv = C_Decrypt(krb_ctx_hSession(context),
(CK_BYTE_PTR)input->data,
length,
(CK_BYTE_PTR)output->data,
&outlen);
if (rv != CKR_OK)
goto cleanup;
}
bzero(tmp_ivec_data, sizeof (tmp_ivec_data));
bcopy(Cn, tmp_ivec_data, partialamount);
length = BLOCK_SIZE;
outlen = length;
mechanism.pParameter = tmp_ivec_data;
mechanism.ulParameterLen = sizeof (tmp_ivec_data);
rv = C_DecryptInit(krb_ctx_hSession(context), &mechanism,
key->hKey);
if (rv != CKR_OK) {
KRB5_LOG(KRB5_ERR, "C_DecryptInit failed in "
"krb5int_aes_decrypt: rv = 0x%x", rv);
goto cleanup;
}
rv = C_Decrypt(krb_ctx_hSession(context),
(CK_BYTE_PTR)Cn_1,
length,
(CK_BYTE_PTR)tmp_output_data,
&outlen);
if (rv != CKR_OK)
goto cleanup;
bcopy(Cn, tmp_input_data, partialamount);
bcopy(tmp_output_data + partialamount,
tmp_input_data + partialamount,
(BLOCK_SIZE - partialamount));
bcopy(tmp_output_data,
output->data + (input->length - partialamount),
partialamount);
if (nblocks > 2) {
mechanism.pParameter = Cn_2;
} else {
if (ivec == NULL) {
bzero(tmp_ivec_data, sizeof (tmp_ivec_data));
} else {
mechanism.pParameter = ivec->data;
mechanism.ulParameterLen = ivec->length;
}
}
rv = C_DecryptInit(krb_ctx_hSession(context), &mechanism,
key->hKey);
if (rv != CKR_OK) {
KRB5_LOG(KRB5_ERR, "C_DecryptInit failed in "
"krb5int_aes_decrypt: rv = 0x%x", rv);
goto cleanup;
}
rv = C_Decrypt(krb_ctx_hSession(context),
(CK_BYTE_PTR)tmp_input_data,
length,
(CK_BYTE_PTR)output->data + (input->length -
(BLOCK_SIZE + partialamount)),
&outlen);
if (rv != CKR_OK)
goto cleanup;
}
if (nblocks > 1 && ivec) {
(void) memcpy(ivec->data,
input->data + ((nblocks - 2) * BLOCK_SIZE),
BLOCK_SIZE);
}
cleanup:
if (rv != CKR_OK)
ret = PKCS_ERR;
if (ret)
bzero(output->data, input->length);
return (ret);
}
#endif
static krb5_error_code
k5_aes_make_key(krb5_context context,
const krb5_data *randombits, krb5_keyblock *key)
{
krb5_error_code ret = 0;
if (key->length != 16 && key->length != 32)
return (KRB5_BAD_KEYSIZE);
if (randombits->length != key->length)
return (KRB5_CRYPTO_INTERNAL);
key->magic = KV5M_KEYBLOCK;
key->dk_list = NULL;
#ifdef _KERNEL
key->kef_key.ck_data = NULL;
key->key_tmpl = NULL;
(void) memcpy(key->contents, randombits->data, randombits->length);
ret = init_key_kef(context->kef_cipher_mt, key);
#else
key->hKey = CK_INVALID_HANDLE;
(void) memcpy(key->contents, randombits->data, randombits->length);
ret = init_key_uef(krb_ctx_hSession(context), key);
#endif
KRB5_LOG0(KRB5_INFO, "k5_aes_make_key() end\n");
return (ret);
}
static krb5_error_code
krb5int_aes_init_state(krb5_context context, const krb5_keyblock *key,
krb5_keyusage usage, krb5_data *state)
{
if (!state)
return (0);
if (state && state->data)
FREE(state->data, state->length);
state->length = BLOCK_SIZE;
state->data = (void *) MALLOC(BLOCK_SIZE);
if (state->data == NULL)
return (ENOMEM);
(void) memset(state->data, 0, state->length);
return (0);
}
const struct krb5_enc_provider krb5int_enc_aes128 = {
BLOCK_SIZE,
16, 16,
krb5int_aes_encrypt,
krb5int_aes_decrypt,
k5_aes_make_key,
krb5int_aes_init_state,
krb5int_default_free_state
};
const struct krb5_enc_provider krb5int_enc_aes256 = {
BLOCK_SIZE,
32, 32,
krb5int_aes_encrypt,
krb5int_aes_decrypt,
k5_aes_make_key,
krb5int_aes_init_state,
krb5int_default_free_state
};