Blame lib/hash_int.c

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