|
Packit |
fd8b60 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95).
|
|
Packit |
fd8b60 |
This cipher is widely believed and has been tested to be equivalent
|
|
Packit |
fd8b60 |
with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark
|
|
Packit |
fd8b60 |
of RSA Data Security)
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
#include "crypto_int.h"
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#define CONFOUNDERLENGTH 8
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
const char l40[] = "fortybits";
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_keyusage
|
|
Packit |
fd8b60 |
krb5int_arcfour_translate_usage(krb5_keyusage usage)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
switch (usage) {
|
|
Packit |
fd8b60 |
case 1: return 1; /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */
|
|
Packit |
fd8b60 |
case 2: return 2; /* ticket from kdc */
|
|
Packit |
fd8b60 |
case 3: return 8; /* as-rep encrypted part */
|
|
Packit |
fd8b60 |
case 4: return 4; /* tgs-req authz data */
|
|
Packit |
fd8b60 |
case 5: return 5; /* tgs-req authz data in subkey */
|
|
Packit |
fd8b60 |
case 6: return 6; /* tgs-req authenticator cksum */
|
|
Packit |
fd8b60 |
case 7: return 7; /* tgs-req authenticator */
|
|
Packit |
fd8b60 |
case 8: return 8;
|
|
Packit |
fd8b60 |
case 9: return 9; /* tgs-rep encrypted with subkey */
|
|
Packit |
fd8b60 |
case 10: return 10; /* ap-rep authentication cksum (never used by MS) */
|
|
Packit |
fd8b60 |
case 11: return 11; /* app-req authenticator */
|
|
Packit |
fd8b60 |
case 12: return 12; /* app-rep encrypted part */
|
|
Packit |
fd8b60 |
case 23: return 13; /* sign wrap token*/
|
|
Packit |
fd8b60 |
default: return usage;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Derive a usage key from a session key and krb5 usage constant. */
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
usage_key(const struct krb5_enc_provider *enc,
|
|
Packit |
fd8b60 |
const struct krb5_hash_provider *hash,
|
|
Packit |
fd8b60 |
const krb5_keyblock *session_keyblock, krb5_keyusage usage,
|
|
Packit |
fd8b60 |
krb5_keyblock *out)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
char salt_buf[14];
|
|
Packit |
fd8b60 |
unsigned int salt_len;
|
|
Packit |
fd8b60 |
krb5_data out_data = make_data(out->contents, out->length);
|
|
Packit |
fd8b60 |
krb5_crypto_iov iov;
|
|
Packit |
fd8b60 |
krb5_keyusage ms_usage;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Generate the salt. */
|
|
Packit |
fd8b60 |
ms_usage = krb5int_arcfour_translate_usage(usage);
|
|
Packit |
fd8b60 |
if (session_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
|
|
Packit |
fd8b60 |
memcpy(salt_buf, l40, 10);
|
|
Packit |
fd8b60 |
store_32_le(ms_usage, salt_buf + 10);
|
|
Packit |
fd8b60 |
salt_len = 14;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
store_32_le(ms_usage, salt_buf);
|
|
Packit |
fd8b60 |
salt_len = 4;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Compute HMAC(key, salt) to produce the usage key. */
|
|
Packit |
fd8b60 |
iov.flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
iov.data = make_data(salt_buf, salt_len);
|
|
Packit |
fd8b60 |
return krb5int_hmac_keyblock(hash, session_keyblock, &iov, 1, &out_data);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Derive an encryption key from a usage key and (typically) checksum. */
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
enc_key(const struct krb5_enc_provider *enc,
|
|
Packit |
fd8b60 |
const struct krb5_hash_provider *hash,
|
|
Packit |
fd8b60 |
const krb5_keyblock *usage_keyblock, const krb5_data *checksum,
|
|
Packit |
fd8b60 |
krb5_keyblock *out)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_keyblock *trunc_keyblock = NULL;
|
|
Packit |
fd8b60 |
krb5_data out_data = make_data(out->contents, out->length);
|
|
Packit |
fd8b60 |
krb5_crypto_iov iov;
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Copy usage_keyblock to trunc_keyblock and truncate if exportable. */
|
|
Packit |
fd8b60 |
ret = krb5int_c_copy_keyblock(NULL, usage_keyblock, &trunc_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
if (trunc_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
|
|
Packit |
fd8b60 |
memset(trunc_keyblock->contents + 7, 0xab, 9);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Compute HMAC(trunc_key, checksum) to produce the encryption key. */
|
|
Packit |
fd8b60 |
iov.flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
iov.data = *checksum;
|
|
Packit |
fd8b60 |
ret = krb5int_hmac_keyblock(hash, trunc_keyblock, &iov, 1, &out_data);
|
|
Packit |
fd8b60 |
krb5int_c_free_keyblock(NULL, trunc_keyblock);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
unsigned int
|
|
Packit |
fd8b60 |
krb5int_arcfour_crypto_length(const struct krb5_keytypes *ktp,
|
|
Packit |
fd8b60 |
krb5_cryptotype type)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
switch (type) {
|
|
Packit |
fd8b60 |
case KRB5_CRYPTO_TYPE_HEADER:
|
|
Packit |
fd8b60 |
return ktp->hash->hashsize + CONFOUNDERLENGTH;
|
|
Packit |
fd8b60 |
case KRB5_CRYPTO_TYPE_PADDING:
|
|
Packit |
fd8b60 |
case KRB5_CRYPTO_TYPE_TRAILER:
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
case KRB5_CRYPTO_TYPE_CHECKSUM:
|
|
Packit |
fd8b60 |
return ktp->hash->hashsize;
|
|
Packit |
fd8b60 |
default:
|
|
Packit |
fd8b60 |
assert(0 &&
|
|
Packit |
fd8b60 |
"invalid cryptotype passed to krb5int_arcfour_crypto_length");
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Encrypt or decrypt using a keyblock. */
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
keyblock_crypt(const struct krb5_enc_provider *enc, krb5_keyblock *keyblock,
|
|
Packit |
fd8b60 |
const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
krb5_key key;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5_k_create_key(NULL, keyblock, &key);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
/* Works for encryption or decryption since arcfour is a stream cipher. */
|
|
Packit |
fd8b60 |
ret = enc->encrypt(key, ivec, data, num_data);
|
|
Packit |
fd8b60 |
krb5_k_free_key(NULL, key);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
krb5int_arcfour_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
|
|
Packit |
fd8b60 |
krb5_keyusage usage, const krb5_data *ivec,
|
|
Packit |
fd8b60 |
krb5_crypto_iov *data, size_t num_data)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const struct krb5_enc_provider *enc = ktp->enc;
|
|
Packit |
fd8b60 |
const struct krb5_hash_provider *hash = ktp->hash;
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
krb5_crypto_iov *header, *trailer;
|
|
Packit |
fd8b60 |
krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL;
|
|
Packit |
fd8b60 |
krb5_data checksum, confounder, header_data;
|
|
Packit |
fd8b60 |
size_t i;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Caller must have provided space for the header, padding
|
|
Packit |
fd8b60 |
* and trailer; per RFC 4757 we will arrange it as:
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Checksum | E(Confounder | Plaintext)
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
|
|
Packit |
fd8b60 |
if (header == NULL ||
|
|
Packit |
fd8b60 |
header->data.length < hash->hashsize + CONFOUNDERLENGTH)
|
|
Packit |
fd8b60 |
return KRB5_BAD_MSIZE;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
header_data = header->data;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Trailer may be absent. */
|
|
Packit |
fd8b60 |
trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
|
|
Packit |
fd8b60 |
if (trailer != NULL)
|
|
Packit |
fd8b60 |
trailer->data.length = 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Ensure that there is no padding. */
|
|
Packit |
fd8b60 |
for (i = 0; i < num_data; i++) {
|
|
Packit |
fd8b60 |
if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING)
|
|
Packit |
fd8b60 |
data[i].data.length = 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
|
|
Packit |
fd8b60 |
&usage_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
|
|
Packit |
fd8b60 |
&enc_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Derive a usage key from the session key and usage. */
|
|
Packit |
fd8b60 |
ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Generate a confounder in the header block, after the checksum. */
|
|
Packit |
fd8b60 |
header->data.length = hash->hashsize + CONFOUNDERLENGTH;
|
|
Packit |
fd8b60 |
confounder = make_data(header->data.data + hash->hashsize,
|
|
Packit |
fd8b60 |
CONFOUNDERLENGTH);
|
|
Packit |
fd8b60 |
ret = krb5_c_random_make_octets(0, &confounder);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
checksum = make_data(header->data.data, hash->hashsize);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Adjust pointers so confounder is at start of header. */
|
|
Packit |
fd8b60 |
header->data.length -= hash->hashsize;
|
|
Packit |
fd8b60 |
header->data.data += hash->hashsize;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Compute the checksum using the usage key. */
|
|
Packit |
fd8b60 |
ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data,
|
|
Packit |
fd8b60 |
&checksum);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Derive the encryption key from the usage key and checksum. */
|
|
Packit |
fd8b60 |
ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
header->data = header_data; /* Restore header pointers. */
|
|
Packit |
fd8b60 |
krb5int_c_free_keyblock(NULL, usage_keyblock);
|
|
Packit |
fd8b60 |
krb5int_c_free_keyblock(NULL, enc_keyblock);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
krb5int_arcfour_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
|
|
Packit |
fd8b60 |
krb5_keyusage usage, const krb5_data *ivec,
|
|
Packit |
fd8b60 |
krb5_crypto_iov *data, size_t num_data)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const struct krb5_enc_provider *enc = ktp->enc;
|
|
Packit |
fd8b60 |
const struct krb5_hash_provider *hash = ktp->hash;
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
krb5_crypto_iov *header, *trailer;
|
|
Packit |
fd8b60 |
krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL;
|
|
Packit |
fd8b60 |
krb5_data checksum, header_data, comp_checksum = empty_data();
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
|
|
Packit |
fd8b60 |
if (header == NULL ||
|
|
Packit |
fd8b60 |
header->data.length != hash->hashsize + CONFOUNDERLENGTH)
|
|
Packit |
fd8b60 |
return KRB5_BAD_MSIZE;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
header_data = header->data;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
|
|
Packit |
fd8b60 |
if (trailer != NULL && trailer->data.length != 0)
|
|
Packit |
fd8b60 |
return KRB5_BAD_MSIZE;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Allocate buffers. */
|
|
Packit |
fd8b60 |
ret = alloc_data(&comp_checksum, hash->hashsize);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
|
|
Packit |
fd8b60 |
&usage_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
|
|
Packit |
fd8b60 |
&enc_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
checksum = make_data(header->data.data, hash->hashsize);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Adjust pointers so confounder is at start of header. */
|
|
Packit |
fd8b60 |
header->data.length -= hash->hashsize;
|
|
Packit |
fd8b60 |
header->data.data += hash->hashsize;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* We may have to try two usage values; see below. */
|
|
Packit |
fd8b60 |
do {
|
|
Packit |
fd8b60 |
/* Derive a usage key from the session key and usage. */
|
|
Packit |
fd8b60 |
ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Derive the encryption key from the usage key and checksum. */
|
|
Packit |
fd8b60 |
ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Decrypt the ciphertext. */
|
|
Packit |
fd8b60 |
ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Compute HMAC(usage key, plaintext) to get the checksum. */
|
|
Packit |
fd8b60 |
ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data,
|
|
Packit |
fd8b60 |
&comp_checksum);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (k5_bcmp(checksum.data, comp_checksum.data, hash->hashsize) != 0) {
|
|
Packit |
fd8b60 |
if (usage == 9) {
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* RFC 4757 specifies usage 8 for TGS-REP encrypted parts
|
|
Packit |
fd8b60 |
* encrypted in a subkey, but the value used by MS is actually
|
|
Packit |
fd8b60 |
* 9. We now use 9 to start with, but fall back to 8 on
|
|
Packit |
fd8b60 |
* failure in case we are communicating with a KDC using the
|
|
Packit |
fd8b60 |
* value from the RFC. ivec is always NULL in this case.
|
|
Packit |
fd8b60 |
* We need to re-encrypt the data in the wrong key first.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
ret = keyblock_crypt(enc, enc_keyblock, NULL, data, num_data);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
usage = 8;
|
|
Packit |
fd8b60 |
continue;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
} while (1);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
header->data = header_data; /* Restore header pointers. */
|
|
Packit |
fd8b60 |
krb5int_c_free_keyblock(NULL, usage_keyblock);
|
|
Packit |
fd8b60 |
krb5int_c_free_keyblock(NULL, enc_keyblock);
|
|
Packit |
fd8b60 |
zapfree(comp_checksum.data, comp_checksum.length);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage,
|
|
Packit |
fd8b60 |
const krb5_data *kd_data, krb5_crypto_iov *data,
|
|
Packit |
fd8b60 |
size_t num_data)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
const struct krb5_enc_provider *enc = &krb5int_enc_arcfour;
|
|
Packit |
fd8b60 |
const struct krb5_hash_provider *hash = &krb5int_hash_md5;
|
|
Packit |
fd8b60 |
krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL;
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes,
|
|
Packit |
fd8b60 |
&usage_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes,
|
|
Packit |
fd8b60 |
&enc_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Derive a usage key from the session key and usage. */
|
|
Packit |
fd8b60 |
ret = usage_key(enc, hash, keyblock, usage, usage_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Derive the encryption key from the usage key and kd_data. */
|
|
Packit |
fd8b60 |
ret = enc_key(enc, hash, usage_keyblock, kd_data, enc_keyblock);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Encrypt or decrypt (encrypt_iov works for both) the input. */
|
|
Packit |
fd8b60 |
ret = keyblock_crypt(enc, enc_keyblock, 0, data, num_data);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
krb5int_c_free_keyblock(NULL, usage_keyblock);
|
|
Packit |
fd8b60 |
krb5int_c_free_keyblock(NULL, enc_keyblock);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|