Line data Source code
1 : /* t-convert.c - Tests for mpi print and scna functions
2 : * Copyright (C) 2013 g10 Code GmbH
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, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #ifdef HAVE_CONFIG_H
21 : # include <config.h>
22 : #endif
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include <string.h>
26 : #include <assert.h>
27 : #include <stdarg.h>
28 :
29 : #define PGM "t-convert"
30 : #include "t-common.h"
31 :
32 :
33 : static void
34 0 : showhex (const char *prefix, const void *buffer, size_t buflen)
35 : {
36 : const unsigned char *s;
37 :
38 0 : if (!verbose)
39 0 : return;
40 0 : fprintf (stderr, "%s: %s ", PGM, prefix);
41 0 : for (s= buffer; buflen; buflen--, s++)
42 0 : fprintf (stderr, "%02x", *s);
43 0 : putc ('\n', stderr);
44 : }
45 :
46 :
47 : /* Allocate a bit string consisting of '0' and '1' from the MPI A. Do
48 : not return any leading zero bits. Caller needs to gcry_free the
49 : result. */
50 : static char *
51 0 : mpi2bitstr_nlz (gcry_mpi_t a)
52 : {
53 : char *p, *buf;
54 0 : size_t length = gcry_mpi_get_nbits (a);
55 :
56 0 : if (!length)
57 : {
58 0 : buf = p = xmalloc (3);
59 0 : *p++ = ' ';
60 0 : *p++ = '0';
61 : }
62 : else
63 : {
64 0 : buf = p = xmalloc (length + 1 + 1);
65 0 : *p++ = gcry_mpi_is_neg (a)? '-':' ';
66 0 : while (length-- > 1)
67 0 : *p++ = gcry_mpi_test_bit (a, length) ? '1':'0';
68 0 : *p++ = gcry_mpi_test_bit (a, 0) ? '1':'0';
69 : }
70 0 : *p = 0;
71 0 : return buf;
72 : }
73 :
74 :
75 : static void
76 0 : showmpi (const char *prefix, gcry_mpi_t a)
77 : {
78 : char *bitstr;
79 :
80 0 : if (!verbose)
81 0 : return;
82 0 : bitstr = mpi2bitstr_nlz (a);
83 0 : fprintf (stderr, "%s: %s%s\n", PGM, prefix, bitstr);
84 0 : xfree (bitstr);
85 : }
86 :
87 :
88 : /* Check that mpi_print does not return a negative zero. */
89 : static void
90 1 : negative_zero (void)
91 : {
92 : gpg_error_t err;
93 : gcry_mpi_t a;
94 : char *buf;
95 1 : void *bufaddr = &buf;
96 1 : struct { const char *name; enum gcry_mpi_format format; } fmts[] =
97 : {
98 : { "STD", GCRYMPI_FMT_STD },
99 : { "PGP", GCRYMPI_FMT_PGP },
100 : { "SSH", GCRYMPI_FMT_SSH },
101 : { "HEX", GCRYMPI_FMT_HEX },
102 : { "USG", GCRYMPI_FMT_USG },
103 : { NULL, 0 }
104 : };
105 : int i;
106 :
107 1 : if (debug)
108 0 : info ("negative zero printing\n");
109 :
110 1 : a = gcry_mpi_new (0);
111 6 : for (i=0; fmts[i].name; i++)
112 : {
113 5 : err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
114 5 : if (err)
115 0 : fail ("error printing a zero as %s: %s\n",
116 : fmts[i].name,gpg_strerror (err) );
117 : else
118 5 : gcry_free (buf);
119 : }
120 :
121 : /* With the current version of libgcrypt the next two statements
122 : should set a to -0. */
123 1 : gcry_mpi_sub_ui (a, a, 1);
124 1 : gcry_mpi_add_ui (a, a, 1);
125 :
126 6 : for (i=0; fmts[i].name; i++)
127 : {
128 5 : err = gcry_mpi_aprint (fmts[i].format, bufaddr, NULL, a);
129 5 : if (err)
130 0 : fail ("error printing a negative zero as %s: %s\n",
131 : fmts[i].name,gpg_strerror (err) );
132 : else
133 5 : gcry_free (buf);
134 : }
135 :
136 1 : gcry_mpi_release (a);
137 1 : }
138 :
139 :
140 : static void
141 1 : check_formats (void)
142 : {
143 : static struct {
144 : int value;
145 : struct {
146 : const char *hex;
147 : size_t stdlen;
148 : const char *std;
149 : size_t sshlen;
150 : const char *ssh;
151 : size_t usglen;
152 : const char *usg;
153 : size_t pgplen;
154 : const char *pgp;
155 : } a;
156 : } data[] = {
157 : { 0, { "00",
158 : 0, "",
159 : 4, "\x00\x00\x00\x00",
160 : 0, "",
161 : 2, "\x00\x00"}
162 : },
163 : { 1, { "01",
164 : 1, "\x01",
165 : 5, "\x00\x00\x00\x01\x01",
166 : 1, "\x01",
167 : 3, "\x00\x01\x01" }
168 : },
169 : { 2, { "02",
170 : 1, "\x02",
171 : 5, "\x00\x00\x00\x01\x02",
172 : 1, "\x02",
173 : 3, "\x00\x02\x02" }
174 : },
175 : { 127, { "7F",
176 : 1, "\x7f",
177 : 5, "\x00\x00\x00\x01\x7f",
178 : 1, "\x7f",
179 : 3, "\x00\x07\x7f" }
180 : },
181 : { 128, { "0080",
182 : 2, "\x00\x80",
183 : 6, "\x00\x00\x00\x02\x00\x80",
184 : 1, "\x80",
185 : 3, "\x00\x08\x80" }
186 : },
187 : { 129, { "0081",
188 : 2, "\x00\x81",
189 : 6, "\x00\x00\x00\x02\x00\x81",
190 : 1, "\x81",
191 : 3, "\x00\x08\x81" }
192 : },
193 : { 255, { "00FF",
194 : 2, "\x00\xff",
195 : 6, "\x00\x00\x00\x02\x00\xff",
196 : 1, "\xff",
197 : 3, "\x00\x08\xff" }
198 : },
199 : { 256, { "0100",
200 : 2, "\x01\x00",
201 : 6, "\x00\x00\x00\x02\x01\x00",
202 : 2, "\x01\x00",
203 : 4, "\x00\x09\x01\x00" }
204 : },
205 : { 257, { "0101",
206 : 2, "\x01\x01",
207 : 6, "\x00\x00\x00\x02\x01\x01",
208 : 2, "\x01\x01",
209 : 4, "\x00\x09\x01\x01" }
210 : },
211 : { -1, { "-01",
212 : 1, "\xff",
213 : 5, "\x00\x00\x00\x01\xff",
214 : 1,"\x01" }
215 : },
216 : { -2, { "-02",
217 : 1, "\xfe",
218 : 5, "\x00\x00\x00\x01\xfe",
219 : 1, "\x02" }
220 : },
221 : { -127, { "-7F",
222 : 1, "\x81",
223 : 5, "\x00\x00\x00\x01\x81",
224 : 1, "\x7f" }
225 : },
226 : { -128, { "-0080",
227 : 1, "\x80",
228 : 5, "\x00\x00\x00\x01\x80",
229 : 1, "\x80" }
230 : },
231 : { -129, { "-0081",
232 : 2, "\xff\x7f",
233 : 6, "\x00\x00\x00\x02\xff\x7f",
234 : 1, "\x81" }
235 : },
236 : { -255, { "-00FF",
237 : 2, "\xff\x01",
238 : 6, "\x00\x00\x00\x02\xff\x01",
239 : 1, "\xff" }
240 : },
241 : { -256, { "-0100",
242 : 2, "\xff\x00",
243 : 6, "\x00\x00\x00\x02\xff\x00",
244 : 2, "\x01\x00" }
245 : },
246 : { -257, { "-0101",
247 : 2, "\xfe\xff",
248 : 6, "\x00\x00\x00\x02\xfe\xff",
249 : 2, "\x01\x01" }
250 : },
251 : { 65535, { "00FFFF",
252 : 3, "\x00\xff\xff",
253 : 7, "\x00\x00\x00\x03\x00\xff\xff",
254 : 2, "\xff\xff",
255 : 4, "\x00\x10\xff\xff" }
256 : },
257 : { 65536, { "010000",
258 : 3, "\x01\00\x00",
259 : 7, "\x00\x00\x00\x03\x01\x00\x00",
260 : 3, "\x01\x00\x00",
261 : 5, "\x00\x11\x01\x00\x00 "}
262 : },
263 : { 65537, { "010001",
264 : 3, "\x01\00\x01",
265 : 7, "\x00\x00\x00\x03\x01\x00\x01",
266 : 3, "\x01\x00\x01",
267 : 5, "\x00\x11\x01\x00\x01" }
268 : },
269 : { -65537, { "-010001",
270 : 3, "\xfe\xff\xff",
271 : 7, "\x00\x00\x00\x03\xfe\xff\xff",
272 : 3, "\x01\x00\x01" }
273 : },
274 : { -65536, { "-010000",
275 : 3, "\xff\x00\x00",
276 : 7, "\x00\x00\x00\x03\xff\x00\x00",
277 : 3, "\x01\x00\x00" }
278 : },
279 : { -65535, { "-00FFFF",
280 : 3, "\xff\x00\x01",
281 : 7, "\x00\x00\x00\x03\xff\x00\x01",
282 : 2, "\xff\xff" }
283 : }
284 : };
285 : gpg_error_t err;
286 : gcry_mpi_t a, b;
287 : char *buf;
288 1 : void *bufaddr = &buf;
289 : int idx;
290 : size_t buflen;
291 :
292 1 : a = gcry_mpi_new (0);
293 24 : for (idx=0; idx < DIM(data); idx++)
294 : {
295 23 : if (debug)
296 0 : info ("print test %d\n", data[idx].value);
297 :
298 23 : if (data[idx].value < 0)
299 : {
300 11 : gcry_mpi_set_ui (a, -data[idx].value);
301 11 : gcry_mpi_neg (a, a);
302 : }
303 : else
304 12 : gcry_mpi_set_ui (a, data[idx].value);
305 :
306 23 : err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
307 23 : if (err)
308 0 : fail ("error printing value %d as %s: %s\n",
309 : data[idx].value, "HEX", gpg_strerror (err));
310 : else
311 : {
312 23 : if (strcmp (buf, data[idx].a.hex))
313 : {
314 0 : fail ("error printing value %d as %s: %s\n",
315 : data[idx].value, "HEX", "wrong result");
316 0 : info ("expected: '%s'\n", data[idx].a.hex);
317 0 : info (" got: '%s'\n", buf);
318 : }
319 23 : gcry_free (buf);
320 : }
321 :
322 23 : err = gcry_mpi_aprint (GCRYMPI_FMT_STD, bufaddr, &buflen, a);
323 23 : if (err)
324 0 : fail ("error printing value %d as %s: %s\n",
325 : data[idx].value, "STD", gpg_strerror (err));
326 : else
327 : {
328 23 : if (buflen != data[idx].a.stdlen
329 23 : || memcmp (buf, data[idx].a.std, data[idx].a.stdlen))
330 : {
331 0 : fail ("error printing value %d as %s: %s\n",
332 : data[idx].value, "STD", "wrong result");
333 0 : showhex ("expected:", data[idx].a.std, data[idx].a.stdlen);
334 0 : showhex (" got:", buf, buflen);
335 : }
336 23 : gcry_free (buf);
337 : }
338 :
339 23 : err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, bufaddr, &buflen, a);
340 23 : if (err)
341 0 : fail ("error printing value %d as %s: %s\n",
342 : data[idx].value, "SSH", gpg_strerror (err));
343 : else
344 : {
345 23 : if (buflen != data[idx].a.sshlen
346 23 : || memcmp (buf, data[idx].a.ssh, data[idx].a.sshlen))
347 : {
348 0 : fail ("error printing value %d as %s: %s\n",
349 : data[idx].value, "SSH", "wrong result");
350 0 : showhex ("expected:", data[idx].a.ssh, data[idx].a.sshlen);
351 0 : showhex (" got:", buf, buflen);
352 : }
353 23 : gcry_free (buf);
354 : }
355 :
356 23 : err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufaddr, &buflen, a);
357 23 : if (err)
358 0 : fail ("error printing value %d as %s: %s\n",
359 : data[idx].value, "USG", gpg_strerror (err));
360 : else
361 : {
362 23 : if (buflen != data[idx].a.usglen
363 23 : || memcmp (buf, data[idx].a.usg, data[idx].a.usglen))
364 : {
365 0 : fail ("error printing value %d as %s: %s\n",
366 : data[idx].value, "USG", "wrong result");
367 0 : showhex ("expected:", data[idx].a.usg, data[idx].a.usglen);
368 0 : showhex (" got:", buf, buflen);
369 : }
370 23 : gcry_free (buf);
371 : }
372 :
373 23 : err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, bufaddr, &buflen, a);
374 23 : if (gcry_mpi_is_neg (a))
375 : {
376 11 : if (gpg_err_code (err) != GPG_ERR_INV_ARG)
377 0 : fail ("error printing value %d as %s: %s\n",
378 : data[idx].value, "PGP", "Expected error not returned");
379 : }
380 12 : else if (err)
381 0 : fail ("error printing value %d as %s: %s\n",
382 : data[idx].value, "PGP", gpg_strerror (err));
383 : else
384 : {
385 12 : if (buflen != data[idx].a.pgplen
386 12 : || memcmp (buf, data[idx].a.pgp, data[idx].a.pgplen))
387 : {
388 0 : fail ("error printing value %d as %s: %s\n",
389 : data[idx].value, "PGP", "wrong result");
390 0 : showhex ("expected:", data[idx].a.pgp, data[idx].a.pgplen);
391 0 : showhex (" got:", buf, buflen);
392 : }
393 12 : gcry_free (buf);
394 : }
395 : }
396 :
397 :
398 : /* Now for the other direction. */
399 24 : for (idx=0; idx < DIM(data); idx++)
400 : {
401 23 : if (debug)
402 0 : info ("scan test %d\n", data[idx].value);
403 :
404 23 : if (data[idx].value < 0)
405 : {
406 11 : gcry_mpi_set_ui (a, -data[idx].value);
407 11 : gcry_mpi_neg (a, a);
408 : }
409 : else
410 12 : gcry_mpi_set_ui (a, data[idx].value);
411 :
412 23 : err = gcry_mpi_scan (&b, GCRYMPI_FMT_HEX, data[idx].a.hex, 0, &buflen);
413 23 : if (err)
414 0 : fail ("error scanning value %d from %s: %s\n",
415 : data[idx].value, "HEX", gpg_strerror (err));
416 : else
417 : {
418 23 : if (gcry_mpi_cmp (a, b))
419 : {
420 0 : fail ("error scanning value %d from %s: %s\n",
421 : data[idx].value, "HEX", "wrong result");
422 0 : showmpi ("expected:", a);
423 0 : showmpi (" got:", b);
424 : }
425 23 : gcry_mpi_release (b);
426 : }
427 :
428 46 : err = gcry_mpi_scan (&b, GCRYMPI_FMT_STD,
429 23 : data[idx].a.std, data[idx].a.stdlen, &buflen);
430 23 : if (err)
431 0 : fail ("error scanning value %d as %s: %s\n",
432 : data[idx].value, "STD", gpg_strerror (err));
433 : else
434 : {
435 23 : if (gcry_mpi_cmp (a, b) || data[idx].a.stdlen != buflen)
436 : {
437 0 : fail ("error scanning value %d from %s: %s (%lu)\n",
438 : data[idx].value, "STD", "wrong result", buflen);
439 0 : showmpi ("expected:", a);
440 0 : showmpi (" got:", b);
441 : }
442 23 : gcry_mpi_release (b);
443 : }
444 :
445 46 : err = gcry_mpi_scan (&b, GCRYMPI_FMT_SSH,
446 23 : data[idx].a.ssh, data[idx].a.sshlen, &buflen);
447 23 : if (err)
448 0 : fail ("error scanning value %d as %s: %s\n",
449 : data[idx].value, "SSH", gpg_strerror (err));
450 : else
451 : {
452 23 : if (gcry_mpi_cmp (a, b) || data[idx].a.sshlen != buflen)
453 : {
454 0 : fail ("error scanning value %d from %s: %s (%lu)\n",
455 : data[idx].value, "SSH", "wrong result", buflen);
456 0 : showmpi ("expected:", a);
457 0 : showmpi (" got:", b);
458 : }
459 23 : gcry_mpi_release (b);
460 : }
461 :
462 46 : err = gcry_mpi_scan (&b, GCRYMPI_FMT_USG,
463 23 : data[idx].a.usg, data[idx].a.usglen, &buflen);
464 23 : if (err)
465 0 : fail ("error scanning value %d as %s: %s\n",
466 : data[idx].value, "USG", gpg_strerror (err));
467 : else
468 : {
469 23 : if (gcry_mpi_is_neg (a))
470 11 : gcry_mpi_neg (b, b);
471 23 : if (gcry_mpi_cmp (a, b) || data[idx].a.usglen != buflen)
472 : {
473 0 : fail ("error scanning value %d from %s: %s (%lu)\n",
474 : data[idx].value, "USG", "wrong result", buflen);
475 0 : showmpi ("expected:", a);
476 0 : showmpi (" got:", b);
477 : }
478 23 : gcry_mpi_release (b);
479 : }
480 :
481 : /* Negative values are not supported by PGP, thus we don't have
482 : an samples. */
483 23 : if (!gcry_mpi_is_neg (a))
484 : {
485 24 : err = gcry_mpi_scan (&b, GCRYMPI_FMT_PGP,
486 12 : data[idx].a.pgp, data[idx].a.pgplen, &buflen);
487 12 : if (err)
488 0 : fail ("error scanning value %d as %s: %s\n",
489 : data[idx].value, "PGP", gpg_strerror (err));
490 : else
491 : {
492 12 : if (gcry_mpi_cmp (a, b) || data[idx].a.pgplen != buflen)
493 : {
494 0 : fail ("error scanning value %d from %s: %s (%lu)\n",
495 : data[idx].value, "PGP", "wrong result", buflen);
496 0 : showmpi ("expected:", a);
497 0 : showmpi (" got:", b);
498 : }
499 12 : gcry_mpi_release (b);
500 : }
501 : }
502 : }
503 :
504 1 : gcry_mpi_release (a);
505 1 : }
506 :
507 :
508 : int
509 1 : main (int argc, char **argv)
510 : {
511 1 : if (argc > 1 && !strcmp (argv[1], "--verbose"))
512 0 : verbose = 1;
513 1 : else if (argc > 1 && !strcmp (argv[1], "--debug"))
514 0 : verbose = debug = 1;
515 :
516 1 : if (!gcry_check_version (GCRYPT_VERSION))
517 0 : die ("version mismatch\n");
518 :
519 1 : xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
520 1 : xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
521 1 : if (debug)
522 0 : xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
523 1 : xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
524 :
525 1 : negative_zero ();
526 1 : check_formats ();
527 :
528 1 : info ("All tests completed. Errors: %d\n", error_count);
529 1 : return error_count ? 1 : 0;
530 : }
|