Exemple #1
0
/* Output: username, bytes_A, len_A */
SRP_Result srp_user_start_authentication(struct SRPUser *usr, char **username,
	const unsigned char *bytes_a, size_t len_a,
	unsigned char **bytes_A, size_t *len_A)
{
	// clang-format on
	if (bytes_a) {
		mpz_from_bin(bytes_a, len_a, usr->a);
	} else {
		if (!mpz_fill_random(usr->a)) goto error_and_exit;
	}

	mpz_powm(usr->A, usr->ng->g, usr->a, usr->ng->N);

	*len_A = mpz_num_bytes(usr->A);
	*bytes_A = (unsigned char *)srp_alloc(*len_A);

	if (!*bytes_A) goto error_and_exit;

	mpz_to_bin(usr->A, *bytes_A);

	usr->bytes_A = *bytes_A;
	if (username) *username = usr->username;

	return SRP_OK;

error_and_exit:
	*len_A = 0;
	*bytes_A = 0;
	*username = 0;
	return SRP_ERR;
}
Exemple #2
0
// clang-format off
SRP_Result srp_create_salted_verification_key( SRP_HashAlgorithm alg,
	SRP_NGType ng_type, const char *username_for_verifier,
	const unsigned char *password, size_t len_password,
	unsigned char **bytes_s,  size_t *len_s,
	unsigned char **bytes_v, size_t *len_v,
	const char *n_hex, const char *g_hex )
{
	SRP_Result ret = SRP_OK;

	mpz_t v; mpz_init(v);
	mpz_t x; mpz_init(x);
	// clang-format on

	NGConstant *ng = new_ng(ng_type, n_hex, g_hex);

	if (!ng) goto error_and_exit;

	if (init_random() != SRP_OK) /* Only happens once */
		goto error_and_exit;

	if (*bytes_s == NULL) {
		size_t size_to_fill = 16;
		*len_s = size_to_fill;
		if (RAND_BUFF_MAX - g_rand_idx < size_to_fill)
			if (fill_buff() != SRP_OK) goto error_and_exit;
		*bytes_s = (unsigned char *)srp_alloc(size_to_fill);
		if (!*bytes_s) goto error_and_exit;
		memcpy(*bytes_s, g_rand_buff + g_rand_idx, size_to_fill);
		g_rand_idx += size_to_fill;
	}

	if (!calculate_x(
			x, alg, *bytes_s, *len_s, username_for_verifier, password, len_password))
		goto error_and_exit;

	srp_dbg_num(x, "Server calculated x: ");

	mpz_powm(v, ng->g, x, ng->N);

	*len_v = mpz_num_bytes(v);

	*bytes_v = (unsigned char *)srp_alloc(*len_v);

	if (!*bytes_v) goto error_and_exit;

	mpz_to_bin(v, *bytes_v);

cleanup_and_exit:
	delete_ng(ng);
	mpz_clear(v);
	mpz_clear(x);
	return ret;
error_and_exit:
	ret = SRP_ERR;
	goto cleanup_and_exit;
}
Exemple #3
0
static SRP_Result hash_num(SRP_HashAlgorithm alg, const mpz_t n, unsigned char *dest)
{
	int nbytes = mpz_num_bytes(n);
	unsigned char *bin = (unsigned char *)srp_alloc(nbytes);
	if (!bin) return SRP_ERR;
	mpz_to_bin(n, bin);
	hash(alg, bin, nbytes, dest);
	srp_free(bin);
	return SRP_OK;
}
Exemple #4
0
static SRP_Result update_hash_n(SRP_HashAlgorithm alg, HashCTX *ctx, const mpz_t n)
{
	size_t len = mpz_num_bytes(n);
	unsigned char *n_bytes = (unsigned char *)srp_alloc(len);
	if (!n_bytes) return SRP_ERR;
	mpz_to_bin(n, n_bytes);
	hash_update(alg, ctx, n_bytes, len);
	srp_free(n_bytes);
	return SRP_OK;
}
Exemple #5
0
static void hash_num( SRP_HashAlgorithm alg, const mpz_t n, unsigned char *dest )
{
	int nbytes = mpz_num_bytes(n);
	unsigned char *bin = (unsigned char *) malloc(nbytes);
	if(!bin)
		return;
	mpz_to_bin(n, bin);
	hash(alg, bin, nbytes, dest);
	free(bin);
}
Exemple #6
0
static void update_hash_n(SRP_HashAlgorithm alg, HashCTX *ctx, const mpz_t n)
{
	size_t len = mpz_num_bytes(n);
	unsigned char* n_bytes = (unsigned char *) malloc(len);
	if (!n_bytes)
		return;
	mpz_to_bin(n, n_bytes);
	hash_update(alg, ctx, n_bytes, len);
	free(n_bytes);
}
Exemple #7
0
static SRP_Result H_nn(
	mpz_t result, SRP_HashAlgorithm alg, const mpz_t N, const mpz_t n1, const mpz_t n2)
{
	unsigned char buff[SHA512_DIGEST_LENGTH];
	size_t len_N = mpz_num_bytes(N);
	size_t len_n1 = mpz_num_bytes(n1);
	size_t len_n2 = mpz_num_bytes(n2);
	size_t nbytes = len_N + len_N;
	unsigned char *bin = (unsigned char *)srp_alloc(nbytes);
	if (!bin) return SRP_ERR;
	if (len_n1 > len_N || len_n2 > len_N) {
		srp_free(bin);
		return SRP_ERR;
	}
	memset(bin, 0, nbytes);
	mpz_to_bin(n1, bin + (len_N - len_n1));
	mpz_to_bin(n2, bin + (len_N + len_N - len_n2));
	hash(alg, bin, nbytes, buff);
	srp_free(bin);
	mpz_from_bin(buff, hash_length(alg), result);
	return SRP_OK;
}
Exemple #8
0
/* Out: bytes_B, len_B.
 *
 * On failure, bytes_B will be set to NULL and len_B will be set to 0
 */
struct SRPVerifier *srp_verifier_new(SRP_HashAlgorithm alg,
	SRP_NGType ng_type, const char *username,
	const unsigned char *bytes_s, size_t len_s,
	const unsigned char *bytes_v, size_t len_v,
	const unsigned char *bytes_A, size_t len_A,
	const unsigned char *bytes_b, size_t len_b,
	unsigned char **bytes_B, size_t *len_B,
	const char *n_hex, const char *g_hex )
{
	mpz_t v; mpz_init(v); mpz_from_bin(bytes_v, len_v, v);
	mpz_t A; mpz_init(A); mpz_from_bin(bytes_A, len_A, A);
	mpz_t u; mpz_init(u);
	mpz_t B; mpz_init(B);
	mpz_t S; mpz_init(S);
	mpz_t b; mpz_init(b);
	mpz_t k; mpz_init(k);
	mpz_t tmp1; mpz_init(tmp1);
	mpz_t tmp2; mpz_init(tmp2);
	mpz_t tmp3; mpz_init(tmp3);
	// clang-format on
	size_t ulen = strlen(username) + 1;
	NGConstant *ng = new_ng(ng_type, n_hex, g_hex);
	struct SRPVerifier *ver = 0;

	*len_B = 0;
	*bytes_B = 0;

	if (!ng) goto cleanup_and_exit;

	ver = (struct SRPVerifier *)srp_alloc(sizeof(struct SRPVerifier));

	if (!ver) goto cleanup_and_exit;

	if (init_random() != SRP_OK) { /* Only happens once */
		srp_free(ver);
		ver = 0;
		goto cleanup_and_exit;
	}

	ver->username = (char *)srp_alloc(ulen);
	ver->hash_alg = alg;
	ver->ng = ng;

	if (!ver->username) {
		srp_free(ver);
		ver = 0;
		goto cleanup_and_exit;
	}

	memcpy((char *)ver->username, username, ulen);

	ver->authenticated = 0;

	/* SRP-6a safety check */
	mpz_mod(tmp1, A, ng->N);
	if (mpz_sgn(tmp1) != 0) {
		if (bytes_b) {
			mpz_from_bin(bytes_b, len_b, b);
		} else {
			if (!mpz_fill_random(b)) goto ver_cleanup_and_exit;
		}

		if (!H_nn(k, alg, ng->N, ng->N, ng->g)) goto ver_cleanup_and_exit;

		/* B = kv + g^b */
		mpz_mulm(tmp1, k, v, ng->N, tmp3);
		mpz_powm(tmp2, ng->g, b, ng->N);
		mpz_addm(B, tmp1, tmp2, ng->N, tmp3);

		if (!H_nn(u, alg, ng->N, A, B)) goto ver_cleanup_and_exit;

		srp_dbg_num(u, "Server calculated u: ");

		/* S = (A *(v^u)) ^ b */
		mpz_powm(tmp1, v, u, ng->N);
		mpz_mulm(tmp2, A, tmp1, ng->N, tmp3);
		mpz_powm(S, tmp2, b, ng->N);

		if (!hash_num(alg, S, ver->session_key)) goto ver_cleanup_and_exit;

		if (!calculate_M(
				alg, ng, ver->M, username, bytes_s, len_s, A, B, ver->session_key)) {
			goto ver_cleanup_and_exit;
		}
		if (!calculate_H_AMK(alg, ver->H_AMK, A, ver->M, ver->session_key)) {
			goto ver_cleanup_and_exit;
		}

		*len_B = mpz_num_bytes(B);
		*bytes_B = (unsigned char *)srp_alloc(*len_B);

		if (!*bytes_B) {
			*len_B = 0;
			goto ver_cleanup_and_exit;
		}

		mpz_to_bin(B, *bytes_B);

		ver->bytes_B = *bytes_B;
	} else {
		srp_free(ver);
		ver = 0;
	}

cleanup_and_exit:
	mpz_clear(v);
	mpz_clear(A);
	mpz_clear(u);
	mpz_clear(k);
	mpz_clear(B);
	mpz_clear(S);
	mpz_clear(b);
	mpz_clear(tmp1);
	mpz_clear(tmp2);
	mpz_clear(tmp3);
	return ver;
ver_cleanup_and_exit:
	srp_free(ver->username);
	srp_free(ver);
	ver = 0;
	goto cleanup_and_exit;
}