1 /*
2  * Copyright (C) 2017 Red Hat, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>
20  *
21  */
22 
23 #include "gnutls_int.h"
24 #include <algorithms.h>
25 #include "errors.h"
26 #include <x509/common.h>
27 #include <pk.h>
28 #include "c-strcase.h"
29 
30 /* Supported ECC curves
31  */
32 
33 static const gnutls_group_entry_st supported_groups[] = {
34 	{
35 	 .name = "SECP192R1",
36 	 .id = GNUTLS_GROUP_SECP192R1,
37 	 .curve = GNUTLS_ECC_CURVE_SECP192R1,
38 	 .tls_id = 19,
39 	 .pk = GNUTLS_PK_ECDSA,
40 	},
41 	{
42 	 .name = "SECP224R1",
43 	 .id = GNUTLS_GROUP_SECP224R1,
44 	 .curve = GNUTLS_ECC_CURVE_SECP224R1,
45 	 .tls_id = 21,
46 	 .pk = GNUTLS_PK_ECDSA,
47 	},
48 	{
49 	 .name = "SECP256R1",
50 	 .id = GNUTLS_GROUP_SECP256R1,
51 	 .curve = GNUTLS_ECC_CURVE_SECP256R1,
52 	 .tls_id = 23,
53 	 .pk = GNUTLS_PK_ECDSA,
54 	},
55 	{
56 	 .name = "SECP384R1",
57 	 .id = GNUTLS_GROUP_SECP384R1,
58 	 .curve = GNUTLS_ECC_CURVE_SECP384R1,
59 	 .tls_id = 24,
60 	 .pk = GNUTLS_PK_ECDSA,
61 	},
62 	{
63 	 .name = "SECP521R1",
64 	 .id = GNUTLS_GROUP_SECP521R1,
65 	 .curve = GNUTLS_ECC_CURVE_SECP521R1,
66 	 .tls_id = 25,
67 	 .pk = GNUTLS_PK_ECDSA,
68 	},
69 	{
70 	 .name = "X25519",
71 	 .id = GNUTLS_GROUP_X25519,
72 	 .curve = GNUTLS_ECC_CURVE_X25519,
73 	 .tls_id = 29,
74 	 .pk = GNUTLS_PK_ECDH_X25519
75 	},
76 #ifdef ENABLE_GOST
77 	/* draft-smyshlyaev-tls12-gost-suites-06, Section 6 */
78 	{
79 	 .name = "GC256A",
80 	 .id = GNUTLS_GROUP_GC256A,
81 	 .curve = GNUTLS_ECC_CURVE_GOST256A,
82 	 .pk = GNUTLS_PK_GOST_12_256,
83 	 .tls_id = 34,
84 	},
85 	{
86 	 .name = "GC256B",
87 	 .id = GNUTLS_GROUP_GC256B,
88 	 .curve = GNUTLS_ECC_CURVE_GOST256B,
89 	 .pk = GNUTLS_PK_GOST_12_256,
90 	 .tls_id = 35,
91 	},
92 	{
93 	 .name = "GC256C",
94 	 .id = GNUTLS_GROUP_GC256C,
95 	 .curve = GNUTLS_ECC_CURVE_GOST256C,
96 	 .pk = GNUTLS_PK_GOST_12_256,
97 	 .tls_id = 36,
98 	},
99 	{
100 	 .name = "GC256D",
101 	 .id = GNUTLS_GROUP_GC256D,
102 	 .curve = GNUTLS_ECC_CURVE_GOST256D,
103 	 .pk = GNUTLS_PK_GOST_12_256,
104 	 .tls_id = 37,
105 	},
106 	{
107 	 .name = "GC512A",
108 	 .id = GNUTLS_GROUP_GC512A,
109 	 .curve = GNUTLS_ECC_CURVE_GOST512A,
110 	 .pk = GNUTLS_PK_GOST_12_512,
111 	 .tls_id = 38,
112 	},
113 	{
114 	 .name = "GC512B",
115 	 .id = GNUTLS_GROUP_GC512B,
116 	 .curve = GNUTLS_ECC_CURVE_GOST512B,
117 	 .pk = GNUTLS_PK_GOST_12_512,
118 	 .tls_id = 39,
119 	},
120 	{
121 	 .name = "GC512C",
122 	 .id = GNUTLS_GROUP_GC512C,
123 	 .curve = GNUTLS_ECC_CURVE_GOST512C,
124 	 .pk = GNUTLS_PK_GOST_12_512,
125 	 .tls_id = 40,
126 	},
127 #endif
128 	{
129 	 .name = "X448",
130 	 .id = GNUTLS_GROUP_X448,
131 	 .curve = GNUTLS_ECC_CURVE_X448,
132 	 .tls_id = 30,
133 	 .pk = GNUTLS_PK_ECDH_X448
134 	},
135 #ifdef ENABLE_DHE
136 	{
137 	 .name = "FFDHE2048",
138 	 .id = GNUTLS_GROUP_FFDHE2048,
139 	 .generator = &gnutls_ffdhe_2048_group_generator,
140 	 .prime = &gnutls_ffdhe_2048_group_prime,
141 	 .q = &gnutls_ffdhe_2048_group_q,
142 	 .q_bits = &gnutls_ffdhe_2048_key_bits,
143 	 .pk = GNUTLS_PK_DH,
144 	 .tls_id = 0x100
145 	},
146 	{
147 	 .name = "FFDHE3072",
148 	 .id = GNUTLS_GROUP_FFDHE3072,
149 	 .generator = &gnutls_ffdhe_3072_group_generator,
150 	 .prime = &gnutls_ffdhe_3072_group_prime,
151 	 .q = &gnutls_ffdhe_3072_group_q,
152 	 .q_bits = &gnutls_ffdhe_3072_key_bits,
153 	 .pk = GNUTLS_PK_DH,
154 	 .tls_id = 0x101
155 	},
156 	{
157 	 .name = "FFDHE4096",
158 	 .id = GNUTLS_GROUP_FFDHE4096,
159 	 .generator = &gnutls_ffdhe_4096_group_generator,
160 	 .prime = &gnutls_ffdhe_4096_group_prime,
161 	 .q = &gnutls_ffdhe_4096_group_q,
162 	 .q_bits = &gnutls_ffdhe_4096_key_bits,
163 	 .pk = GNUTLS_PK_DH,
164 	 .tls_id = 0x102
165 	},
166 	{
167 	 .name = "FFDHE6144",
168 	 .id = GNUTLS_GROUP_FFDHE6144,
169 	 .generator = &gnutls_ffdhe_6144_group_generator,
170 	 .prime = &gnutls_ffdhe_6144_group_prime,
171 	 .q = &gnutls_ffdhe_6144_group_q,
172 	 .q_bits = &gnutls_ffdhe_6144_key_bits,
173 	 .pk = GNUTLS_PK_DH,
174 	 .tls_id = 0x103
175 	},
176 	{
177 	 .name = "FFDHE8192",
178 	 .id = GNUTLS_GROUP_FFDHE8192,
179 	 .generator = &gnutls_ffdhe_8192_group_generator,
180 	 .prime = &gnutls_ffdhe_8192_group_prime,
181 	 .q = &gnutls_ffdhe_8192_group_q,
182 	 .q_bits = &gnutls_ffdhe_8192_key_bits,
183 	 .pk = GNUTLS_PK_DH,
184 	 .tls_id = 0x104
185 	},
186 #endif
187 	{0, 0, 0}
188 };
189 
190 #define GNUTLS_GROUP_LOOP(b) \
191 	{ const gnutls_group_entry_st *p; \
192 		for(p = supported_groups; p->name != NULL; p++) { b ; } }
193 
194 
195 /* Returns the TLS id of the given curve
196  */
_gnutls_tls_id_to_group(unsigned num)197 const gnutls_group_entry_st * _gnutls_tls_id_to_group(unsigned num)
198 {
199 	GNUTLS_GROUP_LOOP(
200 		if (p->tls_id == num &&
201 		    (p->curve == 0 || _gnutls_ecc_curve_is_supported(p->curve))) {
202 			return p;
203 		}
204 	);
205 
206 	return NULL;
207 }
208 
_gnutls_id_to_group(unsigned id)209 const gnutls_group_entry_st * _gnutls_id_to_group(unsigned id)
210 {
211 	if (id == 0)
212 		return NULL;
213 
214 	GNUTLS_GROUP_LOOP(
215 		if (p->id == id &&
216 		    (p->curve == 0 || _gnutls_ecc_curve_is_supported(p->curve))) {
217 			return p;
218 		}
219 	);
220 
221 	return NULL;
222 }
223 
224 /**
225  * gnutls_group_list:
226  *
227  * Get the list of supported elliptic curves.
228  *
229  * This function is not thread safe.
230  *
231  * Returns: Return a (0)-terminated list of #gnutls_group_t
232  *   integers indicating the available groups.
233  *
234  * Since: 3.6.0
235  **/
gnutls_group_list(void)236 const gnutls_group_t *gnutls_group_list(void)
237 {
238 	static gnutls_group_t groups[MAX_ALGOS] = { 0 };
239 
240 	if (groups[0] == 0) {
241 		int i = 0;
242 
243 		GNUTLS_GROUP_LOOP(
244 			if (p->curve == 0 || _gnutls_ecc_curve_is_supported(p->curve))
245 				groups[i++] = p->id;
246 		);
247 		groups[i++] = 0;
248 	}
249 
250 	return groups;
251 }
252 
253 /**
254  * gnutls_group_get_id:
255  * @name: is a group name
256  *
257  * The names are compared in a case insensitive way.
258  *
259  * Returns: return a #gnutls_group_t value corresponding to
260  *   the specified group, or %GNUTLS_GROUP_INVALID on error.
261  *
262  * Since: 3.6.0
263  **/
gnutls_group_get_id(const char * name)264 gnutls_group_t gnutls_group_get_id(const char *name)
265 {
266 	gnutls_group_t ret = GNUTLS_GROUP_INVALID;
267 
268 	GNUTLS_GROUP_LOOP(
269 		if (c_strcasecmp(p->name, name) == 0 && (
270 		    p->curve == 0 ||_gnutls_ecc_curve_is_supported(p->curve))) {
271 			ret = p->id;
272 			break;
273 		}
274 	);
275 
276 	return ret;
277 }
278 
279 /**
280  * gnutls_group_get_name:
281  * @group: is an element from %gnutls_group_t
282  *
283  * Convert a #gnutls_group_t value to a string.
284  *
285  * Returns: a string that contains the name of the specified
286  *   group or %NULL.
287  *
288  * Since: 3.6.0
289  **/
gnutls_group_get_name(gnutls_group_t group)290 const char *gnutls_group_get_name(gnutls_group_t group)
291 {
292 	GNUTLS_GROUP_LOOP(
293 		if (p->id == group) {
294 			return p->name;
295 		}
296 	);
297 
298 	return NULL;
299 }
300