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