aboutsummaryrefslogtreecommitdiff
path: root/src/exhaustive/brainpool_rfc.c
blob: 0c045d57a5b425a6c3cab37b9d7c28c4ae1ffcc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
 * ecgen, tool for generating Elliptic curve domain parameters
 * Copyright (C) 2017-2018 J08nY
 */

#include "brainpool_rfc.h"
#include "brainpool.h"
#include "util/bits.h"

#define brainpool_delegate(func)            \
	int ret = func(curve, args, state);     \
	if (ret != 1) {                         \
		return ret;                         \
	}                                       \
	curve->seed->type = SEED_BRAINPOOL_RFC; \
	return 1;

GENERATOR(brainpool_rfc_gen_seed_argument) {
	brainpool_delegate(brainpool_gen_seed_argument);
}

GENERATOR(brainpool_rfc_gen_seed_random) {
	brainpool_delegate(brainpool_gen_seed_random);
}

GENERATOR(brainpool_rfc_gen_seed_input) {
	brainpool_delegate(brainpool_gen_seed_input);
}

#undef brainpool_delegate

GENERATOR(brainpool_rfc_gen_equation) {
	// field is definitely prime
	pari_sp btop = avma;
	seed_t *seed = curve->seed;
	do {
		if (seed->brainpool.update_seed) {
			brainpool_update_seed(seed->seed);
			seed->brainpool.update_seed = false;
		}

		bits_t *a_bits =
		    brainpool_hash(seed->seed, seed->brainpool.w, seed->brainpool.v);
		GEN a = bits_to_i(a_bits);
		bits_free(&a_bits);
		GEN am = Fp_invsafe(a, curve->field);
		if (am == NULL) {
			brainpool_update_seed(seed->seed);
			avma = btop;
			continue;
		}
		GEN z;
		z = Fp_sqrtn(Fp_muls(am, -3, curve->field), stoi(4), curve->field,
		             NULL);
		if (z == NULL) {
			brainpool_update_seed(seed->seed);
			avma = btop;
			continue;
		}
		seed->brainpool.seed_a = bits_copy(seed->seed);

		GEN b = NULL;
		pari_sp bbtop = avma;
		do {
			if (b != NULL) {
				avma = bbtop;
			}
			brainpool_update_seed(seed->seed);
			bits_t *b_bits = brainpool_hash(seed->seed, seed->brainpool.w,
			                                seed->brainpool.v);
			b = bits_to_i(b_bits);
			bits_free(&b_bits);
		} while (Fp_issquare(b, curve->field));

		seed->brainpool.seed_b = bits_copy(seed->seed);

		GEN mod_a = gmodulo(a, curve->field);
		GEN mod_b = gmodulo(b, curve->field);

		if (gequal0(gmulsg(-16, gadd(gmulsg(4, gpowgs(mod_a, 3)),
		                             gmulsg(27, gsqr(mod_b)))))) {
			brainpool_update_seed(seed->seed);
			bits_free(&seed->brainpool.seed_a);
			bits_free(&seed->brainpool.seed_b);
			avma = btop;
			continue;
		}

		curve->a = mod_a;
		curve->b = mod_b;
		gerepileall(btop, 2, &curve->a, &curve->b);
		break;
	} while (true);

	seed->brainpool.update_seed = true;
	return 1;
}