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