#include "k5-int.h"
#include "dk.h"
krb5_error_code
krb5_derive_key(enc, inkey, outkey, in_constant)
const struct krb5_enc_provider *enc;
const krb5_keyblock *inkey;
krb5_keyblock *outkey;
const krb5_data *in_constant;
{
size_t blocksize, keybytes, keylength, n;
unsigned char *inblockdata, *outblockdata, *rawkey;
krb5_data inblock, outblock;
(*(enc->block_size))(&blocksize);
(*(enc->keysize))(&keybytes, &keylength);
if ((inkey->length != keylength) ||
(outkey->length != keylength))
return(KRB5_CRYPTO_INTERNAL);
if ((inblockdata = (unsigned char *) malloc(blocksize)) == NULL)
return(ENOMEM);
if ((outblockdata = (unsigned char *) malloc(blocksize)) == NULL) {
free(inblockdata);
return(ENOMEM);
}
if ((rawkey = (unsigned char *) malloc(keybytes)) == NULL) {
free(outblockdata);
free(inblockdata);
return(ENOMEM);
}
inblock.data = inblockdata;
inblock.length = blocksize;
outblock.data = outblockdata;
outblock.length = blocksize;
if (in_constant->length == inblock.length) {
memcpy(inblock.data, in_constant->data, inblock.length);
} else {
krb5_nfold(in_constant->length*8, in_constant->data,
inblock.length*8, inblock.data);
}
n = 0;
while (n < keybytes) {
(*(enc->encrypt))(inkey, 0, &inblock, &outblock);
if ((keybytes - n) <= outblock.length) {
memcpy(rawkey+n, outblock.data, (keybytes - n));
break;
}
memcpy(rawkey+n, outblock.data, outblock.length);
memcpy(inblock.data, outblock.data, outblock.length);
n += outblock.length;
}
inblock.data = rawkey;
inblock.length = keybytes;
(*(enc->make_key))(&inblock, outkey);
memset(inblockdata, 0, blocksize);
memset(outblockdata, 0, blocksize);
memset(rawkey, 0, keybytes);
free(rawkey);
free(outblockdata);
free(inblockdata);
return(0);
}
krb5_error_code
krb5_derive_random(enc, inkey, outrnd, in_constant)
const struct krb5_enc_provider *enc;
const krb5_keyblock *inkey;
krb5_data *outrnd;
const krb5_data *in_constant;
{
size_t blocksize, keybytes, keylength, n;
unsigned char *inblockdata, *outblockdata, *rawkey;
krb5_data inblock, outblock;
(*(enc->block_size))(&blocksize);
(*(enc->keysize))(&keybytes, &keylength);
if ((inkey->length != keylength) ||
(outrnd->length != keybytes))
return(KRB5_CRYPTO_INTERNAL);
if ((inblockdata = (unsigned char *) malloc(blocksize)) == NULL)
return(ENOMEM);
if ((outblockdata = (unsigned char *) malloc(blocksize)) == NULL) {
free(inblockdata);
return(ENOMEM);
}
if ((rawkey = (unsigned char *) malloc(keybytes)) == NULL) {
free(outblockdata);
free(inblockdata);
return(ENOMEM);
}
inblock.data = inblockdata;
inblock.length = blocksize;
outblock.data = outblockdata;
outblock.length = blocksize;
if (in_constant->length == inblock.length) {
memcpy(inblock.data, in_constant->data, inblock.length);
} else {
krb5_nfold(in_constant->length*8, in_constant->data,
inblock.length*8, inblock.data);
}
n = 0;
while (n < keybytes) {
(*(enc->encrypt))(inkey, 0, &inblock, &outblock);
if ((keybytes - n) <= outblock.length) {
memcpy(rawkey+n, outblock.data, (keybytes - n));
break;
}
memcpy(rawkey+n, outblock.data, outblock.length);
memcpy(inblock.data, outblock.data, outblock.length);
n += outblock.length;
}
memcpy (outrnd->data, rawkey, keybytes);
memset(inblockdata, 0, blocksize);
memset(outblockdata, 0, blocksize);
memset(rawkey, 0, keybytes);
free(rawkey);
free(outblockdata);
free(inblockdata);
return(0);
}
#include "etypes.h"
void
krb5_random2key (krb5_enctype enctype, krb5_data *inblock,
krb5_keyblock *outkey)
{
int i;
const struct krb5_enc_provider *enc;
for (i=0; i<krb5_enctypes_length; i++) {
if (krb5_enctypes_list[i].etype == enctype)
break;
}
if (i == krb5_enctypes_length)
abort ();
enc = krb5_enctypes_list[i].enc;
enc->make_key (inblock, outkey);
}