|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* Copyright (C) 2000-2012 Free Software Foundation, Inc.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Author: Nikos Mavrogiannopoulos
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This file is part of GnuTLS.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
549fdc |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
549fdc |
* the License, or (at your option) any later version.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
549fdc |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
549fdc |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
549fdc |
* Lesser General Public License for more details.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* This file handles all the internal functions that cope with hashes
|
|
Packit |
549fdc |
* and HMACs.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#include "gnutls_int.h"
|
|
Packit |
549fdc |
#include <hash_int.h>
|
|
Packit |
549fdc |
#include "errors.h"
|
|
Packit |
549fdc |
#include <algorithms.h>
|
|
Packit |
549fdc |
#include <fips.h>
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int _gnutls_hash_init(digest_hd_st * dig, const mac_entry_st * e)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int result;
|
|
Packit |
549fdc |
const gnutls_crypto_digest_st *cc = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
FAIL_IF_LIB_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dig->e = e;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* check if a digest has been registered
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
cc = _gnutls_get_crypto_digest((gnutls_digest_algorithm_t)e->id);
|
|
Packit |
549fdc |
if (cc != NULL && cc->init) {
|
|
Packit |
549fdc |
if (cc->init((gnutls_digest_algorithm_t)e->id, &dig->handle) < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_HASH_FAILED;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dig->hash = cc->hash;
|
|
Packit |
549fdc |
dig->output = cc->output;
|
|
Packit |
549fdc |
dig->deinit = cc->deinit;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
result = _gnutls_digest_ops.init((gnutls_digest_algorithm_t)e->id, &dig->handle);
|
|
Packit |
549fdc |
if (result < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return result;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dig->hash = _gnutls_digest_ops.hash;
|
|
Packit |
549fdc |
dig->output = _gnutls_digest_ops.output;
|
|
Packit |
549fdc |
dig->deinit = _gnutls_digest_ops.deinit;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Returns true(non-zero) or false(0) if the
|
|
Packit |
549fdc |
* provided hash exists
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int _gnutls_digest_exists(gnutls_digest_algorithm_t algo)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
const gnutls_crypto_digest_st *cc = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cc = _gnutls_get_crypto_digest(algo);
|
|
Packit |
549fdc |
if (cc != NULL)
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return _gnutls_digest_ops.exists(algo);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
void _gnutls_hash_deinit(digest_hd_st * handle, void *digest)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (handle->handle == NULL) {
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (digest != NULL)
|
|
Packit |
549fdc |
_gnutls_hash_output(handle, digest);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
handle->deinit(handle->handle);
|
|
Packit |
549fdc |
handle->handle = NULL;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_hash_fast(gnutls_digest_algorithm_t algorithm,
|
|
Packit |
549fdc |
const void *text, size_t textlen, void *digest)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
const gnutls_crypto_digest_st *cc = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
FAIL_IF_LIB_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* check if a digest has been registered
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
cc = _gnutls_get_crypto_digest(algorithm);
|
|
Packit |
549fdc |
if (cc != NULL) {
|
|
Packit |
549fdc |
if (cc->fast(algorithm, text, textlen, digest) < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_HASH_FAILED;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_digest_ops.fast(algorithm, text, textlen, digest);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* HMAC interface */
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_mac_fast(gnutls_mac_algorithm_t algorithm, const void *key,
|
|
Packit |
549fdc |
int keylen, const void *text, size_t textlen,
|
|
Packit |
549fdc |
void *digest)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
const gnutls_crypto_mac_st *cc = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
FAIL_IF_LIB_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* check if a digest has been registered
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
cc = _gnutls_get_crypto_mac(algorithm);
|
|
Packit |
549fdc |
if (cc != NULL) {
|
|
Packit |
549fdc |
if (cc->
|
|
Packit |
549fdc |
fast(algorithm, NULL, 0, key, keylen, text, textlen,
|
|
Packit |
549fdc |
digest) < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_HASH_FAILED;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_mac_ops.fast(algorithm, NULL, 0, key, keylen, text,
|
|
Packit |
549fdc |
textlen, digest);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Returns true(non-zero) or false(0) if the
|
|
Packit |
549fdc |
* provided hash exists
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int _gnutls_mac_exists(gnutls_mac_algorithm_t algo)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
const gnutls_crypto_mac_st *cc = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* exceptionally it exists, as it is not a real MAC */
|
|
Packit |
549fdc |
if (algo == GNUTLS_MAC_AEAD)
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cc = _gnutls_get_crypto_mac(algo);
|
|
Packit |
549fdc |
if (cc != NULL)
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return _gnutls_mac_ops.exists(algo);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_mac_init(mac_hd_st * mac, const mac_entry_st * e,
|
|
Packit |
549fdc |
const void *key, int keylen)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int result;
|
|
Packit |
549fdc |
const gnutls_crypto_mac_st *cc = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
FAIL_IF_LIB_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (unlikely(e == NULL || e->id == GNUTLS_MAC_NULL))
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
mac->e = e;
|
|
Packit |
549fdc |
mac->mac_len = _gnutls_mac_get_algo_len(e);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* check if a digest has been registered
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
cc = _gnutls_get_crypto_mac(e->id);
|
|
Packit |
549fdc |
if (cc != NULL && cc->init != NULL) {
|
|
Packit |
549fdc |
if (cc->init(e->id, &mac->handle) < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_HASH_FAILED;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (cc->setkey(mac->handle, key, keylen) < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
cc->deinit(mac->handle);
|
|
Packit |
549fdc |
return GNUTLS_E_HASH_FAILED;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
mac->hash = cc->hash;
|
|
Packit |
549fdc |
mac->setnonce = cc->setnonce;
|
|
Packit |
549fdc |
mac->output = cc->output;
|
|
Packit |
549fdc |
mac->deinit = cc->deinit;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
result = _gnutls_mac_ops.init(e->id, &mac->handle);
|
|
Packit |
549fdc |
if (result < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return result;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
mac->hash = _gnutls_mac_ops.hash;
|
|
Packit |
549fdc |
mac->setnonce = _gnutls_mac_ops.setnonce;
|
|
Packit |
549fdc |
mac->output = _gnutls_mac_ops.output;
|
|
Packit |
549fdc |
mac->deinit = _gnutls_mac_ops.deinit;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (_gnutls_mac_ops.setkey(mac->handle, key, keylen) < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
mac->deinit(mac->handle);
|
|
Packit |
549fdc |
return GNUTLS_E_HASH_FAILED;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
void _gnutls_mac_deinit(mac_hd_st * handle, void *digest)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (handle->handle == NULL) {
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (digest)
|
|
Packit |
549fdc |
_gnutls_mac_output(handle, digest);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
handle->deinit(handle->handle);
|
|
Packit |
549fdc |
handle->handle = NULL;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#ifdef ENABLE_SSL3
|
|
Packit |
549fdc |
inline static int get_padsize(gnutls_mac_algorithm_t algorithm)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
switch (algorithm) {
|
|
Packit |
549fdc |
case GNUTLS_MAC_MD5:
|
|
Packit |
549fdc |
return 48;
|
|
Packit |
549fdc |
case GNUTLS_MAC_SHA1:
|
|
Packit |
549fdc |
return 40;
|
|
Packit |
549fdc |
default:
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Special functions for SSL3 MAC
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_mac_init_ssl3(digest_hd_st * ret, const mac_entry_st * e,
|
|
Packit |
549fdc |
void *key, int keylen)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
uint8_t ipad[48];
|
|
Packit |
549fdc |
int padsize, result;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
FAIL_IF_LIB_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
padsize = get_padsize(e->id);
|
|
Packit |
549fdc |
if (padsize == 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_HASH_FAILED;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memset(ipad, 0x36, padsize);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
result = _gnutls_hash_init(ret, e);
|
|
Packit |
549fdc |
if (result < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return result;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret->key = key;
|
|
Packit |
549fdc |
ret->keysize = keylen;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (keylen > 0)
|
|
Packit |
549fdc |
_gnutls_hash(ret, key, keylen);
|
|
Packit |
549fdc |
_gnutls_hash(ret, ipad, padsize);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int _gnutls_mac_output_ssl3(digest_hd_st * handle, void *digest)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
uint8_t ret[MAX_HASH_SIZE];
|
|
Packit |
549fdc |
digest_hd_st td;
|
|
Packit |
549fdc |
uint8_t opad[48];
|
|
Packit |
549fdc |
int padsize;
|
|
Packit |
549fdc |
int block, rc;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
padsize = get_padsize(handle->e->id);
|
|
Packit |
549fdc |
if (padsize == 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_INTERNAL_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memset(opad, 0x5C, padsize);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
rc = _gnutls_hash_init(&td, handle->e);
|
|
Packit |
549fdc |
if (rc < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return rc;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (handle->keysize > 0)
|
|
Packit |
549fdc |
_gnutls_hash(&td, handle->key, handle->keysize);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_hash(&td, opad, padsize);
|
|
Packit |
549fdc |
block = _gnutls_mac_get_algo_len(handle->e);
|
|
Packit |
549fdc |
_gnutls_hash_output(handle, ret); /* get the previous hash */
|
|
Packit |
549fdc |
_gnutls_hash(&td, ret, block);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_hash_deinit(&td, digest);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* reset handle */
|
|
Packit |
549fdc |
memset(opad, 0x36, padsize);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (handle->keysize > 0)
|
|
Packit |
549fdc |
_gnutls_hash(handle, handle->key, handle->keysize);
|
|
Packit |
549fdc |
_gnutls_hash(handle, opad, padsize);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int _gnutls_mac_deinit_ssl3(digest_hd_st * handle, void *digest)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (digest != NULL)
|
|
Packit |
549fdc |
ret = _gnutls_mac_output_ssl3(handle, digest);
|
|
Packit |
549fdc |
_gnutls_hash_deinit(handle, NULL);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_mac_deinit_ssl3_handshake(digest_hd_st * handle,
|
|
Packit |
549fdc |
void *digest, uint8_t * key,
|
|
Packit |
549fdc |
uint32_t key_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
uint8_t ret[MAX_HASH_SIZE];
|
|
Packit |
549fdc |
digest_hd_st td;
|
|
Packit |
549fdc |
uint8_t opad[48];
|
|
Packit |
549fdc |
uint8_t ipad[48];
|
|
Packit |
549fdc |
int padsize;
|
|
Packit |
549fdc |
int block, rc;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
padsize = get_padsize(handle->e->id);
|
|
Packit |
549fdc |
if (padsize == 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
rc = GNUTLS_E_INTERNAL_ERROR;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memset(opad, 0x5C, padsize);
|
|
Packit |
549fdc |
memset(ipad, 0x36, padsize);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
rc = _gnutls_hash_init(&td, handle->e);
|
|
Packit |
549fdc |
if (rc < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (key_size > 0)
|
|
Packit |
549fdc |
_gnutls_hash(&td, key, key_size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_hash(&td, opad, padsize);
|
|
Packit |
549fdc |
block = _gnutls_mac_get_algo_len(handle->e);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (key_size > 0)
|
|
Packit |
549fdc |
_gnutls_hash(handle, key, key_size);
|
|
Packit |
549fdc |
_gnutls_hash(handle, ipad, padsize);
|
|
Packit |
549fdc |
_gnutls_hash_deinit(handle, ret); /* get the previous hash */
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_hash(&td, ret, block);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_hash_deinit(&td, digest);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
_gnutls_hash_deinit(handle, NULL);
|
|
Packit |
549fdc |
return rc;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
ssl3_sha(int i, uint8_t * secret, int secret_len,
|
|
Packit |
549fdc |
uint8_t * rnd, int rnd_len, void *digest)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int j, ret;
|
|
Packit |
549fdc |
uint8_t text1[26];
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
digest_hd_st td;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (j = 0; j < i + 1; j++) {
|
|
Packit |
549fdc |
text1[j] = 65 + i; /* A==65 */
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_SHA1));
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_hash(&td, text1, i + 1);
|
|
Packit |
549fdc |
_gnutls_hash(&td, secret, secret_len);
|
|
Packit |
549fdc |
_gnutls_hash(&td, rnd, rnd_len);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_hash_deinit(&td, digest);
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#define SHA1_DIGEST_OUTPUT 20
|
|
Packit |
549fdc |
#define MD5_DIGEST_OUTPUT 16
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
ssl3_md5(int i, uint8_t * secret, int secret_len,
|
|
Packit |
549fdc |
uint8_t * rnd, int rnd_len, void *digest)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
uint8_t tmp[MAX_HASH_SIZE];
|
|
Packit |
549fdc |
digest_hd_st td;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_hash(&td, secret, secret_len);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = ssl3_sha(i, secret, secret_len, rnd, rnd_len, tmp);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
_gnutls_hash_deinit(&td, digest);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_hash(&td, tmp, SHA1_DIGEST_OUTPUT);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_hash_deinit(&td, digest);
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_ssl3_generate_random(void *secret, int secret_len,
|
|
Packit |
549fdc |
void *rnd, int rnd_len,
|
|
Packit |
549fdc |
int ret_bytes, uint8_t * ret)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int i = 0, copy, output_bytes;
|
|
Packit |
549fdc |
uint8_t digest[MAX_HASH_SIZE];
|
|
Packit |
549fdc |
int block = MD5_DIGEST_OUTPUT;
|
|
Packit |
549fdc |
int result, times;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
output_bytes = 0;
|
|
Packit |
549fdc |
do {
|
|
Packit |
549fdc |
output_bytes += block;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
while (output_bytes < ret_bytes);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
times = output_bytes / block;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; i < times; i++) {
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
result =
|
|
Packit |
549fdc |
ssl3_md5(i, secret, secret_len, rnd, rnd_len, digest);
|
|
Packit |
549fdc |
if (result < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return result;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if ((1 + i) * block < ret_bytes) {
|
|
Packit |
549fdc |
copy = block;
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
copy = ret_bytes - (i) * block;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memcpy(&ret[i * block], digest, copy);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#endif
|