Line data Source code
1 : /* mpicoder.c - Coder for the external representation of MPIs
2 : * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
3 : * 2008 Free Software Foundation, Inc.
4 : * Copyright (C) 2013, 2014 g10 Code GmbH
5 : *
6 : * This file is part of Libgcrypt.
7 : *
8 : * Libgcrypt is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU Lesser General Public License as
10 : * published by the Free Software Foundation; either version 2.1 of
11 : * the License, or (at your option) any later version.
12 : *
13 : * Libgcrypt is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU Lesser General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU Lesser General Public
19 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include <config.h>
23 : #include <stdio.h>
24 : #include <string.h>
25 : #include <stdlib.h>
26 :
27 : #include "mpi-internal.h"
28 : #include "g10lib.h"
29 :
30 : /* The maximum length we support in the functions converting an
31 : * external representation to an MPI. This limit is used to catch
32 : * programming errors and to avoid DoS due to insane long allocations.
33 : * The 16 MiB limit is actually ridiculous large but some of those PQC
34 : * algorithms use quite large keys and they might end up using MPIs
35 : * for that. */
36 : #define MAX_EXTERN_SCAN_BYTES (16*1024*1024)
37 :
38 : /* The maximum length (in bits) we support for OpenPGP MPIs. Note
39 : * that OpenPGP's MPI format uses only two bytes and thus would be
40 : * limited to 64k anyway. Note that this limit matches that used by
41 : * GnuPG. */
42 : #define MAX_EXTERN_MPI_BITS 16384
43 :
44 :
45 : /* Helper used to scan PGP style MPIs. Returns NULL on failure. */
46 : static gcry_mpi_t
47 14 : mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
48 : int secure)
49 : {
50 : int i, j;
51 14 : unsigned int nbits, nbytes, nlimbs, nread=0;
52 : mpi_limb_t a;
53 14 : gcry_mpi_t val = MPI_NULL;
54 :
55 14 : if ( *ret_nread < 2 )
56 0 : goto leave;
57 14 : nbits = buffer[0] << 8 | buffer[1];
58 14 : if ( nbits > MAX_EXTERN_MPI_BITS )
59 : {
60 : /* log_debug ("mpi too large (%u bits)\n", nbits); */
61 1 : goto leave;
62 : }
63 13 : buffer += 2;
64 13 : nread = 2;
65 :
66 13 : nbytes = (nbits+7) / 8;
67 13 : nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
68 13 : val = secure? mpi_alloc_secure (nlimbs) : mpi_alloc (nlimbs);
69 13 : i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
70 13 : i %= BYTES_PER_MPI_LIMB;
71 13 : j= val->nlimbs = nlimbs;
72 13 : val->sign = 0;
73 280 : for ( ; j > 0; j-- )
74 : {
75 267 : a = 0;
76 2333 : for (; i < BYTES_PER_MPI_LIMB; i++ )
77 : {
78 2066 : if ( ++nread > *ret_nread )
79 : {
80 : /* log_debug ("mpi larger than buffer"); */
81 0 : mpi_free (val);
82 0 : val = NULL;
83 0 : goto leave;
84 : }
85 2066 : a <<= 8;
86 2066 : a |= *buffer++;
87 : }
88 267 : i = 0;
89 267 : val->d[j-1] = a;
90 : }
91 :
92 : leave:
93 14 : *ret_nread = nread;
94 14 : return val;
95 : }
96 :
97 :
98 : /****************
99 : * Fill the mpi VAL from the hex string in STR.
100 : */
101 : static int
102 17368 : mpi_fromstr (gcry_mpi_t val, const char *str)
103 : {
104 17368 : int sign = 0;
105 17368 : int prepend_zero = 0;
106 : int i, j, c, c1, c2;
107 : unsigned int nbits, nbytes, nlimbs;
108 : mpi_limb_t a;
109 :
110 17368 : if ( *str == '-' )
111 : {
112 4206 : sign = 1;
113 4206 : str++;
114 : }
115 :
116 : /* Skip optional hex prefix. */
117 17368 : if ( *str == '0' && str[1] == 'x' )
118 17180 : str += 2;
119 :
120 17368 : nbits = strlen (str);
121 17368 : if (nbits > MAX_EXTERN_SCAN_BYTES)
122 : {
123 0 : mpi_clear (val);
124 0 : return 1; /* Error. */
125 : }
126 17368 : nbits *= 4;
127 17368 : if ((nbits % 8))
128 95 : prepend_zero = 1;
129 :
130 17368 : nbytes = (nbits+7) / 8;
131 17368 : nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
132 :
133 17368 : if ( val->alloced < nlimbs )
134 17368 : mpi_resize (val, nlimbs);
135 :
136 17368 : i = BYTES_PER_MPI_LIMB - (nbytes % BYTES_PER_MPI_LIMB);
137 17368 : i %= BYTES_PER_MPI_LIMB;
138 17368 : j = val->nlimbs = nlimbs;
139 17368 : val->sign = sign;
140 75593 : for (; j > 0; j--)
141 : {
142 58225 : a = 0;
143 488584 : for (; i < BYTES_PER_MPI_LIMB; i++)
144 : {
145 430359 : if (prepend_zero)
146 : {
147 95 : c1 = '0';
148 95 : prepend_zero = 0;
149 : }
150 : else
151 430264 : c1 = *str++;
152 :
153 430359 : if (!c1)
154 : {
155 0 : mpi_clear (val);
156 0 : return 1; /* Error. */
157 : }
158 430359 : c2 = *str++;
159 430359 : if (!c2)
160 : {
161 0 : mpi_clear (val);
162 0 : return 1; /* Error. */
163 : }
164 430359 : if ( c1 >= '0' && c1 <= '9' )
165 249467 : c = c1 - '0';
166 180892 : else if ( c1 >= 'a' && c1 <= 'f' )
167 40244 : c = c1 - 'a' + 10;
168 140648 : else if ( c1 >= 'A' && c1 <= 'F' )
169 140648 : c = c1 - 'A' + 10;
170 : else
171 : {
172 0 : mpi_clear (val);
173 0 : return 1; /* Error. */
174 : }
175 430359 : c <<= 4;
176 430359 : if ( c2 >= '0' && c2 <= '9' )
177 262550 : c |= c2 - '0';
178 167809 : else if( c2 >= 'a' && c2 <= 'f' )
179 39912 : c |= c2 - 'a' + 10;
180 127897 : else if( c2 >= 'A' && c2 <= 'F' )
181 127897 : c |= c2 - 'A' + 10;
182 : else
183 : {
184 0 : mpi_clear(val);
185 0 : return 1; /* Error. */
186 : }
187 430359 : a <<= 8;
188 430359 : a |= c;
189 : }
190 58225 : i = 0;
191 58225 : val->d[j-1] = a;
192 : }
193 :
194 17368 : return 0; /* Okay. */
195 : }
196 :
197 :
198 : /* Return an allocated buffer with the MPI (msb first). NBYTES
199 : receives the length of this buffer. If FILL_LE is not 0, the
200 : returned value is stored as little endian and right padded with
201 : zeroes so that the returned buffer has at least FILL_LE bytes.
202 :
203 : If EXTRAALLOC > 0 the returned buffer has these number of bytes
204 : extra allocated at the end; if EXTRAALLOC < 0 the returned buffer
205 : has the absolute value of EXTRAALLOC allocated at the begin of the
206 : buffer (the are not initialized) and the MPI is stored right after
207 : this. This feature is useful to allow the caller to prefix the
208 : returned value. EXTRAALLOC is _not_ included in the value stored
209 : at NBYTES.
210 :
211 : Caller must free the return string. This function returns an
212 : allocated buffer with NBYTES set to zero if the value of A is zero.
213 : If sign is not NULL, it will be set to the sign of the A. On error
214 : NULL is returned and ERRNO set appropriately. */
215 : static unsigned char *
216 9916 : do_get_buffer (gcry_mpi_t a, unsigned int fill_le, int extraalloc,
217 : unsigned int *nbytes, int *sign, int force_secure)
218 : {
219 : unsigned char *p, *buffer, *retbuffer;
220 : unsigned int length, tmp;
221 : mpi_limb_t alimb;
222 : int i;
223 : size_t n, n2;
224 :
225 9916 : if (sign)
226 0 : *sign = a->sign;
227 :
228 9916 : *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
229 9916 : n = *nbytes? *nbytes:1; /* Allocate at least one byte. */
230 9916 : if (n < fill_le)
231 7 : n = fill_le;
232 9916 : if (extraalloc < 0)
233 38 : n2 = n + -extraalloc;
234 : else
235 9878 : n2 = n + extraalloc;
236 :
237 9916 : retbuffer = (force_secure || mpi_is_secure(a))? xtrymalloc_secure (n2)
238 : : xtrymalloc (n2);
239 9916 : if (!retbuffer)
240 0 : return NULL;
241 9916 : if (extraalloc < 0)
242 38 : buffer = retbuffer + -extraalloc;
243 : else
244 9878 : buffer = retbuffer;
245 9916 : p = buffer;
246 :
247 90565 : for (i=a->nlimbs-1; i >= 0; i--)
248 : {
249 80649 : alimb = a->d[i];
250 : #if BYTES_PER_MPI_LIMB == 4
251 : *p++ = alimb >> 24;
252 : *p++ = alimb >> 16;
253 : *p++ = alimb >> 8;
254 : *p++ = alimb ;
255 : #elif BYTES_PER_MPI_LIMB == 8
256 80649 : *p++ = alimb >> 56;
257 80649 : *p++ = alimb >> 48;
258 80649 : *p++ = alimb >> 40;
259 80649 : *p++ = alimb >> 32;
260 80649 : *p++ = alimb >> 24;
261 80649 : *p++ = alimb >> 16;
262 80649 : *p++ = alimb >> 8;
263 80649 : *p++ = alimb ;
264 : #else
265 : # error please implement for this limb size.
266 : #endif
267 : }
268 :
269 9916 : if (fill_le)
270 : {
271 4182 : length = *nbytes;
272 : /* Reverse buffer and pad with zeroes. */
273 70982 : for (i=0; i < length/2; i++)
274 : {
275 66800 : tmp = buffer[i];
276 66800 : buffer[i] = buffer[length-1-i];
277 66800 : buffer[length-1-i] = tmp;
278 : }
279 : /* Pad with zeroes. */
280 4406 : for (p = buffer + length; length < fill_le; length++)
281 224 : *p++ = 0;
282 4182 : *nbytes = length;
283 :
284 4182 : return retbuffer;
285 : }
286 :
287 : /* This is sub-optimal but we need to do the shift operation because
288 : the caller has to free the returned buffer. */
289 5734 : for (p=buffer; *nbytes && !*p; p++, --*nbytes)
290 : ;
291 5734 : if (p != buffer)
292 2116 : memmove (buffer, p, *nbytes);
293 5734 : return retbuffer;
294 : }
295 :
296 :
297 : byte *
298 6770 : _gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int fill_le,
299 : unsigned int *r_nbytes, int *sign)
300 : {
301 6770 : return do_get_buffer (a, fill_le, 0, r_nbytes, sign, 0);
302 : }
303 :
304 : byte *
305 3146 : _gcry_mpi_get_buffer_extra (gcry_mpi_t a, unsigned int fill_le, int extraalloc,
306 : unsigned int *r_nbytes, int *sign)
307 : {
308 3146 : return do_get_buffer (a, fill_le, extraalloc, r_nbytes, sign, 0);
309 : }
310 :
311 : byte *
312 0 : _gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned int fill_le,
313 : unsigned int *r_nbytes, int *sign)
314 : {
315 0 : return do_get_buffer (a, fill_le, 0, r_nbytes, sign, 1);
316 : }
317 :
318 :
319 : /*
320 : * Use the NBYTES at BUFFER_ARG to update A. Set the sign of a to
321 : * SIGN.
322 : */
323 : void
324 84276 : _gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg,
325 : unsigned int nbytes, int sign)
326 : {
327 84276 : const unsigned char *buffer = (const unsigned char*)buffer_arg;
328 : const unsigned char *p;
329 : mpi_limb_t alimb;
330 : int nlimbs;
331 : int i;
332 :
333 84276 : if (mpi_is_immutable (a))
334 : {
335 0 : mpi_immutable_failed ();
336 0 : return;
337 : }
338 :
339 84276 : nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
340 84276 : RESIZE_IF_NEEDED(a, nlimbs);
341 84276 : a->sign = sign;
342 :
343 585924 : for (i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; )
344 : {
345 : #if BYTES_PER_MPI_LIMB == 4
346 : alimb = *p-- ;
347 : alimb |= *p-- << 8 ;
348 : alimb |= *p-- << 16 ;
349 : alimb |= *p-- << 24 ;
350 : #elif BYTES_PER_MPI_LIMB == 8
351 417372 : alimb = (mpi_limb_t)*p-- ;
352 417372 : alimb |= (mpi_limb_t)*p-- << 8 ;
353 417372 : alimb |= (mpi_limb_t)*p-- << 16 ;
354 417372 : alimb |= (mpi_limb_t)*p-- << 24 ;
355 417372 : alimb |= (mpi_limb_t)*p-- << 32 ;
356 417372 : alimb |= (mpi_limb_t)*p-- << 40 ;
357 417372 : alimb |= (mpi_limb_t)*p-- << 48 ;
358 417372 : alimb |= (mpi_limb_t)*p-- << 56 ;
359 : #else
360 : # error please implement for this limb size.
361 : #endif
362 417372 : a->d[i++] = alimb;
363 : }
364 84276 : if ( p >= buffer )
365 : {
366 : #if BYTES_PER_MPI_LIMB == 4
367 : alimb = *p--;
368 : if (p >= buffer)
369 : alimb |= *p-- << 8;
370 : if (p >= buffer)
371 : alimb |= *p-- << 16;
372 : if (p >= buffer)
373 : alimb |= *p-- << 24;
374 : #elif BYTES_PER_MPI_LIMB == 8
375 84276 : alimb = (mpi_limb_t)*p--;
376 84276 : if (p >= buffer)
377 78115 : alimb |= (mpi_limb_t)*p-- << 8;
378 84276 : if (p >= buffer)
379 77809 : alimb |= (mpi_limb_t)*p-- << 16;
380 84276 : if (p >= buffer)
381 75524 : alimb |= (mpi_limb_t)*p-- << 24;
382 84276 : if (p >= buffer)
383 19384 : alimb |= (mpi_limb_t)*p-- << 32;
384 84276 : if (p >= buffer)
385 16941 : alimb |= (mpi_limb_t)*p-- << 40;
386 84276 : if (p >= buffer)
387 16168 : alimb |= (mpi_limb_t)*p-- << 48;
388 84276 : if (p >= buffer)
389 15877 : alimb |= (mpi_limb_t)*p-- << 56;
390 : #else
391 : # error please implement for this limb size.
392 : #endif
393 84276 : a->d[i++] = alimb;
394 : }
395 84276 : a->nlimbs = i;
396 84276 : gcry_assert (i == nlimbs);
397 : }
398 :
399 :
400 : static void
401 23 : onecompl (gcry_mpi_t a)
402 : {
403 : mpi_ptr_t ap;
404 : mpi_size_t n;
405 : unsigned int i;
406 : unsigned int nbits;
407 :
408 23 : if (!a || mpi_is_immutable (a))
409 : {
410 0 : mpi_immutable_failed ();
411 23 : return;
412 : }
413 :
414 23 : nbits = mpi_get_nbits (a);
415 :
416 23 : mpi_normalize (a);
417 23 : ap = a->d;
418 23 : n = a->nlimbs;
419 :
420 46 : for( i = 0; i < n; i++ )
421 23 : ap[i] ^= (mpi_limb_t)(-1);
422 :
423 23 : a->sign = 0;
424 23 : mpi_clear_highbit (a, nbits-1);
425 : }
426 :
427 :
428 : /* Perform a two's complement operation on buffer P of size N bytes. */
429 : static void
430 44 : twocompl (unsigned char *p, unsigned int n)
431 : {
432 : int i;
433 :
434 44 : for (i=n-1; i >= 0 && !p[i]; i--)
435 : ;
436 44 : if (i >= 0)
437 : {
438 44 : if ((p[i] & 0x01))
439 36 : p[i] = (((p[i] ^ 0xfe) | 0x01) & 0xff);
440 8 : else if ((p[i] & 0x02))
441 4 : p[i] = (((p[i] ^ 0xfc) | 0x02) & 0xfe);
442 4 : else if ((p[i] & 0x04))
443 0 : p[i] = (((p[i] ^ 0xf8) | 0x04) & 0xfc);
444 4 : else if ((p[i] & 0x08))
445 0 : p[i] = (((p[i] ^ 0xf0) | 0x08) & 0xf8);
446 4 : else if ((p[i] & 0x10))
447 0 : p[i] = (((p[i] ^ 0xe0) | 0x10) & 0xf0);
448 4 : else if ((p[i] & 0x20))
449 0 : p[i] = (((p[i] ^ 0xc0) | 0x20) & 0xe0);
450 4 : else if ((p[i] & 0x40))
451 0 : p[i] = (((p[i] ^ 0x80) | 0x40) & 0xc0);
452 : else
453 4 : p[i] = 0x80;
454 :
455 60 : for (i--; i >= 0; i--)
456 16 : p[i] ^= 0xff;
457 : }
458 44 : }
459 :
460 :
461 : /* Convert the external representation of an integer stored in BUFFER
462 : * with a length of BUFLEN into a newly create MPI returned in
463 : * RET_MPI. If NSCANNED is not NULL, it will receive the number of
464 : * bytes actually scanned after a successful operation. */
465 : gcry_err_code_t
466 87023 : _gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
467 : const void *buffer_arg, size_t buflen, size_t *nscanned)
468 : {
469 87023 : const unsigned char *buffer = (const unsigned char*)buffer_arg;
470 87023 : struct gcry_mpi *a = NULL;
471 : unsigned int len;
472 87023 : int secure = (buffer && _gcry_is_secure (buffer));
473 :
474 87023 : if (buflen > MAX_EXTERN_SCAN_BYTES)
475 : {
476 1 : if (nscanned)
477 0 : *nscanned = 0;
478 1 : return GPG_ERR_INV_OBJ;
479 : }
480 :
481 87022 : if (format == GCRYMPI_FMT_SSH)
482 23 : len = 0;
483 : else
484 86999 : len = buflen;
485 :
486 87022 : if (format == GCRYMPI_FMT_STD)
487 : {
488 134 : const unsigned char *s = buffer;
489 :
490 134 : a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
491 : /BYTES_PER_MPI_LIMB)
492 134 : : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
493 134 : if (len)
494 : {
495 133 : _gcry_mpi_set_buffer (a, s, len, 0);
496 133 : a->sign = !!(*s & 0x80);
497 133 : if (a->sign)
498 : {
499 12 : onecompl (a);
500 12 : mpi_add_ui (a, a, 1);
501 12 : a->sign = 1;
502 : }
503 : }
504 134 : if (ret_mpi)
505 : {
506 134 : mpi_normalize ( a );
507 134 : *ret_mpi = a;
508 : }
509 : else
510 0 : mpi_free(a);
511 134 : if (nscanned)
512 23 : *nscanned = len;
513 134 : return 0;
514 : }
515 86888 : else if (format == GCRYMPI_FMT_USG)
516 : {
517 69483 : a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
518 : /BYTES_PER_MPI_LIMB)
519 69483 : : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
520 :
521 69483 : if (len)
522 69481 : _gcry_mpi_set_buffer (a, buffer, len, 0);
523 69483 : if (ret_mpi)
524 : {
525 69483 : mpi_normalize ( a );
526 69483 : *ret_mpi = a;
527 : }
528 : else
529 0 : mpi_free(a);
530 69483 : if (nscanned)
531 1124 : *nscanned = len;
532 69483 : return 0;
533 : }
534 17405 : else if (format == GCRYMPI_FMT_PGP)
535 : {
536 14 : a = mpi_read_from_buffer (buffer, &len, secure);
537 14 : if (nscanned)
538 12 : *nscanned = len;
539 14 : if (ret_mpi && a)
540 : {
541 13 : mpi_normalize (a);
542 13 : *ret_mpi = a;
543 : }
544 1 : else if (a)
545 : {
546 0 : mpi_free(a);
547 0 : a = NULL;
548 : }
549 14 : return a? 0 : GPG_ERR_INV_OBJ;
550 : }
551 17391 : else if (format == GCRYMPI_FMT_SSH)
552 : {
553 23 : const unsigned char *s = buffer;
554 : size_t n;
555 :
556 : /* This test is not strictly necessary and an assert (!len)
557 : would be sufficient. We keep this test in case we later
558 : allow the BUFLEN argument to act as a sanitiy check. Same
559 : below. */
560 23 : if (len && len < 4)
561 0 : return GPG_ERR_TOO_SHORT;
562 :
563 23 : n = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
564 23 : s += 4;
565 23 : if (len)
566 0 : len -= 4;
567 23 : if (len && n > len)
568 0 : return GPG_ERR_TOO_LARGE;
569 :
570 23 : a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1)
571 : /BYTES_PER_MPI_LIMB)
572 23 : : mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
573 23 : if (n)
574 : {
575 22 : _gcry_mpi_set_buffer( a, s, n, 0 );
576 22 : a->sign = !!(*s & 0x80);
577 22 : if (a->sign)
578 : {
579 11 : onecompl (a);
580 11 : mpi_add_ui (a, a, 1);
581 11 : a->sign = 1;
582 : }
583 : }
584 23 : if (nscanned)
585 23 : *nscanned = n+4;
586 23 : if (ret_mpi)
587 : {
588 23 : mpi_normalize ( a );
589 23 : *ret_mpi = a;
590 : }
591 : else
592 0 : mpi_free(a);
593 23 : return 0;
594 : }
595 17368 : else if (format == GCRYMPI_FMT_HEX)
596 : {
597 : /* We can only handle C strings for now. */
598 17368 : if (buflen)
599 0 : return GPG_ERR_INV_ARG;
600 :
601 17368 : a = secure? mpi_alloc_secure (0) : mpi_alloc(0);
602 17368 : if (mpi_fromstr (a, (const char *)buffer))
603 : {
604 0 : mpi_free (a);
605 0 : return GPG_ERR_INV_OBJ;
606 : }
607 17368 : if (ret_mpi)
608 : {
609 17368 : mpi_normalize ( a );
610 17368 : *ret_mpi = a;
611 : }
612 : else
613 0 : mpi_free(a);
614 17368 : if (nscanned)
615 23 : *nscanned = strlen ((const char*)buffer);
616 17368 : return 0;
617 : }
618 : else
619 0 : return GPG_ERR_INV_ARG;
620 : }
621 :
622 :
623 : /* Convert the big integer A into the external representation
624 : described by FORMAT and store it in the provided BUFFER which has
625 : been allocated by the user with a size of BUFLEN bytes. NWRITTEN
626 : receives the actual length of the external representation unless it
627 : has been passed as NULL. BUFFER may be NULL to query the required
628 : length. */
629 : gcry_err_code_t
630 6466 : _gcry_mpi_print (enum gcry_mpi_format format,
631 : unsigned char *buffer, size_t buflen,
632 : size_t *nwritten, struct gcry_mpi *a)
633 : {
634 6466 : unsigned int nbits = mpi_get_nbits (a);
635 : size_t len;
636 : size_t dummy_nwritten;
637 : int negative;
638 :
639 6466 : if (!nwritten)
640 1304 : nwritten = &dummy_nwritten;
641 :
642 : /* Libgcrypt does no always care to set clear the sign if the value
643 : is 0. For printing this is a bit of a surprise, in particular
644 : because if some of the formats don't support negative numbers but
645 : should be able to print a zero. Thus we need this extra test
646 : for a negative number. */
647 6466 : if (a->sign && _gcry_mpi_cmp_ui (a, 0))
648 99 : negative = 1;
649 : else
650 6367 : negative = 0;
651 :
652 6466 : len = buflen;
653 6466 : *nwritten = 0;
654 6466 : if (format == GCRYMPI_FMT_STD)
655 : {
656 : unsigned char *tmp;
657 2284 : int extra = 0;
658 : unsigned int n;
659 :
660 2284 : tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL);
661 2284 : if (!tmp)
662 0 : return gpg_err_code_from_syserror ();
663 :
664 2284 : if (negative)
665 : {
666 22 : twocompl (tmp, n);
667 22 : if (!(*tmp & 0x80))
668 : {
669 : /* Need to extend the sign. */
670 6 : n++;
671 6 : extra = 2;
672 : }
673 : }
674 2262 : else if (n && (*tmp & 0x80))
675 : {
676 : /* Positive but the high bit of the returned buffer is set.
677 : Thus we need to print an extra leading 0x00 so that the
678 : output is interpreted as a positive number. */
679 976 : n++;
680 976 : extra = 1;
681 : }
682 :
683 2284 : if (buffer && n > len)
684 : {
685 : /* The provided buffer is too short. */
686 0 : xfree (tmp);
687 0 : return GPG_ERR_TOO_SHORT;
688 : }
689 2284 : if (buffer)
690 : {
691 1142 : unsigned char *s = buffer;
692 :
693 1142 : if (extra == 1)
694 488 : *s++ = 0;
695 654 : else if (extra)
696 3 : *s++ = 0xff;
697 1142 : memcpy (s, tmp, n-!!extra);
698 : }
699 2284 : xfree (tmp);
700 2284 : *nwritten = n;
701 2284 : return 0;
702 : }
703 4182 : else if (format == GCRYMPI_FMT_USG)
704 : {
705 4035 : unsigned int n = (nbits + 7)/8;
706 :
707 : /* Note: We ignore the sign for this format. */
708 : /* FIXME: for performance reasons we should put this into
709 : mpi_aprint because we can then use the buffer directly. */
710 :
711 4035 : if (buffer && n > len)
712 0 : return GPG_ERR_TOO_SHORT;
713 4035 : if (buffer)
714 : {
715 : unsigned char *tmp;
716 :
717 2238 : tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL);
718 2238 : if (!tmp)
719 0 : return gpg_err_code_from_syserror ();
720 2238 : memcpy (buffer, tmp, n);
721 2238 : xfree (tmp);
722 : }
723 4035 : *nwritten = n;
724 4035 : return 0;
725 : }
726 147 : else if (format == GCRYMPI_FMT_PGP)
727 : {
728 39 : unsigned int n = (nbits + 7)/8;
729 :
730 : /* The PGP format can only handle unsigned integers. */
731 39 : if (negative)
732 11 : return GPG_ERR_INV_ARG;
733 :
734 28 : if (buffer && n+2 > len)
735 0 : return GPG_ERR_TOO_SHORT;
736 :
737 28 : if (buffer)
738 : {
739 : unsigned char *tmp;
740 14 : unsigned char *s = buffer;
741 :
742 14 : s[0] = nbits >> 8;
743 14 : s[1] = nbits;
744 :
745 14 : tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL);
746 14 : if (!tmp)
747 0 : return gpg_err_code_from_syserror ();
748 14 : memcpy (s+2, tmp, n);
749 14 : xfree (tmp);
750 : }
751 28 : *nwritten = n+2;
752 28 : return 0;
753 : }
754 108 : else if (format == GCRYMPI_FMT_SSH)
755 : {
756 : unsigned char *tmp;
757 50 : int extra = 0;
758 : unsigned int n;
759 :
760 50 : tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL);
761 50 : if (!tmp)
762 0 : return gpg_err_code_from_syserror ();
763 :
764 50 : if (negative)
765 : {
766 22 : twocompl (tmp, n);
767 22 : if (!(*tmp & 0x80))
768 : {
769 : /* Need to extend the sign. */
770 6 : n++;
771 6 : extra = 2;
772 : }
773 : }
774 28 : else if (n && (*tmp & 0x80))
775 : {
776 8 : n++;
777 8 : extra=1;
778 : }
779 :
780 50 : if (buffer && n+4 > len)
781 : {
782 0 : xfree(tmp);
783 0 : return GPG_ERR_TOO_SHORT;
784 : }
785 :
786 50 : if (buffer)
787 : {
788 25 : unsigned char *s = buffer;
789 :
790 25 : *s++ = n >> 24;
791 25 : *s++ = n >> 16;
792 25 : *s++ = n >> 8;
793 25 : *s++ = n;
794 25 : if (extra == 1)
795 4 : *s++ = 0;
796 21 : else if (extra)
797 3 : *s++ = 0xff;
798 25 : memcpy (s, tmp, n-!!extra);
799 : }
800 50 : xfree (tmp);
801 50 : *nwritten = 4+n;
802 50 : return 0;
803 : }
804 58 : else if (format == GCRYMPI_FMT_HEX)
805 : {
806 : unsigned char *tmp;
807 : int i;
808 58 : int extra = 0;
809 58 : unsigned int n = 0;
810 :
811 58 : tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL);
812 58 : if (!tmp)
813 0 : return gpg_err_code_from_syserror ();
814 58 : if (!n || (*tmp & 0x80))
815 22 : extra = 2;
816 :
817 58 : if (buffer && 2*n + extra + negative + 1 > len)
818 : {
819 0 : xfree(tmp);
820 0 : return GPG_ERR_TOO_SHORT;
821 : }
822 58 : if (buffer)
823 : {
824 29 : unsigned char *s = buffer;
825 :
826 29 : if (negative)
827 11 : *s++ = '-';
828 29 : if (extra)
829 : {
830 11 : *s++ = '0';
831 11 : *s++ = '0';
832 : }
833 :
834 305 : for (i=0; i < n; i++)
835 : {
836 276 : unsigned int c = tmp[i];
837 :
838 276 : *s++ = (c >> 4) < 10? '0'+(c>>4) : 'A'+(c>>4)-10 ;
839 276 : c &= 15;
840 276 : *s++ = c < 10? '0'+c : 'A'+c-10 ;
841 : }
842 29 : *s++ = 0;
843 29 : *nwritten = s - buffer;
844 : }
845 : else
846 : {
847 29 : *nwritten = 2*n + extra + negative + 1;
848 : }
849 58 : xfree (tmp);
850 58 : return 0;
851 : }
852 : else
853 0 : return GPG_ERR_INV_ARG;
854 : }
855 :
856 :
857 : /*
858 : * Like gcry_mpi_print but this function allocates the buffer itself.
859 : * The caller has to supply the address of a pointer. NWRITTEN may be
860 : * NULL.
861 : */
862 : gcry_err_code_t
863 129 : _gcry_mpi_aprint (enum gcry_mpi_format format,
864 : unsigned char **buffer, size_t *nwritten,
865 : struct gcry_mpi *a)
866 : {
867 : size_t n;
868 : gcry_err_code_t rc;
869 :
870 129 : *buffer = NULL;
871 129 : rc = _gcry_mpi_print (format, NULL, 0, &n, a);
872 129 : if (rc)
873 11 : return rc;
874 :
875 118 : *buffer = mpi_is_secure(a) ? xtrymalloc_secure (n?n:1) : xtrymalloc (n?n:1);
876 118 : if (!*buffer)
877 0 : return gpg_err_code_from_syserror ();
878 : /* If the returned buffer will have a length of 0, we nevertheless
879 : allocated 1 byte (malloc needs it anyway) and store a 0. */
880 118 : if (!n)
881 6 : **buffer = 0;
882 118 : rc = _gcry_mpi_print( format, *buffer, n, &n, a );
883 118 : if (rc)
884 : {
885 0 : xfree (*buffer);
886 0 : *buffer = NULL;
887 : }
888 118 : else if (nwritten)
889 81 : *nwritten = n;
890 118 : return rc;
891 : }
892 :
893 :
894 : /* Turn VALUE into an octet string and store it in an allocated buffer
895 : at R_FRAME or - if R_RAME is NULL - copy it into the caller
896 : provided buffer SPACE; either SPACE or R_FRAME may be used. If
897 : SPACE if not NULL, the caller must provide a buffer of at least
898 : NBYTES. If the resulting octet string is shorter than NBYTES pad
899 : it to the left with zeroes. If VALUE does not fit into NBYTES
900 : return an error code. */
901 : gpg_err_code_t
902 1154 : _gcry_mpi_to_octet_string (unsigned char **r_frame, void *space,
903 : gcry_mpi_t value, size_t nbytes)
904 : {
905 : gpg_err_code_t rc;
906 : size_t nframe, noff, n;
907 : unsigned char *frame;
908 :
909 1154 : if (!r_frame == !space)
910 0 : return GPG_ERR_INV_ARG; /* Only one may be used. */
911 :
912 1154 : if (r_frame)
913 1070 : *r_frame = NULL;
914 :
915 1154 : rc = _gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nframe, value);
916 1154 : if (rc)
917 0 : return rc;
918 1154 : if (nframe > nbytes)
919 0 : return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */
920 :
921 1154 : noff = (nframe < nbytes)? nbytes - nframe : 0;
922 1154 : n = nframe + noff;
923 1154 : if (space)
924 84 : frame = space;
925 : else
926 : {
927 1070 : frame = mpi_is_secure (value)? xtrymalloc_secure (n) : xtrymalloc (n);
928 1070 : if (!frame)
929 : {
930 0 : rc = gpg_err_code_from_syserror ();
931 0 : return rc;
932 : }
933 : }
934 1154 : if (noff)
935 194 : memset (frame, 0, noff);
936 1154 : nframe += noff;
937 1154 : rc = _gcry_mpi_print (GCRYMPI_FMT_USG, frame+noff, nframe-noff, NULL, value);
938 1154 : if (rc)
939 : {
940 0 : xfree (frame);
941 0 : return rc;
942 : }
943 :
944 1154 : if (r_frame)
945 1070 : *r_frame = frame;
946 1154 : return 0;
947 : }
|