Line data Source code
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
40 288 : _gnutls_mpi_random_modp(bigint_t r, bigint_t p,
41 : gnutls_rnd_level_t level)
42 : {
43 288 : size_t size;
44 288 : int ret;
45 288 : bigint_t tmp;
46 288 : uint8_t tmpbuf[512];
47 288 : uint8_t *buf;
48 288 : int buf_release = 0;
49 :
50 288 : size = ((_gnutls_mpi_get_nbits(p)+64)/8) + 1;
51 :
52 288 : if (size < sizeof(tmpbuf)) {
53 : buf = tmpbuf;
54 : } else {
55 11 : buf = gnutls_malloc(size);
56 11 : if (buf == NULL) {
57 0 : gnutls_assert();
58 0 : goto cleanup;
59 : }
60 : buf_release = 1;
61 : }
62 :
63 288 : ret = gnutls_rnd(level, buf, size);
64 288 : if (ret < 0) {
65 0 : gnutls_assert();
66 0 : goto cleanup;
67 : }
68 :
69 288 : ret = _gnutls_mpi_init_scan(&tmp, buf, size);
70 288 : if (ret < 0) {
71 0 : gnutls_assert();
72 0 : goto cleanup;
73 : }
74 :
75 288 : ret = _gnutls_mpi_modm(tmp, tmp, p);
76 288 : if (ret < 0) {
77 0 : gnutls_assert();
78 0 : goto cleanup;
79 : }
80 :
81 288 : if (_gnutls_mpi_cmp_ui(tmp, 0) == 0) {
82 0 : ret = _gnutls_mpi_add_ui(tmp, tmp, 1);
83 0 : if (ret < 0) {
84 0 : gnutls_assert();
85 0 : goto cleanup;
86 : }
87 : }
88 :
89 288 : if (buf_release != 0) {
90 11 : gnutls_free(buf);
91 : }
92 :
93 288 : if (r != NULL) {
94 288 : ret = _gnutls_mpi_set(r, tmp);
95 288 : if (ret < 0)
96 0 : goto cleanup;
97 :
98 288 : _gnutls_mpi_release(&tmp);
99 288 : return r;
100 : }
101 :
102 0 : return tmp;
103 :
104 0 : cleanup:
105 0 : if (buf_release != 0)
106 0 : gnutls_free(buf);
107 : return NULL;
108 : }
109 :
110 : /* returns %GNUTLS_E_SUCCESS (0) on success
111 : */
112 177690 : int _gnutls_mpi_init_scan(bigint_t * ret_mpi, const void *buffer, size_t nbytes)
113 : {
114 177690 : bigint_t r;
115 177690 : int ret;
116 :
117 177690 : ret = _gnutls_mpi_init(&r);
118 177690 : if (ret < 0)
119 0 : return gnutls_assert_val(ret);
120 :
121 177690 : ret =
122 177690 : _gnutls_mpi_scan(r, buffer, nbytes);
123 177690 : if (ret < 0) {
124 0 : gnutls_assert();
125 0 : _gnutls_mpi_release(&r);
126 0 : return ret;
127 : }
128 :
129 177690 : *ret_mpi = r;
130 :
131 177690 : return 0;
132 : }
133 :
134 : /* returns %GNUTLS_E_SUCCESS (0) on success. Fails if the number is zero.
135 : */
136 : int
137 32119 : _gnutls_mpi_init_scan_nz(bigint_t * ret_mpi, const void *buffer, size_t nbytes)
138 : {
139 32119 : int ret;
140 :
141 32119 : ret = _gnutls_mpi_init_scan(ret_mpi, buffer, nbytes);
142 32119 : if (ret < 0)
143 : return ret;
144 :
145 : /* MPIs with 0 bits are illegal
146 : */
147 32119 : if (_gnutls_mpi_cmp_ui(*ret_mpi, 0) == 0) {
148 21 : _gnutls_mpi_release(ret_mpi);
149 21 : return GNUTLS_E_MPI_SCAN_FAILED;
150 : }
151 :
152 : return 0;
153 : }
154 :
155 : int
156 1076 : _gnutls_mpi_init_scan_le(bigint_t * ret_mpi, const void *buffer, size_t nbytes)
157 : {
158 1076 : bigint_t r;
159 1076 : int ret;
160 :
161 1076 : ret = _gnutls_mpi_init(&r);
162 1076 : if (ret < 0)
163 0 : return gnutls_assert_val(ret);
164 :
165 1076 : ret = _gnutls_mpi_scan_le(r, buffer, nbytes);
166 1076 : if (ret < 0) {
167 0 : gnutls_assert();
168 0 : _gnutls_mpi_release(&r);
169 0 : return ret;
170 : }
171 :
172 1076 : *ret_mpi = r;
173 :
174 1076 : return 0;
175 : }
176 :
177 91 : int _gnutls_mpi_dprint_le(const bigint_t a, gnutls_datum_t * dest)
178 : {
179 91 : int ret;
180 91 : uint8_t *buf = NULL;
181 91 : size_t bytes = 0;
182 :
183 91 : if (dest == NULL || a == NULL)
184 : return GNUTLS_E_INVALID_REQUEST;
185 :
186 91 : _gnutls_mpi_print_le(a, NULL, &bytes);
187 91 : if (bytes != 0)
188 91 : buf = gnutls_malloc(bytes);
189 91 : if (buf == NULL)
190 0 : return GNUTLS_E_MEMORY_ERROR;
191 :
192 91 : ret = _gnutls_mpi_print_le(a, buf, &bytes);
193 91 : if (ret < 0) {
194 0 : gnutls_free(buf);
195 0 : return ret;
196 : }
197 :
198 91 : dest->data = buf;
199 91 : dest->size = bytes;
200 91 : return 0;
201 : }
202 :
203 : /* Always has the first bit zero */
204 7844 : int _gnutls_mpi_dprint_lz(const bigint_t a, gnutls_datum_t * dest)
205 : {
206 7844 : int ret;
207 7844 : uint8_t *buf = NULL;
208 7844 : size_t bytes = 0;
209 :
210 7844 : if (dest == NULL || a == NULL)
211 : return GNUTLS_E_INVALID_REQUEST;
212 :
213 7844 : _gnutls_mpi_print_lz(a, NULL, &bytes);
214 :
215 7844 : if (bytes != 0)
216 7844 : buf = gnutls_malloc(bytes);
217 7844 : if (buf == NULL)
218 0 : return GNUTLS_E_MEMORY_ERROR;
219 :
220 7844 : ret = _gnutls_mpi_print_lz(a, buf, &bytes);
221 7844 : if (ret < 0) {
222 0 : gnutls_free(buf);
223 0 : return ret;
224 : }
225 :
226 7844 : dest->data = buf;
227 7844 : dest->size = bytes;
228 7844 : return 0;
229 : }
230 :
231 11336 : int _gnutls_mpi_dprint(const bigint_t a, gnutls_datum_t * dest)
232 : {
233 11336 : int ret;
234 11336 : uint8_t *buf = NULL;
235 11336 : size_t bytes = 0;
236 :
237 11336 : if (dest == NULL || a == NULL)
238 : return GNUTLS_E_INVALID_REQUEST;
239 :
240 11336 : _gnutls_mpi_print(a, NULL, &bytes);
241 11336 : if (bytes != 0)
242 11336 : buf = gnutls_malloc(bytes);
243 11336 : if (buf == NULL)
244 0 : return GNUTLS_E_MEMORY_ERROR;
245 :
246 11336 : ret = _gnutls_mpi_print(a, buf, &bytes);
247 11336 : if (ret < 0) {
248 0 : gnutls_free(buf);
249 0 : return ret;
250 : }
251 :
252 11336 : dest->data = buf;
253 11336 : dest->size = bytes;
254 11336 : 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
262 14112 : _gnutls_mpi_dprint_size(const bigint_t a, gnutls_datum_t * dest,
263 : size_t size)
264 : {
265 14112 : int ret;
266 14112 : uint8_t *buf = NULL;
267 14112 : size_t bytes = 0;
268 14112 : unsigned int i;
269 :
270 14112 : if (dest == NULL || a == NULL)
271 : return GNUTLS_E_INVALID_REQUEST;
272 :
273 14112 : _gnutls_mpi_print(a, NULL, &bytes);
274 14112 : if (bytes != 0)
275 14112 : buf = gnutls_malloc(MAX(size, bytes));
276 14112 : if (buf == NULL)
277 0 : return GNUTLS_E_MEMORY_ERROR;
278 :
279 14112 : if (bytes <= size) {
280 14112 : size_t diff = size - bytes;
281 14155 : for (i = 0; i < diff; i++)
282 43 : buf[i] = 0;
283 14112 : ret = _gnutls_mpi_print(a, &buf[diff], &bytes);
284 : } else {
285 0 : ret = _gnutls_mpi_print(a, buf, &bytes);
286 : }
287 :
288 14112 : if (ret < 0) {
289 0 : gnutls_free(buf);
290 0 : return ret;
291 : }
292 :
293 14112 : dest->data = buf;
294 14112 : dest->size = MAX(size, bytes);
295 14112 : return 0;
296 : }
297 :
298 : /* like _gnutls_mpi_dprint_size, but prints into preallocated byte buffer */
299 : int
300 1098 : _gnutls_mpi_bprint_size(const bigint_t a, uint8_t *buf, size_t size)
301 : {
302 1098 : int result;
303 1098 : size_t bytes = 0;
304 :
305 1098 : result = _gnutls_mpi_print(a, NULL, &bytes);
306 1098 : if (result != GNUTLS_E_SHORT_MEMORY_BUFFER)
307 0 : return gnutls_assert_val(result);
308 :
309 1098 : if (bytes <= size) {
310 1098 : unsigned i;
311 1098 : size_t diff = size - bytes;
312 :
313 1109 : for (i = 0; i < diff; i++)
314 11 : buf[i] = 0;
315 1098 : result = _gnutls_mpi_print(a, &buf[diff], &bytes);
316 : } else {
317 0 : 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
333 112493 : __gnutls_x509_read_int(ASN1_TYPE node, const char *value,
334 : bigint_t * ret_mpi, unsigned int flags)
335 : {
336 112493 : int result;
337 112493 : uint8_t *tmpstr = NULL;
338 112493 : int tmpstr_size;
339 :
340 112493 : tmpstr_size = 0;
341 112493 : result = asn1_read_value(node, value, NULL, &tmpstr_size);
342 112493 : if (result != ASN1_MEM_ERROR) {
343 48 : gnutls_assert();
344 48 : return _gnutls_asn2err(result);
345 : }
346 :
347 112445 : tmpstr = gnutls_malloc(tmpstr_size);
348 112445 : if (tmpstr == NULL) {
349 0 : gnutls_assert();
350 0 : return GNUTLS_E_MEMORY_ERROR;
351 : }
352 :
353 112445 : result = asn1_read_value(node, value, tmpstr, &tmpstr_size);
354 112445 : if (result != ASN1_SUCCESS) {
355 0 : gnutls_assert();
356 0 : gnutls_free(tmpstr);
357 0 : return _gnutls_asn2err(result);
358 : }
359 :
360 112445 : if (flags & GNUTLS_X509_INT_LE)
361 42 : result = _gnutls_mpi_init_scan_le(ret_mpi, tmpstr,
362 : tmpstr_size);
363 : else
364 112403 : result = _gnutls_mpi_init_scan(ret_mpi, tmpstr,
365 : tmpstr_size);
366 :
367 112445 : if (flags & GNUTLS_X509_INT_OVERWRITE)
368 32282 : zeroize_key(tmpstr, tmpstr_size);
369 112445 : gnutls_free(tmpstr);
370 :
371 112445 : if (result < 0) {
372 0 : gnutls_assert();
373 0 : return result;
374 : }
375 :
376 : return 0;
377 : }
378 :
379 : int
380 80196 : _gnutls_x509_read_int(ASN1_TYPE node, const char *value,
381 : bigint_t * ret_mpi)
382 : {
383 80196 : return __gnutls_x509_read_int(node, value, ret_mpi,
384 : 0);
385 : }
386 :
387 : int
388 32255 : _gnutls_x509_read_key_int(ASN1_TYPE node, const char *value,
389 : bigint_t * ret_mpi)
390 : {
391 32255 : return __gnutls_x509_read_int(node, value, ret_mpi,
392 : GNUTLS_X509_INT_OVERWRITE);
393 : }
394 :
395 : int
396 42 : _gnutls_x509_read_key_int_le(ASN1_TYPE node, const char *value,
397 : bigint_t * ret_mpi)
398 : {
399 42 : 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
407 19058 : __gnutls_x509_write_int(ASN1_TYPE node, const char *value, bigint_t mpi,
408 : unsigned int flags)
409 : {
410 19058 : uint8_t *tmpstr;
411 19058 : size_t s_len;
412 19058 : int result;
413 :
414 19058 : s_len = 0;
415 19058 : if (flags & GNUTLS_X509_INT_LZ)
416 18528 : result = _gnutls_mpi_print_lz(mpi, NULL, &s_len);
417 530 : else if (GNUTLS_X509_INT_LE)
418 530 : result = _gnutls_mpi_print_le(mpi, NULL, &s_len);
419 : else
420 : result = _gnutls_mpi_print(mpi, NULL, &s_len);
421 :
422 19058 : if (result != GNUTLS_E_SHORT_MEMORY_BUFFER) {
423 0 : gnutls_assert();
424 0 : return result;
425 : }
426 :
427 19058 : tmpstr = gnutls_malloc(s_len);
428 19058 : if (tmpstr == NULL) {
429 0 : gnutls_assert();
430 0 : return GNUTLS_E_MEMORY_ERROR;
431 : }
432 :
433 19058 : if (flags & GNUTLS_X509_INT_LZ)
434 18528 : result = _gnutls_mpi_print_lz(mpi, tmpstr, &s_len);
435 530 : else if (GNUTLS_X509_INT_LE)
436 530 : result = _gnutls_mpi_print_le(mpi, tmpstr, &s_len);
437 : else
438 : result = _gnutls_mpi_print(mpi, tmpstr, &s_len);
439 :
440 19058 : if (result != 0) {
441 0 : gnutls_assert();
442 0 : gnutls_free(tmpstr);
443 0 : return GNUTLS_E_MPI_PRINT_FAILED;
444 : }
445 :
446 19058 : result = asn1_write_value(node, value, tmpstr, s_len);
447 :
448 19058 : if (flags & GNUTLS_X509_INT_OVERWRITE)
449 3138 : zeroize_key(tmpstr, s_len);
450 :
451 19058 : gnutls_free(tmpstr);
452 :
453 19058 : if (result != ASN1_SUCCESS) {
454 0 : gnutls_assert();
455 0 : return _gnutls_asn2err(result);
456 : }
457 :
458 : return 0;
459 : }
460 :
461 : int
462 15920 : _gnutls_x509_write_int(ASN1_TYPE node, const char *value, bigint_t mpi,
463 : int lz)
464 : {
465 15920 : return __gnutls_x509_write_int(node, value, mpi,
466 : lz ? GNUTLS_X509_INT_LZ : 0);
467 : }
468 :
469 : int
470 2608 : _gnutls_x509_write_key_int(ASN1_TYPE node, const char *value, bigint_t mpi,
471 : int lz)
472 : {
473 2608 : return __gnutls_x509_write_int(node, value, mpi,
474 : (lz ? GNUTLS_X509_INT_LZ : 0) |
475 : GNUTLS_X509_INT_OVERWRITE);
476 : }
477 :
478 : int
479 530 : _gnutls_x509_write_key_int_le(ASN1_TYPE node, const char *value, bigint_t mpi)
480 : {
481 530 : return __gnutls_x509_write_int(node, value, mpi,
482 : GNUTLS_X509_INT_OVERWRITE |
483 : GNUTLS_X509_INT_LE);
484 : }
|