/* t-b64.c - b64dec tests. * Copyright (C) 2017, 2018 g10 Code GmbH * * This file is part of Libgpg-error. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1-or-later */ #if HAVE_CONFIG_H #include #endif #include #include #if HAVE_STDLIB_H #include #endif #define PGM "t-b64" #include "t-common.h" static const char *test_string = "libgpg-error is free software; " "you can redistribute it and/or modify it under the terms of " "the GNU Lesser General Public License as published by the Free " "Software Foundation; either version 2.1 of the License, or " "(at your option) any later version."; static const char *test_string_b64_0 = "bGliZ3BnLWVycm9yIGlzIGZyZWUgc29" "mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXQgd" "W5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljIEx" "pY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb" "247IGVpdGhlciB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXI" "gb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4="; static const char *test_string_b64_1 = "bGliZ3BnLWVycm9yIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmli\n" "dXRlIGl0IGFuZC9vciBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBH\n" "TlUgTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5\n" "IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIu\n" "MSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIg\n" "dmVyc2lvbi4=\n"; static const char *test_string_b64_2 = "-----BEGIN DATA-----\n" "bGliZ3BnLWVycm9yIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmli\n" "dXRlIGl0IGFuZC9vciBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBH\n" "TlUgTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5\n" "IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIu\n" "MSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIg\n" "dmVyc2lvbi4=\n" "-----END DATA-----\n"; static const char *test_string_b64_3 = "-----BEGIN PGP ARMORED FILE-----\n" "\n" "bGliZ3BnLWVycm9yIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmli\n" "dXRlIGl0IGFuZC9vciBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBH\n" "TlUgTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5\n" "IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIu\n" "MSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIg\n" "dmVyc2lvbi4=\n" "=4BMJ\n" "-----END PGP ARMORED FILE-----\n"; static const char *test_blob_1 = "\x01\x03\x04\xff"; static const char *test_blob_1_b64_0 = "AQME/w=="; static const char *test_blob_2 = "\x01\x03\x04\xff""A"; static const char *test_blob_2_b64_0 = "AQME/0E="; static const char *test_blob_3 = "\x01\x03\x04\xff""AB"; static const char *test_blob_3_b64_0 = "AQME/0FC"; #define FAIL(a) do { fail ("line %d: test %d failed\n", __LINE__, (a)); \ } while(0) static gpg_error_t test_b64enc_string (const char *string, const char *expected, const char *title) { gpg_err_code_t err; estream_t fp; gpgrt_b64state_t state; char *result; fp = es_fopenmem (0, "rwb"); if (!fp) die ("es_fopenmem failed: %s\n", gpg_strerror (gpg_error_from_syserror ())); state = gpgrt_b64enc_start (fp, title); if (!state) { err = gpg_err_code_from_syserror (); fail ("gpgrt_b64enc_start failed: %s\n", gpg_strerror (err)); return err; } err = gpgrt_b64enc_write (state, string, strlen (string)); if (err) { fail ("gpgrt_b64enc_write failed: %s\n", gpg_strerror (err)); return err; } err = gpgrt_b64enc_finish (state); if (err) { fail ("gpgrt_b64enc_finish failed: %s\n", gpg_strerror (err)); return err; } es_fputc (0, fp); if (es_fclose_snatch (fp, (void**)&result, NULL)) die ("es_fclose_snatch failed: %s\n", gpg_strerror (gpg_error_from_syserror ())); if (strcmp (result, expected)) { if (verbose) { gpgrt_log_debug_string (result, "result: "); gpgrt_log_debug_string (expected, "expect: "); } return GPG_ERR_FALSE; } es_free (result); return 0; } static gpg_error_t test_b64dec_string (const char *string, const char *expected, const char *title) { gpg_error_t err; gpgrt_b64state_t state; char *buffer; size_t len; len = strlen (string); buffer = malloc (strlen (string) + 1); if (!buffer) { err = gpg_error_from_syserror (); return err; } strcpy (buffer, string); state = gpgrt_b64dec_start (title); if (!state) { err = gpg_err_code_from_syserror (); fail ("gpgrt_b64dec_start failed: %s\n", gpg_strerror (err)); return err; } err = gpgrt_b64dec_proc (state, buffer, len, &len); if (err) { if (gpg_err_code (err) != GPG_ERR_EOF) { free (buffer); free (state); return err; } } err = gpgrt_b64dec_finish (state); if (err) { free (buffer); return err; } if (len != strlen (expected) || strncmp (buffer, expected, len)) { if (verbose) { gpgrt_log_debug_string (buffer, "result(len=%zu): ", len); gpgrt_log_debug_string (expected, "expect(len=%zu): ", strlen (expected)); } return GPG_ERR_FALSE; } free (buffer); return 0; } static void encoder_tests (void) { gpg_err_code_t err; if (verbose) show ("running encoder tests\n"); err = test_b64enc_string (test_string, test_string_b64_0, ""); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string (test_string, test_string_b64_1, NULL); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string (test_string, test_string_b64_2, "DATA"); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string (test_string, test_string_b64_3, "PGP ARMORED FILE"); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); /* Note that the _test_ function dows not allow to provide a string * with an empdded Nul. */ err = test_b64enc_string (test_blob_1, test_blob_1_b64_0, ""); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string (test_blob_2, test_blob_2_b64_0, ""); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string (test_blob_3, test_blob_3_b64_0, ""); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string ("@", "QA==", ""); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string ("@", "QA==\n", NULL); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string ("@", "-----BEGIN PGP SOMETHING-----\n" "\n" "QA==\n" "=eMoB\n" "-----END PGP SOMETHING-----\n", "PGP SOMETHING"); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string ("", "", ""); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string ("", "", NULL); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64enc_string ("", "", "PGP SOMETHING"); if (err) fail ("encoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); } static void decoder_tests (void) { gpg_err_code_t err; if (verbose) show ("running decoder tests\n"); err = test_b64dec_string (test_string_b64_0, test_string, NULL); if (err) fail ("decoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64dec_string (test_string_b64_1, test_string, NULL); if (err) fail ("decoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64dec_string (test_string_b64_2, test_string, ""); if (err) fail ("decoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); err = test_b64dec_string (test_string_b64_2, test_string, NULL); if (err != GPG_ERR_BAD_DATA) fail ("decoder test at line %d failed: %s\n", __LINE__, gpg_strerror (err)); } static gpg_error_t extra_tests (void) { gpg_err_code_t err; gpgrt_b64state_t state; if (verbose) show ("running extra tests\n"); /* Check that we detect mismacthed use of enc and dec functions. */ state = gpgrt_b64enc_start (es_stdout, NULL); if (!state) { err = gpg_err_code_from_syserror (); fail ("gpgrt_b64enc_start failed: %s\n", gpg_strerror (err)); return err; } err = gpgrt_b64dec_finish (state); if (err != GPG_ERR_CONFLICT) { fail ("gpgrt_b64dec_finish failed: %s\n", gpg_strerror (err)); return err; } state = gpgrt_b64dec_start (NULL); if (!state) { err = gpg_err_code_from_syserror (); fail ("gpgrt_b64dec_start failed: %s\n", gpg_strerror (err)); return err; } err = gpgrt_b64enc_finish (state); if (err != GPG_ERR_CONFLICT) { fail ("gpgrt_b64enc_finish failed: %s\n", gpg_strerror (err)); return err; } return 0; } int main (int argc, char **argv) { int last_argc = -1; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--help")) { puts ( "usage: ./" PGM " [options]\n" "\n" "Options:\n" " --verbose Show what is going on\n" " --debug Flyswatter\n" ); exit (0); } if (!strcmp (*argv, "--verbose")) { verbose = 1; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose = debug = 1; argc--; argv++; } } encoder_tests (); decoder_tests (); extra_tests (); return !!errorcount; }