|
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 |
/*
|
|
Packit |
fd8b60 |
* Because our built-in HMAC implementation doesn't need to invoke any
|
|
Packit |
fd8b60 |
* encryption or keyed hash functions, it is simplest to define it in terms of
|
|
Packit |
fd8b60 |
* keyblocks, and then supply a simple wrapper for the "normal" krb5_key-using
|
|
Packit |
fd8b60 |
* interfaces. The keyblock interfaces are useful for code which creates
|
|
Packit |
fd8b60 |
* intermediate keyblocks.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* The HMAC transform looks like:
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* H(K XOR opad, H(K XOR ipad, text))
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* where H is a cryptographic hash
|
|
Packit |
fd8b60 |
* K is an n byte key
|
|
Packit |
fd8b60 |
* ipad is the byte 0x36 repeated blocksize times
|
|
Packit |
fd8b60 |
* opad is the byte 0x5c repeated blocksize times
|
|
Packit |
fd8b60 |
* and text is the data being protected
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
|
|
Packit |
fd8b60 |
const krb5_keyblock *keyblock,
|
|
Packit |
fd8b60 |
const krb5_crypto_iov *data, size_t num_data,
|
|
Packit |
fd8b60 |
krb5_data *output)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
unsigned char *xorkey = NULL, *ihash = NULL;
|
|
Packit |
fd8b60 |
unsigned int i;
|
|
Packit |
fd8b60 |
krb5_crypto_iov *ihash_iov = NULL, ohash_iov[2];
|
|
Packit |
fd8b60 |
krb5_data hashout;
|
|
Packit |
fd8b60 |
krb5_error_code ret;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (keyblock->length > hash->blocksize)
|
|
Packit |
fd8b60 |
return KRB5_CRYPTO_INTERNAL;
|
|
Packit |
fd8b60 |
if (output->length < hash->hashsize)
|
|
Packit |
fd8b60 |
return KRB5_BAD_MSIZE;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Allocate space for the xor key, hash input vector, and inner hash */
|
|
Packit |
fd8b60 |
xorkey = k5alloc(hash->blocksize, &ret;;
|
|
Packit |
fd8b60 |
if (xorkey == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
ihash = k5alloc(hash->hashsize, &ret;;
|
|
Packit |
fd8b60 |
if (ihash == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
ihash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret;;
|
|
Packit |
fd8b60 |
if (ihash_iov == NULL)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Create the inner padded key. */
|
|
Packit |
fd8b60 |
memset(xorkey, 0x36, hash->blocksize);
|
|
Packit |
fd8b60 |
for (i = 0; i < keyblock->length; i++)
|
|
Packit |
fd8b60 |
xorkey[i] ^= keyblock->contents[i];
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Compute the inner hash over the inner key and input data. */
|
|
Packit |
fd8b60 |
ihash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
ihash_iov[0].data = make_data(xorkey, hash->blocksize);
|
|
Packit |
fd8b60 |
memcpy(ihash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
|
|
Packit |
fd8b60 |
hashout = make_data(ihash, hash->hashsize);
|
|
Packit |
fd8b60 |
ret = hash->hash(ihash_iov, num_data + 1, &hashout);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
goto cleanup;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Create the outer padded key. */
|
|
Packit |
fd8b60 |
memset(xorkey, 0x5c, hash->blocksize);
|
|
Packit |
fd8b60 |
for (i = 0; i < keyblock->length; i++)
|
|
Packit |
fd8b60 |
xorkey[i] ^= keyblock->contents[i];
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Compute the outer hash over the outer key and inner hash value. */
|
|
Packit |
fd8b60 |
ohash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
ohash_iov[0].data = make_data(xorkey, hash->blocksize);
|
|
Packit |
fd8b60 |
ohash_iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
|
|
Packit |
fd8b60 |
ohash_iov[1].data = make_data(ihash, hash->hashsize);
|
|
Packit |
fd8b60 |
output->length = hash->hashsize;
|
|
Packit |
fd8b60 |
ret = hash->hash(ohash_iov, 2, output);
|
|
Packit |
fd8b60 |
if (ret != 0)
|
|
Packit |
fd8b60 |
memset(output->data, 0, output->length);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cleanup:
|
|
Packit |
fd8b60 |
zapfree(xorkey, hash->blocksize);
|
|
Packit |
fd8b60 |
zapfree(ihash, hash->hashsize);
|
|
Packit |
fd8b60 |
free(ihash_iov);
|
|
Packit |
fd8b60 |
return ret;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code
|
|
Packit |
fd8b60 |
krb5int_hmac(const struct krb5_hash_provider *hash, krb5_key key,
|
|
Packit |
fd8b60 |
const krb5_crypto_iov *data, size_t num_data,
|
|
Packit |
fd8b60 |
krb5_data *output)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
return krb5int_hmac_keyblock(hash, &key->keyblock, data, num_data, output);
|
|
Packit |
fd8b60 |
}
|