1/* tsexp.c - S-expression regression tests 2 * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. 3 * 4 * This file is part of Libgcrypt. 5 * 6 * Libgcrypt is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as 8 * published by the Free Software Foundation; either version 2.1 of 9 * the License, or (at your option) any later version. 10 * 11 * Libgcrypt is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 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 "../src/gcrypt.h" 29 30#define PGMNAME "tsexp" 31 32static int verbose; 33static int error_count; 34 35static void 36info (const char *format, ...) 37{ 38 va_list arg_ptr; 39 40 if (verbose) 41 { 42 va_start( arg_ptr, format ) ; 43 vfprintf (stderr, format, arg_ptr ); 44 va_end(arg_ptr); 45 } 46} 47 48static void 49fail ( const char *format, ... ) 50{ 51 va_list arg_ptr ; 52 53 fputs (PGMNAME ": ", stderr); 54 va_start( arg_ptr, format ) ; 55 vfprintf (stderr, format, arg_ptr ); 56 va_end(arg_ptr); 57 error_count++; 58} 59 60 61/* fixme: we need better tests */ 62static void 63basic (void) 64{ 65 int pass; 66 gcry_sexp_t sexp; 67 int idx; 68 char *secure_buffer; 69 size_t secure_buffer_len; 70 const char *string; 71 static struct { 72 const char *token; 73 const char *parm; 74 } values[] = { 75 { "public-key", NULL }, 76 { "dsa", NULL }, 77 { "dsa", "p" }, 78 { "dsa", "y" }, 79 { "dsa", "q" }, 80 { "dsa", "g" }, 81 { NULL } 82 }; 83 84 info ("doing some pretty pointless tests\n"); 85 86 secure_buffer_len = 99; 87 secure_buffer = gcry_xmalloc_secure (secure_buffer_len); 88 memset (secure_buffer, 'G', secure_buffer_len); 89 90 for (pass=0;;pass++) 91 { 92 switch (pass) 93 { 94 case 0: 95 string = ("(public-key (dsa (p #41424344#) (y this_is_y) " 96 "(q #61626364656667#) (g %m)))"); 97 98 if ( gcry_sexp_build (&sexp, NULL, string, 99 gcry_mpi_set_ui (NULL, 42)) ) 100 { 101 fail (" scanning `%s' failed\n", string); 102 return; 103 } 104 break; 105 106 case 1: 107 string = ("(public-key (dsa (p #41424344#) (y this_is_y) " 108 "(q %b) (g %m)))"); 109 110 if ( gcry_sexp_build (&sexp, NULL, string, 111 15, "foo\0\x01\0x02789012345", 112 gcry_mpi_set_ui (NULL, 42)) ) 113 { 114 fail (" scanning `%s' failed\n", string); 115 return; 116 } 117 break; 118 119 case 2: 120 string = ("(public-key (dsa (p #41424344#) (y silly_y_value) " 121 "(q %b) (g %m)))"); 122 123 if ( gcry_sexp_build (&sexp, NULL, string, 124 secure_buffer_len, secure_buffer, 125 gcry_mpi_set_ui (NULL, 17)) ) 126 { 127 fail (" scanning `%s' failed\n", string); 128 return; 129 } 130 if (!gcry_is_secure (sexp)) 131 fail ("gcry_sexp_build did not switch to secure memory\n"); 132 break; 133 134 case 3: 135 { 136 gcry_sexp_t help_sexp; 137 138 if (gcry_sexp_new (&help_sexp, 139 "(foobar-parms (xp #1234#)(xq #03#))", 0, 1)) 140 { 141 fail (" scanning fixed string failed\n"); 142 return; 143 } 144 145 string = ("(public-key (dsa (p #41424344#) (parm %S) " 146 "(y dummy)(q %b) (g %m)))"); 147 if ( gcry_sexp_build (&sexp, NULL, string, help_sexp, 148 secure_buffer_len, secure_buffer, 149 gcry_mpi_set_ui (NULL, 17)) ) 150 { 151 fail (" scanning `%s' failed\n", string); 152 return; 153 } 154 gcry_sexp_release (help_sexp); 155 } 156 break; 157 158 159 default: 160 return; /* Ready. */ 161 } 162 163 164 /* now find something */ 165 for (idx=0; values[idx].token; idx++) 166 { 167 const char *token = values[idx].token; 168 const char *parm = values[idx].parm; 169 gcry_sexp_t s1, s2; 170 gcry_mpi_t a; 171 const char *p; 172 size_t n; 173 174 s1 = gcry_sexp_find_token (sexp, token, strlen(token) ); 175 if (!s1) 176 { 177 fail ("didn't found `%s'\n", token); 178 continue; 179 } 180 181 p = gcry_sexp_nth_data (s1, 0, &n); 182 if (!p) 183 { 184 fail ("no car for `%s'\n", token); 185 continue; 186 } 187 info ("car=`%.*s'\n", (int)n, p); 188 189 s2 = gcry_sexp_cdr (s1); 190 if (!s2) 191 { 192 fail ("no cdr for `%s'\n", token); 193 continue; 194 } 195 196 p = gcry_sexp_nth_data (s2, 0, &n); 197 if (p) 198 { 199 fail ("data at car of `%s'\n", token); 200 continue; 201 } 202 203 if (parm) 204 { 205 s2 = gcry_sexp_find_token (s1, parm, strlen (parm)); 206 if (!s2) 207 { 208 fail ("didn't found `%s'\n", parm); 209 continue; 210 } 211 p = gcry_sexp_nth_data (s2, 0, &n); 212 if (!p) 213 { 214 fail("no car for `%s'\n", parm ); 215 continue; 216 } 217 info ("car=`%.*s'\n", (int)n, p); 218 p = gcry_sexp_nth_data (s2, 1, &n); 219 if (!p) 220 { 221 fail("no cdr for `%s'\n", parm ); 222 continue; 223 } 224 info ("cdr=`%.*s'\n", (int)n, p); 225 226 a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG); 227 if (!a) 228 { 229 fail("failed to cdr the mpi for `%s'\n", parm); 230 continue; 231 } 232 } 233 } 234 235 gcry_sexp_release (sexp); 236 sexp = NULL; 237 } 238 gcry_free (secure_buffer); 239} 240 241 242static void 243canon_len (void) 244{ 245 static struct { 246 size_t textlen; /* length of the buffer */ 247 size_t expected;/* expected length or 0 on error and then ... */ 248 size_t erroff; /* ... and at this offset */ 249 gcry_error_t errcode; /* ... with this error code */ 250 const char *text; 251 } values[] = { 252 { 14, 13, 0, GPG_ERR_NO_ERROR, "(9:abcdefghi) " }, 253 { 16, 15, 0, GPG_ERR_NO_ERROR, "(10:abcdefghix)" }, 254 { 14, 0,14, GPG_ERR_SEXP_STRING_TOO_LONG, "(10:abcdefghi)" }, 255 { 15, 0, 1, GPG_ERR_SEXP_ZERO_PREFIX, "(010:abcdefghi)" }, 256 { 2, 0, 0, GPG_ERR_SEXP_NOT_CANONICAL, "1:"}, 257 { 4, 0, 4, GPG_ERR_SEXP_STRING_TOO_LONG, "(1:)"}, 258 { 5, 5, 0, GPG_ERR_NO_ERROR, "(1:x)"}, 259 { 2, 2, 0, GPG_ERR_NO_ERROR, "()"}, 260 { 4, 2, 0, GPG_ERR_NO_ERROR, "()()"}, 261 { 4, 4, 0, GPG_ERR_NO_ERROR, "(())"}, 262 { 3, 0, 3, GPG_ERR_SEXP_STRING_TOO_LONG, "(()"}, 263 { 3, 0, 1, GPG_ERR_SEXP_BAD_CHARACTER, "( )"}, 264 { 9, 9, 0, GPG_ERR_NO_ERROR, "(3:abc())"}, 265 { 10, 0, 6, GPG_ERR_SEXP_BAD_CHARACTER, "(3:abc ())"}, 266 /* fixme: we need much more cases */ 267 { 0 }, 268 }; 269 int idx; 270 gcry_error_t errcode; 271 size_t n, erroff; 272 273 info ("checking canoncial length test function\n"); 274 for (idx=0; values[idx].text; idx++) 275 { 276 n = gcry_sexp_canon_len ((const unsigned char*)values[idx].text, 277 values[idx].textlen, 278 &erroff, &errcode); 279 280 if (n && n == values[idx].expected) 281 ; /* success */ 282 else if (!n && !values[idx].expected) 283 { /* we expected an error - check that this is the right one */ 284 if (values[idx].erroff != erroff) 285 fail ("canonical length test %d - wrong error offset %u\n", 286 idx, (unsigned int)erroff); 287 if (gcry_err_code (errcode) != values[idx].errcode) 288 fail ("canonical length test %d - wrong error code %d\n", 289 idx, errcode); 290 } 291 else 292 fail ("canonical length test %d failed - n=%u, off=%u, err=%d\n", 293 idx, (unsigned int)n, (unsigned int)erroff, errcode); 294 } 295} 296 297 298static void 299back_and_forth_one (int testno, const char *buffer, size_t length) 300{ 301 gcry_error_t rc; 302 gcry_sexp_t se, se1; 303 size_t n, n1; 304 char *p1; 305 306 rc = gcry_sexp_new (&se, buffer, length, 1); 307 if (rc) 308 { 309 fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc)); 310 return; 311 } 312 n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0); 313 if (!n1) 314 { 315 fail ("baf %d: get required length for canon failed\n", testno); 316 return; 317 } 318 p1 = gcry_xmalloc (n1); 319 n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1); 320 if (n1 != n+1) /* sprints adds an extra 0 but dies not return it */ 321 { 322 fail ("baf %d: length mismatch for canon\n", testno); 323 return; 324 } 325 rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free); 326 if (rc) 327 { 328 fail ("baf %d: gcry_sexp_create failed: %s\n", 329 testno, gpg_strerror (rc)); 330 return; 331 } 332 gcry_sexp_release (se1); 333 334 /* Again but with memory checking. */ 335 p1 = gcry_xmalloc (n1+2); 336 *p1 = '\x55'; 337 p1[n1+1] = '\xaa'; 338 n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1); 339 if (n1 != n+1) /* sprints adds an extra 0 but does not return it */ 340 { 341 fail ("baf %d: length mismatch for canon\n", testno); 342 return; 343 } 344 if (*p1 != '\x55' || p1[n1+1] != '\xaa') 345 fail ("baf %d: memory corrupted (1)\n", testno); 346 rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL); 347 if (rc) 348 { 349 fail ("baf %d: gcry_sexp_create failed: %s\n", 350 testno, gpg_strerror (rc)); 351 return; 352 } 353 if (*p1 != '\x55' || p1[n1+1] != '\xaa') 354 fail ("baf %d: memory corrupted (2)\n", testno); 355 gcry_sexp_release (se1); 356 if (*p1 != '\x55' || p1[n1+1] != '\xaa') 357 fail ("baf %d: memory corrupted (3)\n", testno); 358 gcry_free (p1); 359 360 /* FIXME: we need a lot more tests */ 361 362 gcry_sexp_release (se); 363} 364 365 366 367static void 368back_and_forth (void) 369{ 370 static struct { const char *buf; int len; } tests[] = { 371 { "(7:g34:fgh1::2:())", 0 }, 372 { "(7:g34:fgh1::2:())", 18 }, 373 { 374"(protected-private-key \n" 375" (rsa \n" 376" (n #00BE8A536204687149A48FF9F1715FF3530AD9A836D62102BF4065E5CF5953236DB94F1DF2FF4D525CD4CE7966DDC3C839968E8BAC2948934DF047CC65287CD79F6C23C93E55D7F9231E3942BD496DE383469977635A51ADF4AF747DB958CA02E9940DFC1DC0FC7FC755E7EB6618FEE6DA54B8A06E0CBF9D9257443F9992261435#)\n" 377" (e #010001#)\n" 378" (protected openpgp-s2k3-sha1-aes-cbc \n" 379" (\n" 380" (sha1 #C2A5673BD3882405# \"96\")\n" 381" #8D08AAF6A9209ED69D71EB7E64D78715#)\n" 382" #F7B0B535F8F8E22F4F3DA031224070303F82F9207D42952F1ACF21A4AB1C50304EBB25527992C7B265A9E9FF702826FB88759BDD55E4759E9FCA6C879538C9D043A9C60A326CB6681090BAA731289BD880A7D5774D9999F026E5E7963BFC8C0BDC9F061393CB734B4F259725C0A0A0B15BA39C39146EF6A1B3DC4DF30A22EBE09FD05AE6CB0C8C6532951A925F354F4E26A51964F5BBA50081690C421C8385C4074E9BAB9297D081B857756607EAE652415275A741C89E815558A50AC638EDC5F5030210B4395E3E1A40FF38DCCCB333A19EA88EFE7E4D51B54128C6DF27395646836679AC21B1B25C1DA6F0A7CE9F9BE078EFC7934FA9AE202CBB0AA06C20DFAF9A66FAB7E9073FBE96B9A7F25C3BA45EC3EECA65796AEE313BA148DE5314F30345B452B50B17C4D841A7F27397126E8C10BD0CE3B50A82C0425AAEE7798031671407B681F52916256F78CAF92A477AC27BCBE26DAFD1BCE386A853E2A036F8314BB2E8E5BB1F196434232EFB0288331C2AB16DBC5457CC295EB966CAC5CE73D5DA5D566E469F0EFA82F9A12B8693E0#)\n" 383" )\n" 384" )\n", 0 }, 385 { NULL, 0 } 386 }; 387 int idx; 388 389 for (idx=0; tests[idx].buf; idx++) 390 back_and_forth_one (idx, tests[idx].buf, tests[idx].len); 391} 392 393 394static void 395check_sscan (void) 396{ 397 static struct { 398 const char *text; 399 gcry_error_t expected_err; 400 } values[] = { 401 /* Bug reported by Olivier L'Heureux 2003-10-07 */ 402 { "(7:sig-val(3:dsa" 403 "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64" 404 "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)" 405 "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d" 406 "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e)))", 407 GPG_ERR_NO_ERROR }, 408 { "(7:sig-val(3:dsa" 409 "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64" 410 "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)" 411 "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d" 412 "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))", 413 GPG_ERR_SEXP_UNMATCHED_PAREN }, 414 { "(7:sig-val(3:dsa" 415 "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64" 416 "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)" 417 "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d" 418 "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))))", 419 GPG_ERR_SEXP_UNMATCHED_PAREN }, 420 { NULL, 0 } 421 }; 422 int idx; 423 gcry_error_t err; 424 gcry_sexp_t s; 425 426 info ("checking gcry_sexp_sscan\n"); 427 for (idx=0; values[idx].text; idx++) 428 { 429 err = gcry_sexp_sscan (&s, NULL, 430 values[idx].text, 431 strlen (values[idx].text)); 432 if (gpg_err_code (err) != values[idx].expected_err) 433 fail ("gcry_sexp_sscan test %d failed: %s\n", idx, gpg_strerror (err)); 434 gcry_sexp_release (s); 435 } 436} 437 438 439 440 441int 442main (int argc, char **argv) 443{ 444 if (argc > 1 && !strcmp (argv[1], "--verbose")) 445 verbose = 1; 446 447 gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); 448 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); 449 450 basic (); 451 canon_len (); 452 back_and_forth (); 453 check_sscan (); 454 455 return error_count? 1:0; 456} 457