|
Packit |
fd8b60 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Copyright (C) 1998 by the FundsXpress, INC.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* All rights reserved.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Export of this software from the United States of America may require
|
|
Packit |
fd8b60 |
* a specific license from the United States Government. It is the
|
|
Packit |
fd8b60 |
* responsibility of any person or organization contemplating export to
|
|
Packit |
fd8b60 |
* obtain such a license before exporting.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
|
Packit |
fd8b60 |
* distribute this software and its documentation for any purpose and
|
|
Packit |
fd8b60 |
* without fee is hereby granted, provided that the above copyright
|
|
Packit |
fd8b60 |
* notice appear in all copies and that both that copyright notice and
|
|
Packit |
fd8b60 |
* this permission notice appear in supporting documentation, and that
|
|
Packit |
fd8b60 |
* the name of FundsXpress. not be used in advertising or publicity pertaining
|
|
Packit |
fd8b60 |
* to distribution of the software without specific, written prior
|
|
Packit |
fd8b60 |
* permission. FundsXpress makes no representations about the suitability of
|
|
Packit |
fd8b60 |
* this software for any purpose. It is provided "as is" without express
|
|
Packit |
fd8b60 |
* or implied warranty.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
Packit |
fd8b60 |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
Packit |
fd8b60 |
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#include "crypto_int.h"
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_key
|
|
Packit |
fd8b60 |
find_cached_dkey(struct derived_key *list, const krb5_data *constant)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
for (; list; list = list->next) {
|
|
Packit |
fd8b60 |
if (data_eq(list->constant, *constant)) {
|
|
Packit |
fd8b60 |
krb5_k_reference_key(NULL, list->dkey);
|
|
Packit |
fd8b60 |
return list->dkey;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return NULL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit |
fd8b60 |
add_cached_dkey(krb5_key key, const krb5_data *constant,
|
|
Packit |
fd8b60 |
const krb5_keyblock *dkeyblock, krb5_key *cached_dkey)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_key dkey;
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
struct derived_key *dkent = NULL;
|
|
Packit |
fd8b60 |
char *data = NULL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Allocate fields for the new entry. */
|
|
Packit |
fd8b60 |
dkent = malloc(sizeof(*dkent));
|
|
Packit |
fd8b60 |
if (dkent == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
data = k5memdup(constant->data, constant->length, &ret;;
|
|
Packit |
fd8b60 |
if (data == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
ret = krb5_k_create_key(NULL, dkeyblock, &dkey);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Add the new entry to the list. */
|
|
Packit |
fd8b60 |
dkent->dkey = dkey;
|
|
Packit |
fd8b60 |
dkent->constant.data = data;
|
|
Packit |
fd8b60 |
dkent->constant.length = constant->length;
|
|
Packit |
fd8b60 |
dkent->next = key->derived;
|
|
Packit |
fd8b60 |
key->derived = dkent;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Return a "copy" of the cached key. */
|
|
Packit |
fd8b60 |
krb5_k_reference_key(NULL, dkey);
|
|
Packit |
fd8b60 |
*cached_dkey = dkey;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
free(dkent);
|
|
Packit |
fd8b60 |
free(data);
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
rpm-build |
8f2e36 |
static krb5_error_code
|
|
Packit Service |
a81408 |
derive_random_rfc3961(const struct krb5_enc_provider *enc,
|
|
Packit Service |
a81408 |
krb5_key inkey, krb5_data *outrnd,
|
|
Packit Service |
a81408 |
const krb5_data *in_constant)
|
|
rpm-build |
8f2e36 |
{
|
|
Packit Service |
a81408 |
size_t blocksize, keybytes, n;
|
|
Packit Service |
a81408 |
krb5_error_code ret;
|
|
Packit Service |
a81408 |
krb5_data block = empty_data();
|
|
Packit |
fd8b60 |
|
|
Packit Service |
a81408 |
blocksize = enc->block_size;
|
|
Packit Service |
a81408 |
keybytes = enc->keybytes;
|
|
rpm-build |
8f2e36 |
|
|
Packit Service |
a81408 |
if (blocksize == 1)
|
|
Packit Service |
a81408 |
return KRB5_BAD_ENCTYPE;
|
|
Packit Service |
a81408 |
if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
|
|
Packit |
fd8b60 |
return KRB5_CRYPTO_INTERNAL;
|
|
Packit |
fd8b60 |
|
|
Packit Service |
a81408 |
/* Allocate encryption data buffer. */
|
|
Packit Service |
a81408 |
ret = alloc_data(&block, blocksize);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit Service |
a81408 |
return ret;
|
|
Packit |
fd8b60 |
|
|
Packit Service |
a81408 |
/* Initialize the input block. */
|
|
Packit Service |
a81408 |
if (in_constant->length == blocksize) {
|
|
Packit Service |
a81408 |
memcpy(block.data, in_constant->data, blocksize);
|
|
Packit Service |
a81408 |
} else {
|
|
Packit Service |
a81408 |
krb5int_nfold(in_constant->length * 8,
|
|
Packit Service |
a81408 |
(unsigned char *) in_constant->data,
|
|
Packit Service |
a81408 |
blocksize * 8, (unsigned char *) block.data);
|
|
Packit Service |
a81408 |
}
|
|
Packit |
fd8b60 |
|
|
Packit Service |
a81408 |
/* Loop encrypting the blocks until enough key bytes are generated. */
|
|
Packit Service |
a81408 |
n = 0;
|
|
Packit Service |
a81408 |
while (n < keybytes) {
|
|
Packit Service |
a81408 |
ret = encrypt_block(enc, inkey, &block);
|
|
Packit Service |
a81408 |
if (ret)
|
|
Packit Service |
a81408 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit Service |
a81408 |
if ((keybytes - n) <= blocksize) {
|
|
Packit Service |
a81408 |
memcpy(outrnd->data + n, block.data, (keybytes - n));
|
|
Packit Service |
a81408 |
break;
|
|
Packit Service |
a81408 |
}
|
|
Packit |
fd8b60 |
|
|
Packit Service |
a81408 |
memcpy(outrnd->data + n, block.data, blocksize);
|
|
Packit Service |
a81408 |
n += blocksize;
|
|
Packit Service |
a81408 |
}
|
|
rpm-build |
8f2e36 |
|
|
Packit Service |
a81408 |
cleanup:
|
|
Packit Service |
a81408 |
zapfree(block.data, blocksize);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* NIST SP800-108 KDF in feedback mode (section 5.2).
|
|
Packit |
fd8b60 |
* Parameters:
|
|
Packit |
fd8b60 |
* - CMAC (with enc as the enc provider) is the PRF.
|
|
Packit |
fd8b60 |
* - A block counter of four bytes is used.
|
|
Packit |
fd8b60 |
* - Label is the key derivation constant.
|
|
Packit |
fd8b60 |
* - Context is empty.
|
|
Packit |
fd8b60 |
* - Four bytes are used to encode the output length in the PRF input.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
static krb5_error_code
|
|
Packit Service |
a81408 |
derive_random_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
|
|
Packit Service |
a81408 |
krb5_key inkey, krb5_data *outrnd,
|
|
Packit Service |
a81408 |
const krb5_data *in_constant)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
size_t blocksize, keybytes, n;
|
|
Packit |
fd8b60 |
krb5_crypto_iov iov[6];
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
krb5_data prf;
|
|
Packit |
fd8b60 |
unsigned int i;
|
|
Packit |
fd8b60 |
unsigned char ibuf[4], Lbuf[4];
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
blocksize = enc->block_size;
|
|
Packit |
fd8b60 |
keybytes = enc->keybytes;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
|
|
Packit |
fd8b60 |
return KRB5_CRYPTO_INTERNAL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Allocate encryption data buffer. */
|
|
Packit |
fd8b60 |
ret = alloc_data(&prf, blocksize);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* K(i-1): the previous block of PRF output, initially all-zeros. */
|
|
Packit |
fd8b60 |
iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
iov[0].data = prf;
|
|
Packit |
fd8b60 |
/* [i]2: four-byte big-endian binary string giving the block counter */
|
|
Packit |
fd8b60 |
iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
iov[1].data = make_data(ibuf, sizeof(ibuf));
|
|
Packit |
fd8b60 |
/* Label: the fixed derived-key input */
|
|
Packit |
fd8b60 |
iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
iov[2].data = *in_constant;
|
|
Packit |
fd8b60 |
/* 0x00: separator byte */
|
|
Packit |
fd8b60 |
iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
iov[3].data = make_data("", 1);
|
|
Packit |
fd8b60 |
/* Context: (unused) */
|
|
Packit |
fd8b60 |
iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
iov[4].data = empty_data();
|
|
Packit |
fd8b60 |
/* [L]2: four-byte big-endian binary string giving the output length */
|
|
Packit |
fd8b60 |
iov[5].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
iov[5].data = make_data(Lbuf, sizeof(Lbuf));
|
|
Packit |
fd8b60 |
store_32_be(outrnd->length * 8, Lbuf);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
for (i = 1, n = 0; n < keybytes; i++) {
|
|
Packit |
fd8b60 |
/* Update the block counter. */
|
|
Packit |
fd8b60 |
store_32_be(i, ibuf);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Compute a CMAC checksum, storing the result into K(i-1). */
|
|
Packit |
fd8b60 |
ret = krb5int_cmac_checksum(enc, inkey, iov, 6, &prf;;
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Copy the result into the appropriate part of the output buffer. */
|
|
Packit |
fd8b60 |
if (keybytes - n <= blocksize) {
|
|
Packit |
fd8b60 |
memcpy(outrnd->data + n, prf.data, keybytes - n);
|
|
Packit |
fd8b60 |
break;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
memcpy(outrnd->data + n, prf.data, blocksize);
|
|
Packit |
fd8b60 |
n += blocksize;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
zapfree(prf.data, blocksize);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit Service |
a81408 |
/*
|
|
Packit Service |
a81408 |
* NIST SP800-108 KDF in counter mode (section 5.1).
|
|
Packit Service |
a81408 |
* Parameters:
|
|
Packit Service |
a81408 |
* - HMAC (with hash as the hash provider) is the PRF.
|
|
Packit Service |
a81408 |
* - A block counter of four bytes is used.
|
|
Packit Service |
a81408 |
* - Four bytes are used to encode the output length in the PRF input.
|
|
Packit Service |
a81408 |
*
|
|
Packit Service |
a81408 |
* There are no uses requiring more than a single PRF invocation.
|
|
Packit Service |
a81408 |
*/
|
|
Packit Service |
a81408 |
krb5_error_code
|
|
Packit Service |
a81408 |
k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
|
|
Packit Service |
a81408 |
krb5_key inkey, krb5_data *outrnd,
|
|
Packit Service |
a81408 |
const krb5_data *label, const krb5_data *context)
|
|
Packit |
fd8b60 |
{
|
|
Packit Service |
a81408 |
krb5_crypto_iov iov[5];
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit Service |
a81408 |
krb5_data prf;
|
|
Packit Service |
a81408 |
unsigned char ibuf[4], lbuf[4];
|
|
rpm-build |
8f2e36 |
|
|
Packit Service |
a81408 |
if (hash == NULL || outrnd->length > hash->hashsize)
|
|
Packit |
fd8b60 |
return KRB5_CRYPTO_INTERNAL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Allocate encryption data buffer. */
|
|
Packit Service |
a81408 |
ret = alloc_data(&prf, hash->hashsize);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
|
|
Packit Service |
a81408 |
/* [i]2: four-byte big-endian binary string giving the block counter (1) */
|
|
Packit Service |
a81408 |
iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit Service |
a81408 |
iov[0].data = make_data(ibuf, sizeof(ibuf));
|
|
Packit Service |
a81408 |
store_32_be(1, ibuf);
|
|
Packit Service |
a81408 |
/* Label */
|
|
Packit Service |
a81408 |
iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit Service |
a81408 |
iov[1].data = *label;
|
|
Packit Service |
a81408 |
/* 0x00: separator byte */
|
|
Packit Service |
a81408 |
iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit Service |
a81408 |
iov[2].data = make_data("", 1);
|
|
Packit Service |
a81408 |
/* Context */
|
|
Packit Service |
a81408 |
iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit Service |
a81408 |
iov[3].data = *context;
|
|
Packit Service |
a81408 |
/* [L]2: four-byte big-endian binary string giving the output length */
|
|
Packit Service |
a81408 |
iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit Service |
a81408 |
iov[4].data = make_data(lbuf, sizeof(lbuf));
|
|
Packit Service |
a81408 |
store_32_be(outrnd->length * 8, lbuf);
|
|
rpm-build |
8f2e36 |
|
|
Packit Service |
a81408 |
ret = krb5int_hmac(hash, inkey, iov, 5, &prf;;
|
|
Packit Service |
a81408 |
if (!ret)
|
|
Packit Service |
a81408 |
memcpy(outrnd->data, prf.data, outrnd->length);
|
|
Packit Service |
a81408 |
zapfree(prf.data, prf.length);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
krb5int_derive_random(const struct krb5_enc_provider *enc,
|
|
Packit |
fd8b60 |
const struct krb5_hash_provider *hash,
|
|
Packit |
fd8b60 |
krb5_key inkey, krb5_data *outrnd,
|
|
Packit |
fd8b60 |
const krb5_data *in_constant, enum deriv_alg alg)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_data empty = empty_data();
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
switch (alg) {
|
|
Packit |
fd8b60 |
case DERIVE_RFC3961:
|
|
Packit Service |
a81408 |
return derive_random_rfc3961(enc, inkey, outrnd, in_constant);
|
|
Packit |
fd8b60 |
case DERIVE_SP800_108_CMAC:
|
|
Packit Service |
a81408 |
return derive_random_sp800_108_feedback_cmac(enc, inkey, outrnd,
|
|
Packit Service |
a81408 |
in_constant);
|
|
Packit |
fd8b60 |
case DERIVE_SP800_108_HMAC:
|
|
Packit |
fd8b60 |
return k5_sp800_108_counter_hmac(hash, inkey, outrnd, in_constant,
|
|
Packit |
fd8b60 |
&empty);
|
|
Packit |
fd8b60 |
default:
|
|
Packit |
fd8b60 |
return EINVAL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Compute a derived key into the keyblock outkey. This variation on
|
|
Packit |
fd8b60 |
* krb5int_derive_key does not cache the result, as it is only used
|
|
Packit |
fd8b60 |
* directly in situations which are not expected to be repeated with
|
|
Packit |
fd8b60 |
* the same inkey and constant.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
krb5int_derive_keyblock(const struct krb5_enc_provider *enc,
|
|
Packit |
fd8b60 |
const struct krb5_hash_provider *hash,
|
|
Packit |
fd8b60 |
krb5_key inkey, krb5_keyblock *outkey,
|
|
Packit |
fd8b60 |
const krb5_data *in_constant, enum deriv_alg alg)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
krb5_data rawkey = empty_data();
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Allocate a buffer for the raw key bytes. */
|
|
Packit |
fd8b60 |
ret = alloc_data(&rawkey, enc->keybytes);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Derive pseudo-random data for the key bytes. */
|
|
Packit |
fd8b60 |
ret = krb5int_derive_random(enc, hash, inkey, &rawkey, in_constant, alg);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Postprocess the key. */
|
|
Packit |
fd8b60 |
ret = krb5_c_random_to_key(NULL, inkey->keyblock.enctype, &rawkey, outkey);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
zapfree(rawkey.data, enc->keybytes);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
krb5int_derive_key(const struct krb5_enc_provider *enc,
|
|
Packit |
fd8b60 |
const struct krb5_hash_provider *hash,
|
|
Packit |
fd8b60 |
krb5_key inkey, krb5_key *outkey,
|
|
Packit |
fd8b60 |
const krb5_data *in_constant, enum deriv_alg alg)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_keyblock keyblock;
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
krb5_key dkey;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*outkey = NULL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Check for a cached result. */
|
|
Packit |
fd8b60 |
dkey = find_cached_dkey(inkey->derived, in_constant);
|
|
Packit |
fd8b60 |
if (dkey != NULL) {
|
|
Packit |
fd8b60 |
*outkey = dkey;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Derive into a temporary keyblock. */
|
|
Packit |
fd8b60 |
keyblock.length = enc->keylength;
|
|
Packit |
fd8b60 |
keyblock.contents = malloc(keyblock.length);
|
|
Packit |
fd8b60 |
keyblock.enctype = inkey->keyblock.enctype;
|
|
Packit |
fd8b60 |
if (keyblock.contents == NULL)
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
ret = krb5int_derive_keyblock(enc, hash, inkey, &keyblock, in_constant,
|
|
Packit |
fd8b60 |
alg);
|
|
Packit |
fd8b60 |
if (ret)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Cache the derived key. */
|
|
Packit |
fd8b60 |
ret = add_cached_dkey(inkey, in_constant, &keyblock, &dkey);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*outkey = dkey;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
zapfree(keyblock.contents, keyblock.length);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|