/ external / libecc / src / curves / curves.c
curves.c
  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  }