diff options
Diffstat (limited to 'linden/indra/libgcrypt/libgcrypt-1.2.2/src/sexp.c')
-rw-r--r--[-rwxr-xr-x] | linden/indra/libgcrypt/libgcrypt-1.2.2/src/sexp.c | 3644 |
1 files changed, 1822 insertions, 1822 deletions
diff --git a/linden/indra/libgcrypt/libgcrypt-1.2.2/src/sexp.c b/linden/indra/libgcrypt/libgcrypt-1.2.2/src/sexp.c index 487b830..55ffc43 100755..100644 --- a/linden/indra/libgcrypt/libgcrypt-1.2.2/src/sexp.c +++ b/linden/indra/libgcrypt/libgcrypt-1.2.2/src/sexp.c | |||
@@ -1,1822 +1,1822 @@ | |||
1 | /* sexp.c - S-Expression handling | 1 | /* sexp.c - S-Expression handling |
2 | * Copyright (C) 1999, 2000, 2001, 2002, 2003, | 2 | * Copyright (C) 1999, 2000, 2001, 2002, 2003, |
3 | * 2004 Free Software Foundation, Inc. | 3 | * 2004 Free Software Foundation, Inc. |
4 | * | 4 | * |
5 | * This file is part of Libgcrypt. | 5 | * This file is part of Libgcrypt. |
6 | * | 6 | * |
7 | * Libgcrypt is free software; you can redistribute it and/or modify | 7 | * Libgcrypt is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU Lesser general Public License as | 8 | * it under the terms of the GNU Lesser general Public License as |
9 | * published by the Free Software Foundation; either version 2.1 of | 9 | * published by the Free Software Foundation; either version 2.1 of |
10 | * the License, or (at your option) any later version. | 10 | * the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * Libgcrypt is distributed in the hope that it will be useful, | 12 | * Libgcrypt is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU Lesser General Public License for more details. | 15 | * GNU Lesser General Public License for more details. |
16 | * | 16 | * |
17 | * You should have received a copy of the GNU Lesser General Public | 17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with this program; if not, write to the Free Software | 18 | * License along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | 22 | ||
23 | #include <config.h> | 23 | #include <config.h> |
24 | #include <stdio.h> | 24 | #include <stdio.h> |
25 | #include <stdlib.h> | 25 | #include <stdlib.h> |
26 | #include <string.h> | 26 | #include <string.h> |
27 | #include <stdarg.h> | 27 | #include <stdarg.h> |
28 | #include <ctype.h> | 28 | #include <ctype.h> |
29 | #include <assert.h> | 29 | #include <assert.h> |
30 | 30 | ||
31 | #define GCRYPT_NO_MPI_MACROS 1 | 31 | #define GCRYPT_NO_MPI_MACROS 1 |
32 | #include "g10lib.h" | 32 | #include "g10lib.h" |
33 | #include "memory.h" | 33 | #include "memory.h" |
34 | 34 | ||
35 | typedef struct gcry_sexp *NODE; | 35 | typedef struct gcry_sexp *NODE; |
36 | typedef unsigned short DATALEN; | 36 | typedef unsigned short DATALEN; |
37 | 37 | ||
38 | struct gcry_sexp | 38 | struct gcry_sexp |
39 | { | 39 | { |
40 | byte d[1]; | 40 | byte d[1]; |
41 | }; | 41 | }; |
42 | 42 | ||
43 | #define ST_STOP 0 | 43 | #define ST_STOP 0 |
44 | #define ST_DATA 1 /* datalen follows */ | 44 | #define ST_DATA 1 /* datalen follows */ |
45 | #define ST_HINT 2 /* datalen follows */ | 45 | #define ST_HINT 2 /* datalen follows */ |
46 | #define ST_OPEN 3 | 46 | #define ST_OPEN 3 |
47 | #define ST_CLOSE 4 | 47 | #define ST_CLOSE 4 |
48 | 48 | ||
49 | /* the atoi macros assume that the buffer has only valid digits */ | 49 | /* the atoi macros assume that the buffer has only valid digits */ |
50 | #define atoi_1(p) (*(p) - '0' ) | 50 | #define atoi_1(p) (*(p) - '0' ) |
51 | #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ | 51 | #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ |
52 | *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) | 52 | *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) |
53 | #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) | 53 | #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) |
54 | 54 | ||
55 | #define TOKEN_SPECIALS "-./_:*+=" | 55 | #define TOKEN_SPECIALS "-./_:*+=" |
56 | 56 | ||
57 | 57 | ||
58 | 58 | ||
59 | static gcry_error_t | 59 | static gcry_error_t |
60 | sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, | 60 | sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, |
61 | const char *buffer, size_t length, int argflag, | 61 | const char *buffer, size_t length, int argflag, |
62 | va_list arg_ptr, void **arg_list); | 62 | va_list arg_ptr, void **arg_list); |
63 | 63 | ||
64 | 64 | ||
65 | /* Return true if P points to a byte containing a whitespace according | 65 | /* Return true if P points to a byte containing a whitespace according |
66 | to the S-expressions definition. */ | 66 | to the S-expressions definition. */ |
67 | #undef whitespacep | 67 | #undef whitespacep |
68 | static GPG_ERR_INLINE int | 68 | static GPG_ERR_INLINE int |
69 | whitespacep (const char *p) | 69 | whitespacep (const char *p) |
70 | { | 70 | { |
71 | switch (*p) | 71 | switch (*p) |
72 | { | 72 | { |
73 | case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1; | 73 | case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1; |
74 | default: return 0; | 74 | default: return 0; |
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
78 | 78 | ||
79 | #if 0 | 79 | #if 0 |
80 | static void | 80 | static void |
81 | dump_mpi( gcry_mpi_t a ) | 81 | dump_mpi( gcry_mpi_t a ) |
82 | { | 82 | { |
83 | char buffer[1000]; | 83 | char buffer[1000]; |
84 | size_t n = 1000; | 84 | size_t n = 1000; |
85 | 85 | ||
86 | if( !a ) | 86 | if( !a ) |
87 | fputs("[no MPI]", stderr ); | 87 | fputs("[no MPI]", stderr ); |
88 | else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) ) | 88 | else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) ) |
89 | fputs("[MPI too large to print]", stderr ); | 89 | fputs("[MPI too large to print]", stderr ); |
90 | else | 90 | else |
91 | fputs( buffer, stderr ); | 91 | fputs( buffer, stderr ); |
92 | } | 92 | } |
93 | #endif | 93 | #endif |
94 | 94 | ||
95 | static void | 95 | static void |
96 | dump_string (const byte *p, size_t n, int delim ) | 96 | dump_string (const byte *p, size_t n, int delim ) |
97 | { | 97 | { |
98 | for (; n; n--, p++ ) | 98 | for (; n; n--, p++ ) |
99 | { | 99 | { |
100 | if ((*p & 0x80) || iscntrl( *p ) || *p == delim ) | 100 | if ((*p & 0x80) || iscntrl( *p ) || *p == delim ) |
101 | { | 101 | { |
102 | if( *p == '\n' ) | 102 | if( *p == '\n' ) |
103 | log_printf ("\\n"); | 103 | log_printf ("\\n"); |
104 | else if( *p == '\r' ) | 104 | else if( *p == '\r' ) |
105 | log_printf ("\\r"); | 105 | log_printf ("\\r"); |
106 | else if( *p == '\f' ) | 106 | else if( *p == '\f' ) |
107 | log_printf ("\\f"); | 107 | log_printf ("\\f"); |
108 | else if( *p == '\v' ) | 108 | else if( *p == '\v' ) |
109 | log_printf ("\\v"); | 109 | log_printf ("\\v"); |
110 | else if( *p == '\b' ) | 110 | else if( *p == '\b' ) |
111 | log_printf ("\\b"); | 111 | log_printf ("\\b"); |
112 | else if( !*p ) | 112 | else if( !*p ) |
113 | log_printf ("\\0"); | 113 | log_printf ("\\0"); |
114 | else | 114 | else |
115 | log_printf ("\\x%02x", *p ); | 115 | log_printf ("\\x%02x", *p ); |
116 | } | 116 | } |
117 | else | 117 | else |
118 | log_printf ("%c", *p); | 118 | log_printf ("%c", *p); |
119 | } | 119 | } |
120 | } | 120 | } |
121 | 121 | ||
122 | 122 | ||
123 | void | 123 | void |
124 | gcry_sexp_dump (const gcry_sexp_t a) | 124 | gcry_sexp_dump (const gcry_sexp_t a) |
125 | { | 125 | { |
126 | const byte *p; | 126 | const byte *p; |
127 | int indent = 0; | 127 | int indent = 0; |
128 | int type; | 128 | int type; |
129 | 129 | ||
130 | if (!a) | 130 | if (!a) |
131 | { | 131 | { |
132 | log_printf ( "[nil]\n"); | 132 | log_printf ( "[nil]\n"); |
133 | return; | 133 | return; |
134 | } | 134 | } |
135 | 135 | ||
136 | p = a->d; | 136 | p = a->d; |
137 | while ( (type = *p) != ST_STOP ) | 137 | while ( (type = *p) != ST_STOP ) |
138 | { | 138 | { |
139 | p++; | 139 | p++; |
140 | switch ( type ) | 140 | switch ( type ) |
141 | { | 141 | { |
142 | case ST_OPEN: | 142 | case ST_OPEN: |
143 | log_printf ("%*s[open]\n", 2*indent, ""); | 143 | log_printf ("%*s[open]\n", 2*indent, ""); |
144 | indent++; | 144 | indent++; |
145 | break; | 145 | break; |
146 | case ST_CLOSE: | 146 | case ST_CLOSE: |
147 | if( indent ) | 147 | if( indent ) |
148 | indent--; | 148 | indent--; |
149 | log_printf ("%*s[close]\n", 2*indent, ""); | 149 | log_printf ("%*s[close]\n", 2*indent, ""); |
150 | break; | 150 | break; |
151 | case ST_DATA: { | 151 | case ST_DATA: { |
152 | DATALEN n; | 152 | DATALEN n; |
153 | memcpy ( &n, p, sizeof n ); | 153 | memcpy ( &n, p, sizeof n ); |
154 | p += sizeof n; | 154 | p += sizeof n; |
155 | log_printf ("%*s[data=\"", 2*indent, "" ); | 155 | log_printf ("%*s[data=\"", 2*indent, "" ); |
156 | dump_string (p, n, '\"' ); | 156 | dump_string (p, n, '\"' ); |
157 | log_printf ("\"]\n"); | 157 | log_printf ("\"]\n"); |
158 | p += n; | 158 | p += n; |
159 | } | 159 | } |
160 | break; | 160 | break; |
161 | default: | 161 | default: |
162 | log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type); | 162 | log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type); |
163 | break; | 163 | break; |
164 | } | 164 | } |
165 | } | 165 | } |
166 | } | 166 | } |
167 | 167 | ||
168 | /**************** | 168 | /**************** |
169 | * Pass list through except when it is an empty list - in that case | 169 | * Pass list through except when it is an empty list - in that case |
170 | * return NULL and release the passed list. | 170 | * return NULL and release the passed list. |
171 | */ | 171 | */ |
172 | static gcry_sexp_t | 172 | static gcry_sexp_t |
173 | normalize ( gcry_sexp_t list ) | 173 | normalize ( gcry_sexp_t list ) |
174 | { | 174 | { |
175 | unsigned char *p; | 175 | unsigned char *p; |
176 | 176 | ||
177 | if ( !list ) | 177 | if ( !list ) |
178 | return NULL; | 178 | return NULL; |
179 | p = list->d; | 179 | p = list->d; |
180 | if ( *p == ST_STOP ) { | 180 | if ( *p == ST_STOP ) { |
181 | /* this is "" */ | 181 | /* this is "" */ |
182 | gcry_sexp_release ( list ); | 182 | gcry_sexp_release ( list ); |
183 | return NULL; | 183 | return NULL; |
184 | } | 184 | } |
185 | if( *p == ST_OPEN && p[1] == ST_CLOSE ) { | 185 | if( *p == ST_OPEN && p[1] == ST_CLOSE ) { |
186 | /* this is "()" */ | 186 | /* this is "()" */ |
187 | gcry_sexp_release ( list ); | 187 | gcry_sexp_release ( list ); |
188 | return NULL; | 188 | return NULL; |
189 | } | 189 | } |
190 | 190 | ||
191 | return list; | 191 | return list; |
192 | } | 192 | } |
193 | 193 | ||
194 | /* Create a new S-expression object by reading LENGTH bytes from | 194 | /* Create a new S-expression object by reading LENGTH bytes from |
195 | BUFFER, assuming it is canonilized encoded or autodetected encoding | 195 | BUFFER, assuming it is canonilized encoded or autodetected encoding |
196 | when AUTODETECT is set to 1. With FREEFNC not NULL, ownership of | 196 | when AUTODETECT is set to 1. With FREEFNC not NULL, ownership of |
197 | the buffer is transferred to tyhe newle created object. FREEFNC | 197 | the buffer is transferred to tyhe newle created object. FREEFNC |
198 | should be the freefnc used to release BUFFER; there is no guarantee | 198 | should be the freefnc used to release BUFFER; there is no guarantee |
199 | at which point this function is called; most likey you want to use | 199 | at which point this function is called; most likey you want to use |
200 | free() or gcry_free(). | 200 | free() or gcry_free(). |
201 | 201 | ||
202 | Passing LENGTH and AUTODETECT as 0 is allowed to indicate that | 202 | Passing LENGTH and AUTODETECT as 0 is allowed to indicate that |
203 | BUFFER points to a valid canonical encoded S-expression. A LENGTH | 203 | BUFFER points to a valid canonical encoded S-expression. A LENGTH |
204 | of 0 and AUTODETECT 1 indicates that buffer points to a | 204 | of 0 and AUTODETECT 1 indicates that buffer points to a |
205 | null-terminated string. | 205 | null-terminated string. |
206 | 206 | ||
207 | This function returns 0 and and the pointer to the new object in | 207 | This function returns 0 and and the pointer to the new object in |
208 | RETSEXP or an error code in which case RETSEXP is set to NULL. */ | 208 | RETSEXP or an error code in which case RETSEXP is set to NULL. */ |
209 | gcry_error_t | 209 | gcry_error_t |
210 | gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length, | 210 | gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length, |
211 | int autodetect, void (*freefnc)(void*) ) | 211 | int autodetect, void (*freefnc)(void*) ) |
212 | { | 212 | { |
213 | gcry_error_t errcode; | 213 | gcry_error_t errcode; |
214 | gcry_sexp_t se; | 214 | gcry_sexp_t se; |
215 | volatile va_list dummy_arg_ptr = NULL; | 215 | volatile va_list dummy_arg_ptr = NULL; |
216 | 216 | ||
217 | if (!retsexp) | 217 | if (!retsexp) |
218 | return gcry_error (GPG_ERR_INV_ARG); | 218 | return gcry_error (GPG_ERR_INV_ARG); |
219 | *retsexp = NULL; | 219 | *retsexp = NULL; |
220 | if (autodetect < 0 || autodetect > 1 || !buffer) | 220 | if (autodetect < 0 || autodetect > 1 || !buffer) |
221 | return gcry_error (GPG_ERR_INV_ARG); | 221 | return gcry_error (GPG_ERR_INV_ARG); |
222 | 222 | ||
223 | if (!length && !autodetect) | 223 | if (!length && !autodetect) |
224 | { /* What a brave caller to assume that there is really a canonical | 224 | { /* What a brave caller to assume that there is really a canonical |
225 | encoded S-expression in buffer */ | 225 | encoded S-expression in buffer */ |
226 | length = gcry_sexp_canon_len (buffer, 0, NULL, &errcode); | 226 | length = gcry_sexp_canon_len (buffer, 0, NULL, &errcode); |
227 | if (!length) | 227 | if (!length) |
228 | return errcode; | 228 | return errcode; |
229 | } | 229 | } |
230 | else if (!length && autodetect) | 230 | else if (!length && autodetect) |
231 | { /* buffer is a string */ | 231 | { /* buffer is a string */ |
232 | length = strlen ((char *)buffer); | 232 | length = strlen ((char *)buffer); |
233 | } | 233 | } |
234 | 234 | ||
235 | errcode = sexp_sscan (&se, NULL, buffer, length, 0, dummy_arg_ptr, NULL); | 235 | errcode = sexp_sscan (&se, NULL, buffer, length, 0, dummy_arg_ptr, NULL); |
236 | if (errcode) | 236 | if (errcode) |
237 | return errcode; | 237 | return errcode; |
238 | 238 | ||
239 | *retsexp = se; | 239 | *retsexp = se; |
240 | if (freefnc) | 240 | if (freefnc) |
241 | { | 241 | { |
242 | /* For now we release the buffer immediately. As soon as we | 242 | /* For now we release the buffer immediately. As soon as we |
243 | have changed the internal represenation of S-expression to | 243 | have changed the internal represenation of S-expression to |
244 | the canoncial format - which has the advantage of faster | 244 | the canoncial format - which has the advantage of faster |
245 | parsing - we will use this function as a closure in our | 245 | parsing - we will use this function as a closure in our |
246 | GCRYSEXP object and use the BUFFER directly */ | 246 | GCRYSEXP object and use the BUFFER directly */ |
247 | freefnc (buffer); | 247 | freefnc (buffer); |
248 | } | 248 | } |
249 | return gcry_error (GPG_ERR_NO_ERROR); | 249 | return gcry_error (GPG_ERR_NO_ERROR); |
250 | } | 250 | } |
251 | 251 | ||
252 | /* Same as gcry_sexp_create but don't transfer ownership */ | 252 | /* Same as gcry_sexp_create but don't transfer ownership */ |
253 | gcry_error_t | 253 | gcry_error_t |
254 | gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length, | 254 | gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length, |
255 | int autodetect) | 255 | int autodetect) |
256 | { | 256 | { |
257 | return gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL); | 257 | return gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL); |
258 | } | 258 | } |
259 | 259 | ||
260 | 260 | ||
261 | /**************** | 261 | /**************** |
262 | * Release resource of the given SEXP object. | 262 | * Release resource of the given SEXP object. |
263 | */ | 263 | */ |
264 | void | 264 | void |
265 | gcry_sexp_release( gcry_sexp_t sexp ) | 265 | gcry_sexp_release( gcry_sexp_t sexp ) |
266 | { | 266 | { |
267 | if (sexp) | 267 | if (sexp) |
268 | { | 268 | { |
269 | if (gcry_is_secure (sexp)) | 269 | if (gcry_is_secure (sexp)) |
270 | { | 270 | { |
271 | /* Extra paranoid wiping. */ | 271 | /* Extra paranoid wiping. */ |
272 | const byte *p = sexp->d; | 272 | const byte *p = sexp->d; |
273 | int type; | 273 | int type; |
274 | 274 | ||
275 | while ( (type = *p) != ST_STOP ) | 275 | while ( (type = *p) != ST_STOP ) |
276 | { | 276 | { |
277 | p++; | 277 | p++; |
278 | switch ( type ) | 278 | switch ( type ) |
279 | { | 279 | { |
280 | case ST_OPEN: | 280 | case ST_OPEN: |
281 | break; | 281 | break; |
282 | case ST_CLOSE: | 282 | case ST_CLOSE: |
283 | break; | 283 | break; |
284 | case ST_DATA: | 284 | case ST_DATA: |
285 | { | 285 | { |
286 | DATALEN n; | 286 | DATALEN n; |
287 | memcpy ( &n, p, sizeof n ); | 287 | memcpy ( &n, p, sizeof n ); |
288 | p += sizeof n; | 288 | p += sizeof n; |
289 | p += n; | 289 | p += n; |
290 | } | 290 | } |
291 | break; | 291 | break; |
292 | default: | 292 | default: |
293 | break; | 293 | break; |
294 | } | 294 | } |
295 | } | 295 | } |
296 | wipememory (sexp->d, p - sexp->d); | 296 | wipememory (sexp->d, p - sexp->d); |
297 | } | 297 | } |
298 | gcry_free ( sexp ); | 298 | gcry_free ( sexp ); |
299 | } | 299 | } |
300 | } | 300 | } |
301 | 301 | ||
302 | 302 | ||
303 | /**************** | 303 | /**************** |
304 | * Make a pair from lists a and b, don't use a or b later on. | 304 | * Make a pair from lists a and b, don't use a or b later on. |
305 | * Special behaviour: If one is a single element list we put the | 305 | * Special behaviour: If one is a single element list we put the |
306 | * element straight into the new pair. | 306 | * element straight into the new pair. |
307 | */ | 307 | */ |
308 | gcry_sexp_t | 308 | gcry_sexp_t |
309 | gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b ) | 309 | gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b ) |
310 | { | 310 | { |
311 | /* NYI: Implementation should be quite easy with our new data | 311 | /* NYI: Implementation should be quite easy with our new data |
312 | representation */ | 312 | representation */ |
313 | BUG (); | 313 | BUG (); |
314 | return NULL; | 314 | return NULL; |
315 | } | 315 | } |
316 | 316 | ||
317 | 317 | ||
318 | /**************** | 318 | /**************** |
319 | * Make a list from all items in the array the end of the array is marked | 319 | * Make a list from all items in the array the end of the array is marked |
320 | * with a NULL. | 320 | * with a NULL. |
321 | */ | 321 | */ |
322 | gcry_sexp_t | 322 | gcry_sexp_t |
323 | gcry_sexp_alist( const gcry_sexp_t *array ) | 323 | gcry_sexp_alist( const gcry_sexp_t *array ) |
324 | { | 324 | { |
325 | /* NYI: Implementation should be quite easy with our new data | 325 | /* NYI: Implementation should be quite easy with our new data |
326 | representation. */ | 326 | representation. */ |
327 | BUG (); | 327 | BUG (); |
328 | return NULL; | 328 | return NULL; |
329 | } | 329 | } |
330 | 330 | ||
331 | /**************** | 331 | /**************** |
332 | * Make a list from all items, the end of list is indicated by a NULL | 332 | * Make a list from all items, the end of list is indicated by a NULL |
333 | */ | 333 | */ |
334 | gcry_sexp_t | 334 | gcry_sexp_t |
335 | gcry_sexp_vlist( const gcry_sexp_t a, ... ) | 335 | gcry_sexp_vlist( const gcry_sexp_t a, ... ) |
336 | { | 336 | { |
337 | /* NYI: Implementation should be quite easy with our new data | 337 | /* NYI: Implementation should be quite easy with our new data |
338 | representation. */ | 338 | representation. */ |
339 | BUG (); | 339 | BUG (); |
340 | return NULL; | 340 | return NULL; |
341 | } | 341 | } |
342 | 342 | ||
343 | 343 | ||
344 | /**************** | 344 | /**************** |
345 | * Append n to the list a | 345 | * Append n to the list a |
346 | * Returns: a new ist (which maybe a) | 346 | * Returns: a new ist (which maybe a) |
347 | */ | 347 | */ |
348 | gcry_sexp_t | 348 | gcry_sexp_t |
349 | gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n ) | 349 | gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n ) |
350 | { | 350 | { |
351 | /* NYI: Implementation should be quite easy with our new data | 351 | /* NYI: Implementation should be quite easy with our new data |
352 | representation. */ | 352 | representation. */ |
353 | BUG (); | 353 | BUG (); |
354 | return NULL; | 354 | return NULL; |
355 | } | 355 | } |
356 | 356 | ||
357 | gcry_sexp_t | 357 | gcry_sexp_t |
358 | gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n ) | 358 | gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n ) |
359 | { | 359 | { |
360 | /* NYI: Implementation should be quite easy with our new data | 360 | /* NYI: Implementation should be quite easy with our new data |
361 | representation. */ | 361 | representation. */ |
362 | BUG (); | 362 | BUG (); |
363 | return NULL; | 363 | return NULL; |
364 | } | 364 | } |
365 | 365 | ||
366 | 366 | ||
367 | 367 | ||
368 | /**************** | 368 | /**************** |
369 | * Locate token in a list. The token must be the car of a sublist. | 369 | * Locate token in a list. The token must be the car of a sublist. |
370 | * Returns: A new list with this sublist or NULL if not found. | 370 | * Returns: A new list with this sublist or NULL if not found. |
371 | */ | 371 | */ |
372 | gcry_sexp_t | 372 | gcry_sexp_t |
373 | gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen ) | 373 | gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen ) |
374 | { | 374 | { |
375 | const byte *p; | 375 | const byte *p; |
376 | DATALEN n; | 376 | DATALEN n; |
377 | 377 | ||
378 | if ( !list ) | 378 | if ( !list ) |
379 | return NULL; | 379 | return NULL; |
380 | 380 | ||
381 | if( !toklen ) | 381 | if( !toklen ) |
382 | toklen = strlen(tok); | 382 | toklen = strlen(tok); |
383 | p = list->d; | 383 | p = list->d; |
384 | while ( *p != ST_STOP ) { | 384 | while ( *p != ST_STOP ) { |
385 | if ( *p == ST_OPEN && p[1] == ST_DATA ) { | 385 | if ( *p == ST_OPEN && p[1] == ST_DATA ) { |
386 | const byte *head = p; | 386 | const byte *head = p; |
387 | 387 | ||
388 | p += 2; | 388 | p += 2; |
389 | memcpy ( &n, p, sizeof n ); p += sizeof n; | 389 | memcpy ( &n, p, sizeof n ); p += sizeof n; |
390 | if ( n == toklen && !memcmp( p, tok, toklen ) ) { /* found it */ | 390 | if ( n == toklen && !memcmp( p, tok, toklen ) ) { /* found it */ |
391 | gcry_sexp_t newlist; | 391 | gcry_sexp_t newlist; |
392 | byte *d; | 392 | byte *d; |
393 | int level = 1; | 393 | int level = 1; |
394 | 394 | ||
395 | /* look for the end of the list */ | 395 | /* look for the end of the list */ |
396 | for ( p += n; level; p++ ) { | 396 | for ( p += n; level; p++ ) { |
397 | if ( *p == ST_DATA ) { | 397 | if ( *p == ST_DATA ) { |
398 | memcpy ( &n, ++p, sizeof n ); | 398 | memcpy ( &n, ++p, sizeof n ); |
399 | p += sizeof n + n; | 399 | p += sizeof n + n; |
400 | p--; /* compensate for later increment */ | 400 | p--; /* compensate for later increment */ |
401 | } | 401 | } |
402 | else if ( *p == ST_OPEN ) { | 402 | else if ( *p == ST_OPEN ) { |
403 | level++; | 403 | level++; |
404 | } | 404 | } |
405 | else if ( *p == ST_CLOSE ) { | 405 | else if ( *p == ST_CLOSE ) { |
406 | level--; | 406 | level--; |
407 | } | 407 | } |
408 | else if ( *p == ST_STOP ) { | 408 | else if ( *p == ST_STOP ) { |
409 | BUG (); | 409 | BUG (); |
410 | } | 410 | } |
411 | } while ( level ); | 411 | } while ( level ); |
412 | n = p - head; | 412 | n = p - head; |
413 | 413 | ||
414 | newlist = gcry_xmalloc ( sizeof *newlist + n ); | 414 | newlist = gcry_xmalloc ( sizeof *newlist + n ); |
415 | d = newlist->d; | 415 | d = newlist->d; |
416 | memcpy ( d, head, n ); d += n; | 416 | memcpy ( d, head, n ); d += n; |
417 | *d++ = ST_STOP; | 417 | *d++ = ST_STOP; |
418 | return normalize ( newlist ); | 418 | return normalize ( newlist ); |
419 | } | 419 | } |
420 | p += n; | 420 | p += n; |
421 | } | 421 | } |
422 | else if ( *p == ST_DATA ) { | 422 | else if ( *p == ST_DATA ) { |
423 | memcpy ( &n, ++p, sizeof n ); p += sizeof n; | 423 | memcpy ( &n, ++p, sizeof n ); p += sizeof n; |
424 | p += n; | 424 | p += n; |
425 | } | 425 | } |
426 | else | 426 | else |
427 | p++; | 427 | p++; |
428 | } | 428 | } |
429 | return NULL; | 429 | return NULL; |
430 | } | 430 | } |
431 | 431 | ||
432 | /**************** | 432 | /**************** |
433 | * Return the length of the given list | 433 | * Return the length of the given list |
434 | */ | 434 | */ |
435 | int | 435 | int |
436 | gcry_sexp_length( const gcry_sexp_t list ) | 436 | gcry_sexp_length( const gcry_sexp_t list ) |
437 | { | 437 | { |
438 | const byte *p; | 438 | const byte *p; |
439 | DATALEN n; | 439 | DATALEN n; |
440 | int type; | 440 | int type; |
441 | int length = 0; | 441 | int length = 0; |
442 | int level = 0; | 442 | int level = 0; |
443 | 443 | ||
444 | if ( !list ) | 444 | if ( !list ) |
445 | return 0; | 445 | return 0; |
446 | 446 | ||
447 | p = list->d; | 447 | p = list->d; |
448 | while ( (type=*p) != ST_STOP ) { | 448 | while ( (type=*p) != ST_STOP ) { |
449 | p++; | 449 | p++; |
450 | if ( type == ST_DATA ) { | 450 | if ( type == ST_DATA ) { |
451 | memcpy ( &n, p, sizeof n ); | 451 | memcpy ( &n, p, sizeof n ); |
452 | p += sizeof n + n; | 452 | p += sizeof n + n; |
453 | if ( level == 1 ) | 453 | if ( level == 1 ) |
454 | length++; | 454 | length++; |
455 | } | 455 | } |
456 | else if ( type == ST_OPEN ) { | 456 | else if ( type == ST_OPEN ) { |
457 | if ( level == 1 ) | 457 | if ( level == 1 ) |
458 | length++; | 458 | length++; |
459 | level++; | 459 | level++; |
460 | } | 460 | } |
461 | else if ( type == ST_CLOSE ) { | 461 | else if ( type == ST_CLOSE ) { |
462 | level--; | 462 | level--; |
463 | } | 463 | } |
464 | } | 464 | } |
465 | return length; | 465 | return length; |
466 | } | 466 | } |
467 | 467 | ||
468 | 468 | ||
469 | 469 | ||
470 | /**************** | 470 | /**************** |
471 | * Extract the CAR of the given list | 471 | * Extract the CAR of the given list |
472 | */ | 472 | */ |
473 | gcry_sexp_t | 473 | gcry_sexp_t |
474 | gcry_sexp_nth( const gcry_sexp_t list, int number ) | 474 | gcry_sexp_nth( const gcry_sexp_t list, int number ) |
475 | { | 475 | { |
476 | const byte *p; | 476 | const byte *p; |
477 | DATALEN n; | 477 | DATALEN n; |
478 | gcry_sexp_t newlist; | 478 | gcry_sexp_t newlist; |
479 | byte *d; | 479 | byte *d; |
480 | int level = 0; | 480 | int level = 0; |
481 | 481 | ||
482 | if ( !list || list->d[0] != ST_OPEN ) | 482 | if ( !list || list->d[0] != ST_OPEN ) |
483 | return NULL; | 483 | return NULL; |
484 | p = list->d; | 484 | p = list->d; |
485 | 485 | ||
486 | while ( number > 0 ) { | 486 | while ( number > 0 ) { |
487 | p++; | 487 | p++; |
488 | if ( *p == ST_DATA ) { | 488 | if ( *p == ST_DATA ) { |
489 | memcpy ( &n, ++p, sizeof n ); | 489 | memcpy ( &n, ++p, sizeof n ); |
490 | p += sizeof n + n; | 490 | p += sizeof n + n; |
491 | p--; | 491 | p--; |
492 | if ( !level ) | 492 | if ( !level ) |
493 | number--; | 493 | number--; |
494 | } | 494 | } |
495 | else if ( *p == ST_OPEN ) { | 495 | else if ( *p == ST_OPEN ) { |
496 | level++; | 496 | level++; |
497 | } | 497 | } |
498 | else if ( *p == ST_CLOSE ) { | 498 | else if ( *p == ST_CLOSE ) { |
499 | level--; | 499 | level--; |
500 | if ( !level ) | 500 | if ( !level ) |
501 | number--; | 501 | number--; |
502 | } | 502 | } |
503 | else if ( *p == ST_STOP ) { | 503 | else if ( *p == ST_STOP ) { |
504 | return NULL; | 504 | return NULL; |
505 | } | 505 | } |
506 | } | 506 | } |
507 | p++; | 507 | p++; |
508 | 508 | ||
509 | if ( *p == ST_DATA ) { | 509 | if ( *p == ST_DATA ) { |
510 | memcpy ( &n, p, sizeof n ); p += sizeof n; | 510 | memcpy ( &n, p, sizeof n ); p += sizeof n; |
511 | newlist = gcry_xmalloc ( sizeof *newlist + n + 1 ); | 511 | newlist = gcry_xmalloc ( sizeof *newlist + n + 1 ); |
512 | d = newlist->d; | 512 | d = newlist->d; |
513 | memcpy ( d, p, n ); d += n; | 513 | memcpy ( d, p, n ); d += n; |
514 | *d++ = ST_STOP; | 514 | *d++ = ST_STOP; |
515 | } | 515 | } |
516 | else if ( *p == ST_OPEN ) { | 516 | else if ( *p == ST_OPEN ) { |
517 | const byte *head = p; | 517 | const byte *head = p; |
518 | 518 | ||
519 | level = 1; | 519 | level = 1; |
520 | do { | 520 | do { |
521 | p++; | 521 | p++; |
522 | if ( *p == ST_DATA ) { | 522 | if ( *p == ST_DATA ) { |
523 | memcpy ( &n, ++p, sizeof n ); | 523 | memcpy ( &n, ++p, sizeof n ); |
524 | p += sizeof n + n; | 524 | p += sizeof n + n; |
525 | p--; | 525 | p--; |
526 | } | 526 | } |
527 | else if ( *p == ST_OPEN ) { | 527 | else if ( *p == ST_OPEN ) { |
528 | level++; | 528 | level++; |
529 | } | 529 | } |
530 | else if ( *p == ST_CLOSE ) { | 530 | else if ( *p == ST_CLOSE ) { |
531 | level--; | 531 | level--; |
532 | } | 532 | } |
533 | else if ( *p == ST_STOP ) { | 533 | else if ( *p == ST_STOP ) { |
534 | BUG (); | 534 | BUG (); |
535 | } | 535 | } |
536 | } while ( level ); | 536 | } while ( level ); |
537 | n = p + 1 - head; | 537 | n = p + 1 - head; |
538 | 538 | ||
539 | newlist = gcry_xmalloc ( sizeof *newlist + n ); | 539 | newlist = gcry_xmalloc ( sizeof *newlist + n ); |
540 | d = newlist->d; | 540 | d = newlist->d; |
541 | memcpy ( d, head, n ); d += n; | 541 | memcpy ( d, head, n ); d += n; |
542 | *d++ = ST_STOP; | 542 | *d++ = ST_STOP; |
543 | } | 543 | } |
544 | else | 544 | else |
545 | newlist = NULL; | 545 | newlist = NULL; |
546 | 546 | ||
547 | return normalize (newlist); | 547 | return normalize (newlist); |
548 | } | 548 | } |
549 | 549 | ||
550 | gcry_sexp_t | 550 | gcry_sexp_t |
551 | gcry_sexp_car( const gcry_sexp_t list ) | 551 | gcry_sexp_car( const gcry_sexp_t list ) |
552 | { | 552 | { |
553 | return gcry_sexp_nth ( list, 0 ); | 553 | return gcry_sexp_nth ( list, 0 ); |
554 | } | 554 | } |
555 | 555 | ||
556 | /**************** | 556 | /**************** |
557 | * Get data from the car. The returned value is valid as long as the list | 557 | * Get data from the car. The returned value is valid as long as the list |
558 | * is not modified. | 558 | * is not modified. |
559 | */ | 559 | */ |
560 | const char * | 560 | const char * |
561 | gcry_sexp_nth_data( const gcry_sexp_t list, int number, size_t *datalen ) | 561 | gcry_sexp_nth_data( const gcry_sexp_t list, int number, size_t *datalen ) |
562 | { | 562 | { |
563 | const unsigned char *p; | 563 | const unsigned char *p; |
564 | DATALEN n; | 564 | DATALEN n; |
565 | int level = 0; | 565 | int level = 0; |
566 | 566 | ||
567 | *datalen = 0; | 567 | *datalen = 0; |
568 | if ( !list ) { | 568 | if ( !list ) { |
569 | return NULL; | 569 | return NULL; |
570 | } | 570 | } |
571 | p = list->d; | 571 | p = list->d; |
572 | if ( *p == ST_OPEN ) | 572 | if ( *p == ST_OPEN ) |
573 | p++; /* yep, a list */ | 573 | p++; /* yep, a list */ |
574 | else if (number ) | 574 | else if (number ) |
575 | return NULL; /* not a list but an n > 0 element requested */ | 575 | return NULL; /* not a list but an n > 0 element requested */ |
576 | 576 | ||
577 | /* skip n elements */ | 577 | /* skip n elements */ |
578 | while ( number > 0 ) { | 578 | while ( number > 0 ) { |
579 | if ( *p == ST_DATA ) { | 579 | if ( *p == ST_DATA ) { |
580 | memcpy ( &n, ++p, sizeof n ); | 580 | memcpy ( &n, ++p, sizeof n ); |
581 | p += sizeof n + n; | 581 | p += sizeof n + n; |
582 | p--; | 582 | p--; |
583 | if ( !level ) | 583 | if ( !level ) |
584 | number--; | 584 | number--; |
585 | } | 585 | } |
586 | else if ( *p == ST_OPEN ) { | 586 | else if ( *p == ST_OPEN ) { |
587 | level++; | 587 | level++; |
588 | } | 588 | } |
589 | else if ( *p == ST_CLOSE ) { | 589 | else if ( *p == ST_CLOSE ) { |
590 | level--; | 590 | level--; |
591 | if ( !level ) | 591 | if ( !level ) |
592 | number--; | 592 | number--; |
593 | } | 593 | } |
594 | else if ( *p == ST_STOP ) { | 594 | else if ( *p == ST_STOP ) { |
595 | return NULL; | 595 | return NULL; |
596 | } | 596 | } |
597 | p++; | 597 | p++; |
598 | } | 598 | } |
599 | 599 | ||
600 | 600 | ||
601 | if ( *p == ST_DATA ) { | 601 | if ( *p == ST_DATA ) { |
602 | memcpy ( &n, ++p, sizeof n ); | 602 | memcpy ( &n, ++p, sizeof n ); |
603 | *datalen = n; | 603 | *datalen = n; |
604 | return (const char*)p + sizeof n; | 604 | return (const char*)p + sizeof n; |
605 | } | 605 | } |
606 | 606 | ||
607 | return NULL; | 607 | return NULL; |
608 | } | 608 | } |
609 | 609 | ||
610 | /**************** | 610 | /**************** |
611 | * Get a MPI from the car | 611 | * Get a MPI from the car |
612 | */ | 612 | */ |
613 | gcry_mpi_t | 613 | gcry_mpi_t |
614 | gcry_sexp_nth_mpi( gcry_sexp_t list, int number, int mpifmt ) | 614 | gcry_sexp_nth_mpi( gcry_sexp_t list, int number, int mpifmt ) |
615 | { | 615 | { |
616 | const byte *p; | 616 | const byte *p; |
617 | DATALEN n; | 617 | DATALEN n; |
618 | int level = 0; | 618 | int level = 0; |
619 | 619 | ||
620 | if ( !list ) | 620 | if ( !list ) |
621 | return NULL; | 621 | return NULL; |
622 | if ( !mpifmt ) | 622 | if ( !mpifmt ) |
623 | mpifmt = GCRYMPI_FMT_STD; | 623 | mpifmt = GCRYMPI_FMT_STD; |
624 | 624 | ||
625 | p = list->d; | 625 | p = list->d; |
626 | if ( *p == ST_OPEN ) | 626 | if ( *p == ST_OPEN ) |
627 | p++; /* yep, a list */ | 627 | p++; /* yep, a list */ |
628 | else if (number ) | 628 | else if (number ) |
629 | return NULL; /* not a list but an n > 0 element requested */ | 629 | return NULL; /* not a list but an n > 0 element requested */ |
630 | 630 | ||
631 | /* skip n elements */ | 631 | /* skip n elements */ |
632 | while ( number > 0 ) { | 632 | while ( number > 0 ) { |
633 | if ( *p == ST_DATA ) { | 633 | if ( *p == ST_DATA ) { |
634 | memcpy ( &n, ++p, sizeof n ); | 634 | memcpy ( &n, ++p, sizeof n ); |
635 | p += sizeof n + n; | 635 | p += sizeof n + n; |
636 | p--; | 636 | p--; |
637 | if ( !level ) | 637 | if ( !level ) |
638 | number--; | 638 | number--; |
639 | } | 639 | } |
640 | else if ( *p == ST_OPEN ) { | 640 | else if ( *p == ST_OPEN ) { |
641 | level++; | 641 | level++; |
642 | } | 642 | } |
643 | else if ( *p == ST_CLOSE ) { | 643 | else if ( *p == ST_CLOSE ) { |
644 | level--; | 644 | level--; |
645 | if ( !level ) | 645 | if ( !level ) |
646 | number--; | 646 | number--; |
647 | } | 647 | } |
648 | else if ( *p == ST_STOP ) { | 648 | else if ( *p == ST_STOP ) { |
649 | return NULL; | 649 | return NULL; |
650 | } | 650 | } |
651 | p++; | 651 | p++; |
652 | } | 652 | } |
653 | 653 | ||
654 | if ( *p == ST_DATA ) { | 654 | if ( *p == ST_DATA ) { |
655 | gcry_mpi_t a; | 655 | gcry_mpi_t a; |
656 | size_t nbytes; | 656 | size_t nbytes; |
657 | 657 | ||
658 | memcpy ( &n, ++p, sizeof n ); | 658 | memcpy ( &n, ++p, sizeof n ); |
659 | p += sizeof n; | 659 | p += sizeof n; |
660 | nbytes = n; | 660 | nbytes = n; |
661 | if( !gcry_mpi_scan( &a, mpifmt, p, n, &nbytes ) ) | 661 | if( !gcry_mpi_scan( &a, mpifmt, p, n, &nbytes ) ) |
662 | return a; | 662 | return a; |
663 | } | 663 | } |
664 | 664 | ||
665 | return NULL; | 665 | return NULL; |
666 | } | 666 | } |
667 | 667 | ||
668 | 668 | ||
669 | /**************** | 669 | /**************** |
670 | * Get the CDR | 670 | * Get the CDR |
671 | */ | 671 | */ |
672 | gcry_sexp_t | 672 | gcry_sexp_t |
673 | gcry_sexp_cdr( const gcry_sexp_t list ) | 673 | gcry_sexp_cdr( const gcry_sexp_t list ) |
674 | { | 674 | { |
675 | const byte *p; | 675 | const byte *p; |
676 | const byte *head; | 676 | const byte *head; |
677 | DATALEN n; | 677 | DATALEN n; |
678 | gcry_sexp_t newlist; | 678 | gcry_sexp_t newlist; |
679 | byte *d; | 679 | byte *d; |
680 | int level = 0; | 680 | int level = 0; |
681 | int skip = 1; | 681 | int skip = 1; |
682 | 682 | ||
683 | if ( !list || list->d[0] != ST_OPEN ) | 683 | if ( !list || list->d[0] != ST_OPEN ) |
684 | return NULL; | 684 | return NULL; |
685 | p = list->d; | 685 | p = list->d; |
686 | 686 | ||
687 | while ( skip > 0 ) { | 687 | while ( skip > 0 ) { |
688 | p++; | 688 | p++; |
689 | if ( *p == ST_DATA ) { | 689 | if ( *p == ST_DATA ) { |
690 | memcpy ( &n, ++p, sizeof n ); | 690 | memcpy ( &n, ++p, sizeof n ); |
691 | p += sizeof n + n; | 691 | p += sizeof n + n; |
692 | p--; | 692 | p--; |
693 | if ( !level ) | 693 | if ( !level ) |
694 | skip--; | 694 | skip--; |
695 | } | 695 | } |
696 | else if ( *p == ST_OPEN ) { | 696 | else if ( *p == ST_OPEN ) { |
697 | level++; | 697 | level++; |
698 | } | 698 | } |
699 | else if ( *p == ST_CLOSE ) { | 699 | else if ( *p == ST_CLOSE ) { |
700 | level--; | 700 | level--; |
701 | if ( !level ) | 701 | if ( !level ) |
702 | skip--; | 702 | skip--; |
703 | } | 703 | } |
704 | else if ( *p == ST_STOP ) { | 704 | else if ( *p == ST_STOP ) { |
705 | return NULL; | 705 | return NULL; |
706 | } | 706 | } |
707 | } | 707 | } |
708 | p++; | 708 | p++; |
709 | 709 | ||
710 | head = p; | 710 | head = p; |
711 | level = 0; | 711 | level = 0; |
712 | do { | 712 | do { |
713 | if ( *p == ST_DATA ) { | 713 | if ( *p == ST_DATA ) { |
714 | memcpy ( &n, ++p, sizeof n ); | 714 | memcpy ( &n, ++p, sizeof n ); |
715 | p += sizeof n + n; | 715 | p += sizeof n + n; |
716 | p--; | 716 | p--; |
717 | } | 717 | } |
718 | else if ( *p == ST_OPEN ) { | 718 | else if ( *p == ST_OPEN ) { |
719 | level++; | 719 | level++; |
720 | } | 720 | } |
721 | else if ( *p == ST_CLOSE ) { | 721 | else if ( *p == ST_CLOSE ) { |
722 | level--; | 722 | level--; |
723 | } | 723 | } |
724 | else if ( *p == ST_STOP ) { | 724 | else if ( *p == ST_STOP ) { |
725 | return NULL; | 725 | return NULL; |
726 | } | 726 | } |
727 | p++; | 727 | p++; |
728 | } while ( level ); | 728 | } while ( level ); |
729 | n = p - head; | 729 | n = p - head; |
730 | 730 | ||
731 | newlist = gcry_xmalloc ( sizeof *newlist + n + 2 ); | 731 | newlist = gcry_xmalloc ( sizeof *newlist + n + 2 ); |
732 | d = newlist->d; | 732 | d = newlist->d; |
733 | *d++ = ST_OPEN; | 733 | *d++ = ST_OPEN; |
734 | memcpy ( d, head, n ); d += n; | 734 | memcpy ( d, head, n ); d += n; |
735 | *d++ = ST_CLOSE; | 735 | *d++ = ST_CLOSE; |
736 | *d++ = ST_STOP; | 736 | *d++ = ST_STOP; |
737 | 737 | ||
738 | return normalize (newlist); | 738 | return normalize (newlist); |
739 | } | 739 | } |
740 | 740 | ||
741 | gcry_sexp_t | 741 | gcry_sexp_t |
742 | gcry_sexp_cadr ( const gcry_sexp_t list ) | 742 | gcry_sexp_cadr ( const gcry_sexp_t list ) |
743 | { | 743 | { |
744 | gcry_sexp_t a, b; | 744 | gcry_sexp_t a, b; |
745 | 745 | ||
746 | a = gcry_sexp_cdr ( list ); | 746 | a = gcry_sexp_cdr ( list ); |
747 | b = gcry_sexp_car ( a ); | 747 | b = gcry_sexp_car ( a ); |
748 | gcry_sexp_release ( a ); | 748 | gcry_sexp_release ( a ); |
749 | return b; | 749 | return b; |
750 | } | 750 | } |
751 | 751 | ||
752 | 752 | ||
753 | 753 | ||
754 | static int | 754 | static int |
755 | hextobyte( const unsigned char *s ) | 755 | hextobyte( const unsigned char *s ) |
756 | { | 756 | { |
757 | int c=0; | 757 | int c=0; |
758 | 758 | ||
759 | if( *s >= '0' && *s <= '9' ) | 759 | if( *s >= '0' && *s <= '9' ) |
760 | c = 16 * (*s - '0'); | 760 | c = 16 * (*s - '0'); |
761 | else if( *s >= 'A' && *s <= 'F' ) | 761 | else if( *s >= 'A' && *s <= 'F' ) |
762 | c = 16 * (10 + *s - 'A'); | 762 | c = 16 * (10 + *s - 'A'); |
763 | else if( *s >= 'a' && *s <= 'f' ) { | 763 | else if( *s >= 'a' && *s <= 'f' ) { |
764 | c = 16 * (10 + *s - 'a'); | 764 | c = 16 * (10 + *s - 'a'); |
765 | } | 765 | } |
766 | s++; | 766 | s++; |
767 | if( *s >= '0' && *s <= '9' ) | 767 | if( *s >= '0' && *s <= '9' ) |
768 | c += *s - '0'; | 768 | c += *s - '0'; |
769 | else if( *s >= 'A' && *s <= 'F' ) | 769 | else if( *s >= 'A' && *s <= 'F' ) |
770 | c += 10 + *s - 'A'; | 770 | c += 10 + *s - 'A'; |
771 | else if( *s >= 'a' && *s <= 'f' ) { | 771 | else if( *s >= 'a' && *s <= 'f' ) { |
772 | c += 10 + *s - 'a'; | 772 | c += 10 + *s - 'a'; |
773 | } | 773 | } |
774 | return c; | 774 | return c; |
775 | } | 775 | } |
776 | 776 | ||
777 | struct make_space_ctx | 777 | struct make_space_ctx |
778 | { | 778 | { |
779 | gcry_sexp_t sexp; | 779 | gcry_sexp_t sexp; |
780 | size_t allocated; | 780 | size_t allocated; |
781 | unsigned char *pos; | 781 | unsigned char *pos; |
782 | }; | 782 | }; |
783 | 783 | ||
784 | static void | 784 | static void |
785 | make_space ( struct make_space_ctx *c, size_t n ) | 785 | make_space ( struct make_space_ctx *c, size_t n ) |
786 | { | 786 | { |
787 | size_t used = c->pos - c->sexp->d; | 787 | size_t used = c->pos - c->sexp->d; |
788 | 788 | ||
789 | if ( used + n + sizeof(DATALEN) + 1 >= c->allocated ) { | 789 | if ( used + n + sizeof(DATALEN) + 1 >= c->allocated ) { |
790 | gcry_sexp_t newsexp; | 790 | gcry_sexp_t newsexp; |
791 | byte *newhead; | 791 | byte *newhead; |
792 | 792 | ||
793 | c->allocated += 2*(n+sizeof(DATALEN)+1); | 793 | c->allocated += 2*(n+sizeof(DATALEN)+1); |
794 | newsexp = gcry_xrealloc ( c->sexp, sizeof *newsexp + c->allocated - 1 ); | 794 | newsexp = gcry_xrealloc ( c->sexp, sizeof *newsexp + c->allocated - 1 ); |
795 | newhead = newsexp->d; | 795 | newhead = newsexp->d; |
796 | c->pos = newhead + used; | 796 | c->pos = newhead + used; |
797 | c->sexp = newsexp; | 797 | c->sexp = newsexp; |
798 | } | 798 | } |
799 | } | 799 | } |
800 | 800 | ||
801 | 801 | ||
802 | /* Unquote STRING of LENGTH and store it into BUF. The surrounding | 802 | /* Unquote STRING of LENGTH and store it into BUF. The surrounding |
803 | quotes are must already be removed from STRING. We assume that the | 803 | quotes are must already be removed from STRING. We assume that the |
804 | quoted string is syntacillay correct. */ | 804 | quoted string is syntacillay correct. */ |
805 | static size_t | 805 | static size_t |
806 | unquote_string (const char *string_arg, size_t length, unsigned char *buf) | 806 | unquote_string (const char *string_arg, size_t length, unsigned char *buf) |
807 | { | 807 | { |
808 | const unsigned char *string = (const unsigned char*)string_arg; | 808 | const unsigned char *string = (const unsigned char*)string_arg; |
809 | int esc = 0; | 809 | int esc = 0; |
810 | const unsigned char *s = string; | 810 | const unsigned char *s = string; |
811 | unsigned char *d = buf; | 811 | unsigned char *d = buf; |
812 | size_t n = length; | 812 | size_t n = length; |
813 | 813 | ||
814 | for (; n; n--, s++) | 814 | for (; n; n--, s++) |
815 | { | 815 | { |
816 | if (esc) | 816 | if (esc) |
817 | { | 817 | { |
818 | switch (*s) | 818 | switch (*s) |
819 | { | 819 | { |
820 | case 'b': *d++ = '\b'; break; | 820 | case 'b': *d++ = '\b'; break; |
821 | case 't': *d++ = '\t'; break; | 821 | case 't': *d++ = '\t'; break; |
822 | case 'v': *d++ = '\v'; break; | 822 | case 'v': *d++ = '\v'; break; |
823 | case 'n': *d++ = '\n'; break; | 823 | case 'n': *d++ = '\n'; break; |
824 | case 'f': *d++ = '\f'; break; | 824 | case 'f': *d++ = '\f'; break; |
825 | case 'r': *d++ = '\r'; break; | 825 | case 'r': *d++ = '\r'; break; |
826 | case '"': *d++ = '\"'; break; | 826 | case '"': *d++ = '\"'; break; |
827 | case '\'': *d++ = '\''; break; | 827 | case '\'': *d++ = '\''; break; |
828 | case '\\': *d++ = '\\'; break; | 828 | case '\\': *d++ = '\\'; break; |
829 | 829 | ||
830 | case '\r': /* ignore CR[,LF] */ | 830 | case '\r': /* ignore CR[,LF] */ |
831 | if (n>1 && s[1] == '\n') | 831 | if (n>1 && s[1] == '\n') |
832 | { | 832 | { |
833 | s++; n--; | 833 | s++; n--; |
834 | } | 834 | } |
835 | esc = 0; | 835 | esc = 0; |
836 | break; | 836 | break; |
837 | 837 | ||
838 | case '\n': /* ignore LF[,CR] */ | 838 | case '\n': /* ignore LF[,CR] */ |
839 | if (n>1 && s[1] == '\r') | 839 | if (n>1 && s[1] == '\r') |
840 | { | 840 | { |
841 | s++; n--; | 841 | s++; n--; |
842 | } | 842 | } |
843 | break; | 843 | break; |
844 | 844 | ||
845 | case 'x': /* hex value */ | 845 | case 'x': /* hex value */ |
846 | if (n>2 && hexdigitp (s+1) && hexdigitp (s+2)) | 846 | if (n>2 && hexdigitp (s+1) && hexdigitp (s+2)) |
847 | { | 847 | { |
848 | s++; n--; | 848 | s++; n--; |
849 | *d++ = xtoi_2 (s); | 849 | *d++ = xtoi_2 (s); |
850 | s++; n--; | 850 | s++; n--; |
851 | } | 851 | } |
852 | break; | 852 | break; |
853 | 853 | ||
854 | default: | 854 | default: |
855 | if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2)) | 855 | if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2)) |
856 | { | 856 | { |
857 | *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2); | 857 | *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2); |
858 | s += 2; | 858 | s += 2; |
859 | n -= 2; | 859 | n -= 2; |
860 | } | 860 | } |
861 | break; | 861 | break; |
862 | } | 862 | } |
863 | esc = 0; | 863 | esc = 0; |
864 | } | 864 | } |
865 | else if( *s == '\\' ) | 865 | else if( *s == '\\' ) |
866 | esc = 1; | 866 | esc = 1; |
867 | else | 867 | else |
868 | *d++ = *s; | 868 | *d++ = *s; |
869 | } | 869 | } |
870 | 870 | ||
871 | return d - buf; | 871 | return d - buf; |
872 | } | 872 | } |
873 | 873 | ||
874 | /**************** | 874 | /**************** |
875 | * Scan the provided buffer and return the S expression in our internal | 875 | * Scan the provided buffer and return the S expression in our internal |
876 | * format. Returns a newly allocated expression. If erroff is not NULL and | 876 | * format. Returns a newly allocated expression. If erroff is not NULL and |
877 | * a parsing error has occured, the offset into buffer will be returned. | 877 | * a parsing error has occured, the offset into buffer will be returned. |
878 | * If ARGFLAG is true, the function supports some printf like | 878 | * If ARGFLAG is true, the function supports some printf like |
879 | * expressions. | 879 | * expressions. |
880 | * These are: | 880 | * These are: |
881 | * %m - MPI | 881 | * %m - MPI |
882 | * %s - string (no autoswitch to secure allocation) | 882 | * %s - string (no autoswitch to secure allocation) |
883 | * %d - integer stored as string (no autoswitch to secure allocation) | 883 | * %d - integer stored as string (no autoswitch to secure allocation) |
884 | * %b - memory buffer; this takes _two_ arguments: an integer with the | 884 | * %b - memory buffer; this takes _two_ arguments: an integer with the |
885 | * length of the buffer and a pointer to the buffer. | 885 | * length of the buffer and a pointer to the buffer. |
886 | * all other format elements are currently not defined and return an error. | 886 | * all other format elements are currently not defined and return an error. |
887 | * this includes the "%%" sequence becauce the percent sign is not an | 887 | * this includes the "%%" sequence becauce the percent sign is not an |
888 | * allowed character. | 888 | * allowed character. |
889 | * FIXME: We should find a way to store the secure-MPIs not in the string | 889 | * FIXME: We should find a way to store the secure-MPIs not in the string |
890 | * but as reference to somewhere - this can help us to save huge amounts | 890 | * but as reference to somewhere - this can help us to save huge amounts |
891 | * of secure memory. The problem is, that if only one element is secure, all | 891 | * of secure memory. The problem is, that if only one element is secure, all |
892 | * other elements are automagicaly copied to secure memory too, so the most | 892 | * other elements are automagicaly copied to secure memory too, so the most |
893 | * common operation gcry_sexp_cdr_mpi() will always return a secure MPI | 893 | * common operation gcry_sexp_cdr_mpi() will always return a secure MPI |
894 | * regardless whether it is needed or not. | 894 | * regardless whether it is needed or not. |
895 | */ | 895 | */ |
896 | static gcry_error_t | 896 | static gcry_error_t |
897 | sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, | 897 | sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, |
898 | const char *buffer, size_t length, int argflag, | 898 | const char *buffer, size_t length, int argflag, |
899 | va_list arg_ptr, void **arg_list) | 899 | va_list arg_ptr, void **arg_list) |
900 | { | 900 | { |
901 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | 901 | gcry_err_code_t err = GPG_ERR_NO_ERROR; |
902 | static const char tokenchars[] = | 902 | static const char tokenchars[] = |
903 | "abcdefghijklmnopqrstuvwxyz" | 903 | "abcdefghijklmnopqrstuvwxyz" |
904 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | 904 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
905 | "0123456789-./_:*+="; | 905 | "0123456789-./_:*+="; |
906 | const char *p; | 906 | const char *p; |
907 | size_t n; | 907 | size_t n; |
908 | const char *digptr = NULL; | 908 | const char *digptr = NULL; |
909 | const char *quoted = NULL; | 909 | const char *quoted = NULL; |
910 | const char *tokenp = NULL; | 910 | const char *tokenp = NULL; |
911 | const char *hexfmt = NULL; | 911 | const char *hexfmt = NULL; |
912 | const char *base64 = NULL; | 912 | const char *base64 = NULL; |
913 | const char *disphint = NULL; | 913 | const char *disphint = NULL; |
914 | const char *percent = NULL; | 914 | const char *percent = NULL; |
915 | int hexcount = 0; | 915 | int hexcount = 0; |
916 | int quoted_esc = 0; | 916 | int quoted_esc = 0; |
917 | int datalen = 0; | 917 | int datalen = 0; |
918 | size_t dummy_erroff; | 918 | size_t dummy_erroff; |
919 | struct make_space_ctx c; | 919 | struct make_space_ctx c; |
920 | int arg_counter = 0; | 920 | int arg_counter = 0; |
921 | int level = 0; | 921 | int level = 0; |
922 | 922 | ||
923 | /* FIXME: invent better error codes (?). */ | 923 | /* FIXME: invent better error codes (?). */ |
924 | 924 | ||
925 | if (!erroff) | 925 | if (!erroff) |
926 | erroff = &dummy_erroff; | 926 | erroff = &dummy_erroff; |
927 | 927 | ||
928 | /* Depending on wether ARG_LIST is non-zero or not, this macro gives | 928 | /* Depending on wether ARG_LIST is non-zero or not, this macro gives |
929 | us the next argument, either from the variable argument list as | 929 | us the next argument, either from the variable argument list as |
930 | specified by ARG_PTR or from the argument array ARG_LIST. */ | 930 | specified by ARG_PTR or from the argument array ARG_LIST. */ |
931 | #define ARG_NEXT(storage, type) \ | 931 | #define ARG_NEXT(storage, type) \ |
932 | do \ | 932 | do \ |
933 | { \ | 933 | { \ |
934 | if (!arg_list) \ | 934 | if (!arg_list) \ |
935 | storage = va_arg (arg_ptr, type); \ | 935 | storage = va_arg (arg_ptr, type); \ |
936 | else \ | 936 | else \ |
937 | storage = *((type *) (arg_list[arg_counter++])); \ | 937 | storage = *((type *) (arg_list[arg_counter++])); \ |
938 | } \ | 938 | } \ |
939 | while (0) | 939 | while (0) |
940 | 940 | ||
941 | #define MAKE_SPACE(n) do { make_space ( &c, (n) ); } while (0) | 941 | #define MAKE_SPACE(n) do { make_space ( &c, (n) ); } while (0) |
942 | #define STORE_LEN(p,n) do { \ | 942 | #define STORE_LEN(p,n) do { \ |
943 | DATALEN ashort = (n); \ | 943 | DATALEN ashort = (n); \ |
944 | memcpy ( (p), &ashort, sizeof(ashort) ); \ | 944 | memcpy ( (p), &ashort, sizeof(ashort) ); \ |
945 | (p) += sizeof (ashort); \ | 945 | (p) += sizeof (ashort); \ |
946 | } while (0) | 946 | } while (0) |
947 | 947 | ||
948 | /* We assume that the internal representation takes less memory | 948 | /* We assume that the internal representation takes less memory |
949 | * than the provided one. However, we add space for one extra datalen | 949 | * than the provided one. However, we add space for one extra datalen |
950 | * so that the code which does the ST_CLOSE can use MAKE_SPACE */ | 950 | * so that the code which does the ST_CLOSE can use MAKE_SPACE */ |
951 | c.allocated = length + sizeof(DATALEN); | 951 | c.allocated = length + sizeof(DATALEN); |
952 | if (buffer && length && gcry_is_secure (buffer)) | 952 | if (buffer && length && gcry_is_secure (buffer)) |
953 | c.sexp = gcry_xmalloc_secure (sizeof *c.sexp + c.allocated - 1); | 953 | c.sexp = gcry_xmalloc_secure (sizeof *c.sexp + c.allocated - 1); |
954 | else | 954 | else |
955 | c.sexp = gcry_xmalloc (sizeof *c.sexp + c.allocated - 1); | 955 | c.sexp = gcry_xmalloc (sizeof *c.sexp + c.allocated - 1); |
956 | c.pos = c.sexp->d; | 956 | c.pos = c.sexp->d; |
957 | 957 | ||
958 | for (p = buffer, n = length; n; p++, n--) | 958 | for (p = buffer, n = length; n; p++, n--) |
959 | { | 959 | { |
960 | if (tokenp && !hexfmt) | 960 | if (tokenp && !hexfmt) |
961 | { | 961 | { |
962 | if (strchr (tokenchars, *p)) | 962 | if (strchr (tokenchars, *p)) |
963 | continue; | 963 | continue; |
964 | else | 964 | else |
965 | { | 965 | { |
966 | datalen = p - tokenp; | 966 | datalen = p - tokenp; |
967 | MAKE_SPACE (datalen); | 967 | MAKE_SPACE (datalen); |
968 | *c.pos++ = ST_DATA; | 968 | *c.pos++ = ST_DATA; |
969 | STORE_LEN (c.pos, datalen); | 969 | STORE_LEN (c.pos, datalen); |
970 | memcpy (c.pos, tokenp, datalen); | 970 | memcpy (c.pos, tokenp, datalen); |
971 | c.pos += datalen; | 971 | c.pos += datalen; |
972 | tokenp = NULL; | 972 | tokenp = NULL; |
973 | } | 973 | } |
974 | } | 974 | } |
975 | 975 | ||
976 | if (quoted) | 976 | if (quoted) |
977 | { | 977 | { |
978 | if (quoted_esc) | 978 | if (quoted_esc) |
979 | { | 979 | { |
980 | switch (*p) | 980 | switch (*p) |
981 | { | 981 | { |
982 | case 'b': case 't': case 'v': case 'n': case 'f': | 982 | case 'b': case 't': case 'v': case 'n': case 'f': |
983 | case 'r': case '"': case '\'': case '\\': | 983 | case 'r': case '"': case '\'': case '\\': |
984 | quoted_esc = 0; | 984 | quoted_esc = 0; |
985 | break; | 985 | break; |
986 | 986 | ||
987 | case '0': case '1': case '2': case '3': case '4': | 987 | case '0': case '1': case '2': case '3': case '4': |
988 | case '5': case '6': case '7': | 988 | case '5': case '6': case '7': |
989 | if (!((n > 2) | 989 | if (!((n > 2) |
990 | && (p[1] >= '0') && (p[1] <= '7') | 990 | && (p[1] >= '0') && (p[1] <= '7') |
991 | && (p[2] >= '0') && (p[2] <= '7'))) | 991 | && (p[2] >= '0') && (p[2] <= '7'))) |
992 | { | 992 | { |
993 | *erroff = p - buffer; | 993 | *erroff = p - buffer; |
994 | /* Invalid octal value. */ | 994 | /* Invalid octal value. */ |
995 | err = GPG_ERR_SEXP_BAD_QUOTATION; | 995 | err = GPG_ERR_SEXP_BAD_QUOTATION; |
996 | } | 996 | } |
997 | p += 2; | 997 | p += 2; |
998 | n -= 2; | 998 | n -= 2; |
999 | quoted_esc = 0; | 999 | quoted_esc = 0; |
1000 | break; | 1000 | break; |
1001 | 1001 | ||
1002 | case 'x': | 1002 | case 'x': |
1003 | if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2))) | 1003 | if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2))) |
1004 | { | 1004 | { |
1005 | *erroff = p - buffer; | 1005 | *erroff = p - buffer; |
1006 | /* Invalid hex value. */ | 1006 | /* Invalid hex value. */ |
1007 | err = GPG_ERR_SEXP_BAD_QUOTATION; | 1007 | err = GPG_ERR_SEXP_BAD_QUOTATION; |
1008 | } | 1008 | } |
1009 | p += 2; | 1009 | p += 2; |
1010 | n -= 2; | 1010 | n -= 2; |
1011 | quoted_esc = 0; | 1011 | quoted_esc = 0; |
1012 | break; | 1012 | break; |
1013 | 1013 | ||
1014 | case '\r': | 1014 | case '\r': |
1015 | /* ignore CR[,LF] */ | 1015 | /* ignore CR[,LF] */ |
1016 | if (n && (p[1] == '\n')) | 1016 | if (n && (p[1] == '\n')) |
1017 | { | 1017 | { |
1018 | p++; | 1018 | p++; |
1019 | n--; | 1019 | n--; |
1020 | } | 1020 | } |
1021 | quoted_esc = 0; | 1021 | quoted_esc = 0; |
1022 | break; | 1022 | break; |
1023 | 1023 | ||
1024 | case '\n': | 1024 | case '\n': |
1025 | /* ignore LF[,CR] */ | 1025 | /* ignore LF[,CR] */ |
1026 | if (n && (p[1] == '\r')) | 1026 | if (n && (p[1] == '\r')) |
1027 | { | 1027 | { |
1028 | p++; | 1028 | p++; |
1029 | n--; | 1029 | n--; |
1030 | } | 1030 | } |
1031 | quoted_esc = 0; | 1031 | quoted_esc = 0; |
1032 | break; | 1032 | break; |
1033 | 1033 | ||
1034 | default: | 1034 | default: |
1035 | *erroff = p - buffer; | 1035 | *erroff = p - buffer; |
1036 | /* Invalid quoted string escape. */ | 1036 | /* Invalid quoted string escape. */ |
1037 | err = GPG_ERR_SEXP_BAD_QUOTATION; | 1037 | err = GPG_ERR_SEXP_BAD_QUOTATION; |
1038 | } | 1038 | } |
1039 | } | 1039 | } |
1040 | else if (*p == '\\') | 1040 | else if (*p == '\\') |
1041 | quoted_esc = 1; | 1041 | quoted_esc = 1; |
1042 | else if (*p == '\"') | 1042 | else if (*p == '\"') |
1043 | { | 1043 | { |
1044 | /* Keep it easy - we know that the unquoted string will | 1044 | /* Keep it easy - we know that the unquoted string will |
1045 | never be larger. */ | 1045 | never be larger. */ |
1046 | unsigned char *save; | 1046 | unsigned char *save; |
1047 | size_t len; | 1047 | size_t len; |
1048 | 1048 | ||
1049 | quoted++; /* Skip leading quote. */ | 1049 | quoted++; /* Skip leading quote. */ |
1050 | MAKE_SPACE (p - quoted); | 1050 | MAKE_SPACE (p - quoted); |
1051 | *c.pos++ = ST_DATA; | 1051 | *c.pos++ = ST_DATA; |
1052 | save = c.pos; | 1052 | save = c.pos; |
1053 | STORE_LEN (c.pos, 0); /* Will be fixed up later. */ | 1053 | STORE_LEN (c.pos, 0); /* Will be fixed up later. */ |
1054 | len = unquote_string (quoted, p - quoted, c.pos); | 1054 | len = unquote_string (quoted, p - quoted, c.pos); |
1055 | c.pos += len; | 1055 | c.pos += len; |
1056 | STORE_LEN (save, len); | 1056 | STORE_LEN (save, len); |
1057 | quoted = NULL; | 1057 | quoted = NULL; |
1058 | } | 1058 | } |
1059 | } | 1059 | } |
1060 | else if (hexfmt) | 1060 | else if (hexfmt) |
1061 | { | 1061 | { |
1062 | if (isxdigit (*p)) | 1062 | if (isxdigit (*p)) |
1063 | hexcount++; | 1063 | hexcount++; |
1064 | else if (*p == '#') | 1064 | else if (*p == '#') |
1065 | { | 1065 | { |
1066 | if ((hexcount & 1)) | 1066 | if ((hexcount & 1)) |
1067 | { | 1067 | { |
1068 | *erroff = p - buffer; | 1068 | *erroff = p - buffer; |
1069 | err = GPG_ERR_SEXP_ODD_HEX_NUMBERS; | 1069 | err = GPG_ERR_SEXP_ODD_HEX_NUMBERS; |
1070 | } | 1070 | } |
1071 | 1071 | ||
1072 | datalen = hexcount / 2; | 1072 | datalen = hexcount / 2; |
1073 | MAKE_SPACE (datalen); | 1073 | MAKE_SPACE (datalen); |
1074 | *c.pos++ = ST_DATA; | 1074 | *c.pos++ = ST_DATA; |
1075 | STORE_LEN (c.pos, datalen); | 1075 | STORE_LEN (c.pos, datalen); |
1076 | for (hexfmt++; hexfmt < p; hexfmt++) | 1076 | for (hexfmt++; hexfmt < p; hexfmt++) |
1077 | { | 1077 | { |
1078 | if (whitespacep (hexfmt)) | 1078 | if (whitespacep (hexfmt)) |
1079 | continue; | 1079 | continue; |
1080 | *c.pos++ = hextobyte ((const unsigned char*)hexfmt); | 1080 | *c.pos++ = hextobyte ((const unsigned char*)hexfmt); |
1081 | hexfmt++; | 1081 | hexfmt++; |
1082 | } | 1082 | } |
1083 | hexfmt = NULL; | 1083 | hexfmt = NULL; |
1084 | } | 1084 | } |
1085 | else if (!whitespacep (p)) | 1085 | else if (!whitespacep (p)) |
1086 | { | 1086 | { |
1087 | *erroff = p - buffer; | 1087 | *erroff = p - buffer; |
1088 | err = GPG_ERR_SEXP_BAD_HEX_CHAR; | 1088 | err = GPG_ERR_SEXP_BAD_HEX_CHAR; |
1089 | } | 1089 | } |
1090 | } | 1090 | } |
1091 | else if (base64) | 1091 | else if (base64) |
1092 | { | 1092 | { |
1093 | if (*p == '|') | 1093 | if (*p == '|') |
1094 | base64 = NULL; | 1094 | base64 = NULL; |
1095 | } | 1095 | } |
1096 | else if (digptr) | 1096 | else if (digptr) |
1097 | { | 1097 | { |
1098 | if (digitp (p)) | 1098 | if (digitp (p)) |
1099 | ; | 1099 | ; |
1100 | else if (*p == ':') | 1100 | else if (*p == ':') |
1101 | { | 1101 | { |
1102 | datalen = atoi (digptr); /* FIXME: check for overflow. */ | 1102 | datalen = atoi (digptr); /* FIXME: check for overflow. */ |
1103 | digptr = NULL; | 1103 | digptr = NULL; |
1104 | if (datalen > n - 1) | 1104 | if (datalen > n - 1) |
1105 | { | 1105 | { |
1106 | *erroff = p - buffer; | 1106 | *erroff = p - buffer; |
1107 | /* Buffer too short. */ | 1107 | /* Buffer too short. */ |
1108 | err = GPG_ERR_SEXP_STRING_TOO_LONG; | 1108 | err = GPG_ERR_SEXP_STRING_TOO_LONG; |
1109 | } | 1109 | } |
1110 | /* Make a new list entry. */ | 1110 | /* Make a new list entry. */ |
1111 | MAKE_SPACE (datalen); | 1111 | MAKE_SPACE (datalen); |
1112 | *c.pos++ = ST_DATA; | 1112 | *c.pos++ = ST_DATA; |
1113 | STORE_LEN (c.pos, datalen); | 1113 | STORE_LEN (c.pos, datalen); |
1114 | memcpy (c.pos, p + 1, datalen); | 1114 | memcpy (c.pos, p + 1, datalen); |
1115 | c.pos += datalen; | 1115 | c.pos += datalen; |
1116 | n -= datalen; | 1116 | n -= datalen; |
1117 | p += datalen; | 1117 | p += datalen; |
1118 | } | 1118 | } |
1119 | else if (*p == '\"') | 1119 | else if (*p == '\"') |
1120 | { | 1120 | { |
1121 | digptr = NULL; /* We ignore the optional length. */ | 1121 | digptr = NULL; /* We ignore the optional length. */ |
1122 | quoted = p; | 1122 | quoted = p; |
1123 | quoted_esc = 0; | 1123 | quoted_esc = 0; |
1124 | } | 1124 | } |
1125 | else if (*p == '#') | 1125 | else if (*p == '#') |
1126 | { | 1126 | { |
1127 | digptr = NULL; /* We ignore the optional length. */ | 1127 | digptr = NULL; /* We ignore the optional length. */ |
1128 | hexfmt = p; | 1128 | hexfmt = p; |
1129 | hexcount = 0; | 1129 | hexcount = 0; |
1130 | } | 1130 | } |
1131 | else if (*p == '|') | 1131 | else if (*p == '|') |
1132 | { | 1132 | { |
1133 | digptr = NULL; /* We ignore the optional length. */ | 1133 | digptr = NULL; /* We ignore the optional length. */ |
1134 | base64 = p; | 1134 | base64 = p; |
1135 | } | 1135 | } |
1136 | else | 1136 | else |
1137 | { | 1137 | { |
1138 | *erroff = p - buffer; | 1138 | *erroff = p - buffer; |
1139 | err = GPG_ERR_SEXP_INV_LEN_SPEC; | 1139 | err = GPG_ERR_SEXP_INV_LEN_SPEC; |
1140 | } | 1140 | } |
1141 | } | 1141 | } |
1142 | else if (percent) | 1142 | else if (percent) |
1143 | { | 1143 | { |
1144 | if (*p == 'm') | 1144 | if (*p == 'm') |
1145 | { | 1145 | { |
1146 | /* Insert an MPI. */ | 1146 | /* Insert an MPI. */ |
1147 | gcry_mpi_t m; | 1147 | gcry_mpi_t m; |
1148 | size_t nm = 0; | 1148 | size_t nm = 0; |
1149 | 1149 | ||
1150 | ARG_NEXT (m, gcry_mpi_t); | 1150 | ARG_NEXT (m, gcry_mpi_t); |
1151 | 1151 | ||
1152 | if (gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &nm, m)) | 1152 | if (gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &nm, m)) |
1153 | BUG (); | 1153 | BUG (); |
1154 | 1154 | ||
1155 | MAKE_SPACE (nm); | 1155 | MAKE_SPACE (nm); |
1156 | if ((!gcry_is_secure (c.sexp->d)) | 1156 | if ((!gcry_is_secure (c.sexp->d)) |
1157 | && gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE)) | 1157 | && gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE)) |
1158 | { | 1158 | { |
1159 | /* We have to switch to secure allocation. */ | 1159 | /* We have to switch to secure allocation. */ |
1160 | gcry_sexp_t newsexp; | 1160 | gcry_sexp_t newsexp; |
1161 | byte *newhead; | 1161 | byte *newhead; |
1162 | 1162 | ||
1163 | newsexp = gcry_xmalloc_secure (sizeof *newsexp | 1163 | newsexp = gcry_xmalloc_secure (sizeof *newsexp |
1164 | + c.allocated - 1); | 1164 | + c.allocated - 1); |
1165 | newhead = newsexp->d; | 1165 | newhead = newsexp->d; |
1166 | memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d)); | 1166 | memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d)); |
1167 | c.pos = newhead + (c.pos - c.sexp->d); | 1167 | c.pos = newhead + (c.pos - c.sexp->d); |
1168 | gcry_free (c.sexp); | 1168 | gcry_free (c.sexp); |
1169 | c.sexp = newsexp; | 1169 | c.sexp = newsexp; |
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | *c.pos++ = ST_DATA; | 1172 | *c.pos++ = ST_DATA; |
1173 | STORE_LEN (c.pos, nm); | 1173 | STORE_LEN (c.pos, nm); |
1174 | if (gcry_mpi_print (GCRYMPI_FMT_STD, c.pos, nm, &nm, m)) | 1174 | if (gcry_mpi_print (GCRYMPI_FMT_STD, c.pos, nm, &nm, m)) |
1175 | BUG (); | 1175 | BUG (); |
1176 | c.pos += nm; | 1176 | c.pos += nm; |
1177 | } | 1177 | } |
1178 | else if (*p == 's') | 1178 | else if (*p == 's') |
1179 | { | 1179 | { |
1180 | /* Insert an string. */ | 1180 | /* Insert an string. */ |
1181 | const char *astr; | 1181 | const char *astr; |
1182 | size_t alen; | 1182 | size_t alen; |
1183 | 1183 | ||
1184 | ARG_NEXT (astr, const char *); | 1184 | ARG_NEXT (astr, const char *); |
1185 | alen = strlen (astr); | 1185 | alen = strlen (astr); |
1186 | 1186 | ||
1187 | MAKE_SPACE (alen); | 1187 | MAKE_SPACE (alen); |
1188 | *c.pos++ = ST_DATA; | 1188 | *c.pos++ = ST_DATA; |
1189 | STORE_LEN (c.pos, alen); | 1189 | STORE_LEN (c.pos, alen); |
1190 | memcpy (c.pos, astr, alen); | 1190 | memcpy (c.pos, astr, alen); |
1191 | c.pos += alen; | 1191 | c.pos += alen; |
1192 | } | 1192 | } |
1193 | else if (*p == 'b') | 1193 | else if (*p == 'b') |
1194 | { | 1194 | { |
1195 | /* Insert a memory buffer. */ | 1195 | /* Insert a memory buffer. */ |
1196 | const char *astr; | 1196 | const char *astr; |
1197 | int alen; | 1197 | int alen; |
1198 | 1198 | ||
1199 | ARG_NEXT (alen, int); | 1199 | ARG_NEXT (alen, int); |
1200 | ARG_NEXT (astr, const char *); | 1200 | ARG_NEXT (astr, const char *); |
1201 | 1201 | ||
1202 | MAKE_SPACE (alen); | 1202 | MAKE_SPACE (alen); |
1203 | if (alen | 1203 | if (alen |
1204 | && !gcry_is_secure (c.sexp->d) | 1204 | && !gcry_is_secure (c.sexp->d) |
1205 | && gcry_is_secure (astr)) | 1205 | && gcry_is_secure (astr)) |
1206 | { | 1206 | { |
1207 | /* We have to switch to secure allocation. */ | 1207 | /* We have to switch to secure allocation. */ |
1208 | gcry_sexp_t newsexp; | 1208 | gcry_sexp_t newsexp; |
1209 | byte *newhead; | 1209 | byte *newhead; |
1210 | 1210 | ||
1211 | newsexp = gcry_xmalloc_secure (sizeof *newsexp | 1211 | newsexp = gcry_xmalloc_secure (sizeof *newsexp |
1212 | + c.allocated - 1); | 1212 | + c.allocated - 1); |
1213 | newhead = newsexp->d; | 1213 | newhead = newsexp->d; |
1214 | memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d)); | 1214 | memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d)); |
1215 | c.pos = newhead + (c.pos - c.sexp->d); | 1215 | c.pos = newhead + (c.pos - c.sexp->d); |
1216 | gcry_free (c.sexp); | 1216 | gcry_free (c.sexp); |
1217 | c.sexp = newsexp; | 1217 | c.sexp = newsexp; |
1218 | } | 1218 | } |
1219 | 1219 | ||
1220 | *c.pos++ = ST_DATA; | 1220 | *c.pos++ = ST_DATA; |
1221 | STORE_LEN (c.pos, alen); | 1221 | STORE_LEN (c.pos, alen); |
1222 | memcpy (c.pos, astr, alen); | 1222 | memcpy (c.pos, astr, alen); |
1223 | c.pos += alen; | 1223 | c.pos += alen; |
1224 | } | 1224 | } |
1225 | else if (*p == 'd') | 1225 | else if (*p == 'd') |
1226 | { | 1226 | { |
1227 | /* Insert an integer as string. */ | 1227 | /* Insert an integer as string. */ |
1228 | int aint; | 1228 | int aint; |
1229 | size_t alen; | 1229 | size_t alen; |
1230 | char buf[20]; | 1230 | char buf[20]; |
1231 | 1231 | ||
1232 | ARG_NEXT (aint, int); | 1232 | ARG_NEXT (aint, int); |
1233 | sprintf (buf, "%d", aint); | 1233 | sprintf (buf, "%d", aint); |
1234 | alen = strlen (buf); | 1234 | alen = strlen (buf); |
1235 | MAKE_SPACE (alen); | 1235 | MAKE_SPACE (alen); |
1236 | *c.pos++ = ST_DATA; | 1236 | *c.pos++ = ST_DATA; |
1237 | STORE_LEN (c.pos, alen); | 1237 | STORE_LEN (c.pos, alen); |
1238 | memcpy (c.pos, buf, alen); | 1238 | memcpy (c.pos, buf, alen); |
1239 | c.pos += alen; | 1239 | c.pos += alen; |
1240 | } | 1240 | } |
1241 | else | 1241 | else |
1242 | { | 1242 | { |
1243 | *erroff = p - buffer; | 1243 | *erroff = p - buffer; |
1244 | /* Invalid format specifier. */ | 1244 | /* Invalid format specifier. */ |
1245 | err = GPG_ERR_SEXP_INV_LEN_SPEC; | 1245 | err = GPG_ERR_SEXP_INV_LEN_SPEC; |
1246 | } | 1246 | } |
1247 | percent = NULL; | 1247 | percent = NULL; |
1248 | } | 1248 | } |
1249 | else if (*p == '(') | 1249 | else if (*p == '(') |
1250 | { | 1250 | { |
1251 | if (disphint) | 1251 | if (disphint) |
1252 | { | 1252 | { |
1253 | *erroff = p - buffer; | 1253 | *erroff = p - buffer; |
1254 | /* Open display hint. */ | 1254 | /* Open display hint. */ |
1255 | err = GPG_ERR_SEXP_UNMATCHED_DH; | 1255 | err = GPG_ERR_SEXP_UNMATCHED_DH; |
1256 | } | 1256 | } |
1257 | MAKE_SPACE (0); | 1257 | MAKE_SPACE (0); |
1258 | *c.pos++ = ST_OPEN; | 1258 | *c.pos++ = ST_OPEN; |
1259 | level++; | 1259 | level++; |
1260 | } | 1260 | } |
1261 | else if (*p == ')') | 1261 | else if (*p == ')') |
1262 | { | 1262 | { |
1263 | /* Walk up. */ | 1263 | /* Walk up. */ |
1264 | if (disphint) | 1264 | if (disphint) |
1265 | { | 1265 | { |
1266 | *erroff = p - buffer; | 1266 | *erroff = p - buffer; |
1267 | /* Open display hint. */ | 1267 | /* Open display hint. */ |
1268 | err = GPG_ERR_SEXP_UNMATCHED_DH; | 1268 | err = GPG_ERR_SEXP_UNMATCHED_DH; |
1269 | } | 1269 | } |
1270 | MAKE_SPACE (0); | 1270 | MAKE_SPACE (0); |
1271 | *c.pos++ = ST_CLOSE; | 1271 | *c.pos++ = ST_CLOSE; |
1272 | level--; | 1272 | level--; |
1273 | } | 1273 | } |
1274 | else if (*p == '\"') | 1274 | else if (*p == '\"') |
1275 | { | 1275 | { |
1276 | quoted = p; | 1276 | quoted = p; |
1277 | quoted_esc = 0; | 1277 | quoted_esc = 0; |
1278 | } | 1278 | } |
1279 | else if (*p == '#') | 1279 | else if (*p == '#') |
1280 | { | 1280 | { |
1281 | hexfmt = p; | 1281 | hexfmt = p; |
1282 | hexcount = 0; | 1282 | hexcount = 0; |
1283 | } | 1283 | } |
1284 | else if (*p == '|') | 1284 | else if (*p == '|') |
1285 | base64 = p; | 1285 | base64 = p; |
1286 | else if (*p == '[') | 1286 | else if (*p == '[') |
1287 | { | 1287 | { |
1288 | if (disphint) | 1288 | if (disphint) |
1289 | { | 1289 | { |
1290 | *erroff = p - buffer; | 1290 | *erroff = p - buffer; |
1291 | /* Open display hint. */ | 1291 | /* Open display hint. */ |
1292 | err = GPG_ERR_SEXP_NESTED_DH; | 1292 | err = GPG_ERR_SEXP_NESTED_DH; |
1293 | } | 1293 | } |
1294 | disphint = p; | 1294 | disphint = p; |
1295 | } | 1295 | } |
1296 | else if (*p == ']') | 1296 | else if (*p == ']') |
1297 | { | 1297 | { |
1298 | if (!disphint) | 1298 | if (!disphint) |
1299 | { | 1299 | { |
1300 | *erroff = p - buffer; | 1300 | *erroff = p - buffer; |
1301 | /* Open display hint. */ | 1301 | /* Open display hint. */ |
1302 | err = GPG_ERR_SEXP_UNMATCHED_DH; | 1302 | err = GPG_ERR_SEXP_UNMATCHED_DH; |
1303 | } | 1303 | } |
1304 | disphint = NULL; | 1304 | disphint = NULL; |
1305 | } | 1305 | } |
1306 | else if (digitp (p)) | 1306 | else if (digitp (p)) |
1307 | { | 1307 | { |
1308 | if (*p == '0') | 1308 | if (*p == '0') |
1309 | { | 1309 | { |
1310 | /* A length may not begin with zero. */ | 1310 | /* A length may not begin with zero. */ |
1311 | *erroff = p - buffer; | 1311 | *erroff = p - buffer; |
1312 | err = GPG_ERR_SEXP_ZERO_PREFIX; | 1312 | err = GPG_ERR_SEXP_ZERO_PREFIX; |
1313 | } | 1313 | } |
1314 | digptr = p; | 1314 | digptr = p; |
1315 | } | 1315 | } |
1316 | else if (strchr (tokenchars, *p)) | 1316 | else if (strchr (tokenchars, *p)) |
1317 | tokenp = p; | 1317 | tokenp = p; |
1318 | else if (whitespacep (p)) | 1318 | else if (whitespacep (p)) |
1319 | ; | 1319 | ; |
1320 | else if (*p == '{') | 1320 | else if (*p == '{') |
1321 | { | 1321 | { |
1322 | /* fixme: handle rescanning: we can do this by saving our | 1322 | /* fixme: handle rescanning: we can do this by saving our |
1323 | current state and start over at p+1 -- Hmmm. At this | 1323 | current state and start over at p+1 -- Hmmm. At this |
1324 | point here we are in a well defined state, so we don't | 1324 | point here we are in a well defined state, so we don't |
1325 | need to save it. Great. */ | 1325 | need to save it. Great. */ |
1326 | *erroff = p - buffer; | 1326 | *erroff = p - buffer; |
1327 | err = GPG_ERR_SEXP_UNEXPECTED_PUNC; | 1327 | err = GPG_ERR_SEXP_UNEXPECTED_PUNC; |
1328 | } | 1328 | } |
1329 | else if (strchr ("&\\", *p)) | 1329 | else if (strchr ("&\\", *p)) |
1330 | { | 1330 | { |
1331 | /* Reserved punctuation. */ | 1331 | /* Reserved punctuation. */ |
1332 | *erroff = p - buffer; | 1332 | *erroff = p - buffer; |
1333 | err = GPG_ERR_SEXP_UNEXPECTED_PUNC; | 1333 | err = GPG_ERR_SEXP_UNEXPECTED_PUNC; |
1334 | } | 1334 | } |
1335 | else if (argflag && (*p == '%')) | 1335 | else if (argflag && (*p == '%')) |
1336 | percent = p; | 1336 | percent = p; |
1337 | else | 1337 | else |
1338 | { | 1338 | { |
1339 | /* Bad or unavailable. */ | 1339 | /* Bad or unavailable. */ |
1340 | *erroff = p - buffer; | 1340 | *erroff = p - buffer; |
1341 | err = GPG_ERR_SEXP_BAD_CHARACTER; | 1341 | err = GPG_ERR_SEXP_BAD_CHARACTER; |
1342 | } | 1342 | } |
1343 | } | 1343 | } |
1344 | MAKE_SPACE (0); | 1344 | MAKE_SPACE (0); |
1345 | *c.pos++ = ST_STOP; | 1345 | *c.pos++ = ST_STOP; |
1346 | 1346 | ||
1347 | if (level) | 1347 | if (level) |
1348 | err = GPG_ERR_SEXP_UNMATCHED_PAREN; | 1348 | err = GPG_ERR_SEXP_UNMATCHED_PAREN; |
1349 | 1349 | ||
1350 | if (err) | 1350 | if (err) |
1351 | { | 1351 | { |
1352 | /* Error -> deallocate. */ | 1352 | /* Error -> deallocate. */ |
1353 | if (c.sexp) | 1353 | if (c.sexp) |
1354 | { | 1354 | { |
1355 | /* Extra paranoid wipe on error. */ | 1355 | /* Extra paranoid wipe on error. */ |
1356 | if (gcry_is_secure (c.sexp)) | 1356 | if (gcry_is_secure (c.sexp)) |
1357 | wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1); | 1357 | wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1); |
1358 | gcry_free (c.sexp); | 1358 | gcry_free (c.sexp); |
1359 | } | 1359 | } |
1360 | /* This might be expected by existing code... */ | 1360 | /* This might be expected by existing code... */ |
1361 | *retsexp = NULL; | 1361 | *retsexp = NULL; |
1362 | } | 1362 | } |
1363 | else | 1363 | else |
1364 | *retsexp = normalize (c.sexp); | 1364 | *retsexp = normalize (c.sexp); |
1365 | 1365 | ||
1366 | return gcry_error (err); | 1366 | return gcry_error (err); |
1367 | #undef MAKE_SPACE | 1367 | #undef MAKE_SPACE |
1368 | #undef STORE_LEN | 1368 | #undef STORE_LEN |
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | gcry_error_t | 1371 | gcry_error_t |
1372 | gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...) | 1372 | gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...) |
1373 | { | 1373 | { |
1374 | gcry_error_t rc; | 1374 | gcry_error_t rc; |
1375 | va_list arg_ptr; | 1375 | va_list arg_ptr; |
1376 | 1376 | ||
1377 | va_start (arg_ptr, format); | 1377 | va_start (arg_ptr, format); |
1378 | rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1, | 1378 | rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1, |
1379 | arg_ptr, NULL); | 1379 | arg_ptr, NULL); |
1380 | va_end (arg_ptr); | 1380 | va_end (arg_ptr); |
1381 | 1381 | ||
1382 | return rc; | 1382 | return rc; |
1383 | } | 1383 | } |
1384 | 1384 | ||
1385 | /* Like gcry_sexp_build, but uses an array instead of variable | 1385 | /* Like gcry_sexp_build, but uses an array instead of variable |
1386 | function arguments. */ | 1386 | function arguments. */ |
1387 | gcry_error_t | 1387 | gcry_error_t |
1388 | gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff, | 1388 | gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff, |
1389 | const char *format, void **arg_list) | 1389 | const char *format, void **arg_list) |
1390 | { | 1390 | { |
1391 | /* We don't need the va_list because it is controlled by the | 1391 | /* We don't need the va_list because it is controlled by the |
1392 | following flag, however we have to pass it but can't initialize | 1392 | following flag, however we have to pass it but can't initialize |
1393 | it as there is no portable way to do so. volatile is needed to | 1393 | it as there is no portable way to do so. volatile is needed to |
1394 | suppress the compiler warning */ | 1394 | suppress the compiler warning */ |
1395 | volatile va_list dummy_arg_ptr = NULL; | 1395 | volatile va_list dummy_arg_ptr = NULL; |
1396 | 1396 | ||
1397 | gcry_error_t rc; | 1397 | gcry_error_t rc; |
1398 | 1398 | ||
1399 | rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1, | 1399 | rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1, |
1400 | dummy_arg_ptr, arg_list); | 1400 | dummy_arg_ptr, arg_list); |
1401 | 1401 | ||
1402 | return rc; | 1402 | return rc; |
1403 | } | 1403 | } |
1404 | 1404 | ||
1405 | gcry_error_t | 1405 | gcry_error_t |
1406 | gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, | 1406 | gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, |
1407 | const char *buffer, size_t length) | 1407 | const char *buffer, size_t length) |
1408 | { | 1408 | { |
1409 | /* We don't need the va_list because it is controlled by the | 1409 | /* We don't need the va_list because it is controlled by the |
1410 | following flag, however we have to pass it but can't initialize | 1410 | following flag, however we have to pass it but can't initialize |
1411 | it as there is no portable way to do so. volatile is needed to | 1411 | it as there is no portable way to do so. volatile is needed to |
1412 | suppress the compiler warning */ | 1412 | suppress the compiler warning */ |
1413 | volatile va_list dummy_arg_ptr = NULL; | 1413 | volatile va_list dummy_arg_ptr = NULL; |
1414 | 1414 | ||
1415 | return sexp_sscan (retsexp, erroff, buffer, length, 0, | 1415 | return sexp_sscan (retsexp, erroff, buffer, length, 0, |
1416 | dummy_arg_ptr, NULL); | 1416 | dummy_arg_ptr, NULL); |
1417 | } | 1417 | } |
1418 | 1418 | ||
1419 | 1419 | ||
1420 | /* Figure out a suitable encoding for BUFFER of LENGTH. | 1420 | /* Figure out a suitable encoding for BUFFER of LENGTH. |
1421 | Returns: 0 = Binary | 1421 | Returns: 0 = Binary |
1422 | 1 = String possible | 1422 | 1 = String possible |
1423 | 2 = Token possible | 1423 | 2 = Token possible |
1424 | */ | 1424 | */ |
1425 | static int | 1425 | static int |
1426 | suitable_encoding (const unsigned char *buffer, size_t length) | 1426 | suitable_encoding (const unsigned char *buffer, size_t length) |
1427 | { | 1427 | { |
1428 | const unsigned char *s; | 1428 | const unsigned char *s; |
1429 | int maybe_token = 1; | 1429 | int maybe_token = 1; |
1430 | 1430 | ||
1431 | if (!length) | 1431 | if (!length) |
1432 | return 1; | 1432 | return 1; |
1433 | 1433 | ||
1434 | for (s=buffer; length; s++, length--) | 1434 | for (s=buffer; length; s++, length--) |
1435 | { | 1435 | { |
1436 | if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)) | 1436 | if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)) |
1437 | && !strchr ("\b\t\v\n\f\r\"\'\\", *s)) | 1437 | && !strchr ("\b\t\v\n\f\r\"\'\\", *s)) |
1438 | return 0; /*binary*/ | 1438 | return 0; /*binary*/ |
1439 | if ( maybe_token | 1439 | if ( maybe_token |
1440 | && !alphap (s) && !digitp (s) && !strchr (TOKEN_SPECIALS, *s)) | 1440 | && !alphap (s) && !digitp (s) && !strchr (TOKEN_SPECIALS, *s)) |
1441 | maybe_token = 0; | 1441 | maybe_token = 0; |
1442 | } | 1442 | } |
1443 | s = buffer; | 1443 | s = buffer; |
1444 | if ( maybe_token && !digitp (s) ) | 1444 | if ( maybe_token && !digitp (s) ) |
1445 | return 2; | 1445 | return 2; |
1446 | return 1; | 1446 | return 1; |
1447 | } | 1447 | } |
1448 | 1448 | ||
1449 | 1449 | ||
1450 | static int | 1450 | static int |
1451 | convert_to_hex (const unsigned char *src, size_t len, unsigned char *dest) | 1451 | convert_to_hex (const unsigned char *src, size_t len, unsigned char *dest) |
1452 | { | 1452 | { |
1453 | int i; | 1453 | int i; |
1454 | 1454 | ||
1455 | if (dest) | 1455 | if (dest) |
1456 | { | 1456 | { |
1457 | *dest++ = '#'; | 1457 | *dest++ = '#'; |
1458 | for (i=0; i < len; i++, dest += 2 ) | 1458 | for (i=0; i < len; i++, dest += 2 ) |
1459 | sprintf ((char*)dest, "%02X", src[i]); | 1459 | sprintf ((char*)dest, "%02X", src[i]); |
1460 | *dest++ = '#'; | 1460 | *dest++ = '#'; |
1461 | } | 1461 | } |
1462 | return len*2+2; | 1462 | return len*2+2; |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | static int | 1465 | static int |
1466 | convert_to_string (const unsigned char *s, size_t len, unsigned char *dest) | 1466 | convert_to_string (const unsigned char *s, size_t len, unsigned char *dest) |
1467 | { | 1467 | { |
1468 | if (dest) | 1468 | if (dest) |
1469 | { | 1469 | { |
1470 | unsigned char *p = dest; | 1470 | unsigned char *p = dest; |
1471 | *p++ = '\"'; | 1471 | *p++ = '\"'; |
1472 | for (; len; len--, s++ ) | 1472 | for (; len; len--, s++ ) |
1473 | { | 1473 | { |
1474 | switch (*s) | 1474 | switch (*s) |
1475 | { | 1475 | { |
1476 | case '\b': *p++ = '\\'; *p++ = 'b'; break; | 1476 | case '\b': *p++ = '\\'; *p++ = 'b'; break; |
1477 | case '\t': *p++ = '\\'; *p++ = 't'; break; | 1477 | case '\t': *p++ = '\\'; *p++ = 't'; break; |
1478 | case '\v': *p++ = '\\'; *p++ = 'v'; break; | 1478 | case '\v': *p++ = '\\'; *p++ = 'v'; break; |
1479 | case '\n': *p++ = '\\'; *p++ = 'n'; break; | 1479 | case '\n': *p++ = '\\'; *p++ = 'n'; break; |
1480 | case '\f': *p++ = '\\'; *p++ = 'f'; break; | 1480 | case '\f': *p++ = '\\'; *p++ = 'f'; break; |
1481 | case '\r': *p++ = '\\'; *p++ = 'r'; break; | 1481 | case '\r': *p++ = '\\'; *p++ = 'r'; break; |
1482 | case '\"': *p++ = '\\'; *p++ = '\"'; break; | 1482 | case '\"': *p++ = '\\'; *p++ = '\"'; break; |
1483 | case '\'': *p++ = '\\'; *p++ = '\''; break; | 1483 | case '\'': *p++ = '\\'; *p++ = '\''; break; |
1484 | case '\\': *p++ = '\\'; *p++ = '\\'; break; | 1484 | case '\\': *p++ = '\\'; *p++ = '\\'; break; |
1485 | default: | 1485 | default: |
1486 | if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))) | 1486 | if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))) |
1487 | { | 1487 | { |
1488 | sprintf ((char*)p, "\\x%02x", *s); | 1488 | sprintf ((char*)p, "\\x%02x", *s); |
1489 | p += 4; | 1489 | p += 4; |
1490 | } | 1490 | } |
1491 | else | 1491 | else |
1492 | *p++ = *s; | 1492 | *p++ = *s; |
1493 | } | 1493 | } |
1494 | } | 1494 | } |
1495 | *p++ = '\"'; | 1495 | *p++ = '\"'; |
1496 | return p - dest; | 1496 | return p - dest; |
1497 | } | 1497 | } |
1498 | else | 1498 | else |
1499 | { | 1499 | { |
1500 | int count = 2; | 1500 | int count = 2; |
1501 | for (; len; len--, s++ ) | 1501 | for (; len; len--, s++ ) |
1502 | { | 1502 | { |
1503 | switch (*s) | 1503 | switch (*s) |
1504 | { | 1504 | { |
1505 | case '\b': | 1505 | case '\b': |
1506 | case '\t': | 1506 | case '\t': |
1507 | case '\v': | 1507 | case '\v': |
1508 | case '\n': | 1508 | case '\n': |
1509 | case '\f': | 1509 | case '\f': |
1510 | case '\r': | 1510 | case '\r': |
1511 | case '\"': | 1511 | case '\"': |
1512 | case '\'': | 1512 | case '\'': |
1513 | case '\\': count += 2; break; | 1513 | case '\\': count += 2; break; |
1514 | default: | 1514 | default: |
1515 | if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))) | 1515 | if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))) |
1516 | count += 4; | 1516 | count += 4; |
1517 | else | 1517 | else |
1518 | count++; | 1518 | count++; |
1519 | } | 1519 | } |
1520 | } | 1520 | } |
1521 | return count; | 1521 | return count; |
1522 | } | 1522 | } |
1523 | } | 1523 | } |
1524 | 1524 | ||
1525 | 1525 | ||
1526 | 1526 | ||
1527 | static int | 1527 | static int |
1528 | convert_to_token (const unsigned char *src, size_t len, unsigned char *dest) | 1528 | convert_to_token (const unsigned char *src, size_t len, unsigned char *dest) |
1529 | { | 1529 | { |
1530 | if (dest) | 1530 | if (dest) |
1531 | memcpy (dest, src, len); | 1531 | memcpy (dest, src, len); |
1532 | return len; | 1532 | return len; |
1533 | } | 1533 | } |
1534 | 1534 | ||
1535 | 1535 | ||
1536 | /**************** | 1536 | /**************** |
1537 | * Print SEXP to buffer using the MODE. Returns the length of the | 1537 | * Print SEXP to buffer using the MODE. Returns the length of the |
1538 | * SEXP in buffer or 0 if the buffer is too short (We have at least an | 1538 | * SEXP in buffer or 0 if the buffer is too short (We have at least an |
1539 | * empty list consisting of 2 bytes). If a buffer of NULL is provided, | 1539 | * empty list consisting of 2 bytes). If a buffer of NULL is provided, |
1540 | * the required length is returned. | 1540 | * the required length is returned. |
1541 | */ | 1541 | */ |
1542 | size_t | 1542 | size_t |
1543 | gcry_sexp_sprint (const gcry_sexp_t list, int mode, | 1543 | gcry_sexp_sprint (const gcry_sexp_t list, int mode, |
1544 | void *buffer, size_t maxlength) | 1544 | void *buffer, size_t maxlength) |
1545 | { | 1545 | { |
1546 | static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP }; | 1546 | static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP }; |
1547 | const unsigned char *s; | 1547 | const unsigned char *s; |
1548 | char *d; | 1548 | char *d; |
1549 | DATALEN n; | 1549 | DATALEN n; |
1550 | char numbuf[20]; | 1550 | char numbuf[20]; |
1551 | size_t len = 0; | 1551 | size_t len = 0; |
1552 | int i, indent = 0; | 1552 | int i, indent = 0; |
1553 | 1553 | ||
1554 | s = list? list->d : empty; | 1554 | s = list? list->d : empty; |
1555 | d = buffer; | 1555 | d = buffer; |
1556 | while ( *s != ST_STOP ) | 1556 | while ( *s != ST_STOP ) |
1557 | { | 1557 | { |
1558 | switch ( *s ) | 1558 | switch ( *s ) |
1559 | { | 1559 | { |
1560 | case ST_OPEN: | 1560 | case ST_OPEN: |
1561 | s++; | 1561 | s++; |
1562 | if ( mode != GCRYSEXP_FMT_CANON ) | 1562 | if ( mode != GCRYSEXP_FMT_CANON ) |
1563 | { | 1563 | { |
1564 | if (indent) | 1564 | if (indent) |
1565 | len++; | 1565 | len++; |
1566 | len += indent; | 1566 | len += indent; |
1567 | } | 1567 | } |
1568 | len++; | 1568 | len++; |
1569 | if ( buffer ) | 1569 | if ( buffer ) |
1570 | { | 1570 | { |
1571 | if ( len >= maxlength ) | 1571 | if ( len >= maxlength ) |
1572 | return 0; | 1572 | return 0; |
1573 | if ( mode != GCRYSEXP_FMT_CANON ) | 1573 | if ( mode != GCRYSEXP_FMT_CANON ) |
1574 | { | 1574 | { |
1575 | if (indent) | 1575 | if (indent) |
1576 | *d++ = '\n'; | 1576 | *d++ = '\n'; |
1577 | for (i=0; i < indent; i++) | 1577 | for (i=0; i < indent; i++) |
1578 | *d++ = ' '; | 1578 | *d++ = ' '; |
1579 | } | 1579 | } |
1580 | *d++ = '('; | 1580 | *d++ = '('; |
1581 | } | 1581 | } |
1582 | indent++; | 1582 | indent++; |
1583 | break; | 1583 | break; |
1584 | case ST_CLOSE: | 1584 | case ST_CLOSE: |
1585 | s++; | 1585 | s++; |
1586 | len++; | 1586 | len++; |
1587 | if ( buffer ) | 1587 | if ( buffer ) |
1588 | { | 1588 | { |
1589 | if ( len >= maxlength ) | 1589 | if ( len >= maxlength ) |
1590 | return 0; | 1590 | return 0; |
1591 | *d++ = ')'; | 1591 | *d++ = ')'; |
1592 | } | 1592 | } |
1593 | indent--; | 1593 | indent--; |
1594 | if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON) | 1594 | if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON) |
1595 | { | 1595 | { |
1596 | len++; | 1596 | len++; |
1597 | len += indent; | 1597 | len += indent; |
1598 | if (buffer) | 1598 | if (buffer) |
1599 | { | 1599 | { |
1600 | if (len >= maxlength) | 1600 | if (len >= maxlength) |
1601 | return 0; | 1601 | return 0; |
1602 | *d++ = '\n'; | 1602 | *d++ = '\n'; |
1603 | for (i=0; i < indent; i++) | 1603 | for (i=0; i < indent; i++) |
1604 | *d++ = ' '; | 1604 | *d++ = ' '; |
1605 | } | 1605 | } |
1606 | } | 1606 | } |
1607 | break; | 1607 | break; |
1608 | case ST_DATA: | 1608 | case ST_DATA: |
1609 | s++; | 1609 | s++; |
1610 | memcpy ( &n, s, sizeof n ); s += sizeof n; | 1610 | memcpy ( &n, s, sizeof n ); s += sizeof n; |
1611 | if (mode == GCRYSEXP_FMT_ADVANCED) | 1611 | if (mode == GCRYSEXP_FMT_ADVANCED) |
1612 | { | 1612 | { |
1613 | int type; | 1613 | int type; |
1614 | size_t nn; | 1614 | size_t nn; |
1615 | 1615 | ||
1616 | switch ( (type=suitable_encoding (s, n))) | 1616 | switch ( (type=suitable_encoding (s, n))) |
1617 | { | 1617 | { |
1618 | case 1: nn = convert_to_string (s, n, NULL); break; | 1618 | case 1: nn = convert_to_string (s, n, NULL); break; |
1619 | case 2: nn = convert_to_token (s, n, NULL); break; | 1619 | case 2: nn = convert_to_token (s, n, NULL); break; |
1620 | default: nn = convert_to_hex (s, n, NULL); break; | 1620 | default: nn = convert_to_hex (s, n, NULL); break; |
1621 | } | 1621 | } |
1622 | len += nn; | 1622 | len += nn; |
1623 | if (buffer) | 1623 | if (buffer) |
1624 | { | 1624 | { |
1625 | if (len >= maxlength) | 1625 | if (len >= maxlength) |
1626 | return 0; | 1626 | return 0; |
1627 | switch (type) | 1627 | switch (type) |
1628 | { | 1628 | { |
1629 | case 1: convert_to_string (s, n, (unsigned char*)d); break; | 1629 | case 1: convert_to_string (s, n, (unsigned char*)d); break; |
1630 | case 2: convert_to_token (s, n, (unsigned char*)d); break; | 1630 | case 2: convert_to_token (s, n, (unsigned char*)d); break; |
1631 | default: convert_to_hex (s, n, (unsigned char*)d); break; | 1631 | default: convert_to_hex (s, n, (unsigned char*)d); break; |
1632 | } | 1632 | } |
1633 | d += nn; | 1633 | d += nn; |
1634 | } | 1634 | } |
1635 | if (s[n] != ST_CLOSE) | 1635 | if (s[n] != ST_CLOSE) |
1636 | { | 1636 | { |
1637 | len++; | 1637 | len++; |
1638 | if (buffer) | 1638 | if (buffer) |
1639 | { | 1639 | { |
1640 | if (len >= maxlength) | 1640 | if (len >= maxlength) |
1641 | return 0; | 1641 | return 0; |
1642 | *d++ = ' '; | 1642 | *d++ = ' '; |
1643 | } | 1643 | } |
1644 | } | 1644 | } |
1645 | } | 1645 | } |
1646 | else | 1646 | else |
1647 | { | 1647 | { |
1648 | sprintf (numbuf, "%u:", (unsigned int)n ); | 1648 | sprintf (numbuf, "%u:", (unsigned int)n ); |
1649 | len += strlen (numbuf) + n; | 1649 | len += strlen (numbuf) + n; |
1650 | if ( buffer ) | 1650 | if ( buffer ) |
1651 | { | 1651 | { |
1652 | if ( len >= maxlength ) | 1652 | if ( len >= maxlength ) |
1653 | return 0; | 1653 | return 0; |
1654 | d = stpcpy ( d, numbuf ); | 1654 | d = stpcpy ( d, numbuf ); |
1655 | memcpy ( d, s, n ); d += n; | 1655 | memcpy ( d, s, n ); d += n; |
1656 | } | 1656 | } |
1657 | } | 1657 | } |
1658 | s += n; | 1658 | s += n; |
1659 | break; | 1659 | break; |
1660 | default: | 1660 | default: |
1661 | BUG (); | 1661 | BUG (); |
1662 | } | 1662 | } |
1663 | } | 1663 | } |
1664 | if ( mode != GCRYSEXP_FMT_CANON ) | 1664 | if ( mode != GCRYSEXP_FMT_CANON ) |
1665 | { | 1665 | { |
1666 | len++; | 1666 | len++; |
1667 | if (buffer) | 1667 | if (buffer) |
1668 | { | 1668 | { |
1669 | if ( len >= maxlength ) | 1669 | if ( len >= maxlength ) |
1670 | return 0; | 1670 | return 0; |
1671 | *d++ = '\n'; | 1671 | *d++ = '\n'; |
1672 | } | 1672 | } |
1673 | } | 1673 | } |
1674 | if (buffer) | 1674 | if (buffer) |
1675 | { | 1675 | { |
1676 | if ( len >= maxlength ) | 1676 | if ( len >= maxlength ) |
1677 | return 0; | 1677 | return 0; |
1678 | *d++ = 0; /* for convenience we make a C string */ | 1678 | *d++ = 0; /* for convenience we make a C string */ |
1679 | } | 1679 | } |
1680 | else | 1680 | else |
1681 | len++; /* we need one byte more for this */ | 1681 | len++; /* we need one byte more for this */ |
1682 | 1682 | ||
1683 | return len; | 1683 | return len; |
1684 | } | 1684 | } |
1685 | 1685 | ||
1686 | 1686 | ||
1687 | /* Scan a cannocial encoded buffer with implicit length values and | 1687 | /* Scan a cannocial encoded buffer with implicit length values and |
1688 | return the actual length this S-expression uses. For a valid S-Exp | 1688 | return the actual length this S-expression uses. For a valid S-Exp |
1689 | it should never return 0. If LENGTH is not zero, the maximum | 1689 | it should never return 0. If LENGTH is not zero, the maximum |
1690 | length to scan is given - this can be used for syntax checks of | 1690 | length to scan is given - this can be used for syntax checks of |
1691 | data passed from outside. errorcode and erroff may both be passed as | 1691 | data passed from outside. errorcode and erroff may both be passed as |
1692 | NULL. */ | 1692 | NULL. */ |
1693 | size_t | 1693 | size_t |
1694 | gcry_sexp_canon_len (const unsigned char *buffer, size_t length, | 1694 | gcry_sexp_canon_len (const unsigned char *buffer, size_t length, |
1695 | size_t *erroff, gcry_error_t *errcode) | 1695 | size_t *erroff, gcry_error_t *errcode) |
1696 | { | 1696 | { |
1697 | const unsigned char *p; | 1697 | const unsigned char *p; |
1698 | const char *disphint=NULL; | 1698 | const char *disphint=NULL; |
1699 | unsigned int datalen = 0; | 1699 | unsigned int datalen = 0; |
1700 | size_t dummy_erroff; | 1700 | size_t dummy_erroff; |
1701 | gcry_error_t dummy_errcode; | 1701 | gcry_error_t dummy_errcode; |
1702 | size_t count = 0; | 1702 | size_t count = 0; |
1703 | int level = 0; | 1703 | int level = 0; |
1704 | 1704 | ||
1705 | if (!erroff) | 1705 | if (!erroff) |
1706 | erroff = &dummy_erroff; | 1706 | erroff = &dummy_erroff; |
1707 | if (!errcode) | 1707 | if (!errcode) |
1708 | errcode = &dummy_errcode; | 1708 | errcode = &dummy_errcode; |
1709 | 1709 | ||
1710 | *errcode = gcry_error (GPG_ERR_NO_ERROR); | 1710 | *errcode = gcry_error (GPG_ERR_NO_ERROR); |
1711 | *erroff = 0; | 1711 | *erroff = 0; |
1712 | if (!buffer) | 1712 | if (!buffer) |
1713 | return 0; | 1713 | return 0; |
1714 | if (*buffer != '(') | 1714 | if (*buffer != '(') |
1715 | { | 1715 | { |
1716 | *errcode = gcry_error (GPG_ERR_SEXP_NOT_CANONICAL); | 1716 | *errcode = gcry_error (GPG_ERR_SEXP_NOT_CANONICAL); |
1717 | return 0; | 1717 | return 0; |
1718 | } | 1718 | } |
1719 | 1719 | ||
1720 | for (p=buffer; ; p++, count++ ) | 1720 | for (p=buffer; ; p++, count++ ) |
1721 | { | 1721 | { |
1722 | if (length && count >= length) | 1722 | if (length && count >= length) |
1723 | { | 1723 | { |
1724 | *erroff = count; | 1724 | *erroff = count; |
1725 | *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG); | 1725 | *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG); |
1726 | return 0; | 1726 | return 0; |
1727 | } | 1727 | } |
1728 | 1728 | ||
1729 | if (datalen) | 1729 | if (datalen) |
1730 | { | 1730 | { |
1731 | if (*p == ':') | 1731 | if (*p == ':') |
1732 | { | 1732 | { |
1733 | if (length && (count+datalen) >= length) | 1733 | if (length && (count+datalen) >= length) |
1734 | { | 1734 | { |
1735 | *erroff = count; | 1735 | *erroff = count; |
1736 | *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG); | 1736 | *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG); |
1737 | return 0; | 1737 | return 0; |
1738 | } | 1738 | } |
1739 | count += datalen; | 1739 | count += datalen; |
1740 | p += datalen; | 1740 | p += datalen; |
1741 | datalen = 0; | 1741 | datalen = 0; |
1742 | } | 1742 | } |
1743 | else if (digitp(p)) | 1743 | else if (digitp(p)) |
1744 | datalen = datalen*10 + atoi_1(p); | 1744 | datalen = datalen*10 + atoi_1(p); |
1745 | else | 1745 | else |
1746 | { | 1746 | { |
1747 | *erroff = count; | 1747 | *erroff = count; |
1748 | *errcode = gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC); | 1748 | *errcode = gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC); |
1749 | return 0; | 1749 | return 0; |
1750 | } | 1750 | } |
1751 | } | 1751 | } |
1752 | else if (*p == '(') | 1752 | else if (*p == '(') |
1753 | { | 1753 | { |
1754 | if (disphint) | 1754 | if (disphint) |
1755 | { | 1755 | { |
1756 | *erroff = count; | 1756 | *erroff = count; |
1757 | *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); | 1757 | *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); |
1758 | return 0; | 1758 | return 0; |
1759 | } | 1759 | } |
1760 | level++; | 1760 | level++; |
1761 | } | 1761 | } |
1762 | else if (*p == ')') | 1762 | else if (*p == ')') |
1763 | { /* walk up */ | 1763 | { /* walk up */ |
1764 | if (!level) | 1764 | if (!level) |
1765 | { | 1765 | { |
1766 | *erroff = count; | 1766 | *erroff = count; |
1767 | *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN); | 1767 | *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN); |
1768 | return 0; | 1768 | return 0; |
1769 | } | 1769 | } |
1770 | if (disphint) | 1770 | if (disphint) |
1771 | { | 1771 | { |
1772 | *erroff = count; | 1772 | *erroff = count; |
1773 | *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); | 1773 | *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); |
1774 | return 0; | 1774 | return 0; |
1775 | } | 1775 | } |
1776 | if (!--level) | 1776 | if (!--level) |
1777 | return ++count; /* ready */ | 1777 | return ++count; /* ready */ |
1778 | } | 1778 | } |
1779 | else if (*p == '[') | 1779 | else if (*p == '[') |
1780 | { | 1780 | { |
1781 | if (disphint) | 1781 | if (disphint) |
1782 | { | 1782 | { |
1783 | *erroff = count; | 1783 | *erroff = count; |
1784 | *errcode = gcry_error (GPG_ERR_SEXP_NESTED_DH); | 1784 | *errcode = gcry_error (GPG_ERR_SEXP_NESTED_DH); |
1785 | return 0; | 1785 | return 0; |
1786 | } | 1786 | } |
1787 | disphint = (const char*)p; | 1787 | disphint = (const char*)p; |
1788 | } | 1788 | } |
1789 | else if (*p == ']') | 1789 | else if (*p == ']') |
1790 | { | 1790 | { |
1791 | if( !disphint ) | 1791 | if( !disphint ) |
1792 | { | 1792 | { |
1793 | *erroff = count; | 1793 | *erroff = count; |
1794 | *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); | 1794 | *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); |
1795 | return 0; | 1795 | return 0; |
1796 | } | 1796 | } |
1797 | disphint = NULL; | 1797 | disphint = NULL; |
1798 | } | 1798 | } |
1799 | else if (digitp (p) ) | 1799 | else if (digitp (p) ) |
1800 | { | 1800 | { |
1801 | if (*p == '0') | 1801 | if (*p == '0') |
1802 | { | 1802 | { |
1803 | *erroff = count; | 1803 | *erroff = count; |
1804 | *errcode = gcry_error (GPG_ERR_SEXP_ZERO_PREFIX); | 1804 | *errcode = gcry_error (GPG_ERR_SEXP_ZERO_PREFIX); |
1805 | return 0; | 1805 | return 0; |
1806 | } | 1806 | } |
1807 | datalen = atoi_1 (p); | 1807 | datalen = atoi_1 (p); |
1808 | } | 1808 | } |
1809 | else if (*p == '&' || *p == '\\') | 1809 | else if (*p == '&' || *p == '\\') |
1810 | { | 1810 | { |
1811 | *erroff = count; | 1811 | *erroff = count; |
1812 | *errcode = gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC); | 1812 | *errcode = gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC); |
1813 | return 0; | 1813 | return 0; |
1814 | } | 1814 | } |
1815 | else | 1815 | else |
1816 | { | 1816 | { |
1817 | *erroff = count; | 1817 | *erroff = count; |
1818 | *errcode = gcry_error (GPG_ERR_SEXP_BAD_CHARACTER); | 1818 | *errcode = gcry_error (GPG_ERR_SEXP_BAD_CHARACTER); |
1819 | return 0; | 1819 | return 0; |
1820 | } | 1820 | } |
1821 | } | 1821 | } |
1822 | } | 1822 | } |