xref: /freebsd/crypto/libecc/src/curves/curves.c (revision dd21556857e8d40f66bf5ad54754d9d52669ebf7)
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  */
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  */
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  */
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  */
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  */
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