|
Packit |
fd8b60 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/* lib/crypto/openssl/hmac.c */
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Copyright (C) 2009 by the Massachusetts Institute of Technology.
|
|
Packit |
fd8b60 |
* All rights reserved.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Export of this software from the United States of America may
|
|
Packit |
fd8b60 |
* require a specific license from the United States Government.
|
|
Packit |
fd8b60 |
* It is the responsibility of any person or organization contemplating
|
|
Packit |
fd8b60 |
* export to 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 M.I.T. not be used in advertising or publicity pertaining
|
|
Packit |
fd8b60 |
* to distribution of the software without specific, written prior
|
|
Packit |
fd8b60 |
* permission. Furthermore if you modify this software you must label
|
|
Packit |
fd8b60 |
* your software as modified software and not distribute it in such a
|
|
Packit |
fd8b60 |
* fashion that it might be confused with the original M.I.T. software.
|
|
Packit |
fd8b60 |
* M.I.T. 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 |
|
|
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 |
|
|
Packit |
fd8b60 |
#include "crypto_int.h"
|
|
Packit |
fd8b60 |
#include <openssl/hmac.h>
|
|
Packit |
fd8b60 |
#include <openssl/evp.h>
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* OpenSSL 1.1 makes HMAC_CTX opaque, while 1.0 does not have pointer
|
|
Packit |
fd8b60 |
* constructors or destructors. */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#define HMAC_CTX_new compat_hmac_ctx_new
|
|
Packit |
fd8b60 |
static HMAC_CTX *
|
|
Packit |
fd8b60 |
compat_hmac_ctx_new()
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
HMAC_CTX *ctx;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ctx = calloc(1, sizeof(*ctx));
|
|
Packit |
fd8b60 |
if (ctx != NULL)
|
|
Packit |
fd8b60 |
HMAC_CTX_init(ctx);
|
|
Packit |
fd8b60 |
return ctx;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#define HMAC_CTX_free compat_hmac_ctx_free
|
|
Packit |
fd8b60 |
static void
|
|
Packit |
fd8b60 |
compat_hmac_ctx_free(HMAC_CTX *ctx)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
HMAC_CTX_cleanup(ctx);
|
|
Packit |
fd8b60 |
free(ctx);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
|
|
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 |
static const EVP_MD *
|
|
Packit |
fd8b60 |
map_digest(const struct krb5_hash_provider *hash)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
if (!strncmp(hash->hash_name, "SHA1",4))
|
|
Packit |
fd8b60 |
return EVP_sha1();
|
|
Packit |
fd8b60 |
else if (!strncmp(hash->hash_name, "SHA-256",7))
|
|
Packit |
fd8b60 |
return EVP_sha256();
|
|
Packit |
fd8b60 |
else if (!strncmp(hash->hash_name, "SHA-384",7))
|
|
Packit |
fd8b60 |
return EVP_sha384();
|
|
Packit Service |
e737ee |
else if (!strncmp(hash->hash_name, "MD5", 3))
|
|
Packit |
fd8b60 |
return EVP_md5();
|
|
Packit |
fd8b60 |
else if (!strncmp(hash->hash_name, "MD4", 3))
|
|
Packit |
fd8b60 |
return EVP_md4();
|
|
Packit |
fd8b60 |
else
|
|
Packit |
fd8b60 |
return NULL;
|
|
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 int i = 0, md_len = 0, ok;
|
|
Packit |
fd8b60 |
unsigned char md[EVP_MAX_MD_SIZE];
|
|
Packit |
fd8b60 |
HMAC_CTX *ctx;
|
|
Packit |
fd8b60 |
size_t hashsize, blocksize;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
hashsize = hash->hashsize;
|
|
Packit |
fd8b60 |
blocksize = hash->blocksize;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (keyblock->length > blocksize)
|
|
Packit |
fd8b60 |
return(KRB5_CRYPTO_INTERNAL);
|
|
Packit |
fd8b60 |
if (output->length < hashsize)
|
|
Packit |
fd8b60 |
return(KRB5_BAD_MSIZE);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (!map_digest(hash))
|
|
Packit |
fd8b60 |
return(KRB5_CRYPTO_INTERNAL); // unsupported alg
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ctx = HMAC_CTX_new();
|
|
Packit |
fd8b60 |
if (ctx == NULL)
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
ok = HMAC_Init_ex(ctx, keyblock->contents, keyblock->length,
|
|
Packit |
fd8b60 |
map_digest(hash), NULL);
|
|
Packit |
fd8b60 |
for (i = 0; ok && i < num_data; i++) {
|
|
Packit |
fd8b60 |
const krb5_crypto_iov *iov = &data[i];
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (SIGN_IOV(iov))
|
|
Packit |
fd8b60 |
ok = HMAC_Update(ctx, (uint8_t *)iov->data.data, iov->data.length);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (ok)
|
|
Packit |
fd8b60 |
ok = HMAC_Final(ctx, md, &md_len);
|
|
Packit |
fd8b60 |
if (ok && md_len <= output->length) {
|
|
Packit |
fd8b60 |
output->length = md_len;
|
|
Packit |
fd8b60 |
memcpy(output->data, md, output->length);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
HMAC_CTX_free(ctx);
|
|
Packit |
fd8b60 |
return ok ? 0 : KRB5_CRYPTO_INTERNAL;
|
|
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 |
}
|