Line data Source code
1 : /* sexp.c - S-Expression handling
2 : * Copyright (C) 1999, 2000, 2001, 2002, 2003,
3 : * 2004, 2006, 2007, 2008, 2011 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, write to the Free Software
20 : * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 : */
22 :
23 :
24 : #include <config.h>
25 : #include <stdio.h>
26 : #include <stdlib.h>
27 : #include <string.h>
28 : #include <stdarg.h>
29 : #include <ctype.h>
30 : #include <errno.h>
31 :
32 : #define GCRYPT_NO_MPI_MACROS 1
33 : #include "g10lib.h"
34 :
35 :
36 : /* Notes on the internal memory layout.
37 :
38 : We store an S-expression as one memory buffer with tags, length and
39 : value. The simplest list would thus be:
40 :
41 : /----------+----------+---------+------+-----------+----------\
42 : | open_tag | data_tag | datalen | data | close_tag | stop_tag |
43 : \----------+----------+---------+------+-----------+----------/
44 :
45 : Expressed more compact and with an example:
46 :
47 : /----+----+----+---+----+----\
48 : | OT | DT | DL | D | CT | ST | "(foo)"
49 : \----+----+----+---+----+----/
50 :
51 : The open tag must always be the first tag of a list as requires by
52 : the S-expression specs. At least data element (data_tag, datalen,
53 : data) is required as well. The close_tag finishes the list and
54 : would actually be sufficient. For fail-safe reasons a final stop
55 : tag is always the last byte in a buffer; it has a value of 0 so
56 : that string function accidently applied to an S-expression will
57 : never access unallocated data. We do not support display hints and
58 : thus don't need to represent them. A list may have more an
59 : arbitrary number of data elements but at least one is required.
60 : The length of each data must be greater than 0 and has a current
61 : limit to 65535 bytes (by means of the DATALEN type).
62 :
63 : A list with two data elements:
64 :
65 : /----+----+----+---+----+----+---+----+----\
66 : | OT | DT | DL | D | DT | DL | D | CT | ST | "(foo bar)"
67 : \----+----+----+---+----+----+---+----+----/
68 :
69 : In the above example both DL fields have a value of 3.
70 : A list of a list with one data element:
71 :
72 : /----+----+----+----+---+----+----+----\
73 : | OT | OT | DT | DL | D | CT | CT | ST | "((foo))"
74 : \----+----+----+----+---+----+----+----/
75 :
76 : A list with one element followed by another list:
77 :
78 : /----+----+----+---+----+----+----+---+----+----+----\
79 : | OT | DT | DL | D | OT | DT | DL | D | CT | CT | ST | "(foo (bar))"
80 : \----+----+----+---+----+----+----+---+----+----+----/
81 :
82 : */
83 :
84 : typedef unsigned short DATALEN;
85 :
86 : struct gcry_sexp
87 : {
88 : byte d[1];
89 : };
90 :
91 : #define ST_STOP 0
92 : #define ST_DATA 1 /* datalen follows */
93 : /*#define ST_HINT 2 datalen follows (currently not used) */
94 : #define ST_OPEN 3
95 : #define ST_CLOSE 4
96 :
97 : /* The atoi macros assume that the buffer has only valid digits. */
98 : #define atoi_1(p) (*(p) - '0' )
99 : #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
100 : *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
101 : #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
102 :
103 : #define TOKEN_SPECIALS "-./_:*+="
104 :
105 : static gcry_err_code_t
106 : do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
107 : const char *buffer, size_t length, int argflag,
108 : void **arg_list, va_list arg_ptr);
109 :
110 : static gcry_err_code_t
111 : do_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
112 : const char *buffer, size_t length, int argflag,
113 : void **arg_list, ...);
114 :
115 : /* Return true if P points to a byte containing a whitespace according
116 : to the S-expressions definition. */
117 : #undef whitespacep
118 : static GPG_ERR_INLINE int
119 213305 : whitespacep (const char *p)
120 : {
121 213305 : switch (*p)
122 : {
123 51968 : case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1;
124 161337 : default: return 0;
125 : }
126 : }
127 :
128 :
129 : #if 0
130 : static void
131 : dump_mpi( gcry_mpi_t a )
132 : {
133 : char buffer[1000];
134 : size_t n = 1000;
135 :
136 : if( !a )
137 : fputs("[no MPI]", stderr );
138 : else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) )
139 : fputs("[MPI too large to print]", stderr );
140 : else
141 : fputs( buffer, stderr );
142 : }
143 : #endif
144 :
145 : static void
146 0 : dump_string (const byte *p, size_t n, int delim )
147 : {
148 0 : for (; n; n--, p++ )
149 : {
150 0 : if ((*p & 0x80) || iscntrl( *p ) || *p == delim )
151 : {
152 0 : if( *p == '\n' )
153 0 : log_printf ("\\n");
154 0 : else if( *p == '\r' )
155 0 : log_printf ("\\r");
156 0 : else if( *p == '\f' )
157 0 : log_printf ("\\f");
158 0 : else if( *p == '\v' )
159 0 : log_printf ("\\v");
160 0 : else if( *p == '\b' )
161 0 : log_printf ("\\b");
162 0 : else if( !*p )
163 0 : log_printf ("\\0");
164 : else
165 0 : log_printf ("\\x%02x", *p );
166 : }
167 : else
168 0 : log_printf ("%c", *p);
169 : }
170 0 : }
171 :
172 :
173 : void
174 0 : _gcry_sexp_dump (const gcry_sexp_t a)
175 : {
176 : const byte *p;
177 0 : int indent = 0;
178 : int type;
179 :
180 0 : if (!a)
181 : {
182 0 : log_printf ( "[nil]\n");
183 0 : return;
184 : }
185 :
186 0 : p = a->d;
187 0 : while ( (type = *p) != ST_STOP )
188 : {
189 0 : p++;
190 0 : switch ( type )
191 : {
192 : case ST_OPEN:
193 0 : log_printf ("%*s[open]\n", 2*indent, "");
194 0 : indent++;
195 0 : break;
196 : case ST_CLOSE:
197 0 : if( indent )
198 0 : indent--;
199 0 : log_printf ("%*s[close]\n", 2*indent, "");
200 0 : break;
201 : case ST_DATA: {
202 : DATALEN n;
203 0 : memcpy ( &n, p, sizeof n );
204 0 : p += sizeof n;
205 0 : log_printf ("%*s[data=\"", 2*indent, "" );
206 0 : dump_string (p, n, '\"' );
207 0 : log_printf ("\"]\n");
208 0 : p += n;
209 : }
210 0 : break;
211 : default:
212 0 : log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
213 0 : break;
214 : }
215 : }
216 : }
217 :
218 :
219 : /* Pass list through except when it is an empty list - in that case
220 : * return NULL and release the passed list. This is used to make sure
221 : * that no forbidden empty lists are created.
222 : */
223 : static gcry_sexp_t
224 70681 : normalize ( gcry_sexp_t list )
225 : {
226 : unsigned char *p;
227 :
228 70681 : if ( !list )
229 2 : return NULL;
230 70679 : p = list->d;
231 70679 : if ( *p == ST_STOP )
232 : {
233 : /* this is "" */
234 0 : sexp_release ( list );
235 0 : return NULL;
236 : }
237 70679 : if ( *p == ST_OPEN && p[1] == ST_CLOSE )
238 : {
239 : /* this is "()" */
240 0 : sexp_release ( list );
241 0 : return NULL;
242 : }
243 :
244 70679 : return list;
245 : }
246 :
247 : /* Create a new S-expression object by reading LENGTH bytes from
248 : BUFFER, assuming it is canonical encoded or autodetected encoding
249 : when AUTODETECT is set to 1. With FREEFNC not NULL, ownership of
250 : the buffer is transferred to the newly created object. FREEFNC
251 : should be the freefnc used to release BUFFER; there is no guarantee
252 : at which point this function is called; most likey you want to use
253 : free() or gcry_free().
254 :
255 : Passing LENGTH and AUTODETECT as 0 is allowed to indicate that
256 : BUFFER points to a valid canonical encoded S-expression. A LENGTH
257 : of 0 and AUTODETECT 1 indicates that buffer points to a
258 : null-terminated string.
259 :
260 : This function returns 0 and and the pointer to the new object in
261 : RETSEXP or an error code in which case RETSEXP is set to NULL. */
262 : gcry_err_code_t
263 336 : _gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length,
264 : int autodetect, void (*freefnc)(void*) )
265 : {
266 : gcry_err_code_t errcode;
267 : gcry_sexp_t se;
268 :
269 336 : if (!retsexp)
270 0 : return GPG_ERR_INV_ARG;
271 336 : *retsexp = NULL;
272 336 : if (autodetect < 0 || autodetect > 1 || !buffer)
273 0 : return GPG_ERR_INV_ARG;
274 :
275 336 : if (!length && !autodetect)
276 : { /* What a brave caller to assume that there is really a canonical
277 : encoded S-expression in buffer */
278 0 : length = _gcry_sexp_canon_len (buffer, 0, NULL, &errcode);
279 0 : if (!length)
280 0 : return errcode;
281 : }
282 336 : else if (!length && autodetect)
283 : { /* buffer is a string */
284 159 : length = strlen ((char *)buffer);
285 : }
286 :
287 336 : errcode = do_sexp_sscan (&se, NULL, buffer, length, 0, NULL);
288 336 : if (errcode)
289 0 : return errcode;
290 :
291 336 : *retsexp = se;
292 336 : if (freefnc)
293 : {
294 : /* For now we release the buffer immediately. As soon as we
295 : have changed the internal represenation of S-expression to
296 : the canoncial format - which has the advantage of faster
297 : parsing - we will use this function as a closure in our
298 : GCRYSEXP object and use the BUFFER directly. */
299 3 : freefnc (buffer);
300 : }
301 336 : return 0;
302 : }
303 :
304 : /* Same as gcry_sexp_create but don't transfer ownership */
305 : gcry_err_code_t
306 330 : _gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length,
307 : int autodetect)
308 : {
309 330 : return _gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL);
310 : }
311 :
312 :
313 : /****************
314 : * Release resource of the given SEXP object.
315 : */
316 : void
317 85072 : _gcry_sexp_release( gcry_sexp_t sexp )
318 : {
319 85072 : if (sexp)
320 : {
321 70679 : if (_gcry_is_secure (sexp))
322 : {
323 : /* Extra paranoid wiping. */
324 2 : const byte *p = sexp->d;
325 : int type;
326 :
327 62 : while ( (type = *p) != ST_STOP )
328 : {
329 58 : p++;
330 58 : switch ( type )
331 : {
332 : case ST_OPEN:
333 16 : break;
334 : case ST_CLOSE:
335 16 : break;
336 : case ST_DATA:
337 : {
338 : DATALEN n;
339 26 : memcpy ( &n, p, sizeof n );
340 26 : p += sizeof n;
341 26 : p += n;
342 : }
343 26 : break;
344 : default:
345 0 : break;
346 : }
347 : }
348 2 : wipememory (sexp->d, p - sexp->d);
349 : }
350 70679 : xfree ( sexp );
351 : }
352 85072 : }
353 :
354 :
355 : /****************
356 : * Make a pair from lists a and b, don't use a or b later on.
357 : * Special behaviour: If one is a single element list we put the
358 : * element straight into the new pair.
359 : */
360 : gcry_sexp_t
361 0 : _gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b )
362 : {
363 : (void)a;
364 : (void)b;
365 :
366 : /* NYI: Implementation should be quite easy with our new data
367 : representation */
368 0 : BUG ();
369 : return NULL;
370 : }
371 :
372 :
373 : /****************
374 : * Make a list from all items in the array the end of the array is marked
375 : * with a NULL.
376 : */
377 : gcry_sexp_t
378 0 : _gcry_sexp_alist( const gcry_sexp_t *array )
379 : {
380 : (void)array;
381 :
382 : /* NYI: Implementation should be quite easy with our new data
383 : representation. */
384 0 : BUG ();
385 : return NULL;
386 : }
387 :
388 : /****************
389 : * Make a list from all items, the end of list is indicated by a NULL
390 : */
391 : gcry_sexp_t
392 0 : _gcry_sexp_vlist( const gcry_sexp_t a, ... )
393 : {
394 : (void)a;
395 : /* NYI: Implementation should be quite easy with our new data
396 : representation. */
397 0 : BUG ();
398 : return NULL;
399 : }
400 :
401 :
402 : /****************
403 : * Append n to the list a
404 : * Returns: a new ist (which maybe a)
405 : */
406 : gcry_sexp_t
407 0 : _gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n )
408 : {
409 : (void)a;
410 : (void)n;
411 : /* NYI: Implementation should be quite easy with our new data
412 : representation. */
413 0 : BUG ();
414 : return NULL;
415 : }
416 :
417 : gcry_sexp_t
418 0 : _gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n )
419 : {
420 : (void)a;
421 : (void)n;
422 : /* NYI: Implementation should be quite easy with our new data
423 : representation. */
424 0 : BUG ();
425 : return NULL;
426 : }
427 :
428 :
429 :
430 : /****************
431 : * Locate token in a list. The token must be the car of a sublist.
432 : * Returns: A new list with this sublist or NULL if not found.
433 : */
434 : gcry_sexp_t
435 56717 : _gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen )
436 : {
437 : const byte *p;
438 : DATALEN n;
439 :
440 56717 : if ( !list )
441 0 : return NULL;
442 :
443 56717 : if ( !toklen )
444 32835 : toklen = strlen(tok);
445 :
446 56717 : p = list->d;
447 325362 : while ( *p != ST_STOP )
448 : {
449 260197 : if ( *p == ST_OPEN && p[1] == ST_DATA )
450 97803 : {
451 146072 : const byte *head = p;
452 :
453 146072 : p += 2;
454 146072 : memcpy ( &n, p, sizeof n );
455 146072 : p += sizeof n;
456 146072 : if ( n == toklen && !memcmp( p, tok, toklen ) )
457 : { /* found it */
458 : gcry_sexp_t newlist;
459 : byte *d;
460 48269 : int level = 1;
461 :
462 : /* Look for the end of the list. */
463 304288 : for ( p += n; level; p++ )
464 : {
465 256019 : if ( *p == ST_DATA )
466 : {
467 117870 : memcpy ( &n, ++p, sizeof n );
468 117870 : p += sizeof n + n;
469 117870 : p--; /* Compensate for later increment. */
470 : }
471 138149 : else if ( *p == ST_OPEN )
472 : {
473 44940 : level++;
474 : }
475 93209 : else if ( *p == ST_CLOSE )
476 : {
477 93209 : level--;
478 : }
479 0 : else if ( *p == ST_STOP )
480 : {
481 0 : BUG ();
482 : }
483 : }
484 48269 : n = p - head;
485 :
486 48269 : newlist = xtrymalloc ( sizeof *newlist + n );
487 48269 : if (!newlist)
488 : {
489 : /* No way to return an error code, so we can only
490 : return Not Found. */
491 0 : return NULL;
492 : }
493 48269 : d = newlist->d;
494 48269 : memcpy ( d, head, n ); d += n;
495 48269 : *d++ = ST_STOP;
496 48269 : return normalize ( newlist );
497 : }
498 97803 : p += n;
499 : }
500 114125 : else if ( *p == ST_DATA )
501 : {
502 52565 : memcpy ( &n, ++p, sizeof n ); p += sizeof n;
503 52565 : p += n;
504 : }
505 : else
506 61560 : p++;
507 : }
508 8448 : return NULL;
509 : }
510 :
511 : /****************
512 : * Return the length of the given list
513 : */
514 : int
515 5831 : _gcry_sexp_length (const gcry_sexp_t list)
516 : {
517 : const byte *p;
518 : DATALEN n;
519 : int type;
520 5831 : int length = 0;
521 5831 : int level = 0;
522 :
523 5831 : if (!list)
524 0 : return 0;
525 :
526 5831 : p = list->d;
527 36027 : while ((type=*p) != ST_STOP)
528 : {
529 24365 : p++;
530 24365 : if (type == ST_DATA)
531 : {
532 12703 : memcpy (&n, p, sizeof n);
533 12703 : p += sizeof n + n;
534 12703 : if (level == 1)
535 12703 : length++;
536 : }
537 11662 : else if (type == ST_OPEN)
538 : {
539 5831 : if (level == 1)
540 0 : length++;
541 5831 : level++;
542 : }
543 5831 : else if (type == ST_CLOSE)
544 : {
545 5831 : level--;
546 : }
547 : }
548 5831 : return length;
549 : }
550 :
551 :
552 : /* Return the internal lengths offset of LIST. That is the size of
553 : the buffer from the first ST_OPEN, which is returned at R_OFF, to
554 : the corresponding ST_CLOSE inclusive. */
555 : static size_t
556 138 : get_internal_buffer (const gcry_sexp_t list, size_t *r_off)
557 : {
558 : const unsigned char *p;
559 : DATALEN n;
560 : int type;
561 138 : int level = 0;
562 :
563 138 : *r_off = 0;
564 138 : if (list)
565 : {
566 92 : p = list->d;
567 910 : while ( (type=*p) != ST_STOP )
568 : {
569 818 : p++;
570 818 : if (type == ST_DATA)
571 : {
572 400 : memcpy (&n, p, sizeof n);
573 400 : p += sizeof n + n;
574 : }
575 418 : else if (type == ST_OPEN)
576 : {
577 209 : if (!level)
578 92 : *r_off = (p-1) - list->d;
579 209 : level++;
580 : }
581 209 : else if ( type == ST_CLOSE )
582 : {
583 209 : level--;
584 209 : if (!level)
585 92 : return p - list->d;
586 : }
587 : }
588 : }
589 46 : return 0; /* Not a proper list. */
590 : }
591 :
592 :
593 :
594 : /* Extract the n-th element of the given LIST. Returns NULL for
595 : no-such-element, a corrupt list, or memory failure. */
596 : gcry_sexp_t
597 8561 : _gcry_sexp_nth (const gcry_sexp_t list, int number)
598 : {
599 : const byte *p;
600 : DATALEN n;
601 : gcry_sexp_t newlist;
602 : byte *d;
603 8561 : int level = 0;
604 :
605 8561 : if (!list || list->d[0] != ST_OPEN)
606 0 : return NULL;
607 8561 : p = list->d;
608 :
609 30310 : while (number > 0)
610 : {
611 13188 : p++;
612 13188 : if (*p == ST_DATA)
613 : {
614 8410 : memcpy (&n, ++p, sizeof n);
615 8410 : p += sizeof n + n;
616 8410 : p--;
617 8410 : if (!level)
618 3632 : number--;
619 : }
620 4778 : else if (*p == ST_OPEN)
621 : {
622 2389 : level++;
623 : }
624 2389 : else if (*p == ST_CLOSE)
625 : {
626 2389 : level--;
627 2389 : if ( !level )
628 2389 : number--;
629 : }
630 0 : else if (*p == ST_STOP)
631 : {
632 0 : return NULL;
633 : }
634 : }
635 8561 : p++;
636 :
637 8561 : if (*p == ST_DATA)
638 : {
639 2 : memcpy (&n, p+1, sizeof n);
640 2 : newlist = xtrymalloc (sizeof *newlist + 1 + 1 + sizeof n + n + 1);
641 2 : if (!newlist)
642 0 : return NULL;
643 2 : d = newlist->d;
644 2 : *d++ = ST_OPEN;
645 2 : memcpy (d, p, 1 + sizeof n + n);
646 2 : d += 1 + sizeof n + n;
647 2 : *d++ = ST_CLOSE;
648 2 : *d = ST_STOP;
649 : }
650 8559 : else if (*p == ST_OPEN)
651 : {
652 8557 : const byte *head = p;
653 :
654 8557 : level = 1;
655 : do {
656 92842 : p++;
657 92842 : if (*p == ST_DATA)
658 : {
659 47005 : memcpy (&n, ++p, sizeof n);
660 47005 : p += sizeof n + n;
661 47005 : p--;
662 : }
663 45837 : else if (*p == ST_OPEN)
664 : {
665 18640 : level++;
666 : }
667 27197 : else if (*p == ST_CLOSE)
668 : {
669 27197 : level--;
670 : }
671 0 : else if (*p == ST_STOP)
672 : {
673 0 : BUG ();
674 : }
675 92842 : } while (level);
676 8557 : n = p + 1 - head;
677 :
678 8557 : newlist = xtrymalloc (sizeof *newlist + n);
679 8557 : if (!newlist)
680 0 : return NULL;
681 8557 : d = newlist->d;
682 8557 : memcpy (d, head, n);
683 8557 : d += n;
684 8557 : *d++ = ST_STOP;
685 : }
686 : else
687 2 : newlist = NULL;
688 :
689 8561 : return normalize (newlist);
690 : }
691 :
692 :
693 : gcry_sexp_t
694 4929 : _gcry_sexp_car (const gcry_sexp_t list)
695 : {
696 4929 : return _gcry_sexp_nth (list, 0);
697 : }
698 :
699 :
700 : /* Helper to get data from the car. The returned value is valid as
701 : long as the list is not modified. */
702 : static const char *
703 44817 : do_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen)
704 : {
705 : const byte *p;
706 : DATALEN n;
707 44817 : int level = 0;
708 :
709 44817 : *datalen = 0;
710 44817 : if ( !list )
711 0 : return NULL;
712 :
713 44817 : p = list->d;
714 44817 : if ( *p == ST_OPEN )
715 44788 : p++; /* Yep, a list. */
716 29 : else if (number)
717 0 : return NULL; /* Not a list but N > 0 requested. */
718 :
719 : /* Skip over N elements. */
720 126465 : while (number > 0)
721 : {
722 36831 : if (*p == ST_DATA)
723 : {
724 36831 : memcpy ( &n, ++p, sizeof n );
725 36831 : p += sizeof n + n;
726 36831 : p--;
727 36831 : if ( !level )
728 36831 : number--;
729 : }
730 0 : else if (*p == ST_OPEN)
731 : {
732 0 : level++;
733 : }
734 0 : else if (*p == ST_CLOSE)
735 : {
736 0 : level--;
737 0 : if ( !level )
738 0 : number--;
739 : }
740 0 : else if (*p == ST_STOP)
741 : {
742 0 : return NULL;
743 : }
744 36831 : p++;
745 : }
746 :
747 : /* If this is data, return it. */
748 44817 : if (*p == ST_DATA)
749 : {
750 44793 : memcpy ( &n, ++p, sizeof n );
751 44793 : *datalen = n;
752 44793 : return (const char*)p + sizeof n;
753 : }
754 :
755 24 : return NULL;
756 : }
757 :
758 :
759 : /* Get data from the car. The returned value is valid as long as the
760 : list is not modified. */
761 : const char *
762 12564 : _gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen )
763 : {
764 12564 : return do_sexp_nth_data (list, number, datalen);
765 : }
766 :
767 :
768 : /* Get the nth element of a list which needs to be a simple object.
769 : The returned value is a malloced buffer and needs to be freed by
770 : the caller. This is basically the same as gcry_sexp_nth_data but
771 : with an allocated result. */
772 : void *
773 7720 : _gcry_sexp_nth_buffer (const gcry_sexp_t list, int number, size_t *rlength)
774 : {
775 : const char *s;
776 : size_t n;
777 : char *buf;
778 :
779 7720 : *rlength = 0;
780 7720 : s = do_sexp_nth_data (list, number, &n);
781 7720 : if (!s || !n)
782 6 : return NULL;
783 7714 : buf = xtrymalloc (n);
784 7714 : if (!buf)
785 0 : return NULL;
786 7714 : memcpy (buf, s, n);
787 7714 : *rlength = n;
788 7714 : return buf;
789 : }
790 :
791 :
792 : /* Get a string from the car. The returned value is a malloced string
793 : and needs to be freed by the caller. */
794 : char *
795 11387 : _gcry_sexp_nth_string (const gcry_sexp_t list, int number)
796 : {
797 : const char *s;
798 : size_t n;
799 : char *buf;
800 :
801 11387 : s = do_sexp_nth_data (list, number, &n);
802 11387 : if (!s || n < 1 || (n+1) < 1)
803 0 : return NULL;
804 11387 : buf = xtrymalloc (n+1);
805 11387 : if (!buf)
806 0 : return NULL;
807 11387 : memcpy (buf, s, n);
808 11387 : buf[n] = 0;
809 11387 : return buf;
810 : }
811 :
812 :
813 : /*
814 : * Get a MPI from the car
815 : */
816 : gcry_mpi_t
817 16581 : _gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt)
818 : {
819 : size_t n;
820 : gcry_mpi_t a;
821 :
822 16581 : if (mpifmt == GCRYMPI_FMT_OPAQUE)
823 : {
824 : char *p;
825 :
826 3435 : p = _gcry_sexp_nth_buffer (list, number, &n);
827 3435 : if (!p)
828 0 : return NULL;
829 :
830 3435 : a = _gcry_is_secure (list)? _gcry_mpi_snew (0) : _gcry_mpi_new (0);
831 3435 : if (a)
832 3435 : mpi_set_opaque (a, p, n*8);
833 : else
834 0 : xfree (p);
835 : }
836 : else
837 : {
838 : const char *s;
839 :
840 13146 : if (!mpifmt)
841 6 : mpifmt = GCRYMPI_FMT_STD;
842 :
843 13146 : s = do_sexp_nth_data (list, number, &n);
844 13146 : if (!s)
845 0 : return NULL;
846 :
847 13146 : if (_gcry_mpi_scan (&a, mpifmt, s, n, NULL))
848 0 : return NULL;
849 : }
850 :
851 16581 : return a;
852 : }
853 :
854 :
855 : /****************
856 : * Get the CDR
857 : */
858 : gcry_sexp_t
859 4953 : _gcry_sexp_cdr(const gcry_sexp_t list)
860 : {
861 : const byte *p;
862 : const byte *head;
863 : DATALEN n;
864 : gcry_sexp_t newlist;
865 : byte *d;
866 4953 : int level = 0;
867 4953 : int skip = 1;
868 :
869 4953 : if (!list || list->d[0] != ST_OPEN)
870 0 : return NULL;
871 4953 : p = list->d;
872 :
873 14859 : while (skip > 0)
874 : {
875 4953 : p++;
876 4953 : if (*p == ST_DATA)
877 : {
878 4953 : memcpy ( &n, ++p, sizeof n );
879 4953 : p += sizeof n + n;
880 4953 : p--;
881 4953 : if ( !level )
882 4953 : skip--;
883 : }
884 0 : else if (*p == ST_OPEN)
885 : {
886 0 : level++;
887 : }
888 0 : else if (*p == ST_CLOSE)
889 : {
890 0 : level--;
891 0 : if ( !level )
892 0 : skip--;
893 : }
894 0 : else if (*p == ST_STOP)
895 : {
896 0 : return NULL;
897 : }
898 : }
899 4953 : p++;
900 :
901 4953 : head = p;
902 4953 : level = 0;
903 : do {
904 74664 : if (*p == ST_DATA)
905 : {
906 34836 : memcpy ( &n, ++p, sizeof n );
907 34836 : p += sizeof n + n;
908 34836 : p--;
909 : }
910 39828 : else if (*p == ST_OPEN)
911 : {
912 19914 : level++;
913 : }
914 19914 : else if (*p == ST_CLOSE)
915 : {
916 19914 : level--;
917 : }
918 0 : else if (*p == ST_STOP)
919 : {
920 0 : return NULL;
921 : }
922 74664 : p++;
923 74664 : } while (level);
924 4953 : n = p - head;
925 :
926 4953 : newlist = xtrymalloc (sizeof *newlist + n + 2);
927 4953 : if (!newlist)
928 0 : return NULL;
929 4953 : d = newlist->d;
930 4953 : *d++ = ST_OPEN;
931 4953 : memcpy (d, head, n);
932 4953 : d += n;
933 4953 : *d++ = ST_CLOSE;
934 4953 : *d++ = ST_STOP;
935 :
936 4953 : return normalize (newlist);
937 : }
938 :
939 :
940 : gcry_sexp_t
941 4929 : _gcry_sexp_cadr ( const gcry_sexp_t list )
942 : {
943 : gcry_sexp_t a, b;
944 :
945 4929 : a = _gcry_sexp_cdr (list);
946 4929 : b = _gcry_sexp_car (a);
947 4929 : sexp_release (a);
948 4929 : return b;
949 : }
950 :
951 :
952 : static GPG_ERR_INLINE int
953 112616 : hextonibble (int s)
954 : {
955 112616 : if (s >= '0' && s <= '9')
956 73094 : return s - '0';
957 39522 : else if (s >= 'A' && s <= 'F')
958 35517 : return 10 + s - 'A';
959 4005 : else if (s >= 'a' && s <= 'f')
960 4005 : return 10 + s - 'a';
961 : else
962 0 : return 0;
963 : }
964 :
965 :
966 : struct make_space_ctx
967 : {
968 : gcry_sexp_t sexp;
969 : size_t allocated;
970 : byte *pos;
971 : };
972 :
973 :
974 : static gpg_err_code_t
975 138626 : make_space ( struct make_space_ctx *c, size_t n )
976 : {
977 138626 : size_t used = c->pos - c->sexp->d;
978 :
979 138626 : if ( used + n + sizeof(DATALEN) + 1 >= c->allocated )
980 : {
981 : gcry_sexp_t newsexp;
982 : byte *newhead;
983 : size_t newsize;
984 :
985 16963 : newsize = c->allocated + 2*(n+sizeof(DATALEN)+1);
986 16963 : if (newsize <= c->allocated)
987 0 : return GPG_ERR_TOO_LARGE;
988 16963 : newsexp = xtryrealloc ( c->sexp, sizeof *newsexp + newsize - 1);
989 16963 : if (!newsexp)
990 0 : return gpg_err_code_from_errno (errno);
991 16963 : c->allocated = newsize;
992 16963 : newhead = newsexp->d;
993 16963 : c->pos = newhead + used;
994 16963 : c->sexp = newsexp;
995 : }
996 138626 : return 0;
997 : }
998 :
999 :
1000 : /* Unquote STRING of LENGTH and store it into BUF. The surrounding
1001 : quotes are must already be removed from STRING. We assume that the
1002 : quoted string is syntacillay correct. */
1003 : static size_t
1004 2166 : unquote_string (const char *string, size_t length, unsigned char *buf)
1005 : {
1006 2166 : int esc = 0;
1007 2166 : const unsigned char *s = (const unsigned char*)string;
1008 2166 : unsigned char *d = buf;
1009 2166 : size_t n = length;
1010 :
1011 17353 : for (; n; n--, s++)
1012 : {
1013 15187 : if (esc)
1014 : {
1015 0 : switch (*s)
1016 : {
1017 0 : case 'b': *d++ = '\b'; break;
1018 0 : case 't': *d++ = '\t'; break;
1019 0 : case 'v': *d++ = '\v'; break;
1020 0 : case 'n': *d++ = '\n'; break;
1021 0 : case 'f': *d++ = '\f'; break;
1022 0 : case 'r': *d++ = '\r'; break;
1023 0 : case '"': *d++ = '\"'; break;
1024 0 : case '\'': *d++ = '\''; break;
1025 0 : case '\\': *d++ = '\\'; break;
1026 :
1027 : case '\r': /* ignore CR[,LF] */
1028 0 : if (n>1 && s[1] == '\n')
1029 : {
1030 0 : s++; n--;
1031 : }
1032 0 : break;
1033 :
1034 : case '\n': /* ignore LF[,CR] */
1035 0 : if (n>1 && s[1] == '\r')
1036 : {
1037 0 : s++; n--;
1038 : }
1039 0 : break;
1040 :
1041 : case 'x': /* hex value */
1042 0 : if (n>2 && hexdigitp (s+1) && hexdigitp (s+2))
1043 : {
1044 0 : s++; n--;
1045 0 : *d++ = xtoi_2 (s);
1046 0 : s++; n--;
1047 : }
1048 0 : break;
1049 :
1050 : default:
1051 0 : if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
1052 : {
1053 0 : *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
1054 0 : s += 2;
1055 0 : n -= 2;
1056 : }
1057 0 : break;
1058 : }
1059 0 : esc = 0;
1060 : }
1061 15187 : else if( *s == '\\' )
1062 0 : esc = 1;
1063 : else
1064 15187 : *d++ = *s;
1065 : }
1066 :
1067 2166 : return d - buf;
1068 : }
1069 :
1070 : /****************
1071 : * Scan the provided buffer and return the S expression in our internal
1072 : * format. Returns a newly allocated expression. If erroff is not NULL and
1073 : * a parsing error has occurred, the offset into buffer will be returned.
1074 : * If ARGFLAG is true, the function supports some printf like
1075 : * expressions.
1076 : * These are:
1077 : * %m - MPI
1078 : * %s - string (no autoswitch to secure allocation)
1079 : * %d - integer stored as string (no autoswitch to secure allocation)
1080 : * %b - memory buffer; this takes _two_ arguments: an integer with the
1081 : * length of the buffer and a pointer to the buffer.
1082 : * %S - Copy an gcry_sexp_t here. The S-expression needs to be a
1083 : * regular one, starting with a parenthesis.
1084 : * (no autoswitch to secure allocation)
1085 : * all other format elements are currently not defined and return an error.
1086 : * this includes the "%%" sequence becauce the percent sign is not an
1087 : * allowed character.
1088 : * FIXME: We should find a way to store the secure-MPIs not in the string
1089 : * but as reference to somewhere - this can help us to save huge amounts
1090 : * of secure memory. The problem is, that if only one element is secure, all
1091 : * other elements are automagicaly copied to secure memory too, so the most
1092 : * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
1093 : * regardless whether it is needed or not.
1094 : */
1095 : static gpg_err_code_t
1096 8900 : do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1097 : const char *buffer, size_t length, int argflag,
1098 : void **arg_list, va_list arg_ptr)
1099 : {
1100 8900 : gcry_err_code_t err = 0;
1101 : static const char tokenchars[] =
1102 : "abcdefghijklmnopqrstuvwxyz"
1103 : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1104 : "0123456789-./_:*+=";
1105 : const char *p;
1106 : size_t n;
1107 8900 : const char *digptr = NULL;
1108 8900 : const char *quoted = NULL;
1109 8900 : const char *tokenp = NULL;
1110 8900 : const char *hexfmt = NULL;
1111 8900 : const char *base64 = NULL;
1112 8900 : const char *disphint = NULL;
1113 8900 : const char *percent = NULL;
1114 8900 : int hexcount = 0;
1115 8900 : int quoted_esc = 0;
1116 8900 : int datalen = 0;
1117 : size_t dummy_erroff;
1118 : struct make_space_ctx c;
1119 8900 : int arg_counter = 0;
1120 8900 : int level = 0;
1121 :
1122 8900 : if (!retsexp)
1123 0 : return GPG_ERR_INV_ARG;
1124 8900 : *retsexp = NULL;
1125 :
1126 8900 : if (!buffer)
1127 0 : return GPG_ERR_INV_ARG;
1128 :
1129 8900 : if (!erroff)
1130 8900 : erroff = &dummy_erroff;
1131 :
1132 : /* Depending on whether ARG_LIST is non-zero or not, this macro gives
1133 : us the next argument, either from the variable argument list as
1134 : specified by ARG_PTR or from the argument array ARG_LIST. */
1135 : #define ARG_NEXT(storage, type) \
1136 : do \
1137 : { \
1138 : if (!arg_list) \
1139 : storage = va_arg (arg_ptr, type); \
1140 : else \
1141 : storage = *((type *) (arg_list[arg_counter++])); \
1142 : } \
1143 : while (0)
1144 :
1145 : /* The MAKE_SPACE macro is used before each store operation to
1146 : ensure that the buffer is large enough. It requires a global
1147 : context named C and jumps out to the label LEAVE on error! It
1148 : also sets ERROFF using the variables BUFFER and P. */
1149 : #define MAKE_SPACE(n) do { \
1150 : gpg_err_code_t _ms_err = make_space (&c, (n)); \
1151 : if (_ms_err) \
1152 : { \
1153 : err = _ms_err; \
1154 : *erroff = p - buffer; \
1155 : goto leave; \
1156 : } \
1157 : } while (0)
1158 :
1159 : /* The STORE_LEN macro is used to store the length N at buffer P. */
1160 : #define STORE_LEN(p,n) do { \
1161 : DATALEN ashort = (n); \
1162 : memcpy ( (p), &ashort, sizeof(ashort) ); \
1163 : (p) += sizeof (ashort); \
1164 : } while (0)
1165 :
1166 : /* We assume that the internal representation takes less memory than
1167 : the provided one. However, we add space for one extra datalen so
1168 : that the code which does the ST_CLOSE can use MAKE_SPACE */
1169 8900 : c.allocated = length + sizeof(DATALEN);
1170 8900 : if (length && _gcry_is_secure (buffer))
1171 0 : c.sexp = xtrymalloc_secure (sizeof *c.sexp + c.allocated - 1);
1172 : else
1173 8900 : c.sexp = xtrymalloc (sizeof *c.sexp + c.allocated - 1);
1174 8900 : if (!c.sexp)
1175 : {
1176 0 : err = gpg_err_code_from_errno (errno);
1177 0 : *erroff = 0;
1178 0 : goto leave;
1179 : }
1180 8900 : c.pos = c.sexp->d;
1181 :
1182 494210 : for (p = buffer, n = length; n; p++, n--)
1183 : {
1184 485310 : if (tokenp && !hexfmt)
1185 : {
1186 207732 : if (strchr (tokenchars, *p))
1187 164602 : continue;
1188 : else
1189 : {
1190 43130 : datalen = p - tokenp;
1191 43130 : MAKE_SPACE (datalen);
1192 43130 : *c.pos++ = ST_DATA;
1193 43130 : STORE_LEN (c.pos, datalen);
1194 43130 : memcpy (c.pos, tokenp, datalen);
1195 43130 : c.pos += datalen;
1196 43130 : tokenp = NULL;
1197 : }
1198 : }
1199 :
1200 320708 : if (quoted)
1201 : {
1202 17353 : if (quoted_esc)
1203 : {
1204 0 : switch (*p)
1205 : {
1206 : case 'b': case 't': case 'v': case 'n': case 'f':
1207 : case 'r': case '"': case '\'': case '\\':
1208 0 : quoted_esc = 0;
1209 0 : break;
1210 :
1211 : case '0': case '1': case '2': case '3': case '4':
1212 : case '5': case '6': case '7':
1213 0 : if (!((n > 2)
1214 0 : && (p[1] >= '0') && (p[1] <= '7')
1215 0 : && (p[2] >= '0') && (p[2] <= '7')))
1216 : {
1217 0 : *erroff = p - buffer;
1218 : /* Invalid octal value. */
1219 0 : err = GPG_ERR_SEXP_BAD_QUOTATION;
1220 0 : goto leave;
1221 : }
1222 0 : p += 2;
1223 0 : n -= 2;
1224 0 : quoted_esc = 0;
1225 0 : break;
1226 :
1227 : case 'x':
1228 0 : if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2)))
1229 : {
1230 0 : *erroff = p - buffer;
1231 : /* Invalid hex value. */
1232 0 : err = GPG_ERR_SEXP_BAD_QUOTATION;
1233 0 : goto leave;
1234 : }
1235 0 : p += 2;
1236 0 : n -= 2;
1237 0 : quoted_esc = 0;
1238 0 : break;
1239 :
1240 : case '\r':
1241 : /* ignore CR[,LF] */
1242 0 : if (n && (p[1] == '\n'))
1243 : {
1244 0 : p++;
1245 0 : n--;
1246 : }
1247 0 : quoted_esc = 0;
1248 0 : break;
1249 :
1250 : case '\n':
1251 : /* ignore LF[,CR] */
1252 0 : if (n && (p[1] == '\r'))
1253 : {
1254 0 : p++;
1255 0 : n--;
1256 : }
1257 0 : quoted_esc = 0;
1258 0 : break;
1259 :
1260 : default:
1261 0 : *erroff = p - buffer;
1262 : /* Invalid quoted string escape. */
1263 0 : err = GPG_ERR_SEXP_BAD_QUOTATION;
1264 0 : goto leave;
1265 : }
1266 : }
1267 17353 : else if (*p == '\\')
1268 0 : quoted_esc = 1;
1269 17353 : else if (*p == '\"')
1270 : {
1271 : /* Keep it easy - we know that the unquoted string will
1272 : never be larger. */
1273 : unsigned char *save;
1274 : size_t len;
1275 :
1276 2166 : quoted++; /* Skip leading quote. */
1277 2166 : MAKE_SPACE (p - quoted);
1278 2166 : *c.pos++ = ST_DATA;
1279 2166 : save = c.pos;
1280 2166 : STORE_LEN (c.pos, 0); /* Will be fixed up later. */
1281 2166 : len = unquote_string (quoted, p - quoted, c.pos);
1282 2166 : c.pos += len;
1283 2166 : STORE_LEN (save, len);
1284 2166 : quoted = NULL;
1285 : }
1286 : }
1287 303355 : else if (hexfmt)
1288 : {
1289 118061 : if (isxdigit (*p))
1290 112616 : hexcount++;
1291 5445 : else if (*p == '#')
1292 : {
1293 1160 : if ((hexcount & 1))
1294 : {
1295 0 : *erroff = p - buffer;
1296 0 : err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
1297 0 : goto leave;
1298 : }
1299 :
1300 1160 : datalen = hexcount / 2;
1301 1160 : MAKE_SPACE (datalen);
1302 1160 : *c.pos++ = ST_DATA;
1303 1160 : STORE_LEN (c.pos, datalen);
1304 61753 : for (hexfmt++; hexfmt < p; hexfmt++)
1305 : {
1306 : int tmpc;
1307 :
1308 60593 : if (whitespacep (hexfmt))
1309 4285 : continue;
1310 56308 : tmpc = hextonibble (*(const unsigned char*)hexfmt);
1311 56308 : for (hexfmt++; hexfmt < p && whitespacep (hexfmt); hexfmt++)
1312 : ;
1313 56308 : if (hexfmt < p)
1314 : {
1315 56308 : tmpc *= 16;
1316 56308 : tmpc += hextonibble (*(const unsigned char*)hexfmt);
1317 : }
1318 56308 : *c.pos++ = tmpc;
1319 : }
1320 1160 : hexfmt = NULL;
1321 : }
1322 4285 : else if (!whitespacep (p))
1323 : {
1324 0 : *erroff = p - buffer;
1325 0 : err = GPG_ERR_SEXP_BAD_HEX_CHAR;
1326 0 : goto leave;
1327 : }
1328 : }
1329 185294 : else if (base64)
1330 : {
1331 0 : if (*p == '|')
1332 0 : base64 = NULL;
1333 : }
1334 185294 : else if (digptr)
1335 : {
1336 934 : if (digitp (p))
1337 : ;
1338 742 : else if (*p == ':')
1339 : {
1340 742 : datalen = atoi (digptr); /* FIXME: check for overflow. */
1341 742 : digptr = NULL;
1342 742 : if (datalen > n - 1)
1343 : {
1344 0 : *erroff = p - buffer;
1345 : /* Buffer too short. */
1346 0 : err = GPG_ERR_SEXP_STRING_TOO_LONG;
1347 0 : goto leave;
1348 : }
1349 : /* Make a new list entry. */
1350 742 : MAKE_SPACE (datalen);
1351 742 : *c.pos++ = ST_DATA;
1352 742 : STORE_LEN (c.pos, datalen);
1353 742 : memcpy (c.pos, p + 1, datalen);
1354 742 : c.pos += datalen;
1355 742 : n -= datalen;
1356 742 : p += datalen;
1357 : }
1358 0 : else if (*p == '\"')
1359 : {
1360 0 : digptr = NULL; /* We ignore the optional length. */
1361 0 : quoted = p;
1362 0 : quoted_esc = 0;
1363 : }
1364 0 : else if (*p == '#')
1365 : {
1366 0 : digptr = NULL; /* We ignore the optional length. */
1367 0 : hexfmt = p;
1368 0 : hexcount = 0;
1369 : }
1370 0 : else if (*p == '|')
1371 : {
1372 0 : digptr = NULL; /* We ignore the optional length. */
1373 0 : base64 = p;
1374 : }
1375 : else
1376 : {
1377 0 : *erroff = p - buffer;
1378 0 : err = GPG_ERR_SEXP_INV_LEN_SPEC;
1379 0 : goto leave;
1380 : }
1381 : }
1382 184360 : else if (percent)
1383 : {
1384 11204 : if (*p == 'm' || *p == 'M')
1385 3589 : {
1386 : /* Insert an MPI. */
1387 : gcry_mpi_t m;
1388 3589 : size_t nm = 0;
1389 3589 : int mpifmt = *p == 'm'? GCRYMPI_FMT_STD: GCRYMPI_FMT_USG;
1390 :
1391 3589 : ARG_NEXT (m, gcry_mpi_t);
1392 :
1393 3589 : if (mpi_get_flag (m, GCRYMPI_FLAG_OPAQUE))
1394 : {
1395 : void *mp;
1396 : unsigned int nbits;
1397 :
1398 2086 : mp = mpi_get_opaque (m, &nbits);
1399 2086 : nm = (nbits+7)/8;
1400 2086 : if (mp && nm)
1401 : {
1402 2086 : MAKE_SPACE (nm);
1403 2086 : if (!_gcry_is_secure (c.sexp->d)
1404 2086 : && mpi_get_flag (m, GCRYMPI_FLAG_SECURE))
1405 : {
1406 : /* We have to switch to secure allocation. */
1407 : gcry_sexp_t newsexp;
1408 : byte *newhead;
1409 :
1410 0 : newsexp = xtrymalloc_secure (sizeof *newsexp
1411 : + c.allocated - 1);
1412 0 : if (!newsexp)
1413 : {
1414 0 : err = gpg_err_code_from_errno (errno);
1415 0 : goto leave;
1416 : }
1417 0 : newhead = newsexp->d;
1418 0 : memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1419 0 : c.pos = newhead + (c.pos - c.sexp->d);
1420 0 : xfree (c.sexp);
1421 0 : c.sexp = newsexp;
1422 : }
1423 :
1424 2086 : *c.pos++ = ST_DATA;
1425 2086 : STORE_LEN (c.pos, nm);
1426 2086 : memcpy (c.pos, mp, nm);
1427 2086 : c.pos += nm;
1428 : }
1429 : }
1430 : else
1431 : {
1432 1503 : if (_gcry_mpi_print (mpifmt, NULL, 0, &nm, m))
1433 0 : BUG ();
1434 :
1435 1503 : MAKE_SPACE (nm);
1436 1503 : if (!_gcry_is_secure (c.sexp->d)
1437 1501 : && mpi_get_flag ( m, GCRYMPI_FLAG_SECURE))
1438 : {
1439 : /* We have to switch to secure allocation. */
1440 : gcry_sexp_t newsexp;
1441 : byte *newhead;
1442 :
1443 195 : newsexp = xtrymalloc_secure (sizeof *newsexp
1444 : + c.allocated - 1);
1445 195 : if (!newsexp)
1446 : {
1447 0 : err = gpg_err_code_from_errno (errno);
1448 0 : goto leave;
1449 : }
1450 195 : newhead = newsexp->d;
1451 195 : memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1452 195 : c.pos = newhead + (c.pos - c.sexp->d);
1453 195 : xfree (c.sexp);
1454 195 : c.sexp = newsexp;
1455 : }
1456 :
1457 1503 : *c.pos++ = ST_DATA;
1458 1503 : STORE_LEN (c.pos, nm);
1459 1503 : if (_gcry_mpi_print (mpifmt, c.pos, nm, &nm, m))
1460 0 : BUG ();
1461 1503 : c.pos += nm;
1462 : }
1463 : }
1464 7615 : else if (*p == 's')
1465 : {
1466 : /* Insert an string. */
1467 : const char *astr;
1468 : size_t alen;
1469 :
1470 94 : ARG_NEXT (astr, const char *);
1471 94 : alen = strlen (astr);
1472 :
1473 94 : MAKE_SPACE (alen);
1474 94 : *c.pos++ = ST_DATA;
1475 94 : STORE_LEN (c.pos, alen);
1476 94 : memcpy (c.pos, astr, alen);
1477 94 : c.pos += alen;
1478 : }
1479 7521 : else if (*p == 'b')
1480 : {
1481 : /* Insert a memory buffer. */
1482 : const char *astr;
1483 : int alen;
1484 :
1485 7350 : ARG_NEXT (alen, int);
1486 7350 : ARG_NEXT (astr, const char *);
1487 :
1488 7350 : MAKE_SPACE (alen);
1489 7350 : if (alen
1490 7347 : && !_gcry_is_secure (c.sexp->d)
1491 7347 : && _gcry_is_secure (astr))
1492 : {
1493 : /* We have to switch to secure allocation. */
1494 : gcry_sexp_t newsexp;
1495 : byte *newhead;
1496 :
1497 2 : newsexp = xtrymalloc_secure (sizeof *newsexp
1498 : + c.allocated - 1);
1499 2 : if (!newsexp)
1500 : {
1501 0 : err = gpg_err_code_from_errno (errno);
1502 0 : goto leave;
1503 : }
1504 2 : newhead = newsexp->d;
1505 2 : memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1506 2 : c.pos = newhead + (c.pos - c.sexp->d);
1507 2 : xfree (c.sexp);
1508 2 : c.sexp = newsexp;
1509 : }
1510 :
1511 7350 : *c.pos++ = ST_DATA;
1512 7350 : STORE_LEN (c.pos, alen);
1513 7350 : memcpy (c.pos, astr, alen);
1514 7350 : c.pos += alen;
1515 : }
1516 171 : else if (*p == 'd')
1517 : {
1518 : /* Insert an integer as string. */
1519 : int aint;
1520 : size_t alen;
1521 : char buf[35];
1522 :
1523 33 : ARG_NEXT (aint, int);
1524 33 : sprintf (buf, "%d", aint);
1525 33 : alen = strlen (buf);
1526 33 : MAKE_SPACE (alen);
1527 33 : *c.pos++ = ST_DATA;
1528 33 : STORE_LEN (c.pos, alen);
1529 33 : memcpy (c.pos, buf, alen);
1530 33 : c.pos += alen;
1531 : }
1532 138 : else if (*p == 'u')
1533 : {
1534 : /* Insert an unsigned integer as string. */
1535 : unsigned int aint;
1536 : size_t alen;
1537 : char buf[35];
1538 :
1539 0 : ARG_NEXT (aint, unsigned int);
1540 0 : sprintf (buf, "%u", aint);
1541 0 : alen = strlen (buf);
1542 0 : MAKE_SPACE (alen);
1543 0 : *c.pos++ = ST_DATA;
1544 0 : STORE_LEN (c.pos, alen);
1545 0 : memcpy (c.pos, buf, alen);
1546 0 : c.pos += alen;
1547 : }
1548 138 : else if (*p == 'S')
1549 : {
1550 : /* Insert a gcry_sexp_t. */
1551 : gcry_sexp_t asexp;
1552 : size_t alen, aoff;
1553 :
1554 138 : ARG_NEXT (asexp, gcry_sexp_t);
1555 138 : alen = get_internal_buffer (asexp, &aoff);
1556 138 : if (alen)
1557 : {
1558 92 : MAKE_SPACE (alen);
1559 92 : memcpy (c.pos, asexp->d + aoff, alen);
1560 92 : c.pos += alen;
1561 : }
1562 : }
1563 : else
1564 : {
1565 0 : *erroff = p - buffer;
1566 : /* Invalid format specifier. */
1567 0 : err = GPG_ERR_SEXP_INV_LEN_SPEC;
1568 0 : goto leave;
1569 : }
1570 11204 : percent = NULL;
1571 : }
1572 173156 : else if (*p == '(')
1573 : {
1574 35685 : if (disphint)
1575 : {
1576 0 : *erroff = p - buffer;
1577 : /* Open display hint. */
1578 0 : err = GPG_ERR_SEXP_UNMATCHED_DH;
1579 0 : goto leave;
1580 : }
1581 35685 : MAKE_SPACE (0);
1582 35685 : *c.pos++ = ST_OPEN;
1583 35685 : level++;
1584 : }
1585 137471 : else if (*p == ')')
1586 : {
1587 : /* Walk up. */
1588 35685 : if (disphint)
1589 : {
1590 0 : *erroff = p - buffer;
1591 : /* Open display hint. */
1592 0 : err = GPG_ERR_SEXP_UNMATCHED_DH;
1593 0 : goto leave;
1594 : }
1595 35685 : MAKE_SPACE (0);
1596 35685 : *c.pos++ = ST_CLOSE;
1597 35685 : level--;
1598 : }
1599 101786 : else if (*p == '\"')
1600 : {
1601 2166 : quoted = p;
1602 2166 : quoted_esc = 0;
1603 : }
1604 99620 : else if (*p == '#')
1605 : {
1606 1160 : hexfmt = p;
1607 1160 : hexcount = 0;
1608 : }
1609 98460 : else if (*p == '|')
1610 0 : base64 = p;
1611 98460 : else if (*p == '[')
1612 : {
1613 0 : if (disphint)
1614 : {
1615 0 : *erroff = p - buffer;
1616 : /* Open display hint. */
1617 0 : err = GPG_ERR_SEXP_NESTED_DH;
1618 0 : goto leave;
1619 : }
1620 0 : disphint = p;
1621 : }
1622 98460 : else if (*p == ']')
1623 : {
1624 0 : if (!disphint)
1625 : {
1626 0 : *erroff = p - buffer;
1627 : /* Open display hint. */
1628 0 : err = GPG_ERR_SEXP_UNMATCHED_DH;
1629 0 : goto leave;
1630 : }
1631 0 : disphint = NULL;
1632 : }
1633 98460 : else if (digitp (p))
1634 : {
1635 742 : if (*p == '0')
1636 : {
1637 : /* A length may not begin with zero. */
1638 0 : *erroff = p - buffer;
1639 0 : err = GPG_ERR_SEXP_ZERO_PREFIX;
1640 0 : goto leave;
1641 : }
1642 742 : digptr = p;
1643 : }
1644 97718 : else if (strchr (tokenchars, *p))
1645 43130 : tokenp = p;
1646 54588 : else if (whitespacep (p))
1647 : ;
1648 11204 : else if (*p == '{')
1649 : {
1650 : /* fixme: handle rescanning: we can do this by saving our
1651 : current state and start over at p+1 -- Hmmm. At this
1652 : point here we are in a well defined state, so we don't
1653 : need to save it. Great. */
1654 0 : *erroff = p - buffer;
1655 0 : err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
1656 0 : goto leave;
1657 : }
1658 11204 : else if (strchr ("&\\", *p))
1659 : {
1660 : /* Reserved punctuation. */
1661 0 : *erroff = p - buffer;
1662 0 : err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
1663 0 : goto leave;
1664 : }
1665 11204 : else if (argflag && (*p == '%'))
1666 11204 : percent = p;
1667 : else
1668 : {
1669 : /* Bad or unavailable. */
1670 0 : *erroff = p - buffer;
1671 0 : err = GPG_ERR_SEXP_BAD_CHARACTER;
1672 0 : goto leave;
1673 : }
1674 : }
1675 8900 : MAKE_SPACE (0);
1676 8900 : *c.pos++ = ST_STOP;
1677 :
1678 8900 : if (level && !err)
1679 2 : err = GPG_ERR_SEXP_UNMATCHED_PAREN;
1680 :
1681 : leave:
1682 8900 : if (err)
1683 : {
1684 : /* Error -> deallocate. */
1685 2 : if (c.sexp)
1686 : {
1687 : /* Extra paranoid wipe on error. */
1688 2 : if (_gcry_is_secure (c.sexp))
1689 0 : wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
1690 2 : xfree (c.sexp);
1691 : }
1692 : }
1693 : else
1694 8898 : *retsexp = normalize (c.sexp);
1695 :
1696 8900 : return err;
1697 : #undef MAKE_SPACE
1698 : #undef STORE_LEN
1699 : }
1700 :
1701 :
1702 : static gpg_err_code_t
1703 832 : do_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1704 : const char *buffer, size_t length, int argflag,
1705 : void **arg_list, ...)
1706 : {
1707 : gcry_err_code_t rc;
1708 : va_list arg_ptr;
1709 :
1710 832 : va_start (arg_ptr, arg_list);
1711 832 : rc = do_vsexp_sscan (retsexp, erroff, buffer, length, argflag,
1712 : arg_list, arg_ptr);
1713 832 : va_end (arg_ptr);
1714 :
1715 832 : return rc;
1716 : }
1717 :
1718 :
1719 : gpg_err_code_t
1720 2934 : _gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
1721 : {
1722 : gcry_err_code_t rc;
1723 : va_list arg_ptr;
1724 :
1725 2934 : va_start (arg_ptr, format);
1726 2934 : rc = do_vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
1727 : NULL, arg_ptr);
1728 2934 : va_end (arg_ptr);
1729 :
1730 2934 : return rc;
1731 : }
1732 :
1733 :
1734 : gcry_err_code_t
1735 5134 : _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff,
1736 : const char *format, va_list arg_ptr)
1737 : {
1738 5134 : return do_vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
1739 : NULL, arg_ptr);
1740 : }
1741 :
1742 :
1743 : /* Like gcry_sexp_build, but uses an array instead of variable
1744 : function arguments. */
1745 : gcry_err_code_t
1746 33 : _gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
1747 : const char *format, void **arg_list)
1748 : {
1749 33 : return do_sexp_sscan (retsexp, erroff, format, strlen(format), 1, arg_list);
1750 : }
1751 :
1752 :
1753 : gcry_err_code_t
1754 463 : _gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1755 : const char *buffer, size_t length)
1756 : {
1757 463 : return do_sexp_sscan (retsexp, erroff, buffer, length, 0, NULL);
1758 : }
1759 :
1760 :
1761 : /* Figure out a suitable encoding for BUFFER of LENGTH.
1762 : Returns: 0 = Binary
1763 : 1 = String possible
1764 : 2 = Token possible
1765 : */
1766 : static int
1767 0 : suitable_encoding (const unsigned char *buffer, size_t length)
1768 : {
1769 : const unsigned char *s;
1770 0 : int maybe_token = 1;
1771 :
1772 0 : if (!length)
1773 0 : return 1;
1774 :
1775 0 : if (*buffer & 0x80)
1776 0 : return 0; /* If the MSB is set we assume that buffer represents a
1777 : negative number. */
1778 0 : if (!*buffer)
1779 0 : return 0; /* Starting with a zero is pretty much a binary string. */
1780 :
1781 0 : for (s=buffer; length; s++, length--)
1782 : {
1783 0 : if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
1784 0 : && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
1785 0 : return 0; /*binary*/
1786 0 : if ( maybe_token
1787 0 : && !alphap (s) && !digitp (s) && !strchr (TOKEN_SPECIALS, *s))
1788 0 : maybe_token = 0;
1789 : }
1790 0 : s = buffer;
1791 0 : if ( maybe_token && !digitp (s) )
1792 0 : return 2;
1793 0 : return 1;
1794 : }
1795 :
1796 :
1797 : static int
1798 0 : convert_to_hex (const unsigned char *src, size_t len, char *dest)
1799 : {
1800 : int i;
1801 :
1802 0 : if (dest)
1803 : {
1804 0 : *dest++ = '#';
1805 0 : for (i=0; i < len; i++, dest += 2 )
1806 0 : sprintf (dest, "%02X", src[i]);
1807 0 : *dest++ = '#';
1808 : }
1809 0 : return len*2+2;
1810 : }
1811 :
1812 : static int
1813 0 : convert_to_string (const unsigned char *s, size_t len, char *dest)
1814 : {
1815 0 : if (dest)
1816 : {
1817 0 : char *p = dest;
1818 0 : *p++ = '\"';
1819 0 : for (; len; len--, s++ )
1820 : {
1821 0 : switch (*s)
1822 : {
1823 0 : case '\b': *p++ = '\\'; *p++ = 'b'; break;
1824 0 : case '\t': *p++ = '\\'; *p++ = 't'; break;
1825 0 : case '\v': *p++ = '\\'; *p++ = 'v'; break;
1826 0 : case '\n': *p++ = '\\'; *p++ = 'n'; break;
1827 0 : case '\f': *p++ = '\\'; *p++ = 'f'; break;
1828 0 : case '\r': *p++ = '\\'; *p++ = 'r'; break;
1829 0 : case '\"': *p++ = '\\'; *p++ = '\"'; break;
1830 0 : case '\'': *p++ = '\\'; *p++ = '\''; break;
1831 0 : case '\\': *p++ = '\\'; *p++ = '\\'; break;
1832 : default:
1833 0 : if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1834 : {
1835 0 : sprintf (p, "\\x%02x", *s);
1836 0 : p += 4;
1837 : }
1838 : else
1839 0 : *p++ = *s;
1840 : }
1841 : }
1842 0 : *p++ = '\"';
1843 0 : return p - dest;
1844 : }
1845 : else
1846 : {
1847 0 : int count = 2;
1848 0 : for (; len; len--, s++ )
1849 : {
1850 0 : switch (*s)
1851 : {
1852 : case '\b':
1853 : case '\t':
1854 : case '\v':
1855 : case '\n':
1856 : case '\f':
1857 : case '\r':
1858 : case '\"':
1859 : case '\'':
1860 0 : case '\\': count += 2; break;
1861 : default:
1862 0 : if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1863 0 : count += 4;
1864 : else
1865 0 : count++;
1866 : }
1867 : }
1868 0 : return count;
1869 : }
1870 : }
1871 :
1872 :
1873 :
1874 : static int
1875 0 : convert_to_token (const unsigned char *src, size_t len, char *dest)
1876 : {
1877 0 : if (dest)
1878 0 : memcpy (dest, src, len);
1879 0 : return len;
1880 : }
1881 :
1882 :
1883 : /****************
1884 : * Print SEXP to buffer using the MODE. Returns the length of the
1885 : * SEXP in buffer or 0 if the buffer is too short (We have at least an
1886 : * empty list consisting of 2 bytes). If a buffer of NULL is provided,
1887 : * the required length is returned.
1888 : */
1889 : size_t
1890 349 : _gcry_sexp_sprint (const gcry_sexp_t list, int mode,
1891 : void *buffer, size_t maxlength )
1892 : {
1893 : static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
1894 : const unsigned char *s;
1895 : char *d;
1896 : DATALEN n;
1897 : char numbuf[20];
1898 349 : size_t len = 0;
1899 349 : int i, indent = 0;
1900 :
1901 349 : s = list? list->d : empty;
1902 349 : d = buffer;
1903 3677 : while ( *s != ST_STOP )
1904 : {
1905 2979 : switch ( *s )
1906 : {
1907 : case ST_OPEN:
1908 829 : s++;
1909 829 : if ( mode != GCRYSEXP_FMT_CANON )
1910 : {
1911 0 : if (indent)
1912 0 : len++;
1913 0 : len += indent;
1914 : }
1915 829 : len++;
1916 829 : if ( buffer )
1917 : {
1918 419 : if ( len >= maxlength )
1919 0 : return 0;
1920 419 : if ( mode != GCRYSEXP_FMT_CANON )
1921 : {
1922 0 : if (indent)
1923 0 : *d++ = '\n';
1924 0 : for (i=0; i < indent; i++)
1925 0 : *d++ = ' ';
1926 : }
1927 419 : *d++ = '(';
1928 : }
1929 829 : indent++;
1930 829 : break;
1931 : case ST_CLOSE:
1932 829 : s++;
1933 829 : len++;
1934 829 : if ( buffer )
1935 : {
1936 419 : if ( len >= maxlength )
1937 0 : return 0;
1938 419 : *d++ = ')';
1939 : }
1940 829 : indent--;
1941 829 : if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
1942 : {
1943 0 : len++;
1944 0 : len += indent;
1945 0 : if (buffer)
1946 : {
1947 0 : if (len >= maxlength)
1948 0 : return 0;
1949 0 : *d++ = '\n';
1950 0 : for (i=0; i < indent; i++)
1951 0 : *d++ = ' ';
1952 : }
1953 : }
1954 829 : break;
1955 : case ST_DATA:
1956 1321 : s++;
1957 1321 : memcpy ( &n, s, sizeof n ); s += sizeof n;
1958 1321 : if (mode == GCRYSEXP_FMT_ADVANCED)
1959 : {
1960 : int type;
1961 : size_t nn;
1962 :
1963 0 : switch ( (type=suitable_encoding (s, n)))
1964 : {
1965 0 : case 1: nn = convert_to_string (s, n, NULL); break;
1966 0 : case 2: nn = convert_to_token (s, n, NULL); break;
1967 0 : default: nn = convert_to_hex (s, n, NULL); break;
1968 : }
1969 0 : len += nn;
1970 0 : if (buffer)
1971 : {
1972 0 : if (len >= maxlength)
1973 0 : return 0;
1974 0 : switch (type)
1975 : {
1976 0 : case 1: convert_to_string (s, n, d); break;
1977 0 : case 2: convert_to_token (s, n, d); break;
1978 0 : default: convert_to_hex (s, n, d); break;
1979 : }
1980 0 : d += nn;
1981 : }
1982 0 : if (s[n] != ST_CLOSE)
1983 : {
1984 0 : len++;
1985 0 : if (buffer)
1986 : {
1987 0 : if (len >= maxlength)
1988 0 : return 0;
1989 0 : *d++ = ' ';
1990 : }
1991 : }
1992 : }
1993 : else
1994 : {
1995 1321 : sprintf (numbuf, "%u:", (unsigned int)n );
1996 1321 : len += strlen (numbuf) + n;
1997 1321 : if ( buffer )
1998 : {
1999 670 : if ( len >= maxlength )
2000 0 : return 0;
2001 670 : d = stpcpy ( d, numbuf );
2002 670 : memcpy ( d, s, n ); d += n;
2003 : }
2004 : }
2005 1321 : s += n;
2006 1321 : break;
2007 : default:
2008 0 : BUG ();
2009 : }
2010 : }
2011 349 : if ( mode != GCRYSEXP_FMT_CANON )
2012 : {
2013 0 : len++;
2014 0 : if (buffer)
2015 : {
2016 0 : if ( len >= maxlength )
2017 0 : return 0;
2018 0 : *d++ = '\n';
2019 : }
2020 : }
2021 349 : if (buffer)
2022 : {
2023 176 : if ( len >= maxlength )
2024 0 : return 0;
2025 176 : *d++ = 0; /* for convenience we make a C string */
2026 : }
2027 : else
2028 173 : len++; /* we need one byte more for this */
2029 :
2030 349 : return len;
2031 : }
2032 :
2033 :
2034 : /* Scan a canonical encoded buffer with implicit length values and
2035 : return the actual length this S-expression uses. For a valid S-Exp
2036 : it should never return 0. If LENGTH is not zero, the maximum
2037 : length to scan is given - this can be used for syntax checks of
2038 : data passed from outside. errorcode and erroff may both be passed as
2039 : NULL. */
2040 : size_t
2041 14 : _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
2042 : size_t *erroff, gcry_err_code_t *errcode)
2043 : {
2044 : const unsigned char *p;
2045 14 : const unsigned char *disphint = NULL;
2046 14 : unsigned int datalen = 0;
2047 : size_t dummy_erroff;
2048 : gcry_err_code_t dummy_errcode;
2049 14 : size_t count = 0;
2050 14 : int level = 0;
2051 :
2052 14 : if (!erroff)
2053 0 : erroff = &dummy_erroff;
2054 14 : if (!errcode)
2055 0 : errcode = &dummy_errcode;
2056 :
2057 14 : *errcode = GPG_ERR_NO_ERROR;
2058 14 : *erroff = 0;
2059 14 : if (!buffer)
2060 0 : return 0;
2061 14 : if (*buffer != '(')
2062 : {
2063 1 : *errcode = GPG_ERR_SEXP_NOT_CANONICAL;
2064 1 : return 0;
2065 : }
2066 :
2067 48 : for (p=buffer; ; p++, count++ )
2068 : {
2069 48 : if (length && count >= length)
2070 : {
2071 3 : *erroff = count;
2072 3 : *errcode = GPG_ERR_SEXP_STRING_TOO_LONG;
2073 3 : return 0;
2074 : }
2075 :
2076 45 : if (datalen)
2077 : {
2078 9 : if (*p == ':')
2079 : {
2080 7 : if (length && (count+datalen) >= length)
2081 : {
2082 0 : *erroff = count;
2083 0 : *errcode = GPG_ERR_SEXP_STRING_TOO_LONG;
2084 0 : return 0;
2085 : }
2086 7 : count += datalen;
2087 7 : p += datalen;
2088 7 : datalen = 0;
2089 : }
2090 2 : else if (digitp(p))
2091 2 : datalen = datalen*10 + atoi_1(p);
2092 : else
2093 : {
2094 0 : *erroff = count;
2095 0 : *errcode = GPG_ERR_SEXP_INV_LEN_SPEC;
2096 0 : return 0;
2097 : }
2098 : }
2099 36 : else if (*p == '(')
2100 : {
2101 16 : if (disphint)
2102 : {
2103 0 : *erroff = count;
2104 0 : *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
2105 0 : return 0;
2106 : }
2107 16 : level++;
2108 : }
2109 20 : else if (*p == ')')
2110 : { /* walk up */
2111 10 : if (!level)
2112 : {
2113 0 : *erroff = count;
2114 0 : *errcode = GPG_ERR_SEXP_UNMATCHED_PAREN;
2115 0 : return 0;
2116 : }
2117 10 : if (disphint)
2118 : {
2119 0 : *erroff = count;
2120 0 : *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
2121 0 : return 0;
2122 : }
2123 10 : if (!--level)
2124 7 : return ++count; /* ready */
2125 : }
2126 10 : else if (*p == '[')
2127 : {
2128 0 : if (disphint)
2129 : {
2130 0 : *erroff = count;
2131 0 : *errcode = GPG_ERR_SEXP_NESTED_DH;
2132 0 : return 0;
2133 : }
2134 0 : disphint = p;
2135 : }
2136 10 : else if (*p == ']')
2137 : {
2138 0 : if ( !disphint )
2139 : {
2140 0 : *erroff = count;
2141 0 : *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
2142 0 : return 0;
2143 : }
2144 0 : disphint = NULL;
2145 : }
2146 10 : else if (digitp (p) )
2147 : {
2148 8 : if (*p == '0')
2149 : {
2150 1 : *erroff = count;
2151 1 : *errcode = GPG_ERR_SEXP_ZERO_PREFIX;
2152 1 : return 0;
2153 : }
2154 7 : datalen = atoi_1 (p);
2155 : }
2156 2 : else if (*p == '&' || *p == '\\')
2157 : {
2158 0 : *erroff = count;
2159 0 : *errcode = GPG_ERR_SEXP_UNEXPECTED_PUNC;
2160 0 : return 0;
2161 : }
2162 : else
2163 : {
2164 2 : *erroff = count;
2165 2 : *errcode = GPG_ERR_SEXP_BAD_CHARACTER;
2166 2 : return 0;
2167 : }
2168 35 : }
2169 : }
2170 :
2171 :
2172 : /* Extract MPIs from an s-expression using a list of parameters. The
2173 : * names of these parameters are given by the string LIST. Some
2174 : * special characters may be given to control the conversion:
2175 : *
2176 : * + :: Switch to unsigned integer format (default).
2177 : * - :: Switch to standard signed format.
2178 : * / :: Switch to opaque format.
2179 : * & :: Switch to buffer descriptor mode - see below.
2180 : * ? :: The previous parameter is optional.
2181 : *
2182 : * In general parameter names are single letters. To use a string for
2183 : * a parameter name, enclose the name in single quotes.
2184 : *
2185 : * Unless in gcry_buffer_t mode for each parameter name a pointer to
2186 : * an MPI variable is expected and finally a NULL is expected.
2187 : * Example:
2188 : *
2189 : * _gcry_sexp_extract_param (key, NULL, "n/x+ed",
2190 : * &mpi_n, &mpi_x, &mpi_e, NULL)
2191 : *
2192 : * This stores the parameter "N" from KEY as an unsigned MPI into
2193 : * MPI_N, the parameter "X" as an opaque MPI into MPI_X, and the
2194 : * parameter "E" again as an unsigned MPI into MPI_E.
2195 : *
2196 : * If in buffer descriptor mode a pointer to gcry_buffer_t descriptor
2197 : * is expected instead of a pointer to an MPI. The caller may use two
2198 : * different operation modes: If the DATA field of the provided buffer
2199 : * descriptor is NULL, the function allocates a new buffer and stores
2200 : * it at DATA; the other fields are set accordingly with OFF being 0.
2201 : * If DATA is not NULL, the function assumes that DATA, SIZE, and OFF
2202 : * describe a buffer where to but the data; on return the LEN field
2203 : * receives the number of bytes copied to that buffer; if the buffer
2204 : * is too small, the function immediately returns with an error code
2205 : * (and LEN set to 0).
2206 : *
2207 : * PATH is an optional string used to locate a token. The exclamation
2208 : * mark separated tokens are used to via gcry_sexp_find_token to find
2209 : * a start point inside SEXP.
2210 : *
2211 : * The function returns NULL on success. On error an error code is
2212 : * returned and the passed MPIs are either unchanged or set to NULL.
2213 : */
2214 : gpg_err_code_t
2215 7150 : _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
2216 : const char *list, va_list arg_ptr)
2217 : {
2218 : gpg_err_code_t rc;
2219 : const char *s, *s2;
2220 : gcry_mpi_t *array[20];
2221 : char arrayisdesc[20];
2222 : int idx;
2223 : gcry_sexp_t l1;
2224 7150 : int mode = '+'; /* Default to GCRYMPI_FMT_USG. */
2225 7150 : gcry_sexp_t freethis = NULL;
2226 :
2227 7150 : memset (arrayisdesc, 0, sizeof arrayisdesc);
2228 :
2229 : /* First copy all the args into an array. This is required so that
2230 : we are able to release already allocated MPIs if later an error
2231 : was found. */
2232 32703 : for (s=list, idx=0; *s && idx < DIM (array); s++)
2233 : {
2234 25556 : if (*s == '&' || *s == '+' || *s == '-' || *s == '/' || *s == '?')
2235 : ;
2236 16643 : else if (whitespacep (s))
2237 : ;
2238 : else
2239 : {
2240 16636 : if (*s == '\'')
2241 : {
2242 4 : s++;
2243 4 : s2 = strchr (s, '\'');
2244 4 : if (!s2 || s2 == s)
2245 : {
2246 : /* Closing quote not found or empty string. */
2247 2 : return GPG_ERR_SYNTAX;
2248 : }
2249 2 : s = s2;
2250 : }
2251 16634 : array[idx] = va_arg (arg_ptr, gcry_mpi_t *);
2252 16634 : if (!array[idx])
2253 1 : return GPG_ERR_MISSING_VALUE; /* NULL pointer given. */
2254 16633 : idx++;
2255 : }
2256 : }
2257 7147 : if (*s)
2258 0 : return GPG_ERR_LIMIT_REACHED; /* Too many list elements. */
2259 7147 : if (va_arg (arg_ptr, gcry_mpi_t *))
2260 1 : return GPG_ERR_INV_ARG; /* Not enough list elemends. */
2261 :
2262 : /* Drill down. */
2263 14305 : while (path && *path)
2264 : {
2265 : size_t n;
2266 :
2267 15 : s = strchr (path, '!');
2268 15 : if (s == path)
2269 : {
2270 1 : rc = GPG_ERR_NOT_FOUND;
2271 1 : goto cleanup;
2272 : }
2273 14 : n = s? s - path : 0;
2274 14 : l1 = _gcry_sexp_find_token (sexp, path, n);
2275 14 : if (!l1)
2276 : {
2277 1 : rc = GPG_ERR_NOT_FOUND;
2278 1 : goto cleanup;
2279 : }
2280 13 : sexp = l1; l1 = NULL;
2281 13 : sexp_release (freethis);
2282 13 : freethis = sexp;
2283 13 : if (n)
2284 6 : path += n + 1;
2285 : else
2286 7 : path = NULL;
2287 : }
2288 :
2289 :
2290 : /* Now extract all parameters. */
2291 32656 : for (s=list, idx=0; *s; s++)
2292 : {
2293 25517 : if (*s == '&' || *s == '+' || *s == '-' || *s == '/')
2294 4629 : mode = *s;
2295 20888 : else if (whitespacep (s))
2296 : ;
2297 20881 : else if (*s == '?')
2298 : ; /* Only used via lookahead. */
2299 : else
2300 : {
2301 16597 : if (*s == '\'')
2302 : {
2303 : /* Find closing quote, find token, set S to closing quote. */
2304 2 : s++;
2305 2 : s2 = strchr (s, '\'');
2306 2 : if (!s2 || s2 == s)
2307 : {
2308 : /* Closing quote not found or empty string. */
2309 0 : rc = GPG_ERR_SYNTAX;
2310 0 : goto cleanup;
2311 : }
2312 2 : l1 = _gcry_sexp_find_token (sexp, s, s2 - s);
2313 2 : s = s2;
2314 : }
2315 : else
2316 16595 : l1 = _gcry_sexp_find_token (sexp, s, 1);
2317 :
2318 16597 : if (!l1 && s[1] == '?')
2319 : {
2320 : /* Optional element not found. */
2321 6414 : if (mode == '&')
2322 : {
2323 0 : gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2324 0 : if (!spec->data)
2325 : {
2326 0 : spec->size = 0;
2327 0 : spec->off = 0;
2328 : }
2329 0 : spec->len = 0;
2330 : }
2331 : else
2332 3207 : *array[idx] = NULL;
2333 : }
2334 13390 : else if (!l1)
2335 : {
2336 5 : rc = GPG_ERR_NO_OBJ; /* List element not found. */
2337 5 : goto cleanup;
2338 : }
2339 : else
2340 : {
2341 13385 : if (mode == '&')
2342 : {
2343 4 : gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2344 :
2345 4 : if (spec->data)
2346 : {
2347 : const char *pbuf;
2348 : size_t nbuf;
2349 :
2350 2 : pbuf = _gcry_sexp_nth_data (l1, 1, &nbuf);
2351 2 : if (!pbuf || !nbuf)
2352 : {
2353 0 : rc = GPG_ERR_INV_OBJ;
2354 0 : goto cleanup;
2355 : }
2356 2 : if (spec->off + nbuf > spec->size)
2357 : {
2358 0 : rc = GPG_ERR_BUFFER_TOO_SHORT;
2359 0 : goto cleanup;
2360 : }
2361 2 : memcpy ((char*)spec->data + spec->off, pbuf, nbuf);
2362 2 : spec->len = nbuf;
2363 2 : arrayisdesc[idx] = 1;
2364 : }
2365 : else
2366 : {
2367 2 : spec->data = _gcry_sexp_nth_buffer (l1, 1, &spec->size);
2368 2 : if (!spec->data)
2369 : {
2370 0 : rc = GPG_ERR_INV_OBJ; /* Or out of core. */
2371 0 : goto cleanup;
2372 : }
2373 2 : spec->len = spec->size;
2374 2 : spec->off = 0;
2375 2 : arrayisdesc[idx] = 2;
2376 : }
2377 : }
2378 13381 : else if (mode == '/')
2379 3433 : *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
2380 9948 : else if (mode == '-')
2381 73 : *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_STD);
2382 : else
2383 9875 : *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
2384 13385 : sexp_release (l1); l1 = NULL;
2385 13385 : if (!*array[idx])
2386 : {
2387 0 : rc = GPG_ERR_INV_OBJ; /* Conversion failed. */
2388 0 : goto cleanup;
2389 : }
2390 : }
2391 16592 : idx++;
2392 : }
2393 : }
2394 :
2395 7139 : sexp_release (freethis);
2396 7139 : return 0;
2397 :
2398 : cleanup:
2399 7 : sexp_release (freethis);
2400 7 : sexp_release (l1);
2401 46 : while (idx--)
2402 : {
2403 32 : if (!arrayisdesc[idx])
2404 : {
2405 32 : _gcry_mpi_release (*array[idx]);
2406 32 : *array[idx] = NULL;
2407 : }
2408 0 : else if (arrayisdesc[idx] == 1)
2409 : {
2410 : /* Caller provided buffer. */
2411 0 : gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2412 0 : spec->len = 0;
2413 : }
2414 : else
2415 : {
2416 : /* We might have allocated a buffer. */
2417 0 : gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2418 0 : xfree (spec->data);
2419 0 : spec->data = NULL;
2420 0 : spec->size = spec->off = spec->len = 0;
2421 : }
2422 : }
2423 7 : return rc;
2424 : }
2425 :
2426 : gpg_err_code_t
2427 7130 : _gcry_sexp_extract_param (gcry_sexp_t sexp, const char *path,
2428 : const char *list, ...)
2429 : {
2430 : gcry_err_code_t rc;
2431 : va_list arg_ptr;
2432 :
2433 7130 : va_start (arg_ptr, list);
2434 7130 : rc = _gcry_sexp_vextract_param (sexp, path, list, arg_ptr);
2435 7130 : va_end (arg_ptr);
2436 7130 : return rc;
2437 : }
|