1 /*
2  * Copyright (C) 2001-2012 Free Software Foundation, 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 /* Here lie everything that has to do with large numbers, libgcrypt and
24  * other stuff that didn't fit anywhere else.
25  */
26 
27 #include "gnutls_int.h"
28 #include <libtasn1.h>
29 #include "errors.h"
30 #include <num.h>
31 #include <mpi.h>
32 #include <random.h>
33 #include <x509/x509_int.h>
34 
35 /* Functions that refer to the mpi library.
36  */
37 
38 /* Returns a random number r, 0 < r < p */
39 bigint_t
_gnutls_mpi_random_modp(bigint_t r,bigint_t p,gnutls_rnd_level_t level)40 _gnutls_mpi_random_modp(bigint_t r, bigint_t p,
41 		      gnutls_rnd_level_t level)
42 {
43 	size_t size;
44 	int ret;
45 	bigint_t tmp;
46 	uint8_t tmpbuf[512];
47 	uint8_t *buf;
48 	int buf_release = 0;
49 
50 	size = ((_gnutls_mpi_get_nbits(p)+64)/8) + 1;
51 
52 	if (size < sizeof(tmpbuf)) {
53 		buf = tmpbuf;
54 	} else {
55 		buf = gnutls_malloc(size);
56 		if (buf == NULL) {
57 			gnutls_assert();
58 			goto cleanup;
59 		}
60 		buf_release = 1;
61 	}
62 
63 	ret = gnutls_rnd(level, buf, size);
64 	if (ret < 0) {
65 		gnutls_assert();
66 		goto cleanup;
67 	}
68 
69 	ret = _gnutls_mpi_init_scan(&tmp, buf, size);
70 	if (ret < 0) {
71 		gnutls_assert();
72 		goto cleanup;
73 	}
74 
75 	ret = _gnutls_mpi_modm(tmp, tmp, p);
76 	if (ret < 0) {
77 		gnutls_assert();
78 		goto cleanup;
79 	}
80 
81 	if (_gnutls_mpi_cmp_ui(tmp, 0) == 0) {
82 		ret = _gnutls_mpi_add_ui(tmp, tmp, 1);
83 		if (ret < 0) {
84 			gnutls_assert();
85 			goto cleanup;
86 		}
87 	}
88 
89 	if (buf_release != 0) {
90 		gnutls_free(buf);
91 	}
92 
93 	if (r != NULL) {
94 		ret = _gnutls_mpi_set(r, tmp);
95 		if (ret < 0)
96 			goto cleanup;
97 
98 		_gnutls_mpi_release(&tmp);
99 		return r;
100 	}
101 
102 	return tmp;
103 
104       cleanup:
105 	if (buf_release != 0)
106 		gnutls_free(buf);
107 	return NULL;
108 }
109 
110 /* returns %GNUTLS_E_SUCCESS (0) on success
111  */
_gnutls_mpi_init_scan(bigint_t * ret_mpi,const void * buffer,size_t nbytes)112 int _gnutls_mpi_init_scan(bigint_t * ret_mpi, const void *buffer, size_t nbytes)
113 {
114 bigint_t r;
115 int ret;
116 
117 	ret = _gnutls_mpi_init(&r);
118 	if (ret < 0)
119 		return gnutls_assert_val(ret);
120 
121 	ret =
122 	    _gnutls_mpi_scan(r, buffer, nbytes);
123 	if (ret < 0) {
124 		gnutls_assert();
125 		_gnutls_mpi_release(&r);
126 		return ret;
127 	}
128 
129 	*ret_mpi = r;
130 
131 	return 0;
132 }
133 
134 /* returns %GNUTLS_E_SUCCESS (0) on success. Fails if the number is zero.
135  */
136 int
_gnutls_mpi_init_scan_nz(bigint_t * ret_mpi,const void * buffer,size_t nbytes)137 _gnutls_mpi_init_scan_nz(bigint_t * ret_mpi, const void *buffer, size_t nbytes)
138 {
139 	int ret;
140 
141 	ret = _gnutls_mpi_init_scan(ret_mpi, buffer, nbytes);
142 	if (ret < 0)
143 		return ret;
144 
145 	/* MPIs with 0 bits are illegal
146 	 */
147 	if (_gnutls_mpi_cmp_ui(*ret_mpi, 0) == 0) {
148 		_gnutls_mpi_release(ret_mpi);
149 		return GNUTLS_E_MPI_SCAN_FAILED;
150 	}
151 
152 	return 0;
153 }
154 
155 int
_gnutls_mpi_init_scan_le(bigint_t * ret_mpi,const void * buffer,size_t nbytes)156 _gnutls_mpi_init_scan_le(bigint_t * ret_mpi, const void *buffer, size_t nbytes)
157 {
158 	bigint_t r;
159 	int ret;
160 
161 	ret = _gnutls_mpi_init(&r);
162 	if (ret < 0)
163 		return gnutls_assert_val(ret);
164 
165 	ret = _gnutls_mpi_scan_le(r, buffer, nbytes);
166 	if (ret < 0) {
167 		gnutls_assert();
168 		_gnutls_mpi_release(&r);
169 		return ret;
170 	}
171 
172 	*ret_mpi = r;
173 
174 	return 0;
175 }
176 
_gnutls_mpi_dprint_le(const bigint_t a,gnutls_datum_t * dest)177 int _gnutls_mpi_dprint_le(const bigint_t a, gnutls_datum_t * dest)
178 {
179 	int ret;
180 	uint8_t *buf = NULL;
181 	size_t bytes = 0;
182 
183 	if (dest == NULL || a == NULL)
184 		return GNUTLS_E_INVALID_REQUEST;
185 
186 	_gnutls_mpi_print_le(a, NULL, &bytes);
187 	if (bytes != 0)
188 		buf = gnutls_malloc(bytes);
189 	if (buf == NULL)
190 		return GNUTLS_E_MEMORY_ERROR;
191 
192 	ret = _gnutls_mpi_print_le(a, buf, &bytes);
193 	if (ret < 0) {
194 		gnutls_free(buf);
195 		return ret;
196 	}
197 
198 	dest->data = buf;
199 	dest->size = bytes;
200 	return 0;
201 }
202 
203 /* Always has the first bit zero */
_gnutls_mpi_dprint_lz(const bigint_t a,gnutls_datum_t * dest)204 int _gnutls_mpi_dprint_lz(const bigint_t a, gnutls_datum_t * dest)
205 {
206 	int ret;
207 	uint8_t *buf = NULL;
208 	size_t bytes = 0;
209 
210 	if (dest == NULL || a == NULL)
211 		return GNUTLS_E_INVALID_REQUEST;
212 
213 	_gnutls_mpi_print_lz(a, NULL, &bytes);
214 
215 	if (bytes != 0)
216 		buf = gnutls_malloc(bytes);
217 	if (buf == NULL)
218 		return GNUTLS_E_MEMORY_ERROR;
219 
220 	ret = _gnutls_mpi_print_lz(a, buf, &bytes);
221 	if (ret < 0) {
222 		gnutls_free(buf);
223 		return ret;
224 	}
225 
226 	dest->data = buf;
227 	dest->size = bytes;
228 	return 0;
229 }
230 
_gnutls_mpi_dprint(const bigint_t a,gnutls_datum_t * dest)231 int _gnutls_mpi_dprint(const bigint_t a, gnutls_datum_t * dest)
232 {
233 	int ret;
234 	uint8_t *buf = NULL;
235 	size_t bytes = 0;
236 
237 	if (dest == NULL || a == NULL)
238 		return GNUTLS_E_INVALID_REQUEST;
239 
240 	_gnutls_mpi_print(a, NULL, &bytes);
241 	if (bytes != 0)
242 		buf = gnutls_malloc(bytes);
243 	if (buf == NULL)
244 		return GNUTLS_E_MEMORY_ERROR;
245 
246 	ret = _gnutls_mpi_print(a, buf, &bytes);
247 	if (ret < 0) {
248 		gnutls_free(buf);
249 		return ret;
250 	}
251 
252 	dest->data = buf;
253 	dest->size = bytes;
254 	return 0;
255 }
256 
257 /* This function will copy the mpi data into a datum,
258  * but will set minimum size to 'size'. That means that
259  * the output value is left padded with zeros.
260  */
261 int
_gnutls_mpi_dprint_size(const bigint_t a,gnutls_datum_t * dest,size_t size)262 _gnutls_mpi_dprint_size(const bigint_t a, gnutls_datum_t * dest,
263 			size_t size)
264 {
265 	int ret;
266 	uint8_t *buf = NULL;
267 	size_t bytes = 0;
268 	unsigned int i;
269 
270 	if (dest == NULL || a == NULL)
271 		return GNUTLS_E_INVALID_REQUEST;
272 
273 	_gnutls_mpi_print(a, NULL, &bytes);
274 	if (bytes != 0)
275 		buf = gnutls_malloc(MAX(size, bytes));
276 	if (buf == NULL)
277 		return GNUTLS_E_MEMORY_ERROR;
278 
279 	if (bytes <= size) {
280 		size_t diff = size - bytes;
281 		for (i = 0; i < diff; i++)
282 			buf[i] = 0;
283 		ret = _gnutls_mpi_print(a, &buf[diff], &bytes);
284 	} else {
285 		ret = _gnutls_mpi_print(a, buf, &bytes);
286 	}
287 
288 	if (ret < 0) {
289 		gnutls_free(buf);
290 		return ret;
291 	}
292 
293 	dest->data = buf;
294 	dest->size = MAX(size, bytes);
295 	return 0;
296 }
297 
298 /* like _gnutls_mpi_dprint_size, but prints into preallocated byte buffer */
299 int
_gnutls_mpi_bprint_size(const bigint_t a,uint8_t * buf,size_t size)300 _gnutls_mpi_bprint_size(const bigint_t a, uint8_t *buf, size_t size)
301 {
302 	int result;
303 	size_t bytes = 0;
304 
305 	result = _gnutls_mpi_print(a, NULL, &bytes);
306 	if (result != GNUTLS_E_SHORT_MEMORY_BUFFER)
307 		return gnutls_assert_val(result);
308 
309 	if (bytes <= size) {
310 		unsigned i;
311 		size_t diff = size - bytes;
312 
313 		for (i = 0; i < diff; i++)
314 			buf[i] = 0;
315 		result = _gnutls_mpi_print(a, &buf[diff], &bytes);
316 	} else {
317 		result = _gnutls_mpi_print(a, buf, &bytes);
318 	}
319 
320 	return result;
321 }
322 
323 /* Flags for __gnutls_x509_read_int() and __gnutls_x509_write_int */
324 #define GNUTLS_X509_INT_OVERWRITE	(1 << 0)
325 #define GNUTLS_X509_INT_LE		(1 << 1)
326 #define GNUTLS_X509_INT_LZ		(1 << 2) /* write only */
327 
328 /* this function reads an integer
329  * from asn1 structs. Combines the read and mpi_scan
330  * steps.
331  */
332 static int
__gnutls_x509_read_int(ASN1_TYPE node,const char * value,bigint_t * ret_mpi,unsigned int flags)333 __gnutls_x509_read_int(ASN1_TYPE node, const char *value,
334 		       bigint_t * ret_mpi, unsigned int flags)
335 {
336 	int result;
337 	uint8_t *tmpstr = NULL;
338 	int tmpstr_size;
339 
340 	tmpstr_size = 0;
341 	result = asn1_read_value(node, value, NULL, &tmpstr_size);
342 	if (result != ASN1_MEM_ERROR) {
343 		gnutls_assert();
344 		return _gnutls_asn2err(result);
345 	}
346 
347 	tmpstr = gnutls_malloc(tmpstr_size);
348 	if (tmpstr == NULL) {
349 		gnutls_assert();
350 		return GNUTLS_E_MEMORY_ERROR;
351 	}
352 
353 	result = asn1_read_value(node, value, tmpstr, &tmpstr_size);
354 	if (result != ASN1_SUCCESS) {
355 		gnutls_assert();
356 		gnutls_free(tmpstr);
357 		return _gnutls_asn2err(result);
358 	}
359 
360 	if (flags & GNUTLS_X509_INT_LE)
361 		result = _gnutls_mpi_init_scan_le(ret_mpi, tmpstr,
362 						  tmpstr_size);
363 	else
364 		result = _gnutls_mpi_init_scan(ret_mpi, tmpstr,
365 					       tmpstr_size);
366 
367 	if (flags & GNUTLS_X509_INT_OVERWRITE)
368 		zeroize_key(tmpstr, tmpstr_size);
369 	gnutls_free(tmpstr);
370 
371 	if (result < 0) {
372 		gnutls_assert();
373 		return result;
374 	}
375 
376 	return 0;
377 }
378 
379 int
_gnutls_x509_read_int(ASN1_TYPE node,const char * value,bigint_t * ret_mpi)380 _gnutls_x509_read_int(ASN1_TYPE node, const char *value,
381 		      bigint_t * ret_mpi)
382 {
383 	return __gnutls_x509_read_int(node, value, ret_mpi,
384 				      0);
385 }
386 
387 int
_gnutls_x509_read_key_int(ASN1_TYPE node,const char * value,bigint_t * ret_mpi)388 _gnutls_x509_read_key_int(ASN1_TYPE node, const char *value,
389 		      bigint_t * ret_mpi)
390 {
391 	return __gnutls_x509_read_int(node, value, ret_mpi,
392 				      GNUTLS_X509_INT_OVERWRITE);
393 }
394 
395 int
_gnutls_x509_read_key_int_le(ASN1_TYPE node,const char * value,bigint_t * ret_mpi)396 _gnutls_x509_read_key_int_le(ASN1_TYPE node, const char *value,
397 			     bigint_t * ret_mpi)
398 {
399 	return __gnutls_x509_read_int(node, value, ret_mpi,
400 				      GNUTLS_X509_INT_OVERWRITE |
401 				      GNUTLS_X509_INT_LE);
402 }
403 
404 /* Writes the specified integer into the specified node.
405  */
406 static int
__gnutls_x509_write_int(ASN1_TYPE node,const char * value,bigint_t mpi,unsigned int flags)407 __gnutls_x509_write_int(ASN1_TYPE node, const char *value, bigint_t mpi,
408 			unsigned int flags)
409 {
410 	uint8_t *tmpstr;
411 	size_t s_len;
412 	int result;
413 
414 	s_len = 0;
415 	if (flags & GNUTLS_X509_INT_LZ)
416 		result = _gnutls_mpi_print_lz(mpi, NULL, &s_len);
417 	else if (GNUTLS_X509_INT_LE)
418 		result = _gnutls_mpi_print_le(mpi, NULL, &s_len);
419 	else
420 		result = _gnutls_mpi_print(mpi, NULL, &s_len);
421 
422 	if (result != GNUTLS_E_SHORT_MEMORY_BUFFER) {
423 		gnutls_assert();
424 		return result;
425 	}
426 
427 	tmpstr = gnutls_malloc(s_len);
428 	if (tmpstr == NULL) {
429 		gnutls_assert();
430 		return GNUTLS_E_MEMORY_ERROR;
431 	}
432 
433 	if (flags & GNUTLS_X509_INT_LZ)
434 		result = _gnutls_mpi_print_lz(mpi, tmpstr, &s_len);
435 	else if (GNUTLS_X509_INT_LE)
436 		result = _gnutls_mpi_print_le(mpi, tmpstr, &s_len);
437 	else
438 		result = _gnutls_mpi_print(mpi, tmpstr, &s_len);
439 
440 	if (result != 0) {
441 		gnutls_assert();
442 		gnutls_free(tmpstr);
443 		return GNUTLS_E_MPI_PRINT_FAILED;
444 	}
445 
446 	result = asn1_write_value(node, value, tmpstr, s_len);
447 
448 	if (flags & GNUTLS_X509_INT_OVERWRITE)
449 		zeroize_key(tmpstr, s_len);
450 
451 	gnutls_free(tmpstr);
452 
453 	if (result != ASN1_SUCCESS) {
454 		gnutls_assert();
455 		return _gnutls_asn2err(result);
456 	}
457 
458 	return 0;
459 }
460 
461 int
_gnutls_x509_write_int(ASN1_TYPE node,const char * value,bigint_t mpi,int lz)462 _gnutls_x509_write_int(ASN1_TYPE node, const char *value, bigint_t mpi,
463 		       int lz)
464 {
465 	return __gnutls_x509_write_int(node, value, mpi,
466 				       lz ? GNUTLS_X509_INT_LZ : 0);
467 }
468 
469 int
_gnutls_x509_write_key_int(ASN1_TYPE node,const char * value,bigint_t mpi,int lz)470 _gnutls_x509_write_key_int(ASN1_TYPE node, const char *value, bigint_t mpi,
471 		       int lz)
472 {
473 	return __gnutls_x509_write_int(node, value, mpi,
474 				       (lz ? GNUTLS_X509_INT_LZ : 0) |
475 				       GNUTLS_X509_INT_OVERWRITE);
476 }
477 
478 int
_gnutls_x509_write_key_int_le(ASN1_TYPE node,const char * value,bigint_t mpi)479 _gnutls_x509_write_key_int_le(ASN1_TYPE node, const char *value, bigint_t mpi)
480 {
481 	return __gnutls_x509_write_int(node, value, mpi,
482 				       GNUTLS_X509_INT_OVERWRITE |
483 				       GNUTLS_X509_INT_LE);
484 }
485