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 accidentally 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 0 : whitespacep (const char *p)
120 : {
121 0 : switch (*p)
122 : {
123 0 : case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1;
124 0 : 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 0 : normalize ( gcry_sexp_t list )
225 : {
226 : unsigned char *p;
227 :
228 0 : if ( !list )
229 0 : return NULL;
230 0 : p = list->d;
231 0 : if ( *p == ST_STOP )
232 : {
233 : /* this is "" */
234 0 : sexp_release ( list );
235 0 : return NULL;
236 : }
237 0 : if ( *p == ST_OPEN && p[1] == ST_CLOSE )
238 : {
239 : /* this is "()" */
240 0 : sexp_release ( list );
241 0 : return NULL;
242 : }
243 :
244 0 : 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 0 : _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 0 : if (!retsexp)
270 0 : return GPG_ERR_INV_ARG;
271 0 : *retsexp = NULL;
272 0 : if (autodetect < 0 || autodetect > 1 || !buffer)
273 0 : return GPG_ERR_INV_ARG;
274 :
275 0 : 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 0 : else if (!length && autodetect)
283 : { /* buffer is a string */
284 0 : length = strlen ((char *)buffer);
285 : }
286 :
287 0 : errcode = do_sexp_sscan (&se, NULL, buffer, length, 0, NULL);
288 0 : if (errcode)
289 0 : return errcode;
290 :
291 0 : *retsexp = se;
292 0 : 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 0 : freefnc (buffer);
300 : }
301 0 : return 0;
302 : }
303 :
304 : /* Same as gcry_sexp_create but don't transfer ownership */
305 : gcry_err_code_t
306 0 : _gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length,
307 : int autodetect)
308 : {
309 0 : 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 0 : _gcry_sexp_release( gcry_sexp_t sexp )
318 : {
319 0 : if (sexp)
320 : {
321 0 : if (_gcry_is_secure (sexp))
322 : {
323 : /* Extra paranoid wiping. */
324 0 : const byte *p = sexp->d;
325 : int type;
326 :
327 0 : while ( (type = *p) != ST_STOP )
328 : {
329 0 : p++;
330 0 : switch ( type )
331 : {
332 : case ST_OPEN:
333 0 : break;
334 : case ST_CLOSE:
335 0 : break;
336 : case ST_DATA:
337 : {
338 : DATALEN n;
339 0 : memcpy ( &n, p, sizeof n );
340 0 : p += sizeof n;
341 0 : p += n;
342 : }
343 0 : break;
344 : default:
345 0 : break;
346 : }
347 : }
348 0 : wipememory (sexp->d, p - sexp->d);
349 : }
350 0 : xfree ( sexp );
351 : }
352 0 : }
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 0 : _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 0 : if ( !list )
441 0 : return NULL;
442 :
443 0 : if ( !toklen )
444 0 : toklen = strlen(tok);
445 :
446 0 : p = list->d;
447 0 : while ( *p != ST_STOP )
448 : {
449 0 : if ( *p == ST_OPEN && p[1] == ST_DATA )
450 0 : {
451 0 : const byte *head = p;
452 :
453 0 : p += 2;
454 0 : memcpy ( &n, p, sizeof n );
455 0 : p += sizeof n;
456 0 : if ( n == toklen && !memcmp( p, tok, toklen ) )
457 : { /* found it */
458 : gcry_sexp_t newlist;
459 : byte *d;
460 0 : int level = 1;
461 :
462 : /* Look for the end of the list. */
463 0 : for ( p += n; level; p++ )
464 : {
465 0 : if ( *p == ST_DATA )
466 : {
467 0 : memcpy ( &n, ++p, sizeof n );
468 0 : p += sizeof n + n;
469 0 : p--; /* Compensate for later increment. */
470 : }
471 0 : else if ( *p == ST_OPEN )
472 : {
473 0 : level++;
474 : }
475 0 : else if ( *p == ST_CLOSE )
476 : {
477 0 : level--;
478 : }
479 0 : else if ( *p == ST_STOP )
480 : {
481 0 : BUG ();
482 : }
483 : }
484 0 : n = p - head;
485 :
486 0 : newlist = xtrymalloc ( sizeof *newlist + n );
487 0 : 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 0 : d = newlist->d;
494 0 : memcpy ( d, head, n ); d += n;
495 0 : *d++ = ST_STOP;
496 0 : return normalize ( newlist );
497 : }
498 0 : p += n;
499 : }
500 0 : else if ( *p == ST_DATA )
501 : {
502 0 : memcpy ( &n, ++p, sizeof n ); p += sizeof n;
503 0 : p += n;
504 : }
505 : else
506 0 : p++;
507 : }
508 0 : return NULL;
509 : }
510 :
511 : /****************
512 : * Return the length of the given list
513 : */
514 : int
515 0 : _gcry_sexp_length (const gcry_sexp_t list)
516 : {
517 : const byte *p;
518 : DATALEN n;
519 : int type;
520 0 : int length = 0;
521 0 : int level = 0;
522 :
523 0 : if (!list)
524 0 : return 0;
525 :
526 0 : p = list->d;
527 0 : while ((type=*p) != ST_STOP)
528 : {
529 0 : p++;
530 0 : if (type == ST_DATA)
531 : {
532 0 : memcpy (&n, p, sizeof n);
533 0 : p += sizeof n + n;
534 0 : if (level == 1)
535 0 : length++;
536 : }
537 0 : else if (type == ST_OPEN)
538 : {
539 0 : if (level == 1)
540 0 : length++;
541 0 : level++;
542 : }
543 0 : else if (type == ST_CLOSE)
544 : {
545 0 : level--;
546 : }
547 : }
548 0 : 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 0 : 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 0 : int level = 0;
562 :
563 0 : *r_off = 0;
564 0 : if (list)
565 : {
566 0 : p = list->d;
567 0 : while ( (type=*p) != ST_STOP )
568 : {
569 0 : p++;
570 0 : if (type == ST_DATA)
571 : {
572 0 : memcpy (&n, p, sizeof n);
573 0 : p += sizeof n + n;
574 : }
575 0 : else if (type == ST_OPEN)
576 : {
577 0 : if (!level)
578 0 : *r_off = (p-1) - list->d;
579 0 : level++;
580 : }
581 0 : else if ( type == ST_CLOSE )
582 : {
583 0 : level--;
584 0 : if (!level)
585 0 : return p - list->d;
586 : }
587 : }
588 : }
589 0 : 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 0 : _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 0 : int level = 0;
604 :
605 0 : if (!list || list->d[0] != ST_OPEN)
606 0 : return NULL;
607 0 : p = list->d;
608 :
609 0 : while (number > 0)
610 : {
611 0 : p++;
612 0 : if (*p == ST_DATA)
613 : {
614 0 : memcpy (&n, ++p, sizeof n);
615 0 : p += sizeof n + n;
616 0 : p--;
617 0 : if (!level)
618 0 : number--;
619 : }
620 0 : else if (*p == ST_OPEN)
621 : {
622 0 : level++;
623 : }
624 0 : else if (*p == ST_CLOSE)
625 : {
626 0 : level--;
627 0 : if ( !level )
628 0 : number--;
629 : }
630 0 : else if (*p == ST_STOP)
631 : {
632 0 : return NULL;
633 : }
634 : }
635 0 : p++;
636 :
637 0 : if (*p == ST_DATA)
638 : {
639 0 : memcpy (&n, p+1, sizeof n);
640 0 : newlist = xtrymalloc (sizeof *newlist + 1 + 1 + sizeof n + n + 1);
641 0 : if (!newlist)
642 0 : return NULL;
643 0 : d = newlist->d;
644 0 : *d++ = ST_OPEN;
645 0 : memcpy (d, p, 1 + sizeof n + n);
646 0 : d += 1 + sizeof n + n;
647 0 : *d++ = ST_CLOSE;
648 0 : *d = ST_STOP;
649 : }
650 0 : else if (*p == ST_OPEN)
651 : {
652 0 : const byte *head = p;
653 :
654 0 : level = 1;
655 : do {
656 0 : p++;
657 0 : if (*p == ST_DATA)
658 : {
659 0 : memcpy (&n, ++p, sizeof n);
660 0 : p += sizeof n + n;
661 0 : p--;
662 : }
663 0 : else if (*p == ST_OPEN)
664 : {
665 0 : level++;
666 : }
667 0 : else if (*p == ST_CLOSE)
668 : {
669 0 : level--;
670 : }
671 0 : else if (*p == ST_STOP)
672 : {
673 0 : BUG ();
674 : }
675 0 : } while (level);
676 0 : n = p + 1 - head;
677 :
678 0 : newlist = xtrymalloc (sizeof *newlist + n);
679 0 : if (!newlist)
680 0 : return NULL;
681 0 : d = newlist->d;
682 0 : memcpy (d, head, n);
683 0 : d += n;
684 0 : *d++ = ST_STOP;
685 : }
686 : else
687 0 : newlist = NULL;
688 :
689 0 : return normalize (newlist);
690 : }
691 :
692 :
693 : gcry_sexp_t
694 0 : _gcry_sexp_car (const gcry_sexp_t list)
695 : {
696 0 : 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 0 : do_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen)
704 : {
705 : const byte *p;
706 : DATALEN n;
707 0 : int level = 0;
708 :
709 0 : *datalen = 0;
710 0 : if ( !list )
711 0 : return NULL;
712 :
713 0 : p = list->d;
714 0 : if ( *p == ST_OPEN )
715 0 : p++; /* Yep, a list. */
716 0 : else if (number)
717 0 : return NULL; /* Not a list but N > 0 requested. */
718 :
719 : /* Skip over N elements. */
720 0 : while (number > 0)
721 : {
722 0 : if (*p == ST_DATA)
723 : {
724 0 : memcpy ( &n, ++p, sizeof n );
725 0 : p += sizeof n + n;
726 0 : p--;
727 0 : if ( !level )
728 0 : 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 0 : p++;
745 : }
746 :
747 : /* If this is data, return it. */
748 0 : if (*p == ST_DATA)
749 : {
750 0 : memcpy ( &n, ++p, sizeof n );
751 0 : *datalen = n;
752 0 : return (const char*)p + sizeof n;
753 : }
754 :
755 0 : 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 0 : _gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen )
763 : {
764 0 : 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 0 : _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 0 : *rlength = 0;
780 0 : s = do_sexp_nth_data (list, number, &n);
781 0 : if (!s || !n)
782 0 : return NULL;
783 0 : buf = xtrymalloc (n);
784 0 : if (!buf)
785 0 : return NULL;
786 0 : memcpy (buf, s, n);
787 0 : *rlength = n;
788 0 : 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 0 : _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 0 : s = do_sexp_nth_data (list, number, &n);
802 0 : if (!s || n < 1 || (n+1) < 1)
803 0 : return NULL;
804 0 : buf = xtrymalloc (n+1);
805 0 : if (!buf)
806 0 : return NULL;
807 0 : memcpy (buf, s, n);
808 0 : buf[n] = 0;
809 0 : return buf;
810 : }
811 :
812 :
813 : /*
814 : * Get a MPI from the car
815 : */
816 : gcry_mpi_t
817 0 : _gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt)
818 : {
819 : size_t n;
820 : gcry_mpi_t a;
821 :
822 0 : if (mpifmt == GCRYMPI_FMT_OPAQUE)
823 : {
824 : char *p;
825 :
826 0 : p = _gcry_sexp_nth_buffer (list, number, &n);
827 0 : if (!p)
828 0 : return NULL;
829 :
830 0 : a = _gcry_is_secure (list)? _gcry_mpi_snew (0) : _gcry_mpi_new (0);
831 0 : if (a)
832 0 : mpi_set_opaque (a, p, n*8);
833 : else
834 0 : xfree (p);
835 : }
836 : else
837 : {
838 : const char *s;
839 :
840 0 : if (!mpifmt)
841 0 : mpifmt = GCRYMPI_FMT_STD;
842 :
843 0 : s = do_sexp_nth_data (list, number, &n);
844 0 : if (!s)
845 0 : return NULL;
846 :
847 0 : if (_gcry_mpi_scan (&a, mpifmt, s, n, NULL))
848 0 : return NULL;
849 : }
850 :
851 0 : return a;
852 : }
853 :
854 :
855 : /****************
856 : * Get the CDR
857 : */
858 : gcry_sexp_t
859 0 : _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 0 : int level = 0;
867 0 : int skip = 1;
868 :
869 0 : if (!list || list->d[0] != ST_OPEN)
870 0 : return NULL;
871 0 : p = list->d;
872 :
873 0 : while (skip > 0)
874 : {
875 0 : p++;
876 0 : if (*p == ST_DATA)
877 : {
878 0 : memcpy ( &n, ++p, sizeof n );
879 0 : p += sizeof n + n;
880 0 : p--;
881 0 : if ( !level )
882 0 : 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 0 : p++;
900 :
901 0 : head = p;
902 0 : level = 0;
903 : do {
904 0 : if (*p == ST_DATA)
905 : {
906 0 : memcpy ( &n, ++p, sizeof n );
907 0 : p += sizeof n + n;
908 0 : p--;
909 : }
910 0 : else if (*p == ST_OPEN)
911 : {
912 0 : level++;
913 : }
914 0 : else if (*p == ST_CLOSE)
915 : {
916 0 : level--;
917 : }
918 0 : else if (*p == ST_STOP)
919 : {
920 0 : return NULL;
921 : }
922 0 : p++;
923 0 : } while (level);
924 0 : n = p - head;
925 :
926 0 : newlist = xtrymalloc (sizeof *newlist + n + 2);
927 0 : if (!newlist)
928 0 : return NULL;
929 0 : d = newlist->d;
930 0 : *d++ = ST_OPEN;
931 0 : memcpy (d, head, n);
932 0 : d += n;
933 0 : *d++ = ST_CLOSE;
934 0 : *d++ = ST_STOP;
935 :
936 0 : return normalize (newlist);
937 : }
938 :
939 :
940 : gcry_sexp_t
941 0 : _gcry_sexp_cadr ( const gcry_sexp_t list )
942 : {
943 : gcry_sexp_t a, b;
944 :
945 0 : a = _gcry_sexp_cdr (list);
946 0 : b = _gcry_sexp_car (a);
947 0 : sexp_release (a);
948 0 : return b;
949 : }
950 :
951 :
952 : static GPG_ERR_INLINE int
953 0 : hextonibble (int s)
954 : {
955 0 : if (s >= '0' && s <= '9')
956 0 : return s - '0';
957 0 : else if (s >= 'A' && s <= 'F')
958 0 : return 10 + s - 'A';
959 0 : else if (s >= 'a' && s <= 'f')
960 0 : 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 0 : make_space ( struct make_space_ctx *c, size_t n )
976 : {
977 0 : size_t used = c->pos - c->sexp->d;
978 :
979 0 : if ( used + n + sizeof(DATALEN) + 1 >= c->allocated )
980 : {
981 : gcry_sexp_t newsexp;
982 : byte *newhead;
983 : size_t newsize;
984 :
985 0 : newsize = c->allocated + 2*(n+sizeof(DATALEN)+1);
986 0 : if (newsize <= c->allocated)
987 0 : return GPG_ERR_TOO_LARGE;
988 0 : newsexp = xtryrealloc ( c->sexp, sizeof *newsexp + newsize - 1);
989 0 : if (!newsexp)
990 0 : return gpg_err_code_from_errno (errno);
991 0 : c->allocated = newsize;
992 0 : newhead = newsexp->d;
993 0 : c->pos = newhead + used;
994 0 : c->sexp = newsexp;
995 : }
996 0 : 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 0 : unquote_string (const char *string, size_t length, unsigned char *buf)
1005 : {
1006 0 : int esc = 0;
1007 0 : const unsigned char *s = (const unsigned char*)string;
1008 0 : unsigned char *d = buf;
1009 0 : size_t n = length;
1010 :
1011 0 : for (; n; n--, s++)
1012 : {
1013 0 : 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 0 : else if( *s == '\\' )
1062 0 : esc = 1;
1063 : else
1064 0 : *d++ = *s;
1065 : }
1066 :
1067 0 : 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 0 : 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 0 : 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 0 : const char *digptr = NULL;
1108 0 : const char *quoted = NULL;
1109 0 : const char *tokenp = NULL;
1110 0 : const char *hexfmt = NULL;
1111 0 : const char *base64 = NULL;
1112 0 : const char *disphint = NULL;
1113 0 : const char *percent = NULL;
1114 0 : int hexcount = 0;
1115 0 : int quoted_esc = 0;
1116 0 : int datalen = 0;
1117 : size_t dummy_erroff;
1118 : struct make_space_ctx c;
1119 0 : int arg_counter = 0;
1120 0 : int level = 0;
1121 :
1122 0 : if (!retsexp)
1123 0 : return GPG_ERR_INV_ARG;
1124 0 : *retsexp = NULL;
1125 :
1126 0 : if (!buffer)
1127 0 : return GPG_ERR_INV_ARG;
1128 :
1129 0 : if (!erroff)
1130 0 : 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 0 : c.allocated = length + sizeof(DATALEN);
1170 0 : if (length && _gcry_is_secure (buffer))
1171 0 : c.sexp = xtrymalloc_secure (sizeof *c.sexp + c.allocated - 1);
1172 : else
1173 0 : c.sexp = xtrymalloc (sizeof *c.sexp + c.allocated - 1);
1174 0 : if (!c.sexp)
1175 : {
1176 0 : err = gpg_err_code_from_errno (errno);
1177 0 : *erroff = 0;
1178 0 : goto leave;
1179 : }
1180 0 : c.pos = c.sexp->d;
1181 :
1182 0 : for (p = buffer, n = length; n; p++, n--)
1183 : {
1184 0 : if (tokenp && !hexfmt)
1185 : {
1186 0 : if (strchr (tokenchars, *p))
1187 0 : continue;
1188 : else
1189 : {
1190 0 : datalen = p - tokenp;
1191 0 : MAKE_SPACE (datalen);
1192 0 : *c.pos++ = ST_DATA;
1193 0 : STORE_LEN (c.pos, datalen);
1194 0 : memcpy (c.pos, tokenp, datalen);
1195 0 : c.pos += datalen;
1196 0 : tokenp = NULL;
1197 : }
1198 : }
1199 :
1200 0 : if (quoted)
1201 : {
1202 0 : 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 0 : else if (*p == '\\')
1268 0 : quoted_esc = 1;
1269 0 : 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 0 : quoted++; /* Skip leading quote. */
1277 0 : MAKE_SPACE (p - quoted);
1278 0 : *c.pos++ = ST_DATA;
1279 0 : save = c.pos;
1280 0 : STORE_LEN (c.pos, 0); /* Will be fixed up later. */
1281 0 : len = unquote_string (quoted, p - quoted, c.pos);
1282 0 : c.pos += len;
1283 0 : STORE_LEN (save, len);
1284 0 : quoted = NULL;
1285 : }
1286 : }
1287 0 : else if (hexfmt)
1288 : {
1289 0 : if (isxdigit (*p))
1290 0 : hexcount++;
1291 0 : else if (*p == '#')
1292 : {
1293 0 : 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 0 : datalen = hexcount / 2;
1301 0 : MAKE_SPACE (datalen);
1302 0 : *c.pos++ = ST_DATA;
1303 0 : STORE_LEN (c.pos, datalen);
1304 0 : for (hexfmt++; hexfmt < p; hexfmt++)
1305 : {
1306 : int tmpc;
1307 :
1308 0 : if (whitespacep (hexfmt))
1309 0 : continue;
1310 0 : tmpc = hextonibble (*(const unsigned char*)hexfmt);
1311 0 : for (hexfmt++; hexfmt < p && whitespacep (hexfmt); hexfmt++)
1312 : ;
1313 0 : if (hexfmt < p)
1314 : {
1315 0 : tmpc *= 16;
1316 0 : tmpc += hextonibble (*(const unsigned char*)hexfmt);
1317 : }
1318 0 : *c.pos++ = tmpc;
1319 : }
1320 0 : hexfmt = NULL;
1321 : }
1322 0 : 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 0 : else if (base64)
1330 : {
1331 0 : if (*p == '|')
1332 0 : base64 = NULL;
1333 : }
1334 0 : else if (digptr)
1335 : {
1336 0 : if (digitp (p))
1337 : ;
1338 0 : else if (*p == ':')
1339 : {
1340 0 : datalen = atoi (digptr); /* FIXME: check for overflow. */
1341 0 : digptr = NULL;
1342 0 : 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 0 : MAKE_SPACE (datalen);
1351 0 : *c.pos++ = ST_DATA;
1352 0 : STORE_LEN (c.pos, datalen);
1353 0 : memcpy (c.pos, p + 1, datalen);
1354 0 : c.pos += datalen;
1355 0 : n -= datalen;
1356 0 : 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 0 : else if (percent)
1383 : {
1384 0 : if (*p == 'm' || *p == 'M')
1385 0 : {
1386 : /* Insert an MPI. */
1387 : gcry_mpi_t m;
1388 0 : size_t nm = 0;
1389 0 : int mpifmt = *p == 'm'? GCRYMPI_FMT_STD: GCRYMPI_FMT_USG;
1390 :
1391 0 : ARG_NEXT (m, gcry_mpi_t);
1392 :
1393 0 : if (mpi_get_flag (m, GCRYMPI_FLAG_OPAQUE))
1394 : {
1395 : void *mp;
1396 : unsigned int nbits;
1397 :
1398 0 : mp = mpi_get_opaque (m, &nbits);
1399 0 : nm = (nbits+7)/8;
1400 0 : if (mp && nm)
1401 : {
1402 0 : MAKE_SPACE (nm);
1403 0 : if (!_gcry_is_secure (c.sexp->d)
1404 0 : && 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 0 : *c.pos++ = ST_DATA;
1425 0 : STORE_LEN (c.pos, nm);
1426 0 : memcpy (c.pos, mp, nm);
1427 0 : c.pos += nm;
1428 : }
1429 : }
1430 : else
1431 : {
1432 0 : if (_gcry_mpi_print (mpifmt, NULL, 0, &nm, m))
1433 0 : BUG ();
1434 :
1435 0 : MAKE_SPACE (nm);
1436 0 : if (!_gcry_is_secure (c.sexp->d)
1437 0 : && 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 0 : newsexp = xtrymalloc_secure (sizeof *newsexp
1444 : + c.allocated - 1);
1445 0 : if (!newsexp)
1446 : {
1447 0 : err = gpg_err_code_from_errno (errno);
1448 0 : goto leave;
1449 : }
1450 0 : newhead = newsexp->d;
1451 0 : memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1452 0 : c.pos = newhead + (c.pos - c.sexp->d);
1453 0 : xfree (c.sexp);
1454 0 : c.sexp = newsexp;
1455 : }
1456 :
1457 0 : *c.pos++ = ST_DATA;
1458 0 : STORE_LEN (c.pos, nm);
1459 0 : if (_gcry_mpi_print (mpifmt, c.pos, nm, &nm, m))
1460 0 : BUG ();
1461 0 : c.pos += nm;
1462 : }
1463 : }
1464 0 : else if (*p == 's')
1465 : {
1466 : /* Insert an string. */
1467 : const char *astr;
1468 : size_t alen;
1469 :
1470 0 : ARG_NEXT (astr, const char *);
1471 0 : alen = strlen (astr);
1472 :
1473 0 : MAKE_SPACE (alen);
1474 0 : *c.pos++ = ST_DATA;
1475 0 : STORE_LEN (c.pos, alen);
1476 0 : memcpy (c.pos, astr, alen);
1477 0 : c.pos += alen;
1478 : }
1479 0 : else if (*p == 'b')
1480 : {
1481 : /* Insert a memory buffer. */
1482 : const char *astr;
1483 : int alen;
1484 :
1485 0 : ARG_NEXT (alen, int);
1486 0 : ARG_NEXT (astr, const char *);
1487 :
1488 0 : MAKE_SPACE (alen);
1489 0 : if (alen
1490 0 : && !_gcry_is_secure (c.sexp->d)
1491 0 : && _gcry_is_secure (astr))
1492 : {
1493 : /* We have to switch to secure allocation. */
1494 : gcry_sexp_t newsexp;
1495 : byte *newhead;
1496 :
1497 0 : newsexp = xtrymalloc_secure (sizeof *newsexp
1498 : + c.allocated - 1);
1499 0 : if (!newsexp)
1500 : {
1501 0 : err = gpg_err_code_from_errno (errno);
1502 0 : goto leave;
1503 : }
1504 0 : newhead = newsexp->d;
1505 0 : memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1506 0 : c.pos = newhead + (c.pos - c.sexp->d);
1507 0 : xfree (c.sexp);
1508 0 : c.sexp = newsexp;
1509 : }
1510 :
1511 0 : *c.pos++ = ST_DATA;
1512 0 : STORE_LEN (c.pos, alen);
1513 0 : memcpy (c.pos, astr, alen);
1514 0 : c.pos += alen;
1515 : }
1516 0 : else if (*p == 'd')
1517 : {
1518 : /* Insert an integer as string. */
1519 : int aint;
1520 : size_t alen;
1521 : char buf[35];
1522 :
1523 0 : ARG_NEXT (aint, int);
1524 0 : sprintf (buf, "%d", aint);
1525 0 : alen = strlen (buf);
1526 0 : MAKE_SPACE (alen);
1527 0 : *c.pos++ = ST_DATA;
1528 0 : STORE_LEN (c.pos, alen);
1529 0 : memcpy (c.pos, buf, alen);
1530 0 : c.pos += alen;
1531 : }
1532 0 : 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 0 : else if (*p == 'S')
1549 : {
1550 : /* Insert a gcry_sexp_t. */
1551 : gcry_sexp_t asexp;
1552 : size_t alen, aoff;
1553 :
1554 0 : ARG_NEXT (asexp, gcry_sexp_t);
1555 0 : alen = get_internal_buffer (asexp, &aoff);
1556 0 : if (alen)
1557 : {
1558 0 : MAKE_SPACE (alen);
1559 0 : memcpy (c.pos, asexp->d + aoff, alen);
1560 0 : 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 0 : percent = NULL;
1571 : }
1572 0 : else if (*p == '(')
1573 : {
1574 0 : 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 0 : MAKE_SPACE (0);
1582 0 : *c.pos++ = ST_OPEN;
1583 0 : level++;
1584 : }
1585 0 : else if (*p == ')')
1586 : {
1587 : /* Walk up. */
1588 0 : 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 :
1596 0 : if (level == 0)
1597 : {
1598 0 : *erroff = p - buffer;
1599 0 : err = GPG_ERR_SEXP_UNMATCHED_PAREN;
1600 0 : goto leave;
1601 : }
1602 0 : MAKE_SPACE (0);
1603 0 : *c.pos++ = ST_CLOSE;
1604 0 : level--;
1605 : }
1606 0 : else if (*p == '\"')
1607 : {
1608 0 : quoted = p;
1609 0 : quoted_esc = 0;
1610 : }
1611 0 : else if (*p == '#')
1612 : {
1613 0 : hexfmt = p;
1614 0 : hexcount = 0;
1615 : }
1616 0 : else if (*p == '|')
1617 0 : base64 = p;
1618 0 : else if (*p == '[')
1619 : {
1620 0 : if (disphint)
1621 : {
1622 0 : *erroff = p - buffer;
1623 : /* Open display hint. */
1624 0 : err = GPG_ERR_SEXP_NESTED_DH;
1625 0 : goto leave;
1626 : }
1627 0 : disphint = p;
1628 : }
1629 0 : else if (*p == ']')
1630 : {
1631 0 : if (!disphint)
1632 : {
1633 0 : *erroff = p - buffer;
1634 : /* Open display hint. */
1635 0 : err = GPG_ERR_SEXP_UNMATCHED_DH;
1636 0 : goto leave;
1637 : }
1638 0 : disphint = NULL;
1639 : }
1640 0 : else if (digitp (p))
1641 : {
1642 0 : if (*p == '0')
1643 : {
1644 : /* A length may not begin with zero. */
1645 0 : *erroff = p - buffer;
1646 0 : err = GPG_ERR_SEXP_ZERO_PREFIX;
1647 0 : goto leave;
1648 : }
1649 0 : digptr = p;
1650 : }
1651 0 : else if (strchr (tokenchars, *p))
1652 0 : tokenp = p;
1653 0 : else if (whitespacep (p))
1654 : ;
1655 0 : else if (*p == '{')
1656 : {
1657 : /* fixme: handle rescanning: we can do this by saving our
1658 : current state and start over at p+1 -- Hmmm. At this
1659 : point here we are in a well defined state, so we don't
1660 : need to save it. Great. */
1661 0 : *erroff = p - buffer;
1662 0 : err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
1663 0 : goto leave;
1664 : }
1665 0 : else if (strchr ("&\\", *p))
1666 : {
1667 : /* Reserved punctuation. */
1668 0 : *erroff = p - buffer;
1669 0 : err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
1670 0 : goto leave;
1671 : }
1672 0 : else if (argflag && (*p == '%'))
1673 0 : percent = p;
1674 : else
1675 : {
1676 : /* Bad or unavailable. */
1677 0 : *erroff = p - buffer;
1678 0 : err = GPG_ERR_SEXP_BAD_CHARACTER;
1679 0 : goto leave;
1680 : }
1681 : }
1682 0 : MAKE_SPACE (0);
1683 0 : *c.pos++ = ST_STOP;
1684 :
1685 0 : if (level && !err)
1686 0 : err = GPG_ERR_SEXP_UNMATCHED_PAREN;
1687 :
1688 : leave:
1689 0 : if (err)
1690 : {
1691 : /* Error -> deallocate. */
1692 0 : if (c.sexp)
1693 : {
1694 : /* Extra paranoid wipe on error. */
1695 0 : if (_gcry_is_secure (c.sexp))
1696 0 : wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
1697 0 : xfree (c.sexp);
1698 : }
1699 : }
1700 : else
1701 0 : *retsexp = normalize (c.sexp);
1702 :
1703 0 : return err;
1704 : #undef MAKE_SPACE
1705 : #undef STORE_LEN
1706 : }
1707 :
1708 :
1709 : static gpg_err_code_t
1710 0 : do_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1711 : const char *buffer, size_t length, int argflag,
1712 : void **arg_list, ...)
1713 : {
1714 : gcry_err_code_t rc;
1715 : va_list arg_ptr;
1716 :
1717 0 : va_start (arg_ptr, arg_list);
1718 0 : rc = do_vsexp_sscan (retsexp, erroff, buffer, length, argflag,
1719 : arg_list, arg_ptr);
1720 0 : va_end (arg_ptr);
1721 :
1722 0 : return rc;
1723 : }
1724 :
1725 :
1726 : gpg_err_code_t
1727 0 : _gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
1728 : {
1729 : gcry_err_code_t rc;
1730 : va_list arg_ptr;
1731 :
1732 0 : va_start (arg_ptr, format);
1733 0 : rc = do_vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
1734 : NULL, arg_ptr);
1735 0 : va_end (arg_ptr);
1736 :
1737 0 : return rc;
1738 : }
1739 :
1740 :
1741 : gcry_err_code_t
1742 0 : _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff,
1743 : const char *format, va_list arg_ptr)
1744 : {
1745 0 : return do_vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
1746 : NULL, arg_ptr);
1747 : }
1748 :
1749 :
1750 : /* Like gcry_sexp_build, but uses an array instead of variable
1751 : function arguments. */
1752 : gcry_err_code_t
1753 0 : _gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
1754 : const char *format, void **arg_list)
1755 : {
1756 0 : return do_sexp_sscan (retsexp, erroff, format, strlen(format), 1, arg_list);
1757 : }
1758 :
1759 :
1760 : gcry_err_code_t
1761 0 : _gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1762 : const char *buffer, size_t length)
1763 : {
1764 0 : return do_sexp_sscan (retsexp, erroff, buffer, length, 0, NULL);
1765 : }
1766 :
1767 :
1768 : /* Figure out a suitable encoding for BUFFER of LENGTH.
1769 : Returns: 0 = Binary
1770 : 1 = String possible
1771 : 2 = Token possible
1772 : */
1773 : static int
1774 0 : suitable_encoding (const unsigned char *buffer, size_t length)
1775 : {
1776 : const unsigned char *s;
1777 0 : int maybe_token = 1;
1778 :
1779 0 : if (!length)
1780 0 : return 1;
1781 :
1782 0 : if (*buffer & 0x80)
1783 0 : return 0; /* If the MSB is set we assume that buffer represents a
1784 : negative number. */
1785 0 : if (!*buffer)
1786 0 : return 0; /* Starting with a zero is pretty much a binary string. */
1787 :
1788 0 : for (s=buffer; length; s++, length--)
1789 : {
1790 0 : if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
1791 0 : && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
1792 0 : return 0; /*binary*/
1793 0 : if ( maybe_token
1794 0 : && !alphap (s) && !digitp (s) && !strchr (TOKEN_SPECIALS, *s))
1795 0 : maybe_token = 0;
1796 : }
1797 0 : s = buffer;
1798 0 : if ( maybe_token && !digitp (s) )
1799 0 : return 2;
1800 0 : return 1;
1801 : }
1802 :
1803 :
1804 : static int
1805 0 : convert_to_hex (const unsigned char *src, size_t len, char *dest)
1806 : {
1807 : int i;
1808 :
1809 0 : if (dest)
1810 : {
1811 0 : *dest++ = '#';
1812 0 : for (i=0; i < len; i++, dest += 2 )
1813 0 : sprintf (dest, "%02X", src[i]);
1814 0 : *dest++ = '#';
1815 : }
1816 0 : return len*2+2;
1817 : }
1818 :
1819 : static int
1820 0 : convert_to_string (const unsigned char *s, size_t len, char *dest)
1821 : {
1822 0 : if (dest)
1823 : {
1824 0 : char *p = dest;
1825 0 : *p++ = '\"';
1826 0 : for (; len; len--, s++ )
1827 : {
1828 0 : switch (*s)
1829 : {
1830 0 : case '\b': *p++ = '\\'; *p++ = 'b'; break;
1831 0 : case '\t': *p++ = '\\'; *p++ = 't'; break;
1832 0 : case '\v': *p++ = '\\'; *p++ = 'v'; break;
1833 0 : case '\n': *p++ = '\\'; *p++ = 'n'; break;
1834 0 : case '\f': *p++ = '\\'; *p++ = 'f'; break;
1835 0 : case '\r': *p++ = '\\'; *p++ = 'r'; break;
1836 0 : case '\"': *p++ = '\\'; *p++ = '\"'; break;
1837 0 : case '\'': *p++ = '\\'; *p++ = '\''; break;
1838 0 : case '\\': *p++ = '\\'; *p++ = '\\'; break;
1839 : default:
1840 0 : if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1841 : {
1842 0 : sprintf (p, "\\x%02x", *s);
1843 0 : p += 4;
1844 : }
1845 : else
1846 0 : *p++ = *s;
1847 : }
1848 : }
1849 0 : *p++ = '\"';
1850 0 : return p - dest;
1851 : }
1852 : else
1853 : {
1854 0 : int count = 2;
1855 0 : for (; len; len--, s++ )
1856 : {
1857 0 : switch (*s)
1858 : {
1859 : case '\b':
1860 : case '\t':
1861 : case '\v':
1862 : case '\n':
1863 : case '\f':
1864 : case '\r':
1865 : case '\"':
1866 : case '\'':
1867 0 : case '\\': count += 2; break;
1868 : default:
1869 0 : if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1870 0 : count += 4;
1871 : else
1872 0 : count++;
1873 : }
1874 : }
1875 0 : return count;
1876 : }
1877 : }
1878 :
1879 :
1880 :
1881 : static int
1882 0 : convert_to_token (const unsigned char *src, size_t len, char *dest)
1883 : {
1884 0 : if (dest)
1885 0 : memcpy (dest, src, len);
1886 0 : return len;
1887 : }
1888 :
1889 :
1890 : /****************
1891 : * Print SEXP to buffer using the MODE. Returns the length of the
1892 : * SEXP in buffer or 0 if the buffer is too short (We have at least an
1893 : * empty list consisting of 2 bytes). If a buffer of NULL is provided,
1894 : * the required length is returned.
1895 : */
1896 : size_t
1897 0 : _gcry_sexp_sprint (const gcry_sexp_t list, int mode,
1898 : void *buffer, size_t maxlength )
1899 : {
1900 : static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
1901 : const unsigned char *s;
1902 : char *d;
1903 : DATALEN n;
1904 : char numbuf[20];
1905 0 : size_t len = 0;
1906 0 : int i, indent = 0;
1907 :
1908 0 : s = list? list->d : empty;
1909 0 : d = buffer;
1910 0 : while ( *s != ST_STOP )
1911 : {
1912 0 : switch ( *s )
1913 : {
1914 : case ST_OPEN:
1915 0 : s++;
1916 0 : if ( mode != GCRYSEXP_FMT_CANON )
1917 : {
1918 0 : if (indent)
1919 0 : len++;
1920 0 : len += indent;
1921 : }
1922 0 : len++;
1923 0 : if ( buffer )
1924 : {
1925 0 : if ( len >= maxlength )
1926 0 : return 0;
1927 0 : if ( mode != GCRYSEXP_FMT_CANON )
1928 : {
1929 0 : if (indent)
1930 0 : *d++ = '\n';
1931 0 : for (i=0; i < indent; i++)
1932 0 : *d++ = ' ';
1933 : }
1934 0 : *d++ = '(';
1935 : }
1936 0 : indent++;
1937 0 : break;
1938 : case ST_CLOSE:
1939 0 : s++;
1940 0 : len++;
1941 0 : if ( buffer )
1942 : {
1943 0 : if ( len >= maxlength )
1944 0 : return 0;
1945 0 : *d++ = ')';
1946 : }
1947 0 : indent--;
1948 0 : if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
1949 : {
1950 0 : len++;
1951 0 : len += indent;
1952 0 : if (buffer)
1953 : {
1954 0 : if (len >= maxlength)
1955 0 : return 0;
1956 0 : *d++ = '\n';
1957 0 : for (i=0; i < indent; i++)
1958 0 : *d++ = ' ';
1959 : }
1960 : }
1961 0 : break;
1962 : case ST_DATA:
1963 0 : s++;
1964 0 : memcpy ( &n, s, sizeof n ); s += sizeof n;
1965 0 : if (mode == GCRYSEXP_FMT_ADVANCED)
1966 : {
1967 : int type;
1968 : size_t nn;
1969 :
1970 0 : switch ( (type=suitable_encoding (s, n)))
1971 : {
1972 0 : case 1: nn = convert_to_string (s, n, NULL); break;
1973 0 : case 2: nn = convert_to_token (s, n, NULL); break;
1974 0 : default: nn = convert_to_hex (s, n, NULL); break;
1975 : }
1976 0 : len += nn;
1977 0 : if (buffer)
1978 : {
1979 0 : if (len >= maxlength)
1980 0 : return 0;
1981 0 : switch (type)
1982 : {
1983 0 : case 1: convert_to_string (s, n, d); break;
1984 0 : case 2: convert_to_token (s, n, d); break;
1985 0 : default: convert_to_hex (s, n, d); break;
1986 : }
1987 0 : d += nn;
1988 : }
1989 0 : if (s[n] != ST_CLOSE)
1990 : {
1991 0 : len++;
1992 0 : if (buffer)
1993 : {
1994 0 : if (len >= maxlength)
1995 0 : return 0;
1996 0 : *d++ = ' ';
1997 : }
1998 : }
1999 : }
2000 : else
2001 : {
2002 0 : sprintf (numbuf, "%u:", (unsigned int)n );
2003 0 : len += strlen (numbuf) + n;
2004 0 : if ( buffer )
2005 : {
2006 0 : if ( len >= maxlength )
2007 0 : return 0;
2008 0 : d = stpcpy ( d, numbuf );
2009 0 : memcpy ( d, s, n ); d += n;
2010 : }
2011 : }
2012 0 : s += n;
2013 0 : break;
2014 : default:
2015 0 : BUG ();
2016 : }
2017 : }
2018 0 : if ( mode != GCRYSEXP_FMT_CANON )
2019 : {
2020 0 : len++;
2021 0 : if (buffer)
2022 : {
2023 0 : if ( len >= maxlength )
2024 0 : return 0;
2025 0 : *d++ = '\n';
2026 : }
2027 : }
2028 0 : if (buffer)
2029 : {
2030 0 : if ( len >= maxlength )
2031 0 : return 0;
2032 0 : *d++ = 0; /* for convenience we make a C string */
2033 : }
2034 : else
2035 0 : len++; /* we need one byte more for this */
2036 :
2037 0 : return len;
2038 : }
2039 :
2040 :
2041 : /* Scan a canonical encoded buffer with implicit length values and
2042 : return the actual length this S-expression uses. For a valid S-Exp
2043 : it should never return 0. If LENGTH is not zero, the maximum
2044 : length to scan is given - this can be used for syntax checks of
2045 : data passed from outside. errorcode and erroff may both be passed as
2046 : NULL. */
2047 : size_t
2048 0 : _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
2049 : size_t *erroff, gcry_err_code_t *errcode)
2050 : {
2051 : const unsigned char *p;
2052 0 : const unsigned char *disphint = NULL;
2053 0 : unsigned int datalen = 0;
2054 : size_t dummy_erroff;
2055 : gcry_err_code_t dummy_errcode;
2056 0 : size_t count = 0;
2057 0 : int level = 0;
2058 :
2059 0 : if (!erroff)
2060 0 : erroff = &dummy_erroff;
2061 0 : if (!errcode)
2062 0 : errcode = &dummy_errcode;
2063 :
2064 0 : *errcode = GPG_ERR_NO_ERROR;
2065 0 : *erroff = 0;
2066 0 : if (!buffer)
2067 0 : return 0;
2068 0 : if (*buffer != '(')
2069 : {
2070 0 : *errcode = GPG_ERR_SEXP_NOT_CANONICAL;
2071 0 : return 0;
2072 : }
2073 :
2074 0 : for (p=buffer; ; p++, count++ )
2075 : {
2076 0 : if (length && count >= length)
2077 : {
2078 0 : *erroff = count;
2079 0 : *errcode = GPG_ERR_SEXP_STRING_TOO_LONG;
2080 0 : return 0;
2081 : }
2082 :
2083 0 : if (datalen)
2084 : {
2085 0 : if (*p == ':')
2086 : {
2087 0 : if (length && (count+datalen) >= length)
2088 : {
2089 0 : *erroff = count;
2090 0 : *errcode = GPG_ERR_SEXP_STRING_TOO_LONG;
2091 0 : return 0;
2092 : }
2093 0 : count += datalen;
2094 0 : p += datalen;
2095 0 : datalen = 0;
2096 : }
2097 0 : else if (digitp(p))
2098 0 : datalen = datalen*10 + atoi_1(p);
2099 : else
2100 : {
2101 0 : *erroff = count;
2102 0 : *errcode = GPG_ERR_SEXP_INV_LEN_SPEC;
2103 0 : return 0;
2104 : }
2105 : }
2106 0 : else if (*p == '(')
2107 : {
2108 0 : if (disphint)
2109 : {
2110 0 : *erroff = count;
2111 0 : *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
2112 0 : return 0;
2113 : }
2114 0 : level++;
2115 : }
2116 0 : else if (*p == ')')
2117 : { /* walk up */
2118 0 : if (!level)
2119 : {
2120 0 : *erroff = count;
2121 0 : *errcode = GPG_ERR_SEXP_UNMATCHED_PAREN;
2122 0 : return 0;
2123 : }
2124 0 : if (disphint)
2125 : {
2126 0 : *erroff = count;
2127 0 : *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
2128 0 : return 0;
2129 : }
2130 0 : if (!--level)
2131 0 : return ++count; /* ready */
2132 : }
2133 0 : else if (*p == '[')
2134 : {
2135 0 : if (disphint)
2136 : {
2137 0 : *erroff = count;
2138 0 : *errcode = GPG_ERR_SEXP_NESTED_DH;
2139 0 : return 0;
2140 : }
2141 0 : disphint = p;
2142 : }
2143 0 : else if (*p == ']')
2144 : {
2145 0 : if ( !disphint )
2146 : {
2147 0 : *erroff = count;
2148 0 : *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
2149 0 : return 0;
2150 : }
2151 0 : disphint = NULL;
2152 : }
2153 0 : else if (digitp (p) )
2154 : {
2155 0 : if (*p == '0')
2156 : {
2157 0 : *erroff = count;
2158 0 : *errcode = GPG_ERR_SEXP_ZERO_PREFIX;
2159 0 : return 0;
2160 : }
2161 0 : datalen = atoi_1 (p);
2162 : }
2163 0 : else if (*p == '&' || *p == '\\')
2164 : {
2165 0 : *erroff = count;
2166 0 : *errcode = GPG_ERR_SEXP_UNEXPECTED_PUNC;
2167 0 : return 0;
2168 : }
2169 : else
2170 : {
2171 0 : *erroff = count;
2172 0 : *errcode = GPG_ERR_SEXP_BAD_CHARACTER;
2173 0 : return 0;
2174 : }
2175 : }
2176 : }
2177 :
2178 :
2179 : /* Extract MPIs from an s-expression using a list of parameters. The
2180 : * names of these parameters are given by the string LIST. Some
2181 : * special characters may be given to control the conversion:
2182 : *
2183 : * + :: Switch to unsigned integer format (default).
2184 : * - :: Switch to standard signed format.
2185 : * / :: Switch to opaque format.
2186 : * & :: Switch to buffer descriptor mode - see below.
2187 : * ? :: The previous parameter is optional.
2188 : *
2189 : * In general parameter names are single letters. To use a string for
2190 : * a parameter name, enclose the name in single quotes.
2191 : *
2192 : * Unless in gcry_buffer_t mode for each parameter name a pointer to
2193 : * an MPI variable is expected that must be set to NULL prior to
2194 : * invoking this function, and finally a NULL is expected. Example:
2195 : *
2196 : * _gcry_sexp_extract_param (key, NULL, "n/x+ed",
2197 : * &mpi_n, &mpi_x, &mpi_e, NULL)
2198 : *
2199 : * This stores the parameter "N" from KEY as an unsigned MPI into
2200 : * MPI_N, the parameter "X" as an opaque MPI into MPI_X, and the
2201 : * parameter "E" again as an unsigned MPI into MPI_E.
2202 : *
2203 : * If in buffer descriptor mode a pointer to gcry_buffer_t descriptor
2204 : * is expected instead of a pointer to an MPI. The caller may use two
2205 : * different operation modes: If the DATA field of the provided buffer
2206 : * descriptor is NULL, the function allocates a new buffer and stores
2207 : * it at DATA; the other fields are set accordingly with OFF being 0.
2208 : * If DATA is not NULL, the function assumes that DATA, SIZE, and OFF
2209 : * describe a buffer where to but the data; on return the LEN field
2210 : * receives the number of bytes copied to that buffer; if the buffer
2211 : * is too small, the function immediately returns with an error code
2212 : * (and LEN set to 0).
2213 : *
2214 : * PATH is an optional string used to locate a token. The exclamation
2215 : * mark separated tokens are used to via gcry_sexp_find_token to find
2216 : * a start point inside SEXP.
2217 : *
2218 : * The function returns 0 on success. On error an error code is
2219 : * returned, all passed MPIs that might have been allocated up to this
2220 : * point are deallocated and set to NULL, and all passed buffers are
2221 : * either truncated if the caller supplied the buffer, or deallocated
2222 : * if the function allocated the buffer.
2223 : */
2224 : gpg_err_code_t
2225 0 : _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
2226 : const char *list, va_list arg_ptr)
2227 : {
2228 : gpg_err_code_t rc;
2229 : const char *s, *s2;
2230 : gcry_mpi_t *array[20];
2231 : char arrayisdesc[20];
2232 : int idx;
2233 : gcry_sexp_t l1;
2234 0 : int mode = '+'; /* Default to GCRYMPI_FMT_USG. */
2235 0 : gcry_sexp_t freethis = NULL;
2236 :
2237 0 : memset (arrayisdesc, 0, sizeof arrayisdesc);
2238 :
2239 : /* First copy all the args into an array. This is required so that
2240 : we are able to release already allocated MPIs if later an error
2241 : was found. */
2242 0 : for (s=list, idx=0; *s && idx < DIM (array); s++)
2243 : {
2244 0 : if (*s == '&' || *s == '+' || *s == '-' || *s == '/' || *s == '?')
2245 : ;
2246 0 : else if (whitespacep (s))
2247 : ;
2248 : else
2249 : {
2250 0 : if (*s == '\'')
2251 : {
2252 0 : s++;
2253 0 : s2 = strchr (s, '\'');
2254 0 : if (!s2 || s2 == s)
2255 : {
2256 : /* Closing quote not found or empty string. */
2257 0 : return GPG_ERR_SYNTAX;
2258 : }
2259 0 : s = s2;
2260 : }
2261 0 : array[idx] = va_arg (arg_ptr, gcry_mpi_t *);
2262 0 : if (!array[idx])
2263 0 : return GPG_ERR_MISSING_VALUE; /* NULL pointer given. */
2264 0 : idx++;
2265 : }
2266 : }
2267 0 : if (*s)
2268 0 : return GPG_ERR_LIMIT_REACHED; /* Too many list elements. */
2269 0 : if (va_arg (arg_ptr, gcry_mpi_t *))
2270 0 : return GPG_ERR_INV_ARG; /* Not enough list elemends. */
2271 :
2272 : /* Drill down. */
2273 0 : while (path && *path)
2274 : {
2275 : size_t n;
2276 :
2277 0 : s = strchr (path, '!');
2278 0 : if (s == path)
2279 : {
2280 0 : rc = GPG_ERR_NOT_FOUND;
2281 0 : goto cleanup;
2282 : }
2283 0 : n = s? s - path : 0;
2284 0 : l1 = _gcry_sexp_find_token (sexp, path, n);
2285 0 : if (!l1)
2286 : {
2287 0 : rc = GPG_ERR_NOT_FOUND;
2288 0 : goto cleanup;
2289 : }
2290 0 : sexp = l1; l1 = NULL;
2291 0 : sexp_release (freethis);
2292 0 : freethis = sexp;
2293 0 : if (n)
2294 0 : path += n + 1;
2295 : else
2296 0 : path = NULL;
2297 : }
2298 :
2299 :
2300 : /* Now extract all parameters. */
2301 0 : for (s=list, idx=0; *s; s++)
2302 : {
2303 0 : if (*s == '&' || *s == '+' || *s == '-' || *s == '/')
2304 0 : mode = *s;
2305 0 : else if (whitespacep (s))
2306 : ;
2307 0 : else if (*s == '?')
2308 : ; /* Only used via lookahead. */
2309 : else
2310 : {
2311 0 : if (*s == '\'')
2312 : {
2313 : /* Find closing quote, find token, set S to closing quote. */
2314 0 : s++;
2315 0 : s2 = strchr (s, '\'');
2316 0 : if (!s2 || s2 == s)
2317 : {
2318 : /* Closing quote not found or empty string. */
2319 0 : rc = GPG_ERR_SYNTAX;
2320 0 : goto cleanup;
2321 : }
2322 0 : l1 = _gcry_sexp_find_token (sexp, s, s2 - s);
2323 0 : s = s2;
2324 : }
2325 : else
2326 0 : l1 = _gcry_sexp_find_token (sexp, s, 1);
2327 :
2328 0 : if (!l1 && s[1] == '?')
2329 : {
2330 : /* Optional element not found. */
2331 0 : if (mode == '&')
2332 : {
2333 0 : gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2334 0 : if (!spec->data)
2335 : {
2336 0 : spec->size = 0;
2337 0 : spec->off = 0;
2338 : }
2339 0 : spec->len = 0;
2340 : }
2341 : else
2342 0 : *array[idx] = NULL;
2343 : }
2344 0 : else if (!l1)
2345 : {
2346 0 : rc = GPG_ERR_NO_OBJ; /* List element not found. */
2347 0 : goto cleanup;
2348 : }
2349 : else
2350 : {
2351 0 : if (mode == '&')
2352 : {
2353 0 : gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2354 :
2355 0 : if (spec->data)
2356 : {
2357 : const char *pbuf;
2358 : size_t nbuf;
2359 :
2360 0 : pbuf = _gcry_sexp_nth_data (l1, 1, &nbuf);
2361 0 : if (!pbuf || !nbuf)
2362 : {
2363 0 : rc = GPG_ERR_INV_OBJ;
2364 0 : goto cleanup;
2365 : }
2366 0 : if (spec->off + nbuf > spec->size)
2367 : {
2368 0 : rc = GPG_ERR_BUFFER_TOO_SHORT;
2369 0 : goto cleanup;
2370 : }
2371 0 : memcpy ((char*)spec->data + spec->off, pbuf, nbuf);
2372 0 : spec->len = nbuf;
2373 0 : arrayisdesc[idx] = 1;
2374 : }
2375 : else
2376 : {
2377 0 : spec->data = _gcry_sexp_nth_buffer (l1, 1, &spec->size);
2378 0 : if (!spec->data)
2379 : {
2380 0 : rc = GPG_ERR_INV_OBJ; /* Or out of core. */
2381 0 : goto cleanup;
2382 : }
2383 0 : spec->len = spec->size;
2384 0 : spec->off = 0;
2385 0 : arrayisdesc[idx] = 2;
2386 : }
2387 : }
2388 0 : else if (mode == '/')
2389 0 : *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
2390 0 : else if (mode == '-')
2391 0 : *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_STD);
2392 : else
2393 0 : *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
2394 0 : sexp_release (l1); l1 = NULL;
2395 0 : if (!*array[idx])
2396 : {
2397 0 : rc = GPG_ERR_INV_OBJ; /* Conversion failed. */
2398 0 : goto cleanup;
2399 : }
2400 : }
2401 0 : idx++;
2402 : }
2403 : }
2404 :
2405 0 : sexp_release (freethis);
2406 0 : return 0;
2407 :
2408 : cleanup:
2409 0 : sexp_release (freethis);
2410 0 : sexp_release (l1);
2411 0 : while (idx--)
2412 : {
2413 0 : if (!arrayisdesc[idx])
2414 : {
2415 0 : _gcry_mpi_release (*array[idx]);
2416 0 : *array[idx] = NULL;
2417 : }
2418 0 : else if (arrayisdesc[idx] == 1)
2419 : {
2420 : /* Caller provided buffer. */
2421 0 : gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2422 0 : spec->len = 0;
2423 : }
2424 : else
2425 : {
2426 : /* We might have allocated a buffer. */
2427 0 : gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2428 0 : xfree (spec->data);
2429 0 : spec->data = NULL;
2430 0 : spec->size = spec->off = spec->len = 0;
2431 : }
2432 : }
2433 0 : return rc;
2434 : }
2435 :
2436 : gpg_err_code_t
2437 0 : _gcry_sexp_extract_param (gcry_sexp_t sexp, const char *path,
2438 : const char *list, ...)
2439 : {
2440 : gcry_err_code_t rc;
2441 : va_list arg_ptr;
2442 :
2443 0 : va_start (arg_ptr, list);
2444 0 : rc = _gcry_sexp_vextract_param (sexp, path, list, arg_ptr);
2445 0 : va_end (arg_ptr);
2446 0 : return rc;
2447 : }
|