/*
* Copyright (C) 2008 Free Software Foundation
*
* Author: Simon Josefsson
*
* This file is part of GNUTLS-EXTRA.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
#include
#include
#include
static int
md5init (void **ctx)
{
*ctx = gnutls_malloc (sizeof (struct md5_ctx));
if (!*ctx)
return GNUTLS_E_MEMORY_ERROR;
md5_init_ctx (*ctx);
return 0;
}
static int
md5hash (void *ctx, const void *text, size_t textsize)
{
md5_process_bytes (text, textsize, ctx);
return 0;
}
static int
md5copy (void **dst_ctx, void *src_ctx)
{
*dst_ctx = gnutls_malloc (sizeof (struct md5_ctx));
if (!*dst_ctx)
return GNUTLS_E_MEMORY_ERROR;
memcpy (*dst_ctx, src_ctx, sizeof (struct md5_ctx));
return 0;
}
static int
md5output (void *src_ctx, void *digest, size_t digestsize)
{
char out[MD5_DIGEST_SIZE];
md5_finish_ctx (src_ctx, out);
memcpy (digest, out, digestsize);
return 0;
}
static void
md5deinit (void *ctx)
{
gnutls_free (ctx);
}
struct hmacctx
{
char *data;
size_t datasize;
char *key;
size_t keysize;
};
static int
hmacmd5init (void **ctx)
{
struct hmacctx *p;
p = gnutls_malloc (sizeof (struct hmacctx));
if (!p)
return -1;
p->data = NULL;
p->datasize = 0;
p->key = NULL;
p->keysize = 0;
*ctx = p;
return 0;
}
static int
hmacmd5setkey (void *ctx, const void *key, size_t keysize)
{
struct hmacctx *p = ctx;
if (p->key)
gnutls_free (p->key);
p->key = gnutls_malloc (keysize);
if (!p->key)
return -1;
memcpy (p->key, key, keysize);
p->keysize = keysize;
return 0;
}
static int
hmacmd5hash (void *ctx, const void *text, size_t textsize)
{
struct hmacctx *p = ctx;
char *new;
new = gnutls_realloc (p->data, p->datasize + textsize);
if (!new)
return -1;
memcpy (new + p->datasize, text, textsize);
p->data = new;
p->datasize += textsize;
return 0;
}
static int
hmacmd5copy (void **dst_ctx, void *src_ctx)
{
struct hmacctx *p = src_ctx;
struct hmacctx *q;
q = gnutls_malloc (sizeof (struct hmacctx));
if (!q)
return -1;
q->data = gnutls_malloc (p->datasize);
if (!q->data)
{
gnutls_free (q);
return -1;
}
memcpy (q->data, p->data, p->datasize);
q->datasize = p->datasize;
q->key = gnutls_malloc (p->keysize);
if (!q->key)
{
gnutls_free (q);
gnutls_free (q->data);
return -1;
}
memcpy (q->key, p->key, p->keysize);
q->keysize = p->keysize;
*dst_ctx = q;
return 0;
}
static int
hmacmd5output (void *ctx, void *digest, size_t digestsize)
{
struct hmacctx *p = ctx;
char out[MD5_DIGEST_SIZE];
int ret;
ret = hmac_md5 (p->key, p->keysize, p->data, p->datasize, out);
if (ret)
return GNUTLS_E_HASH_FAILED;
memcpy (digest, out, digestsize);
return 0;
}
static void
hmacmd5deinit (void *ctx)
{
struct hmacctx *p = ctx;
if (p->data)
gnutls_free (p->data);
if (p->key)
gnutls_free (p->key);
gnutls_free (p);
}
static gnutls_crypto_single_digest_st dig = {
md5init,
NULL,
md5hash,
md5copy,
md5output,
md5deinit
};
static gnutls_crypto_single_mac_st mac = {
hmacmd5init,
hmacmd5setkey,
hmacmd5hash,
hmacmd5copy,
hmacmd5output,
hmacmd5deinit
};
/**
* gnutls_register_md5_handler:
*
* Register a non-libgcrypt based MD5 and HMAC-MD5 handler. This is
* useful if you run Libgcrypt in FIPS-mode. Normally TLS requires
* use of MD5, so without this you cannot use GnuTLS with libgcrypt in
* FIPS mode.
*
* Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
*
* Since: 2.6.0
**/
int
gnutls_register_md5_handler (void)
{
int ret;
ret = gnutls_crypto_single_digest_register (GNUTLS_DIG_MD5, INT_MAX, &dig);
if (ret)
return ret;
ret = gnutls_crypto_single_mac_register (GNUTLS_MAC_MD5, INT_MAX, &mac);
if (ret)
return ret;
return 0;
}