Line data Source code
1 : /* t-sexp.c - S-expression regression tests
2 : * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
3 : * Copyright (C) 2014 g10 Code GmbH
4 : *
5 : * This file is part of Libgcrypt.
6 : *
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
9 : * published by the Free Software Foundation; either version 2.1 of
10 : * the License, or (at your option) any later version.
11 : *
12 : * Libgcrypt is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU Lesser General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU Lesser General Public
18 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif
24 : #include <stdio.h>
25 : #include <stdlib.h>
26 : #include <string.h>
27 : #include <stdarg.h>
28 : #include <assert.h>
29 : #include "../src/gcrypt-int.h"
30 :
31 : #define PGMNAME "t-sexp"
32 : #include "t-common.h"
33 :
34 :
35 : /* Convert STRING consisting of hex characters into its binary
36 : representation and return it as an allocated buffer. The valid
37 : length of the buffer is returned at R_LENGTH. The string is
38 : delimited by end of string. The function returns NULL on
39 : error. */
40 : static void *
41 8 : hex2buffer (const char *string, size_t *r_length)
42 : {
43 : const char *s;
44 : unsigned char *buffer;
45 : size_t length;
46 :
47 8 : buffer = xmalloc (strlen(string)/2+1);
48 8 : length = 0;
49 266 : for (s=string; *s; s +=2 )
50 : {
51 258 : if (!hexdigitp (s) || !hexdigitp (s+1))
52 0 : return NULL; /* Invalid hex digits. */
53 258 : ((unsigned char*)buffer)[length++] = xtoi_2 (s);
54 : }
55 8 : *r_length = length;
56 8 : return buffer;
57 : }
58 :
59 :
60 : static gcry_mpi_t
61 55 : hex2mpi (const char *string)
62 : {
63 : gpg_error_t err;
64 : gcry_mpi_t val;
65 :
66 55 : err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
67 55 : if (err)
68 0 : die ("hex2mpi '%s' failed: %s\n", string, gpg_strerror (err));
69 55 : return val;
70 : }
71 :
72 : static gcry_mpi_t
73 5 : hex2mpiopa (const char *string)
74 : {
75 : char *buffer;
76 : size_t buflen;
77 : gcry_mpi_t val;
78 :
79 5 : buffer = hex2buffer (string, &buflen);
80 5 : if (!buffer)
81 0 : die ("hex2mpiopa '%s' failed: parser error\n", string);
82 5 : val = gcry_mpi_set_opaque (NULL, buffer, buflen*8);
83 5 : if (!buffer)
84 0 : die ("hex2mpiopa '%s' failed: set_opaque error%s\n", string);
85 5 : return val;
86 : }
87 :
88 :
89 : /* Compare A to B, where B is given as a hex string. */
90 : static int
91 60 : cmp_mpihex (gcry_mpi_t a, const char *b)
92 : {
93 : gcry_mpi_t bval;
94 : int res;
95 :
96 60 : if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
97 5 : bval = hex2mpiopa (b);
98 : else
99 55 : bval = hex2mpi (b);
100 60 : res = gcry_mpi_cmp (a, bval);
101 60 : gcry_mpi_release (bval);
102 60 : return res;
103 : }
104 :
105 : /* Compare A to B, where A is a buffer and B a hex string. */
106 : static int
107 3 : cmp_bufhex (const void *a, size_t alen, const char *b)
108 : {
109 : void *bbuf;
110 : size_t blen;
111 : int res;
112 :
113 3 : if (!a && !b)
114 0 : return 0;
115 3 : if (a && !b)
116 0 : return 1;
117 3 : if (!a && b)
118 0 : return -1;
119 :
120 3 : bbuf = hex2buffer (b, &blen);
121 3 : if (!bbuf)
122 0 : die ("cmp_bufhex: error converting hex string\n");
123 3 : if (alen != blen)
124 0 : return alen < blen? -1 : 1;
125 3 : res = memcmp (a, bbuf, alen);
126 3 : xfree (bbuf);
127 3 : return res;
128 : }
129 :
130 :
131 :
132 : /* fixme: we need better tests */
133 : static void
134 1 : basic (void)
135 : {
136 : int pass;
137 : gcry_sexp_t sexp;
138 : int idx;
139 : char *secure_buffer;
140 : size_t secure_buffer_len;
141 : const char *string;
142 : static struct {
143 : const char *token;
144 : const char *parm;
145 : } values[] = {
146 : { "public-key", NULL },
147 : { "dsa", NULL },
148 : { "dsa", "p" },
149 : { "dsa", "y" },
150 : { "dsa", "q" },
151 : { "dsa", "g" },
152 : { NULL }
153 : };
154 :
155 1 : info ("doing some pretty pointless tests\n");
156 :
157 1 : secure_buffer_len = 99;
158 1 : secure_buffer = gcry_xmalloc_secure (secure_buffer_len);
159 1 : memset (secure_buffer, 'G', secure_buffer_len);
160 :
161 5 : for (pass=0;;pass++)
162 : {
163 : gcry_mpi_t m;
164 :
165 5 : switch (pass)
166 : {
167 : case 0:
168 1 : string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
169 : "(q #61626364656667#) (g %m)))");
170 :
171 1 : m = gcry_mpi_set_ui (NULL, 42);
172 1 : if ( gcry_sexp_build (&sexp, NULL, string, m ) )
173 : {
174 0 : gcry_mpi_release (m);
175 0 : fail (" scanning `%s' failed\n", string);
176 0 : return;
177 : }
178 1 : gcry_mpi_release (m);
179 1 : break;
180 :
181 : case 1:
182 1 : string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
183 : "(q %b) (g %m)))");
184 :
185 1 : m = gcry_mpi_set_ui (NULL, 42);
186 1 : if ( gcry_sexp_build (&sexp, NULL, string,
187 : 15, "foo\0\x01\0x02789012345", m) )
188 : {
189 0 : gcry_mpi_release (m);
190 0 : fail (" scanning `%s' failed\n", string);
191 0 : return;
192 : }
193 1 : gcry_mpi_release (m);
194 1 : break;
195 :
196 : case 2:
197 1 : string = ("(public-key (dsa (p #41424344#) (y silly_y_value) "
198 : "(q %b) (g %m)))");
199 :
200 1 : m = gcry_mpi_set_ui (NULL, 17);
201 1 : if ( gcry_sexp_build (&sexp, NULL, string,
202 : secure_buffer_len, secure_buffer, m) )
203 : {
204 0 : gcry_mpi_release (m);
205 0 : fail (" scanning `%s' failed\n", string);
206 0 : return;
207 : }
208 1 : gcry_mpi_release (m);
209 1 : if (!gcry_is_secure (sexp))
210 0 : fail ("gcry_sexp_build did not switch to secure memory\n");
211 1 : break;
212 :
213 : case 3:
214 : {
215 : gcry_sexp_t help_sexp;
216 :
217 1 : if (gcry_sexp_new (&help_sexp,
218 : "(foobar-parms (xp #1234#)(xq #03#))", 0, 1))
219 : {
220 0 : fail (" scanning fixed string failed\n");
221 0 : return;
222 : }
223 :
224 1 : string = ("(public-key (dsa (p #41424344#) (parm %S) "
225 : "(y dummy)(q %b) (g %m)))");
226 1 : m = gcry_mpi_set_ui (NULL, 17);
227 1 : if ( gcry_sexp_build (&sexp, NULL, string, help_sexp,
228 : secure_buffer_len, secure_buffer, m) )
229 : {
230 0 : gcry_mpi_release (m);
231 0 : fail (" scanning `%s' failed\n", string);
232 0 : return;
233 : }
234 1 : gcry_mpi_release (m);
235 1 : gcry_sexp_release (help_sexp);
236 : }
237 1 : break;
238 :
239 :
240 : default:
241 1 : return; /* Ready. */
242 : }
243 :
244 :
245 : /* now find something */
246 28 : for (idx=0; values[idx].token; idx++)
247 : {
248 24 : const char *token = values[idx].token;
249 24 : const char *parm = values[idx].parm;
250 : gcry_sexp_t s1, s2;
251 : gcry_mpi_t a;
252 : const char *p;
253 : size_t n;
254 :
255 24 : s1 = gcry_sexp_find_token (sexp, token, strlen(token) );
256 24 : if (!s1)
257 : {
258 0 : fail ("didn't found `%s'\n", token);
259 0 : continue;
260 : }
261 :
262 24 : p = gcry_sexp_nth_data (s1, 0, &n);
263 24 : if (!p)
264 : {
265 0 : gcry_sexp_release (s1);
266 0 : fail ("no car for `%s'\n", token);
267 0 : continue;
268 : }
269 : /* info ("car=`%.*s'\n", (int)n, p); */
270 :
271 24 : s2 = gcry_sexp_cdr (s1);
272 24 : if (!s2)
273 : {
274 0 : gcry_sexp_release (s1);
275 0 : fail ("no cdr for `%s'\n", token);
276 0 : continue;
277 : }
278 :
279 24 : p = gcry_sexp_nth_data (s2, 0, &n);
280 24 : gcry_sexp_release (s2);
281 24 : if (p)
282 : {
283 0 : gcry_sexp_release (s1);
284 0 : fail ("data at car of `%s'\n", token);
285 0 : continue;
286 : }
287 :
288 24 : if (parm)
289 : {
290 16 : s2 = gcry_sexp_find_token (s1, parm, strlen (parm));
291 16 : gcry_sexp_release (s1);
292 16 : if (!s2)
293 : {
294 0 : fail ("didn't found `%s'\n", parm);
295 0 : continue;
296 : }
297 16 : p = gcry_sexp_nth_data (s2, 0, &n);
298 16 : if (!p)
299 : {
300 0 : gcry_sexp_release (s2);
301 0 : fail("no car for `%s'\n", parm );
302 0 : continue;
303 : }
304 : /* info ("car=`%.*s'\n", (int)n, p); */
305 16 : p = gcry_sexp_nth_data (s2, 1, &n);
306 16 : if (!p)
307 : {
308 0 : gcry_sexp_release (s2);
309 0 : fail("no cdr for `%s'\n", parm );
310 0 : continue;
311 : }
312 : /* info ("cdr=`%.*s'\n", (int)n, p); */
313 :
314 16 : a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG);
315 16 : gcry_sexp_release (s2);
316 16 : if (!a)
317 : {
318 0 : fail("failed to cdr the mpi for `%s'\n", parm);
319 0 : continue;
320 : }
321 16 : gcry_mpi_release (a);
322 : }
323 : else
324 8 : gcry_sexp_release (s1);
325 : }
326 :
327 4 : gcry_sexp_release (sexp);
328 4 : sexp = NULL;
329 4 : }
330 : gcry_free (secure_buffer);
331 : }
332 :
333 :
334 : static void
335 1 : canon_len (void)
336 : {
337 : static struct {
338 : size_t textlen; /* length of the buffer */
339 : size_t expected;/* expected length or 0 on error and then ... */
340 : size_t erroff; /* ... and at this offset */
341 : gcry_error_t errcode; /* ... with this error code */
342 : const char *text;
343 : } values[] = {
344 : { 14, 13, 0, GPG_ERR_NO_ERROR, "(9:abcdefghi) " },
345 : { 16, 15, 0, GPG_ERR_NO_ERROR, "(10:abcdefghix)" },
346 : { 14, 0,14, GPG_ERR_SEXP_STRING_TOO_LONG, "(10:abcdefghi)" },
347 : { 15, 0, 1, GPG_ERR_SEXP_ZERO_PREFIX, "(010:abcdefghi)" },
348 : { 2, 0, 0, GPG_ERR_SEXP_NOT_CANONICAL, "1:"},
349 : { 4, 0, 4, GPG_ERR_SEXP_STRING_TOO_LONG, "(1:)"},
350 : { 5, 5, 0, GPG_ERR_NO_ERROR, "(1:x)"},
351 : { 2, 2, 0, GPG_ERR_NO_ERROR, "()"},
352 : { 4, 2, 0, GPG_ERR_NO_ERROR, "()()"},
353 : { 4, 4, 0, GPG_ERR_NO_ERROR, "(())"},
354 : { 3, 0, 3, GPG_ERR_SEXP_STRING_TOO_LONG, "(()"},
355 : { 3, 0, 1, GPG_ERR_SEXP_BAD_CHARACTER, "( )"},
356 : { 9, 9, 0, GPG_ERR_NO_ERROR, "(3:abc())"},
357 : { 10, 0, 6, GPG_ERR_SEXP_BAD_CHARACTER, "(3:abc ())"},
358 : /* fixme: we need much more cases */
359 : { 0 },
360 : };
361 : int idx;
362 : gcry_error_t errcode;
363 : size_t n, erroff;
364 :
365 1 : info ("checking canoncial length test function\n");
366 15 : for (idx=0; values[idx].text; idx++)
367 : {
368 14 : n = gcry_sexp_canon_len ((const unsigned char*)values[idx].text,
369 : values[idx].textlen,
370 : &erroff, &errcode);
371 :
372 14 : if (n && n == values[idx].expected)
373 : ; /* success */
374 7 : else if (!n && !values[idx].expected)
375 : { /* we expected an error - check that this is the right one */
376 7 : if (values[idx].erroff != erroff)
377 0 : fail ("canonical length test %d - wrong error offset %u\n",
378 : idx, (unsigned int)erroff);
379 14 : if (gcry_err_code (errcode) != values[idx].errcode)
380 0 : fail ("canonical length test %d - wrong error code %d\n",
381 : idx, errcode);
382 : }
383 : else
384 0 : fail ("canonical length test %d failed - n=%u, off=%u, err=%d\n",
385 : idx, (unsigned int)n, (unsigned int)erroff, errcode);
386 : }
387 1 : }
388 :
389 :
390 : static void
391 3 : back_and_forth_one (int testno, const char *buffer, size_t length)
392 : {
393 : gcry_error_t rc;
394 : gcry_sexp_t se, se1;
395 : size_t n, n1;
396 : char *p1;
397 :
398 3 : rc = gcry_sexp_new (&se, buffer, length, 1);
399 3 : if (rc)
400 : {
401 0 : fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc));
402 0 : return;
403 : }
404 3 : n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
405 3 : if (!n1)
406 : {
407 0 : fail ("baf %d: get required length for canon failed\n", testno);
408 0 : return;
409 : }
410 3 : p1 = gcry_xmalloc (n1);
411 3 : n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
412 3 : if (n1 != n+1) /* sprints adds an extra 0 but dies not return it */
413 : {
414 0 : fail ("baf %d: length mismatch for canon\n", testno);
415 0 : return;
416 : }
417 3 : rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
418 3 : if (rc)
419 : {
420 0 : fail ("baf %d: gcry_sexp_create failed: %s\n",
421 : testno, gpg_strerror (rc));
422 0 : return;
423 : }
424 3 : gcry_sexp_release (se1);
425 :
426 : /* Again but with memory checking. */
427 3 : p1 = gcry_xmalloc (n1+2);
428 3 : *p1 = '\x55';
429 3 : p1[n1+1] = '\xaa';
430 3 : n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1);
431 3 : if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
432 : {
433 0 : fail ("baf %d: length mismatch for canon\n", testno);
434 0 : return;
435 : }
436 3 : if (*p1 != '\x55' || p1[n1+1] != '\xaa')
437 0 : fail ("baf %d: memory corrupted (1)\n", testno);
438 3 : rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL);
439 3 : if (rc)
440 : {
441 0 : fail ("baf %d: gcry_sexp_create failed: %s\n",
442 : testno, gpg_strerror (rc));
443 0 : return;
444 : }
445 3 : if (*p1 != '\x55' || p1[n1+1] != '\xaa')
446 0 : fail ("baf %d: memory corrupted (2)\n", testno);
447 3 : gcry_sexp_release (se1);
448 3 : if (*p1 != '\x55' || p1[n1+1] != '\xaa')
449 0 : fail ("baf %d: memory corrupted (3)\n", testno);
450 3 : gcry_free (p1);
451 :
452 : /* FIXME: we need a lot more tests */
453 :
454 3 : gcry_sexp_release (se);
455 : }
456 :
457 :
458 :
459 : static void
460 1 : back_and_forth (void)
461 : {
462 : static struct { const char *buf; int len; } tests[] = {
463 : { "(7:g34:fgh1::2:())", 0 },
464 : { "(7:g34:fgh1::2:())", 18 },
465 : {
466 : "(protected-private-key \n"
467 : " (rsa \n"
468 : " (n #00BE8A536204687149A48FF9F1715FF3530AD9A836D62102BF4065E5CF5953236DB94F1DF2FF4D525CD4CE7966DDC3C839968E8BAC2948934DF047CC65287CD79F6C23C93E55D7F9231E3942BD496DE383469977635A51ADF4AF747DB958CA02E9940DFC1DC0FC7FC755E7EB6618FEE6DA54B8A06E0CBF9D9257443F9992261435#)\n"
469 : " (e #010001#)\n"
470 : " (protected openpgp-s2k3-sha1-aes-cbc \n"
471 : " (\n"
472 : " (sha1 #C2A5673BD3882405# \"96\")\n"
473 : " #8D08AAF6A9209ED69D71EB7E64D78715#)\n"
474 : " #F7B0B535F8F8E22F4F3DA031224070303F82F9207D42952F1ACF21A4AB1C50304EBB25527992C7B265A9E9FF702826FB88759BDD55E4759E9FCA6C879538C9D043A9C60A326CB6681090BAA731289BD880A7D5774D9999F026E5E7963BFC8C0BDC9F061393CB734B4F259725C0A0A0B15BA39C39146EF6A1B3DC4DF30A22EBE09FD05AE6CB0C8C6532951A925F354F4E26A51964F5BBA50081690C421C8385C4074E9BAB9297D081B857756607EAE652415275A741C89E815558A50AC638EDC5F5030210B4395E3E1A40FF38DCCCB333A19EA88EFE7E4D51B54128C6DF27395646836679AC21B1B25C1DA6F0A7CE9F9BE078EFC7934FA9AE202CBB0AA06C20DFAF9A66FAB7E9073FBE96B9A7F25C3BA45EC3EECA65796AEE313BA148DE5314F30345B452B50B17C4D841A7F27397126E8C10BD0CE3B50A82C0425AAEE7798031671407B681F52916256F78CAF92A477AC27BCBE26DAFD1BCE386A853E2A036F8314BB2E8E5BB1F196434232EFB0288331C2AB16DBC5457CC295EB966CAC5CE73D5DA5D566E469F0EFA82F9A12B8693E0#)\n"
475 : " )\n"
476 : " )\n", 0 },
477 : { NULL, 0 }
478 : };
479 : int idx;
480 :
481 4 : for (idx=0; tests[idx].buf; idx++)
482 3 : back_and_forth_one (idx, tests[idx].buf, tests[idx].len);
483 1 : }
484 :
485 :
486 : static void
487 1 : check_sscan (void)
488 : {
489 : static struct {
490 : const char *text;
491 : gcry_error_t expected_err;
492 : } values[] = {
493 : /* Bug reported by Olivier L'Heureux 2003-10-07 */
494 : { "(7:sig-val(3:dsa"
495 : "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
496 : "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
497 : "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
498 : "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e)))",
499 : GPG_ERR_NO_ERROR },
500 : { "(7:sig-val(3:dsa"
501 : "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
502 : "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
503 : "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
504 : "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))",
505 : GPG_ERR_SEXP_UNMATCHED_PAREN },
506 : { "(7:sig-val(3:dsa"
507 : "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
508 : "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
509 : "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
510 : "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))))",
511 : GPG_ERR_SEXP_UNMATCHED_PAREN },
512 : { NULL, 0 }
513 : };
514 : int idx;
515 : gcry_error_t err;
516 : gcry_sexp_t s;
517 :
518 1 : info ("checking gcry_sexp_sscan\n");
519 4 : for (idx=0; values[idx].text; idx++)
520 : {
521 3 : err = gcry_sexp_sscan (&s, NULL,
522 : values[idx].text,
523 : strlen (values[idx].text));
524 3 : if (gpg_err_code (err) != values[idx].expected_err)
525 0 : fail ("gcry_sexp_sscan test %d failed: %s\n", idx, gpg_strerror (err));
526 3 : gcry_sexp_release (s);
527 : }
528 1 : }
529 :
530 :
531 : static void
532 1 : check_extract_param (void)
533 : {
534 : /* This sample data is a real key but with some parameters of the
535 : public key modified. */
536 : static char sample1[] =
537 : "(key-data"
538 : " (public-key"
539 : " (ecc"
540 : " (curve Ed25519)"
541 : " (p #6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
542 : " (a #EF#)"
543 : " (b #C2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6#)"
544 : " (g #14"
545 : " 216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
546 : " 6666666666666666666666666666666666666666666666666666666666666658#)"
547 : " (n #0000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
548 : " (q #20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
549 : "))"
550 : " (private-key"
551 : " (ecc"
552 : " (curve Ed25519)"
553 : " (p #7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
554 : " (a #FF#)"
555 : " (b #D2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6#)"
556 : " (g #04"
557 : " 216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
558 : " 6666666666666666666666666666666666666666666666666666666666666658#)"
559 : " (n #1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
560 : " (q #30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
561 : " (d #56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276#)"
562 : ")))";
563 :
564 : static char sample1_p[] =
565 : "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED";
566 : static char sample1_px[] =
567 : "6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED";
568 : static char sample1_a[] = "FF";
569 : static char sample1_ax[] = "EF";
570 : static char sample1_b[] =
571 : "D2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6";
572 : static char sample1_bx[] =
573 : "C2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6";
574 : static char sample1_g[] =
575 : "04"
576 : "216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
577 : "6666666666666666666666666666666666666666666666666666666666666658";
578 : static char sample1_gx[] =
579 : "14"
580 : "216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
581 : "6666666666666666666666666666666666666666666666666666666666666658";
582 : static char sample1_n[] =
583 : "1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
584 : static char sample1_nx[] =
585 : "0000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
586 : static char sample1_q[] =
587 : "30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
588 : static char sample1_qx[] =
589 : "20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
590 : static char sample1_d[] =
591 : "56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276";
592 :
593 : static struct {
594 : const char *sexp_str;
595 : const char *path;
596 : const char *list;
597 : int nparam;
598 : gpg_err_code_t expected_err;
599 : const char *exp_p;
600 : const char *exp_a;
601 : const char *exp_b;
602 : const char *exp_g;
603 : const char *exp_n;
604 : const char *exp_q;
605 : const char *exp_d;
606 : } tests[] = {
607 : {
608 : sample1,
609 : NULL,
610 : "pabgnqd", 6,
611 : GPG_ERR_MISSING_VALUE,
612 : },
613 : {
614 : sample1,
615 : NULL,
616 : "pabgnq", 7,
617 : GPG_ERR_INV_ARG
618 : },
619 : {
620 : sample1,
621 : NULL,
622 : "pab'gnq", 7,
623 : GPG_ERR_SYNTAX
624 : },
625 : {
626 : sample1,
627 : NULL,
628 : "pab''gnq", 7,
629 : GPG_ERR_SYNTAX
630 : },
631 : {
632 : sample1,
633 : NULL,
634 : "pabgnqd", 7,
635 : 0,
636 : sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
637 : sample1_qx, sample1_d
638 : },
639 : {
640 : sample1,
641 : NULL,
642 : " pab\tg nq\nd ", 7,
643 : 0,
644 : sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
645 : sample1_qx, sample1_d
646 : },
647 : {
648 : sample1,
649 : NULL,
650 : "abg", 3,
651 : 0,
652 : sample1_ax, sample1_bx, sample1_gx
653 : },
654 : {
655 : sample1,
656 : NULL,
657 : "ab'g'", 3,
658 : 0,
659 : sample1_ax, sample1_bx, sample1_gx
660 : },
661 : {
662 : sample1,
663 : NULL,
664 : "x?abg", 4,
665 : 0,
666 : NULL, sample1_ax, sample1_bx, sample1_gx
667 : },
668 : {
669 : sample1,
670 : NULL,
671 : "p?abg", 4,
672 : GPG_ERR_USER_1,
673 : NULL, sample1_ax, sample1_bx, sample1_gx
674 : },
675 : {
676 : sample1,
677 : NULL,
678 : "pax?gnqd", 7,
679 : 0,
680 : sample1_px, sample1_ax, NULL, sample1_gx, sample1_nx,
681 : sample1_qx, sample1_d
682 : },
683 : {
684 : sample1,
685 : "public-key",
686 : "pabgnqd", 7,
687 : GPG_ERR_NO_OBJ, /* d is not in public key. */
688 : sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
689 : sample1_qx, sample1_d
690 : },
691 : {
692 : sample1,
693 : "private-key",
694 : "pabgnqd", 7,
695 : 0,
696 : sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
697 : sample1_q, sample1_d
698 : },
699 : {
700 : sample1,
701 : "public-key!ecc",
702 : "pabgnq", 6,
703 : 0,
704 : sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
705 : sample1_qx
706 : },
707 : {
708 : sample1,
709 : "public-key!ecc!foo",
710 : "pabgnq", 6,
711 : GPG_ERR_NOT_FOUND
712 : },
713 : {
714 : sample1,
715 : "public-key!!ecc",
716 : "pabgnq", 6,
717 : GPG_ERR_NOT_FOUND
718 : },
719 : {
720 : sample1,
721 : "private-key",
722 : "pa/bgnqd", 7,
723 : 0,
724 : sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
725 : sample1_q, sample1_d
726 : },
727 : {
728 : sample1,
729 : "private-key",
730 : "p-a+bgnqd", 7,
731 : 0,
732 : sample1_p, "-01", sample1_b, sample1_g, sample1_n,
733 : sample1_q, sample1_d
734 : },
735 : {NULL}
736 : };
737 : int idx, i;
738 : const char *paramstr;
739 : int paramidx;
740 : gpg_error_t err;
741 : gcry_sexp_t sxp;
742 : gcry_mpi_t mpis[7];
743 : gcry_buffer_t ioarray[7];
744 : char iobuffer[200];
745 :
746 1 : info ("checking gcry_sexp_extract_param\n");
747 19 : for (idx=0; tests[idx].sexp_str; idx++)
748 : {
749 18 : err = gcry_sexp_new (&sxp, tests[idx].sexp_str, 0, 1);
750 18 : if (err)
751 0 : die ("converting string to sexp failed: %s", gpg_strerror (err));
752 :
753 18 : memset (mpis, 0, sizeof mpis);
754 18 : switch (tests[idx].nparam)
755 : {
756 : case 0:
757 0 : err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
758 : NULL);
759 0 : break;
760 : case 1:
761 0 : err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
762 : mpis+0, NULL);
763 0 : break;
764 : case 2:
765 0 : err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
766 : mpis+0, mpis+1, NULL);
767 0 : break;
768 : case 3:
769 2 : err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
770 : mpis+0, mpis+1, mpis+2, NULL);
771 2 : break;
772 : case 4:
773 2 : err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
774 : mpis+0, mpis+1, mpis+2, mpis+3, NULL);
775 2 : break;
776 : case 5:
777 0 : err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
778 : mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
779 : NULL);
780 0 : break;
781 : case 6:
782 4 : err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
783 : mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
784 : mpis+5, NULL);
785 4 : break;
786 : case 7:
787 10 : err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
788 : mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
789 : mpis+5, mpis+6, NULL);
790 10 : break;
791 : default:
792 0 : die ("test %d: internal error", idx);
793 : }
794 :
795 18 : if (tests[idx].expected_err
796 8 : && tests[idx].expected_err != GPG_ERR_USER_1)
797 : {
798 14 : if (tests[idx].expected_err != gpg_err_code (err))
799 0 : fail ("gcry_sexp_extract_param test %d failed: "
800 : "expected error '%s' - got '%s'", idx,
801 0 : gpg_strerror (tests[idx].expected_err),gpg_strerror (err));
802 :
803 : }
804 11 : else if (err)
805 : {
806 0 : fail ("gcry_sexp_extract_param test %d failed: %s",
807 : idx, gpg_strerror (err));
808 : }
809 : else /* No error - check the extracted values. */
810 : {
811 88 : for (paramidx=0; paramidx < DIM (mpis); paramidx++)
812 : {
813 77 : switch (paramidx)
814 : {
815 11 : case 0: paramstr = tests[idx].exp_p; break;
816 11 : case 1: paramstr = tests[idx].exp_a; break;
817 11 : case 2: paramstr = tests[idx].exp_b; break;
818 11 : case 3: paramstr = tests[idx].exp_g; break;
819 11 : case 4: paramstr = tests[idx].exp_n; break;
820 11 : case 5: paramstr = tests[idx].exp_q; break;
821 11 : case 6: paramstr = tests[idx].exp_d; break;
822 : default:
823 0 : die ("test %d: internal error: bad param %d",
824 : idx, paramidx);
825 : }
826 :
827 77 : if (tests[idx].expected_err == GPG_ERR_USER_1
828 7 : && mpis[paramidx] && !paramstr && paramidx == 0)
829 : ; /* Okay Special case error for param 0. */
830 76 : else if (!mpis[paramidx] && !paramstr)
831 : ; /* Okay. */
832 59 : else if (!mpis[paramidx] && paramstr)
833 0 : fail ("test %d: value for param %d expected but not returned",
834 : idx, paramidx);
835 59 : else if (mpis[paramidx] && !paramstr)
836 0 : fail ("test %d: value for param %d not expected",
837 : idx, paramidx);
838 59 : else if (cmp_mpihex (mpis[paramidx], paramstr))
839 : {
840 0 : fail ("test %d: param %d mismatch", idx, paramidx);
841 0 : gcry_log_debug ("expected: %s\n", paramstr);
842 0 : gcry_log_debugmpi (" got", mpis[paramidx]);
843 : }
844 59 : else if (tests[idx].expected_err && paramidx == 0)
845 0 : fail ("test %d: param %d: expected error '%s' - got 'Success'",
846 0 : idx, paramidx, gpg_strerror (tests[idx].expected_err));
847 : }
848 :
849 : }
850 :
851 144 : for (i=0; i < DIM (mpis); i++)
852 126 : gcry_mpi_release (mpis[i]);
853 18 : gcry_sexp_release (sxp);
854 : }
855 :
856 1 : info ("checking gcry_sexp_extract_param/desc\n");
857 :
858 1 : memset (ioarray, 0, sizeof ioarray);
859 :
860 1 : err = gcry_sexp_new (&sxp, sample1, 0, 1);
861 1 : if (err)
862 0 : die ("converting string to sexp failed: %s", gpg_strerror (err));
863 :
864 1 : ioarray[1].size = sizeof iobuffer;
865 1 : ioarray[1].data = iobuffer;
866 1 : ioarray[1].off = 0;
867 1 : ioarray[2].size = sizeof iobuffer;
868 1 : ioarray[2].data = iobuffer;
869 1 : ioarray[2].off = 50;
870 1 : assert (ioarray[2].off < sizeof iobuffer);
871 1 : err = gcry_sexp_extract_param (sxp, "key-data!private-key", "&pab",
872 : ioarray+0, ioarray+1, ioarray+2, NULL);
873 1 : if (err)
874 0 : fail ("gcry_sexp_extract_param with desc failed: %s", gpg_strerror (err));
875 : else
876 : {
877 1 : if (!ioarray[0].data)
878 0 : fail ("gcry_sexp_extract_param/desc failed: no P");
879 1 : else if (ioarray[0].size != 32)
880 0 : fail ("gcry_sexp_extract_param/desc failed: P has wrong size");
881 1 : else if (ioarray[0].len != 32)
882 0 : fail ("gcry_sexp_extract_param/desc failed: P has wrong length");
883 1 : else if (ioarray[0].off)
884 0 : fail ("gcry_sexp_extract_param/desc failed: P has OFF set");
885 1 : else if (cmp_bufhex (ioarray[0].data, ioarray[0].len, sample1_p))
886 : {
887 0 : fail ("gcry_sexp_extract_param/desc failed: P mismatch");
888 0 : gcry_log_debug ("expected: %s\n", sample1_p);
889 0 : gcry_log_debughex (" got", ioarray[0].data, ioarray[0].len);
890 : }
891 :
892 1 : if (!ioarray[1].data)
893 0 : fail ("gcry_sexp_extract_param/desc failed: A buffer lost");
894 1 : else if (ioarray[1].size != sizeof iobuffer)
895 0 : fail ("gcry_sexp_extract_param/desc failed: A size changed");
896 1 : else if (ioarray[1].off != 0)
897 0 : fail ("gcry_sexp_extract_param/desc failed: A off changed");
898 1 : else if (ioarray[1].len != 1)
899 0 : fail ("gcry_sexp_extract_param/desc failed: A has wrong length");
900 1 : else if (cmp_bufhex ((char *)ioarray[1].data + ioarray[1].off,
901 : ioarray[1].len, sample1_a))
902 : {
903 0 : fail ("gcry_sexp_extract_param/desc failed: A mismatch");
904 0 : gcry_log_debug ("expected: %s\n", sample1_a);
905 0 : gcry_log_debughex (" got",
906 0 : (char *)ioarray[1].data + ioarray[1].off,
907 : ioarray[1].len);
908 : }
909 :
910 1 : if (!ioarray[2].data)
911 0 : fail ("gcry_sexp_extract_param/desc failed: B buffer lost");
912 1 : else if (ioarray[2].size != sizeof iobuffer)
913 0 : fail ("gcry_sexp_extract_param/desc failed: B size changed");
914 1 : else if (ioarray[2].off != 50)
915 0 : fail ("gcry_sexp_extract_param/desc failed: B off changed");
916 1 : else if (ioarray[2].len != 32)
917 0 : fail ("gcry_sexp_extract_param/desc failed: B has wrong length");
918 1 : else if (cmp_bufhex ((char *)ioarray[2].data + ioarray[2].off,
919 : ioarray[2].len, sample1_b))
920 : {
921 0 : fail ("gcry_sexp_extract_param/desc failed: B mismatch");
922 0 : gcry_log_debug ("expected: %s\n", sample1_b);
923 0 : gcry_log_debughex (" got",
924 0 : (char *)ioarray[2].data + ioarray[2].off,
925 : ioarray[2].len);
926 : }
927 :
928 1 : xfree (ioarray[0].data);
929 : }
930 :
931 1 : gcry_sexp_release (sxp);
932 :
933 1 : info ("checking gcry_sexp_extract_param long name\n");
934 :
935 1 : memset (ioarray, 0, sizeof ioarray);
936 1 : memset (mpis, 0, sizeof mpis);
937 :
938 1 : err = gcry_sexp_new (&sxp, sample1, 0, 1);
939 1 : if (err)
940 0 : die ("converting string to sexp failed: %s", gpg_strerror (err));
941 :
942 1 : err = gcry_sexp_extract_param (sxp, "key-data!private-key",
943 : "&'curve'+p",
944 : ioarray+0, mpis+0, NULL);
945 1 : if (err)
946 0 : fail ("gcry_sexp_extract_param long name failed: %s", gpg_strerror (err));
947 :
948 1 : if (!ioarray[0].data)
949 0 : fail ("gcry_sexp_extract_param long name failed: no curve");
950 1 : else if (ioarray[0].size != 7)
951 0 : fail ("gcry_sexp_extract_param long name failed: curve has wrong size");
952 1 : else if (ioarray[0].len != 7)
953 0 : fail ("gcry_sexp_extract_param long name failed: curve has wrong length");
954 1 : else if (ioarray[0].off)
955 0 : fail ("gcry_sexp_extract_param long name failed: curve has OFF set");
956 1 : else if (strncmp (ioarray[0].data, "Ed25519", 7))
957 : {
958 0 : fail ("gcry_sexp_extract_param long name failed: curve mismatch");
959 0 : gcry_log_debug ("expected: %s\n", "Ed25519");
960 0 : gcry_log_debug (" got: %.*s\n",
961 0 : (int)ioarray[0].len, (char*)ioarray[0].data);
962 : }
963 :
964 1 : if (!mpis[0])
965 0 : fail ("gcry_sexp_extract_param long name failed: p not returned");
966 1 : else if (cmp_mpihex (mpis[0], sample1_p))
967 : {
968 0 : fail ("gcry_sexp_extract_param long name failed: p mismatch");
969 0 : gcry_log_debug ("expected: %s\n", sample1_p);
970 0 : gcry_log_debugmpi (" got", mpis[0]);
971 : }
972 :
973 1 : gcry_free (ioarray[0].data);
974 1 : gcry_mpi_release (mpis[0]);
975 :
976 1 : gcry_sexp_release (sxp);
977 :
978 1 : }
979 :
980 :
981 : /* A test based on bug 1594. */
982 : static void
983 1 : bug_1594 (void)
984 : {
985 : static char thing[] =
986 : "(signature"
987 : " (public-key"
988 : " (rsa"
989 : " (n #00A53A6B3A50BE571F805BD98ECE1FCE4CE291C3D4D3E971740E1EE6D447F526"
990 : " 6AC8973DDC82F0ADD234CC82E0A0A3F48B81ACC8B038DB8ACC3E78DC2ED2642F"
991 : " 6BA353FCA60F47C2801DEB477B37FB8B2F5508AA1C6D922780DB142DEA19B812"
992 : " C4E64F1138AD3BD61C58DB2D2591BE0BF36A1AC588AA45763BCDFF581050ABA8"
993 : " CA47BD9723ADD6A308AE28471EDD2B16D03C941D4F2B7E019C43AF8972880633"
994 : " 54E97B7E19F1677D84B69A26B184A77B719DD72C48E0EE36107046F786566A9D"
995 : " 13BAD724D6D78F24700FC22FC000E1B2A8C1B08ED62008395B0764CD9B55E80D"
996 : " A0A2B61C698DC27EA98E68BB576ACFC2B91B4D7283E7D960948D049D6E3C4CB1"
997 : " F489B460A120A4BB6C04A843FD3A67454136DE61CF68A927871EFFA9141BD372"
998 : " A748593C703E0301F039A9E674C50301BFC385BABE5B154250E7D57B82DB31F1"
999 : " E1AC696F870DCD8FE8DEC75608B988FCA3B484F1FD7755BF452F99597269AF02"
1000 : " E8AF87D0F93DB427291659183D077254C835BFB6DDFD87CD0B5E0738682FCD34"
1001 : " 923F22551F73944E6CBE3ED6879B4414676B5DA0F30ED21DFA12BD2230C3C5D2"
1002 : " EA116A3EFEB4AEC21C58E63FAFA549A63190F01859445E9B80F427B80FD4C884"
1003 : " 2AD41FE760A3E9DEDFB56CEBE8EA783838B2B392CACDDC760CCE212E388AFBC1"
1004 : " 95DC6D0ED87E9091F82A82CE372738C8DE8ABD76ACD06AC8B80AA0597162DF59"
1005 : " 67#)"
1006 : " (e #010001#))))";
1007 : gcry_sexp_t sig, pubkey, n, n_val;
1008 :
1009 1 : info ("checking fix for bug 1594\n");
1010 :
1011 1 : if (gcry_sexp_new (&sig, thing, 0, 1))
1012 0 : die ("scanning fixed string failed\n");
1013 1 : pubkey = gcry_sexp_find_token (sig, "public-key", 0);
1014 1 : gcry_sexp_release (sig);
1015 1 : if (!pubkey)
1016 : {
1017 0 : fail ("'public-key' token not found");
1018 0 : return;
1019 : }
1020 1 : n = gcry_sexp_find_token (pubkey, "n", 0);
1021 1 : if (!n)
1022 : {
1023 0 : fail ("'n' token not found");
1024 0 : gcry_sexp_release (pubkey);
1025 0 : return;
1026 : }
1027 1 : n_val = gcry_sexp_nth (n, 1);
1028 : /* Bug 1594 would require the following test:
1029 : * if (n_val)
1030 : * fail ("extracting 1-th of 'n' list did not fail");
1031 : * However, we meanwhile modified the S-expression functions to
1032 : * behave like Scheme to allow the access of any element of a list.
1033 : */
1034 1 : if (!n_val)
1035 0 : fail ("extracting 1-th of 'n' list failed");
1036 : /*gcry_log_debugsxp ("1-th", n_val); => "(#00A5...#)" */
1037 1 : gcry_sexp_release (n_val);
1038 1 : n_val = gcry_sexp_nth (n, 2);
1039 1 : if (n_val)
1040 0 : fail ("extracting 2-th of 'n' list did not fail");
1041 1 : n_val = gcry_sexp_nth (n, 0);
1042 1 : if (!n_val)
1043 0 : fail ("extracting 0-th of 'n' list failed");
1044 : /*gcry_log_debugsxp ("0-th", n_val); => "(n)" */
1045 1 : if (gcry_sexp_nth (n_val, 1))
1046 0 : fail ("extracting 1-th of car of 'n' list did not fail");
1047 1 : gcry_sexp_release (n_val);
1048 1 : gcry_sexp_release (n);
1049 1 : gcry_sexp_release (pubkey);
1050 : }
1051 :
1052 :
1053 : int
1054 1 : main (int argc, char **argv)
1055 : {
1056 1 : int last_argc = -1;
1057 :
1058 1 : if (argc)
1059 : {
1060 1 : argc--; argv++;
1061 : }
1062 2 : while (argc && last_argc != argc )
1063 : {
1064 0 : last_argc = argc;
1065 0 : if (!strcmp (*argv, "--"))
1066 : {
1067 0 : argc--; argv++;
1068 0 : break;
1069 : }
1070 0 : else if (!strcmp (*argv, "--help"))
1071 : {
1072 0 : puts (
1073 : "usage: " PGMNAME " [options]\n"
1074 : "\n"
1075 : "Options:\n"
1076 : " --verbose Show what is going on\n"
1077 : " --debug Flyswatter\n"
1078 : );
1079 0 : exit (0);
1080 : }
1081 0 : else if (!strcmp (*argv, "--verbose"))
1082 : {
1083 0 : verbose = 1;
1084 0 : argc--; argv++;
1085 : }
1086 0 : else if (!strcmp (*argv, "--debug"))
1087 : {
1088 0 : verbose = debug = 1;
1089 0 : argc--; argv++;
1090 : }
1091 0 : else if (!strncmp (*argv, "--", 2))
1092 0 : die ("unknown option '%s'", *argv);
1093 : }
1094 :
1095 1 : if (debug)
1096 0 : gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
1097 1 : gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
1098 1 : gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
1099 1 : if (!gcry_check_version (GCRYPT_VERSION))
1100 0 : die ("version mismatch");
1101 : /* #include "../src/gcrypt-int.h" indicates that internal interfaces
1102 : may be used; thus better do an exact version check. */
1103 1 : if (strcmp (gcry_check_version (NULL), GCRYPT_VERSION))
1104 0 : die ("exact version match failed");
1105 1 : gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
1106 1 : gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
1107 :
1108 1 : basic ();
1109 1 : canon_len ();
1110 1 : back_and_forth ();
1111 1 : check_sscan ();
1112 1 : check_extract_param ();
1113 1 : bug_1594 ();
1114 :
1115 1 : return errorcount? 1:0;
1116 : }
|