1 /*
2 * Copyright (C) 2017 - This file is part of libecc project
3 *
4 * Authors:
5 * Ryad BENADJILA <ryadbenadjila@gmail.com>
6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8 *
9 * Contributors:
10 * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11 * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12 *
13 * This software is licensed under a dual BSD and GPL v2 license.
14 * See LICENSE file at the root folder of the project.
15 */
16 #include <libecc/curves/curves.h>
17
18 /*
19 * From a null-terminated string 'ec_name' of exact length 'ec_name_len'
20 * (including final null character), the function returns a pointer
21 * to the parameters for that curve via 'ec_params'. The function returns
22 * -1 on error or if the search was unsuccessful. It returns 0 on success.
23 * 'ec_params' is not meaningful on error.
24 */
ec_get_curve_params_by_name(const u8 * ec_name,u8 ec_name_len,const ec_str_params ** ec_s_params)25 int ec_get_curve_params_by_name(const u8 *ec_name, u8 ec_name_len,
26 const ec_str_params **ec_s_params)
27 {
28 const ec_str_params *params;
29 u8 comp_len, name_len;
30 u32 len;
31 const ec_mapping *map;
32 const u8 *name;
33 unsigned int i;
34 int ret, check;
35
36 MUST_HAVE((ec_name != NULL), ret, err);
37 MUST_HAVE((ec_s_params != NULL), ret, err);
38 MUST_HAVE(((ec_name_len > 2) && (ec_name_len <= MAX_CURVE_NAME_LEN)), ret, err);
39
40 /*
41 * User has been warned ec_name_len is expected to include final
42 * null character.
43 */
44 ret = local_strnlen((const char *)ec_name, ec_name_len, &len); EG(ret, err);
45 comp_len = (u8)len;
46 MUST_HAVE(((comp_len + 1) == ec_name_len), ret, err);
47
48 /* Iterate on our list of curves */
49 ret = -1;
50 for (i = 0; i < EC_CURVES_NUM; i++) {
51 map = &ec_maps[i];
52 params = map->params;
53
54 MUST_HAVE((params != NULL), ret, err);
55 MUST_HAVE((params->name != NULL), ret, err);
56 MUST_HAVE((params->name->buf != NULL), ret, err);
57
58 name = params->name->buf;
59 name_len = params->name->buflen;
60
61 if (name_len != ec_name_len) {
62 continue;
63 }
64
65 if ((!are_str_equal((const char *)ec_name, (const char *)name, &check)) && check) {
66 (*ec_s_params) = params;
67 ret = 0;
68 break;
69 }
70 }
71
72 err:
73 return ret;
74 }
75
76 /*
77 * From given curve type 'ec_type', the function provides a pointer to the
78 * parameters for that curve if it is known, using 'ec_params' out parameter.
79 * On error, or if the curve is unknown, the function returns -1, in which
80 * case 'ec_params' is not meaningful. The function returns 0 on success.
81 */
ec_get_curve_params_by_type(ec_curve_type ec_type,const ec_str_params ** ec_s_params)82 int ec_get_curve_params_by_type(ec_curve_type ec_type,
83 const ec_str_params **ec_s_params)
84 {
85 const ec_str_params *params;
86 const ec_mapping *map;
87 const u8 *name;
88 u32 len;
89 u8 name_len;
90 unsigned int i;
91 int ret;
92
93 MUST_HAVE((ec_s_params != NULL), ret, err);
94
95 ret = -1;
96 for (i = 0; i < EC_CURVES_NUM; i++) {
97 map = &ec_maps[i];
98 params = map->params;
99
100 MUST_HAVE((params != NULL), ret, err);
101
102 if (ec_type == map->type) {
103 /* Do some sanity check before returning */
104 MUST_HAVE((params->name != NULL), ret, err);
105 MUST_HAVE((params->name->buf != NULL), ret, err);
106
107 name = params->name->buf;
108 ret = local_strlen((const char *)name, &len); EG(ret, err);
109 MUST_HAVE(len < 256, ret, err);
110 name_len = (u8)len;
111
112 MUST_HAVE((params->name->buflen == (name_len + 1)), ret, err);
113
114 (*ec_s_params) = params;
115 ret = 0;
116 break;
117 }
118 }
119
120 err:
121 return ret;
122 }
123
124 /*
125 * From a null-terminated string 'ec_name' of exact length 'ec_name_len'
126 * (including final null character), the function returns the curve type
127 * via 'ec_type'. The function returns -1 on error or if the search was
128 * unsuccessful. It returns 0 on success. 'ec_types' is not meaningful
129 * on error.
130 */
ec_get_curve_type_by_name(const u8 * ec_name,u8 ec_name_len,ec_curve_type * ec_type)131 int ec_get_curve_type_by_name(const u8 *ec_name, u8 ec_name_len,
132 ec_curve_type *ec_type)
133 {
134 const ec_str_params *params;
135 u32 len;
136 u8 name_len, comp_len;
137 const ec_mapping *map;
138 const u8 *name;
139 unsigned int i;
140 int ret, check;
141
142 /* No need to bother w/ obvious crap */
143 MUST_HAVE(((ec_name_len > 2) && (ec_name_len <= MAX_CURVE_NAME_LEN)), ret, err);
144 MUST_HAVE((ec_type != NULL), ret, err);
145 MUST_HAVE((ec_name != NULL), ret, err);
146
147 /*
148 * User has been warned ec_name_len is expected to include final
149 * null character.
150 */
151 ret = local_strnlen((const char *)ec_name, ec_name_len, &len); EG(ret, err);
152 MUST_HAVE(len < 256, ret, err);
153 comp_len = (u8)len;
154 MUST_HAVE(((comp_len + 1) == ec_name_len), ret, err);
155
156 /* Iterate on our list of curves */
157 ret = -1;
158 for (i = 0; i < EC_CURVES_NUM; i++) {
159 map = &ec_maps[i];
160 params = map->params;
161
162 MUST_HAVE((params != NULL), ret, err);
163 MUST_HAVE((params->name != NULL), ret, err);
164 MUST_HAVE((params->name->buf != NULL), ret, err);
165
166 name = params->name->buf;
167 name_len = params->name->buflen;
168
169 if (name_len != ec_name_len) {
170 continue;
171 }
172
173 if((!are_str_equal((const char *)ec_name, (const char *)name, &check)) && check) {
174 (*ec_type) = map->type;
175 ret = 0;
176 break;
177 }
178 }
179
180 err:
181 return ret;
182 }
183
184 /*
185 * Given a curve type, the function finds the curve described by given type
186 * and write its name (null terminated string) to given output buffer 'out'
187 * of length 'outlen'. 0 is returned on success, -1 otherwise.
188 */
ec_get_curve_name_by_type(const ec_curve_type ec_type,u8 * out,u8 outlen)189 int ec_get_curve_name_by_type(const ec_curve_type ec_type, u8 *out, u8 outlen)
190 {
191 const ec_str_params *by_type;
192 const u8 *name;
193 u8 name_len;
194 int ret;
195
196 MUST_HAVE((out != NULL), ret, err);
197
198 /* Let's first do the lookup by type */
199 ret = ec_get_curve_params_by_type(ec_type, &by_type); EG(ret, err);
200
201 /* Found a curve for that type. Let's check name matches. */
202 MUST_HAVE((by_type != NULL), ret, err);
203 MUST_HAVE((by_type->name != NULL), ret, err);
204 MUST_HAVE((by_type->name->buf != NULL), ret, err);
205
206 name_len = by_type->name->buflen;
207 name = by_type->name->buf;
208
209 /* Not enough room to copy curve name? */
210 MUST_HAVE((name_len <= outlen), ret, err);
211
212 ret = local_memcpy(out, name, name_len);
213
214 err:
215 return ret;
216 }
217
218 /*
219 * The function verifies the coherency between given curve type value and
220 * associated name 'ec_name' of length 'ec_name_len' (including final
221 * null character). The function returns 0 if the curve type is known
222 * and provided name matches expected one. The function returns -1
223 * otherwise.
224 */
ec_check_curve_type_and_name(const ec_curve_type ec_type,const u8 * ec_name,u8 ec_name_len)225 int ec_check_curve_type_and_name(const ec_curve_type ec_type,
226 const u8 *ec_name, u8 ec_name_len)
227 {
228 const ec_str_params *by_type;
229 const u8 *name;
230 u8 name_len;
231 int ret, check;
232
233 /* No need to bother w/ obvious crap */
234 MUST_HAVE((ec_name != NULL), ret, err);
235 MUST_HAVE(((ec_name_len > 2) && (ec_name_len <= MAX_CURVE_NAME_LEN)), ret, err);
236
237 /* Let's first do the lookup by type */
238 ret = ec_get_curve_params_by_type(ec_type, &by_type); EG(ret, err);
239
240 /* Found a curve for that type. Let's check name matches. */
241 MUST_HAVE((by_type != NULL), ret, err);
242 MUST_HAVE((by_type->name != NULL), ret, err);
243 MUST_HAVE((by_type->name->buf != NULL), ret, err);
244
245 name = by_type->name->buf;
246 name_len = by_type->name->buflen;
247
248 MUST_HAVE((name_len == ec_name_len), ret, err);
249
250 if ((!are_str_equal((const char *)ec_name, (const char *)name, &check)) && (!check)) {
251 ret = -1;
252 }
253
254 err:
255 return ret;
256 }
257