/src/gnutls/lib/algorithms/groups.c
Line | Count | Source (jump to first uncovered line) |
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 | | { .name = "X25519", |
70 | | .id = GNUTLS_GROUP_X25519, |
71 | | .curve = GNUTLS_ECC_CURVE_X25519, |
72 | | .tls_id = 29, |
73 | | .pk = GNUTLS_PK_ECDH_X25519 }, |
74 | | #ifdef ENABLE_GOST |
75 | | /* draft-smyshlyaev-tls12-gost-suites-06, Section 6 */ |
76 | | { |
77 | | .name = "GC256A", |
78 | | .id = GNUTLS_GROUP_GC256A, |
79 | | .curve = GNUTLS_ECC_CURVE_GOST256A, |
80 | | .pk = GNUTLS_PK_GOST_12_256, |
81 | | .tls_id = 34, |
82 | | }, |
83 | | { |
84 | | .name = "GC256B", |
85 | | .id = GNUTLS_GROUP_GC256B, |
86 | | .curve = GNUTLS_ECC_CURVE_GOST256B, |
87 | | .pk = GNUTLS_PK_GOST_12_256, |
88 | | .tls_id = 35, |
89 | | }, |
90 | | { |
91 | | .name = "GC256C", |
92 | | .id = GNUTLS_GROUP_GC256C, |
93 | | .curve = GNUTLS_ECC_CURVE_GOST256C, |
94 | | .pk = GNUTLS_PK_GOST_12_256, |
95 | | .tls_id = 36, |
96 | | }, |
97 | | { |
98 | | .name = "GC256D", |
99 | | .id = GNUTLS_GROUP_GC256D, |
100 | | .curve = GNUTLS_ECC_CURVE_GOST256D, |
101 | | .pk = GNUTLS_PK_GOST_12_256, |
102 | | .tls_id = 37, |
103 | | }, |
104 | | { |
105 | | .name = "GC512A", |
106 | | .id = GNUTLS_GROUP_GC512A, |
107 | | .curve = GNUTLS_ECC_CURVE_GOST512A, |
108 | | .pk = GNUTLS_PK_GOST_12_512, |
109 | | .tls_id = 38, |
110 | | }, |
111 | | { |
112 | | .name = "GC512B", |
113 | | .id = GNUTLS_GROUP_GC512B, |
114 | | .curve = GNUTLS_ECC_CURVE_GOST512B, |
115 | | .pk = GNUTLS_PK_GOST_12_512, |
116 | | .tls_id = 39, |
117 | | }, |
118 | | { |
119 | | .name = "GC512C", |
120 | | .id = GNUTLS_GROUP_GC512C, |
121 | | .curve = GNUTLS_ECC_CURVE_GOST512C, |
122 | | .pk = GNUTLS_PK_GOST_12_512, |
123 | | .tls_id = 40, |
124 | | }, |
125 | | #endif |
126 | | { .name = "X448", |
127 | | .id = GNUTLS_GROUP_X448, |
128 | | .curve = GNUTLS_ECC_CURVE_X448, |
129 | | .tls_id = 30, |
130 | | .pk = GNUTLS_PK_ECDH_X448 }, |
131 | | #ifdef ENABLE_DHE |
132 | | { .name = "FFDHE2048", |
133 | | .id = GNUTLS_GROUP_FFDHE2048, |
134 | | .generator = &gnutls_ffdhe_2048_group_generator, |
135 | | .prime = &gnutls_ffdhe_2048_group_prime, |
136 | | .q = &gnutls_ffdhe_2048_group_q, |
137 | | .q_bits = &gnutls_ffdhe_2048_key_bits, |
138 | | .pk = GNUTLS_PK_DH, |
139 | | .tls_id = 0x100 }, |
140 | | { .name = "FFDHE3072", |
141 | | .id = GNUTLS_GROUP_FFDHE3072, |
142 | | .generator = &gnutls_ffdhe_3072_group_generator, |
143 | | .prime = &gnutls_ffdhe_3072_group_prime, |
144 | | .q = &gnutls_ffdhe_3072_group_q, |
145 | | .q_bits = &gnutls_ffdhe_3072_key_bits, |
146 | | .pk = GNUTLS_PK_DH, |
147 | | .tls_id = 0x101 }, |
148 | | { .name = "FFDHE4096", |
149 | | .id = GNUTLS_GROUP_FFDHE4096, |
150 | | .generator = &gnutls_ffdhe_4096_group_generator, |
151 | | .prime = &gnutls_ffdhe_4096_group_prime, |
152 | | .q = &gnutls_ffdhe_4096_group_q, |
153 | | .q_bits = &gnutls_ffdhe_4096_key_bits, |
154 | | .pk = GNUTLS_PK_DH, |
155 | | .tls_id = 0x102 }, |
156 | | { .name = "FFDHE6144", |
157 | | .id = GNUTLS_GROUP_FFDHE6144, |
158 | | .generator = &gnutls_ffdhe_6144_group_generator, |
159 | | .prime = &gnutls_ffdhe_6144_group_prime, |
160 | | .q = &gnutls_ffdhe_6144_group_q, |
161 | | .q_bits = &gnutls_ffdhe_6144_key_bits, |
162 | | .pk = GNUTLS_PK_DH, |
163 | | .tls_id = 0x103 }, |
164 | | { .name = "FFDHE8192", |
165 | | .id = GNUTLS_GROUP_FFDHE8192, |
166 | | .generator = &gnutls_ffdhe_8192_group_generator, |
167 | | .prime = &gnutls_ffdhe_8192_group_prime, |
168 | | .q = &gnutls_ffdhe_8192_group_q, |
169 | | .q_bits = &gnutls_ffdhe_8192_key_bits, |
170 | | .pk = GNUTLS_PK_DH, |
171 | | .tls_id = 0x104 }, |
172 | | #endif |
173 | | { 0, 0, 0 } |
174 | | }; |
175 | | |
176 | | #define GNUTLS_GROUP_LOOP(b) \ |
177 | 0 | { \ |
178 | 0 | const gnutls_group_entry_st *p; \ |
179 | 0 | for (p = supported_groups; p->name != NULL; p++) { \ |
180 | 0 | b; \ |
181 | 0 | } \ |
182 | 0 | } |
183 | | |
184 | | /* Returns the TLS id of the given curve |
185 | | */ |
186 | | const gnutls_group_entry_st *_gnutls_tls_id_to_group(unsigned num) |
187 | 0 | { |
188 | 0 | GNUTLS_GROUP_LOOP( |
189 | 0 | if (p->tls_id == num && |
190 | 0 | (p->curve == 0 || |
191 | 0 | _gnutls_ecc_curve_is_supported(p->curve))) { return p; }); |
192 | |
|
193 | 0 | return NULL; |
194 | 0 | } |
195 | | |
196 | | const gnutls_group_entry_st *_gnutls_id_to_group(unsigned id) |
197 | 0 | { |
198 | 0 | if (id == 0) |
199 | 0 | return NULL; |
200 | | |
201 | 0 | GNUTLS_GROUP_LOOP( |
202 | 0 | if (p->id == id && (p->curve == 0 || |
203 | 0 | _gnutls_ecc_curve_is_supported(p->curve))) { |
204 | 0 | return p; |
205 | 0 | }); |
206 | |
|
207 | 0 | return NULL; |
208 | 0 | } |
209 | | |
210 | | /** |
211 | | * gnutls_group_list: |
212 | | * |
213 | | * Get the list of supported elliptic curves. |
214 | | * |
215 | | * This function is not thread safe. |
216 | | * |
217 | | * Returns: Return a (0)-terminated list of #gnutls_group_t |
218 | | * integers indicating the available groups. |
219 | | * |
220 | | * Since: 3.6.0 |
221 | | **/ |
222 | | const gnutls_group_t *gnutls_group_list(void) |
223 | 0 | { |
224 | 0 | static gnutls_group_t groups[MAX_ALGOS] = { 0 }; |
225 | |
|
226 | 0 | if (groups[0] == 0) { |
227 | 0 | int i = 0; |
228 | |
|
229 | 0 | GNUTLS_GROUP_LOOP(if (p->curve == 0 || |
230 | 0 | _gnutls_ecc_curve_is_supported(p->curve)) |
231 | 0 | groups[i++] = p->id;); |
232 | 0 | groups[i++] = 0; |
233 | 0 | } |
234 | |
|
235 | 0 | return groups; |
236 | 0 | } |
237 | | |
238 | | /** |
239 | | * gnutls_group_get_id: |
240 | | * @name: is a group name |
241 | | * |
242 | | * The names are compared in a case insensitive way. |
243 | | * |
244 | | * Returns: return a #gnutls_group_t value corresponding to |
245 | | * the specified group, or %GNUTLS_GROUP_INVALID on error. |
246 | | * |
247 | | * Since: 3.6.0 |
248 | | **/ |
249 | | gnutls_group_t gnutls_group_get_id(const char *name) |
250 | 0 | { |
251 | 0 | gnutls_group_t ret = GNUTLS_GROUP_INVALID; |
252 | |
|
253 | 0 | GNUTLS_GROUP_LOOP(if (c_strcasecmp(p->name, name) == 0 && |
254 | 0 | (p->curve == 0 || |
255 | 0 | _gnutls_ecc_curve_is_supported(p->curve))) { |
256 | 0 | ret = p->id; |
257 | 0 | break; |
258 | 0 | }); |
259 | |
|
260 | 0 | return ret; |
261 | 0 | } |
262 | | |
263 | | /* Similar to gnutls_group_get_id, except that it does not check if |
264 | | * the curve is supported. |
265 | | */ |
266 | | gnutls_group_t _gnutls_group_get_id(const char *name) |
267 | 0 | { |
268 | 0 | gnutls_group_t ret = GNUTLS_GROUP_INVALID; |
269 | |
|
270 | 0 | GNUTLS_GROUP_LOOP(if (c_strcasecmp(p->name, name) == 0) { |
271 | 0 | ret = p->id; |
272 | 0 | break; |
273 | 0 | }); |
274 | |
|
275 | 0 | return ret; |
276 | 0 | } |
277 | | |
278 | | /** |
279 | | * gnutls_group_get_name: |
280 | | * @group: is an element from %gnutls_group_t |
281 | | * |
282 | | * Convert a #gnutls_group_t value to a string. |
283 | | * |
284 | | * Returns: a string that contains the name of the specified |
285 | | * group or %NULL. |
286 | | * |
287 | | * Since: 3.6.0 |
288 | | **/ |
289 | | const char *gnutls_group_get_name(gnutls_group_t group) |
290 | 0 | { |
291 | 0 | GNUTLS_GROUP_LOOP(if (p->id == group) { return p->name; }); |
292 | |
|
293 | 0 | return NULL; |
294 | 0 | } |