Blame lib/srp.c

Packit Service 4684c1
/*
Packit Service 4684c1
 * Copyright (C) 2001-2016 Free Software Foundation, Inc.
Packit Service 4684c1
 * Copyright (C) 2015-2016 Red Hat, Inc.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Author: Nikos Mavrogiannopoulos
Packit Service 4684c1
 *
Packit Service 4684c1
 * This file is part of GnuTLS.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The GnuTLS is free software; you can redistribute it and/or
Packit Service 4684c1
 * modify it under the terms of the GNU Lesser General Public License
Packit Service 4684c1
 * as published by the Free Software Foundation; either version 2.1 of
Packit Service 4684c1
 * the License, or (at your option) any later version.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This library is distributed in the hope that it will be useful, but
Packit Service 4684c1
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4684c1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 4684c1
 * Lesser General Public License for more details.
Packit Service 4684c1
 *
Packit Service 4684c1
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 4684c1
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
Packit Service 4684c1
 *
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
#include "gnutls_int.h"
Packit Service 4684c1
#include "errors.h"
Packit Service 4684c1
#include <auth/srp_kx.h>
Packit Service 4684c1
#include <state.h>
Packit Service 4684c1
Packit Service 4684c1
#ifdef ENABLE_SRP
Packit Service 4684c1
Packit Service 4684c1
#include "srp.h"
Packit Service 4684c1
#include <auth/srp_passwd.h>
Packit Service 4684c1
#include <mpi.h>
Packit Service 4684c1
#include <num.h>
Packit Service 4684c1
#include <file.h>
Packit Service 4684c1
#include <algorithms.h>
Packit Service 4684c1
#include <random.h>
Packit Service 4684c1
Packit Service 4684c1
#include "debug.h"
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/* Here functions for SRP (like g^x mod n) are defined 
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
static int
Packit Service 4684c1
_gnutls_srp_gx(uint8_t * text, size_t textsize, uint8_t ** result,
Packit Service 4684c1
	       bigint_t g, bigint_t prime)
Packit Service 4684c1
{
Packit Service 4684c1
	bigint_t x, e = NULL;
Packit Service 4684c1
	size_t result_size;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
Packit Service 4684c1
	if (_gnutls_mpi_init_scan_nz(&x, text, textsize)) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_MPI_SCAN_FAILED;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_init(&e);
Packit Service 4684c1
	if (ret < 0)
Packit Service 4684c1
		goto cleanup;
Packit Service 4684c1
Packit Service 4684c1
	/* e = g^x mod prime (n) */
Packit Service 4684c1
	ret = _gnutls_mpi_powm(e, g, x, prime);
Packit Service 4684c1
	if (ret < 0)
Packit Service 4684c1
		goto cleanup;
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_print(e, NULL, &result_size);
Packit Service 4684c1
	if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
Packit Service 4684c1
		*result = gnutls_malloc(result_size);
Packit Service 4684c1
		if ((*result) == NULL) {
Packit Service 4684c1
			ret = GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
			goto cleanup;
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		ret = _gnutls_mpi_print(e, *result, &result_size);
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			goto cleanup;
Packit Service 4684c1
Packit Service 4684c1
		ret = result_size;
Packit Service 4684c1
	} else {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		ret = GNUTLS_E_MPI_PRINT_FAILED;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
cleanup:
Packit Service 4684c1
	_gnutls_mpi_release(&e);
Packit Service 4684c1
	_gnutls_mpi_release(&x);
Packit Service 4684c1
Packit Service 4684c1
	return ret;
Packit Service 4684c1
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/****************
Packit Service 4684c1
 * Choose a random value b and calculate B = (k* v + g^b) % N.
Packit Service 4684c1
 * where k == SHA1(N|g)
Packit Service 4684c1
 * Return: B and if ret_b is not NULL b.
Packit Service 4684c1
 */
Packit Service 4684c1
bigint_t
Packit Service 4684c1
_gnutls_calc_srp_B(bigint_t * ret_b, bigint_t g, bigint_t n, bigint_t v)
Packit Service 4684c1
{
Packit Service 4684c1
	bigint_t tmpB = NULL, tmpV = NULL;
Packit Service 4684c1
	bigint_t b = NULL, B = NULL, k = NULL;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
Packit Service 4684c1
	/* calculate:  B = (k*v + g^b) % N 
Packit Service 4684c1
	 */
Packit Service 4684c1
	ret = _gnutls_mpi_init_multi(&tmpV, &tmpB, &B, &b, NULL);
Packit Service 4684c1
	if (ret < 0)
Packit Service 4684c1
		return NULL;
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_mpi_random_modp(b, n, GNUTLS_RND_RANDOM);
Packit Service 4684c1
Packit Service 4684c1
	k = _gnutls_calc_srp_u(n, g, n);
Packit Service 4684c1
	if (k == NULL) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto error;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_mulm(tmpV, k, v, n);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto error;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_powm(tmpB, g, b, n);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto error;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_addm(B, tmpV, tmpB, n);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto error;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_mpi_release(&k);
Packit Service 4684c1
	_gnutls_mpi_release(&tmpB);
Packit Service 4684c1
	_gnutls_mpi_release(&tmpV);
Packit Service 4684c1
Packit Service 4684c1
	if (ret_b)
Packit Service 4684c1
		*ret_b = b;
Packit Service 4684c1
	else
Packit Service 4684c1
		_gnutls_mpi_release(&b);
Packit Service 4684c1
Packit Service 4684c1
	return B;
Packit Service 4684c1
Packit Service 4684c1
      error:
Packit Service 4684c1
	_gnutls_mpi_release(&b);
Packit Service 4684c1
	_gnutls_mpi_release(&B);
Packit Service 4684c1
	_gnutls_mpi_release(&k);
Packit Service 4684c1
	_gnutls_mpi_release(&tmpB);
Packit Service 4684c1
	_gnutls_mpi_release(&tmpV);
Packit Service 4684c1
	return NULL;
Packit Service 4684c1
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* This calculates the SHA1(A | B)
Packit Service 4684c1
 * A and B will be left-padded with zeros to fill n_size.
Packit Service 4684c1
 */
Packit Service 4684c1
bigint_t _gnutls_calc_srp_u(bigint_t A, bigint_t B, bigint_t n)
Packit Service 4684c1
{
Packit Service 4684c1
	size_t b_size, a_size;
Packit Service 4684c1
	uint8_t *holder, hd[MAX_HASH_SIZE];
Packit Service 4684c1
	size_t holder_size, hash_size, n_size;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
	bigint_t res;
Packit Service 4684c1
Packit Service 4684c1
	/* get the size of n in bytes */
Packit Service 4684c1
	_gnutls_mpi_print(n, NULL, &n_size);
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_mpi_print(A, NULL, &a_size);
Packit Service 4684c1
	_gnutls_mpi_print(B, NULL, &b_size);
Packit Service 4684c1
Packit Service 4684c1
	if (a_size > n_size || b_size > n_size) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return NULL;	/* internal error */
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	holder_size = n_size + n_size;
Packit Service 4684c1
Packit Service 4684c1
	holder = gnutls_calloc(1, holder_size);
Packit Service 4684c1
	if (holder == NULL)
Packit Service 4684c1
		return NULL;
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_mpi_print(A, &holder[n_size - a_size], &a_size);
Packit Service 4684c1
	_gnutls_mpi_print(B, &holder[n_size + n_size - b_size], &b_size);
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_hash_fast(GNUTLS_DIG_SHA1, holder, holder_size, hd);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_free(holder);
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return NULL;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	/* convert the bytes of hd to integer
Packit Service 4684c1
	 */
Packit Service 4684c1
	hash_size = 20;		/* SHA */
Packit Service 4684c1
	ret = _gnutls_mpi_init_scan_nz(&res, hd, hash_size);
Packit Service 4684c1
	gnutls_free(holder);
Packit Service 4684c1
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return NULL;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return res;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* S = (A * v^u) ^ b % N 
Packit Service 4684c1
 * this is our shared key (server premaster secret)
Packit Service 4684c1
 */
Packit Service 4684c1
bigint_t
Packit Service 4684c1
_gnutls_calc_srp_S1(bigint_t A, bigint_t b, bigint_t u, bigint_t v,
Packit Service 4684c1
		    bigint_t n)
Packit Service 4684c1
{
Packit Service 4684c1
	bigint_t tmp1 = NULL, tmp2 = NULL;
Packit Service 4684c1
	bigint_t S = NULL;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_init_multi(&S, &tmp1, &tmp2, NULL);
Packit Service 4684c1
	if (ret < 0)
Packit Service 4684c1
		return NULL;
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_powm(tmp1, v, u, n);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto error;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_mulm(tmp2, A, tmp1, n);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto error;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_mpi_powm(S, tmp2, b, n);
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_mpi_release(&tmp1);
Packit Service 4684c1
	_gnutls_mpi_release(&tmp2);
Packit Service 4684c1
Packit Service 4684c1
	return S;
Packit Service 4684c1
Packit Service 4684c1
error:
Packit Service 4684c1
	_gnutls_mpi_release(&S);
Packit Service 4684c1
	_gnutls_mpi_release(&tmp1);
Packit Service 4684c1
	_gnutls_mpi_release(&tmp2);
Packit Service 4684c1
	return NULL;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* A = g^a % N 
Packit Service 4684c1
 * returns A and a (which is random)
Packit Service 4684c1
 */
Packit Service 4684c1
bigint_t _gnutls_calc_srp_A(bigint_t * a, bigint_t g, bigint_t n)
Packit Service 4684c1
{
Packit Service 4684c1
	bigint_t tmpa;
Packit Service 4684c1
	bigint_t A;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_init_multi(&A, &tmpa, NULL);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return NULL;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_mpi_random_modp(tmpa, n, GNUTLS_RND_RANDOM);
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_powm(A, g, tmpa, n);
Packit Service 4684c1
	if (ret < 0)
Packit Service 4684c1
		goto error;
Packit Service 4684c1
Packit Service 4684c1
	if (a != NULL)
Packit Service 4684c1
		*a = tmpa;
Packit Service 4684c1
	else
Packit Service 4684c1
		_gnutls_mpi_release(&tmpa);
Packit Service 4684c1
Packit Service 4684c1
	return A;
Packit Service 4684c1
error:
Packit Service 4684c1
	_gnutls_mpi_release(&tmpa);
Packit Service 4684c1
	_gnutls_mpi_release(&A);
Packit Service 4684c1
	return NULL;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* generate x = SHA(s | SHA(U | ":" | p))
Packit Service 4684c1
 * The output is exactly 20 bytes
Packit Service 4684c1
 */
Packit Service 4684c1
static int
Packit Service 4684c1
_gnutls_calc_srp_sha(const char *username, const char *_password,
Packit Service 4684c1
		     uint8_t * salt, int salt_size, size_t * size,
Packit Service 4684c1
		     void *digest, unsigned allow_invalid_pass)
Packit Service 4684c1
{
Packit Service 4684c1
	digest_hd_st td;
Packit Service 4684c1
	uint8_t res[MAX_HASH_SIZE];
Packit Service 4684c1
	int ret;
Packit Service 4684c1
	const mac_entry_st *me = mac_to_entry(GNUTLS_MAC_SHA1);
Packit Service 4684c1
	char *password;
Packit Service 4684c1
	gnutls_datum_t pout;
Packit Service 4684c1
Packit Service 4684c1
	*size = 20;
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_utf8_password_normalize(_password, strlen(_password), &pout, allow_invalid_pass);
Packit Service 4684c1
	if (ret < 0)
Packit Service 4684c1
		return gnutls_assert_val(ret);
Packit Service 4684c1
	password = (char*)pout.data;
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_hash_init(&td, me);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		ret = GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
		goto cleanup;
Packit Service 4684c1
	}
Packit Service 4684c1
	_gnutls_hash(&td, username, strlen(username));
Packit Service 4684c1
	_gnutls_hash(&td, ":", 1);
Packit Service 4684c1
	_gnutls_hash(&td, password, strlen(password));
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_hash_deinit(&td, res);
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_hash_init(&td, me);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		ret = GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
		goto cleanup;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_hash(&td, salt, salt_size);
Packit Service 4684c1
	_gnutls_hash(&td, res, 20);	/* 20 bytes is the output of sha1 */
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_hash_deinit(&td, digest);
Packit Service 4684c1
	ret = 0;
Packit Service 4684c1
Packit Service 4684c1
 cleanup:
Packit Service 4684c1
	gnutls_free(password);
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
int
Packit Service 4684c1
_gnutls_calc_srp_x(char *username, char *password, uint8_t * salt,
Packit Service 4684c1
		   size_t salt_size, size_t * size, void *digest)
Packit Service 4684c1
{
Packit Service 4684c1
Packit Service 4684c1
	return _gnutls_calc_srp_sha(username, password, salt,
Packit Service 4684c1
				    salt_size, size, digest, 1);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/* S = (B - k*g^x) ^ (a + u * x) % N
Packit Service 4684c1
 * this is our shared key (client premaster secret)
Packit Service 4684c1
 */
Packit Service 4684c1
bigint_t
Packit Service 4684c1
_gnutls_calc_srp_S2(bigint_t B, bigint_t g, bigint_t x, bigint_t a,
Packit Service 4684c1
		    bigint_t u, bigint_t n)
Packit Service 4684c1
{
Packit Service 4684c1
	bigint_t S = NULL, tmp1 = NULL, tmp2 = NULL;
Packit Service 4684c1
	bigint_t tmp4 = NULL, tmp3 = NULL, k = NULL;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_init_multi(&S, &tmp1, &tmp2, &tmp3, &tmp4, NULL);
Packit Service 4684c1
	if (ret < 0)
Packit Service 4684c1
		return NULL;
Packit Service 4684c1
Packit Service 4684c1
	k = _gnutls_calc_srp_u(n, g, n);
Packit Service 4684c1
	if (k == NULL) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto freeall;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_powm(tmp1, g, x, n);	/* g^x */
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto freeall;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_mulm(tmp3, tmp1, k, n);	/* k*g^x mod n */
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto freeall;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_subm(tmp2, B, tmp3, n);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto freeall;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_mul(tmp1, u, x);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto freeall;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_add(tmp4, a, tmp1);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto freeall;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_mpi_powm(S, tmp2, tmp4, n);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto freeall;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_mpi_release(&tmp1);
Packit Service 4684c1
	_gnutls_mpi_release(&tmp2);
Packit Service 4684c1
	_gnutls_mpi_release(&tmp3);
Packit Service 4684c1
	_gnutls_mpi_release(&tmp4);
Packit Service 4684c1
	_gnutls_mpi_release(&k);
Packit Service 4684c1
Packit Service 4684c1
	return S;
Packit Service 4684c1
Packit Service 4684c1
      freeall:
Packit Service 4684c1
	_gnutls_mpi_release(&k);
Packit Service 4684c1
	_gnutls_mpi_release(&tmp1);
Packit Service 4684c1
	_gnutls_mpi_release(&tmp2);
Packit Service 4684c1
	_gnutls_mpi_release(&tmp3);
Packit Service 4684c1
	_gnutls_mpi_release(&tmp4);
Packit Service 4684c1
	_gnutls_mpi_release(&S);
Packit Service 4684c1
	return NULL;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_free_client_credentials:
Packit Service 4684c1
 * @sc: is a #gnutls_srp_client_credentials_t type.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Free a gnutls_srp_client_credentials_t structure.
Packit Service 4684c1
 **/
Packit Service 4684c1
void gnutls_srp_free_client_credentials(gnutls_srp_client_credentials_t sc)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_free(sc->username);
Packit Service 4684c1
	gnutls_free(sc->password);
Packit Service 4684c1
	gnutls_free(sc);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_allocate_client_credentials:
Packit Service 4684c1
 * @sc: is a pointer to a #gnutls_srp_server_credentials_t type.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Allocate a gnutls_srp_client_credentials_t structure.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
Packit Service 4684c1
 *   error code.
Packit Service 4684c1
 **/
Packit Service 4684c1
int
Packit Service 4684c1
gnutls_srp_allocate_client_credentials(gnutls_srp_client_credentials_t *
Packit Service 4684c1
				       sc)
Packit Service 4684c1
{
Packit Service 4684c1
	*sc = gnutls_calloc(1, sizeof(srp_client_credentials_st));
Packit Service 4684c1
Packit Service 4684c1
	if (*sc == NULL)
Packit Service 4684c1
		return GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
Packit Service 4684c1
	return 0;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_set_client_credentials:
Packit Service 4684c1
 * @res: is a #gnutls_srp_client_credentials_t type.
Packit Service 4684c1
 * @username: is the user's userid
Packit Service 4684c1
 * @password: is the user's password
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function sets the username and password, in a
Packit Service 4684c1
 * #gnutls_srp_client_credentials_t type.  Those will be used in
Packit Service 4684c1
 * SRP authentication.  @username should be an ASCII string or UTF-8
Packit Service 4684c1
 * string. In case of a UTF-8 string it is recommended to be following
Packit Service 4684c1
 * the PRECIS framework for usernames (rfc8265). The password can
Packit Service 4684c1
 * be in ASCII format, or normalized using gnutls_utf8_password_normalize().
Packit Service 4684c1
Packit Service 4684c1
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
Packit Service 4684c1
 *   error code.
Packit Service 4684c1
 **/
Packit Service 4684c1
int
Packit Service 4684c1
gnutls_srp_set_client_credentials(gnutls_srp_client_credentials_t res,
Packit Service 4684c1
				  const char *username,
Packit Service 4684c1
				  const char *password)
Packit Service 4684c1
{
Packit Service 4684c1
Packit Service 4684c1
	if (username == NULL || password == NULL) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_INVALID_REQUEST;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	res->username = gnutls_strdup(username);
Packit Service 4684c1
	if (res->username == NULL)
Packit Service 4684c1
		return GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
Packit Service 4684c1
	res->password = gnutls_strdup(password);
Packit Service 4684c1
	if (res->password == NULL) {
Packit Service 4684c1
		gnutls_free(res->username);
Packit Service 4684c1
		return GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return 0;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_free_server_credentials:
Packit Service 4684c1
 * @sc: is a #gnutls_srp_server_credentials_t type.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Free a gnutls_srp_server_credentials_t structure.
Packit Service 4684c1
 **/
Packit Service 4684c1
void gnutls_srp_free_server_credentials(gnutls_srp_server_credentials_t sc)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_free(sc->password_file);
Packit Service 4684c1
	gnutls_free(sc->password_conf_file);
Packit Service 4684c1
Packit Service 4684c1
	gnutls_free(sc);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Size of the default (random) seed if
Packit Service 4684c1
 * gnutls_srp_set_server_fake_salt_seed() is not called to set
Packit Service 4684c1
 * a seed.
Packit Service 4684c1
 */
Packit Service 4684c1
#define DEFAULT_FAKE_SALT_SEED_SIZE 20
Packit Service 4684c1
Packit Service 4684c1
/* Size of the fake salts generated if
Packit Service 4684c1
 * gnutls_srp_set_server_fake_salt_seed() is not called to set
Packit Service 4684c1
 * another size.
Packit Service 4684c1
 */
Packit Service 4684c1
#define DEFAULT_FAKE_SALT_SIZE 16
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_allocate_server_credentials:
Packit Service 4684c1
 * @sc: is a pointer to a #gnutls_srp_server_credentials_t type.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Allocate a gnutls_srp_server_credentials_t structure.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
Packit Service 4684c1
 *   error code.
Packit Service 4684c1
 **/
Packit Service 4684c1
int
Packit Service 4684c1
gnutls_srp_allocate_server_credentials(gnutls_srp_server_credentials_t *
Packit Service 4684c1
				       sc)
Packit Service 4684c1
{
Packit Service 4684c1
	int ret;
Packit Service 4684c1
	*sc = gnutls_calloc(1, sizeof(srp_server_cred_st));
Packit Service 4684c1
Packit Service 4684c1
	if (*sc == NULL)
Packit Service 4684c1
		return GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
Packit Service 4684c1
	(*sc)->fake_salt_seed_size = DEFAULT_FAKE_SALT_SEED_SIZE;
Packit Service 4684c1
	ret = gnutls_rnd(GNUTLS_RND_RANDOM, (*sc)->fake_salt_seed,
Packit Service 4684c1
			 DEFAULT_FAKE_SALT_SEED_SIZE);
Packit Service 4684c1
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		goto cleanup;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	(*sc)->fake_salt_length = DEFAULT_FAKE_SALT_SIZE;
Packit Service 4684c1
	return 0;
Packit Service 4684c1
Packit Service 4684c1
cleanup:
Packit Service 4684c1
	gnutls_free(*sc);
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_set_server_credentials_file:
Packit Service 4684c1
 * @res: is a #gnutls_srp_server_credentials_t type.
Packit Service 4684c1
 * @password_file: is the SRP password file (tpasswd)
Packit Service 4684c1
 * @password_conf_file: is the SRP password conf file (tpasswd.conf)
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function sets the password files, in a
Packit Service 4684c1
 * #gnutls_srp_server_credentials_t type.  Those password files
Packit Service 4684c1
 * hold usernames and verifiers and will be used for SRP
Packit Service 4684c1
 * authentication.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
Packit Service 4684c1
 *   error code.
Packit Service 4684c1
 **/
Packit Service 4684c1
int
Packit Service 4684c1
gnutls_srp_set_server_credentials_file(gnutls_srp_server_credentials_t res,
Packit Service 4684c1
				       const char *password_file,
Packit Service 4684c1
				       const char *password_conf_file)
Packit Service 4684c1
{
Packit Service 4684c1
Packit Service 4684c1
	if (password_file == NULL || password_conf_file == NULL) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_INVALID_REQUEST;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	/* Check if the files can be opened */
Packit Service 4684c1
	if (_gnutls_file_exists(password_file) != 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_FILE_ERROR;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	if (_gnutls_file_exists(password_conf_file) != 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_FILE_ERROR;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	res->password_file = gnutls_strdup(password_file);
Packit Service 4684c1
	if (res->password_file == NULL) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	res->password_conf_file = gnutls_strdup(password_conf_file);
Packit Service 4684c1
	if (res->password_conf_file == NULL) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		gnutls_free(res->password_file);
Packit Service 4684c1
		return GNUTLS_E_MEMORY_ERROR;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return 0;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_set_server_credentials_function:
Packit Service 4684c1
 * @cred: is a #gnutls_srp_server_credentials_t type.
Packit Service 4684c1
 * @func: is the callback function
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function can be used to set a callback to retrieve the user's
Packit Service 4684c1
 * SRP credentials.  The callback's function form is:
Packit Service 4684c1
 *
Packit Service 4684c1
 * int (*callback)(gnutls_session_t, const char* username,
Packit Service 4684c1
 *  gnutls_datum_t *salt, gnutls_datum_t *verifier, gnutls_datum_t *generator,
Packit Service 4684c1
 *  gnutls_datum_t *prime);
Packit Service 4684c1
 *
Packit Service 4684c1
 * @username contains the actual username.
Packit Service 4684c1
 * The @salt, @verifier, @generator and @prime must be filled
Packit Service 4684c1
 * in using the gnutls_malloc(). For convenience @prime and @generator
Packit Service 4684c1
 * may also be one of the static parameters defined in gnutls.h.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Initially, the data field is NULL in every #gnutls_datum_t
Packit Service 4684c1
 * structure that the callback has to fill in. When the
Packit Service 4684c1
 * callback is done GnuTLS deallocates all of those buffers
Packit Service 4684c1
 * which are non-NULL, regardless of the return value.
Packit Service 4684c1
 *
Packit Service 4684c1
 * In order to prevent attackers from guessing valid usernames,
Packit Service 4684c1
 * if a user does not exist, g and n values should be filled in
Packit Service 4684c1
 * using a random user's parameters. In that case the callback must
Packit Service 4684c1
 * return the special value (1).
Packit Service 4684c1
 * See #gnutls_srp_set_server_fake_salt_seed too.
Packit Service 4684c1
 * If this is not required for your application, return a negative
Packit Service 4684c1
 * number from the callback to abort the handshake.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The callback function will only be called once per handshake.
Packit Service 4684c1
 * The callback function should return 0 on success, while
Packit Service 4684c1
 * -1 indicates an error.
Packit Service 4684c1
 **/
Packit Service 4684c1
void
Packit Service 4684c1
gnutls_srp_set_server_credentials_function(gnutls_srp_server_credentials_t
Packit Service 4684c1
					   cred,
Packit Service 4684c1
					   gnutls_srp_server_credentials_function
Packit Service 4684c1
					   *func)
Packit Service 4684c1
{
Packit Service 4684c1
	cred->pwd_callback = func;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_set_client_credentials_function:
Packit Service 4684c1
 * @cred: is a #gnutls_srp_server_credentials_t type.
Packit Service 4684c1
 * @func: is the callback function
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function can be used to set a callback to retrieve the
Packit Service 4684c1
 * username and password for client SRP authentication.  The
Packit Service 4684c1
 * callback's function form is:
Packit Service 4684c1
 *
Packit Service 4684c1
 * int (*callback)(gnutls_session_t, char** username, char**password);
Packit Service 4684c1
 *
Packit Service 4684c1
 * The @username and @password must be allocated using
Packit Service 4684c1
 * gnutls_malloc().
Packit Service 4684c1
 *
Packit Service 4684c1
 * The @username should be an ASCII string or UTF-8
Packit Service 4684c1
 * string. In case of a UTF-8 string it is recommended to be following
Packit Service 4684c1
 * the PRECIS framework for usernames (rfc8265). The password can
Packit Service 4684c1
 * be in ASCII format, or normalized using gnutls_utf8_password_normalize().
Packit Service 4684c1
 *
Packit Service 4684c1
 * The callback function will be called once per handshake before the
Packit Service 4684c1
 * initial hello message is sent.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The callback should not return a negative error code the second
Packit Service 4684c1
 * time called, since the handshake procedure will be aborted.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The callback function should return 0 on success.
Packit Service 4684c1
 * -1 indicates an error.
Packit Service 4684c1
 **/
Packit Service 4684c1
void
Packit Service 4684c1
gnutls_srp_set_client_credentials_function(gnutls_srp_client_credentials_t
Packit Service 4684c1
					   cred,
Packit Service 4684c1
					   gnutls_srp_client_credentials_function
Packit Service 4684c1
					   * func)
Packit Service 4684c1
{
Packit Service 4684c1
	cred->get_function = func;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_server_get_username:
Packit Service 4684c1
 * @session: is a gnutls session
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function will return the username of the peer.  This should
Packit Service 4684c1
 * only be called in case of SRP authentication and in case of a
Packit Service 4684c1
 * server.  Returns NULL in case of an error.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: SRP username of the peer, or NULL in case of error.
Packit Service 4684c1
 **/
Packit Service 4684c1
const char *gnutls_srp_server_get_username(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	srp_server_auth_info_t info;
Packit Service 4684c1
Packit Service 4684c1
	CHECK_AUTH_TYPE(GNUTLS_CRD_SRP, NULL);
Packit Service 4684c1
Packit Service 4684c1
	info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
Packit Service 4684c1
	if (info == NULL)
Packit Service 4684c1
		return NULL;
Packit Service 4684c1
	return info->username;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_verifier:
Packit Service 4684c1
 * @username: is the user's name
Packit Service 4684c1
 * @password: is the user's password
Packit Service 4684c1
 * @salt: should be some randomly generated bytes
Packit Service 4684c1
 * @generator: is the generator of the group
Packit Service 4684c1
 * @prime: is the group's prime
Packit Service 4684c1
 * @res: where the verifier will be stored.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function will create an SRP verifier, as specified in
Packit Service 4684c1
 * RFC2945.  The @prime and @generator should be one of the static
Packit Service 4684c1
 * parameters defined in gnutls/gnutls.h or may be generated.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The verifier will be allocated with @gnutls_malloc() and will be stored in
Packit Service 4684c1
 * @res using binary format.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
Packit Service 4684c1
 *   error code.
Packit Service 4684c1
 **/
Packit Service 4684c1
int
Packit Service 4684c1
gnutls_srp_verifier(const char *username, const char *password,
Packit Service 4684c1
		    const gnutls_datum_t * salt,
Packit Service 4684c1
		    const gnutls_datum_t * generator,
Packit Service 4684c1
		    const gnutls_datum_t * prime, gnutls_datum_t * res)
Packit Service 4684c1
{
Packit Service 4684c1
	bigint_t _n, _g;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
	size_t digest_size = 20, size;
Packit Service 4684c1
	uint8_t digest[20];
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_calc_srp_sha(username, password, salt->data,
Packit Service 4684c1
				   salt->size, &digest_size, digest, 0);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return ret;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	size = prime->size;
Packit Service 4684c1
	if (_gnutls_mpi_init_scan_nz(&_n, prime->data, size)) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_MPI_SCAN_FAILED;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	size = generator->size;
Packit Service 4684c1
	if (_gnutls_mpi_init_scan_nz(&_g, generator->data, size)) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		_gnutls_mpi_release(&_n);
Packit Service 4684c1
		return GNUTLS_E_MPI_SCAN_FAILED;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_srp_gx(digest, 20, &res->data, _g, _n);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		_gnutls_mpi_release(&_n);
Packit Service 4684c1
		_gnutls_mpi_release(&_g);
Packit Service 4684c1
		return ret;
Packit Service 4684c1
	}
Packit Service 4684c1
	res->size = ret;
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_mpi_release(&_n);
Packit Service 4684c1
	_gnutls_mpi_release(&_g);
Packit Service 4684c1
Packit Service 4684c1
	return 0;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_set_prime_bits:
Packit Service 4684c1
 * @session: is a #gnutls_session_t type.
Packit Service 4684c1
 * @bits: is the number of bits
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function sets the minimum accepted number of bits, for use in
Packit Service 4684c1
 * an SRP key exchange.  If zero, the default 2048 bits will be used.
Packit Service 4684c1
 *
Packit Service 4684c1
 * In the client side it sets the minimum accepted number of bits.  If
Packit Service 4684c1
 * a server sends a prime with less bits than that
Packit Service 4684c1
 * %GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER will be returned by the
Packit Service 4684c1
 * handshake.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function has no effect in server side.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Since: 2.6.0
Packit Service 4684c1
 **/
Packit Service 4684c1
void gnutls_srp_set_prime_bits(gnutls_session_t session, unsigned int bits)
Packit Service 4684c1
{
Packit Service 4684c1
	session->internals.dh_prime_bits = bits;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_srp_set_server_fake_salt_seed:
Packit Service 4684c1
 * @cred: is a #gnutls_srp_server_credentials_t type
Packit Service 4684c1
 * @seed: is the seed data, only needs to be valid until the function
Packit Service 4684c1
 * returns; size of the seed must be greater than zero
Packit Service 4684c1
 * @salt_length: is the length of the generated fake salts
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function sets the seed that is used to generate salts for
Packit Service 4684c1
 * invalid (non-existent) usernames.
Packit Service 4684c1
 *
Packit Service 4684c1
 * In order to prevent attackers from guessing valid usernames,
Packit Service 4684c1
 * when a user does not exist gnutls generates a salt and a verifier
Packit Service 4684c1
 * and proceeds with the protocol as usual.
Packit Service 4684c1
 * The authentication will ultimately fail, but the client cannot tell
Packit Service 4684c1
 * whether the username is valid (exists) or invalid.
Packit Service 4684c1
 *
Packit Service 4684c1
 * If an attacker learns the seed, given a salt (which is part of the
Packit Service 4684c1
 * handshake) which was generated when the seed was in use, it can tell
Packit Service 4684c1
 * whether or not the authentication failed because of an unknown username.
Packit Service 4684c1
 * This seed cannot be used to reveal application data or passwords.
Packit Service 4684c1
 *
Packit Service 4684c1
 * @salt_length should represent the salt length your application uses.
Packit Service 4684c1
 * Generating fake salts longer than 20 bytes is not supported.
Packit Service 4684c1
 *
Packit Service 4684c1
 * By default the seed is a random value, different each time a
Packit Service 4684c1
 * #gnutls_srp_server_credentials_t is allocated and fake salts are
Packit Service 4684c1
 * 16 bytes long.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Since: 3.3.0
Packit Service 4684c1
 **/
Packit Service 4684c1
void
Packit Service 4684c1
gnutls_srp_set_server_fake_salt_seed(gnutls_srp_server_credentials_t cred,
Packit Service 4684c1
				     const gnutls_datum_t * seed,
Packit Service 4684c1
				     unsigned int salt_length)
Packit Service 4684c1
{
Packit Service 4684c1
	unsigned seed_size = seed->size;
Packit Service 4684c1
	const unsigned char *seed_data = seed->data;
Packit Service 4684c1
Packit Service 4684c1
	if (seed_size > sizeof(cred->fake_salt_seed))
Packit Service 4684c1
		seed_size = sizeof(cred->fake_salt_seed);
Packit Service 4684c1
Packit Service 4684c1
	memcpy(cred->fake_salt_seed, seed_data, seed_size);
Packit Service 4684c1
	cred->fake_salt_seed_size = seed_size;
Packit Service 4684c1
Packit Service 4684c1
	/* Cap the salt length at the output size of the MAC algorithm
Packit Service 4684c1
	 * we are using to generate the fake salts.
Packit Service 4684c1
	 */
Packit Service 4684c1
	const mac_entry_st * me = mac_to_entry(SRP_FAKE_SALT_MAC);
Packit Service 4684c1
	const size_t mac_len = me->output_size;
Packit Service 4684c1
Packit Service 4684c1
	cred->fake_salt_length = (salt_length < mac_len ? salt_length : mac_len);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#endif				/* ENABLE_SRP */