diff options
author | Werner Koch <wk@gnupg.org> | 2018-03-22 17:20:52 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2018-03-22 17:38:24 +0100 |
commit | ffc8f805165a13d16ed227051c59d732117ec9d4 (patch) | |
tree | 61c75b91c4da65929381313489c7e00715015cea | |
parent | b3df10d6620894bc4047af1e14239b258e440803 (diff) | |
download | libgpg-error-ffc8f805165a13d16ed227051c59d732117ec9d4.tar.gz |
core: Add Base-64 encoder.
* src/b64enc.c: Change to fit into libgpg-error.
* src/Makefile.am: Add b64enc.c
* src/b64dec.c: Use xtrymalloc etc. Always use gpg_err_code_t.
(_gpgrt_b64dec_start): Set decoder flag
(_gpgrt_b64dec_finish): Check for conflict.
(_gpgrt_b64state): Move to ...
* src/gpgrt-int.h: here. Add new fields.
* src/visibility.c (gpgrt_b64enc_start): New.
(gpgrt_b64enc_write): New.
(gpgrt_b64enc_finish): New.
* src/gpg-error.vers, src/gpg-error.def.in: Add new functions.
* src/gpg-error.h.in: Ditto.
* src/visibility.h: Ditto.
* tests/t-b64dec.c: Remove.
* tests/t-b64.c: New.
* tests/Makefile.am (TESTS): Replace t-b64dec by t-b64.
--
Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r-- | NEWS | 15 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/b64dec.c | 43 | ||||
-rw-r--r-- | src/b64enc.c | 228 | ||||
-rw-r--r-- | src/gpg-error.def.in | 4 | ||||
-rw-r--r-- | src/gpg-error.h.in | 14 | ||||
-rw-r--r-- | src/gpg-error.vers | 5 | ||||
-rw-r--r-- | src/gpgrt-int.h | 26 | ||||
-rw-r--r-- | src/visibility.c | 18 | ||||
-rw-r--r-- | src/visibility.h | 6 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/t-b64.c | 373 | ||||
-rw-r--r-- | tests/t-b64dec.c | 123 |
13 files changed, 567 insertions, 292 deletions
@@ -4,13 +4,16 @@ Noteworthy changes in version 1.29 (unreleased) [C23/A23/R_] * Interface changes relative to the 1.28 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - gpgrt_argparse New API. - gpgrt_usage New API. - gpgrt_strusage New API. - gpgrt_set_strusage New API. - gpgrt_set_usage_outfnc New API. - gpgrt_set_fixed_string_mapper New API. + gpgrt_argparse New. + gpgrt_usage New. + gpgrt_strusage New. + gpgrt_set_strusage New. + gpgrt_set_usage_outfnc New. + gpgrt_set_fixed_string_mapper New. GPGRT_ENABLE_ARGPARSE_MACROS New macro. + gpgrt_b64enc_start New. + gpgrt_b64enc_write New. + gpgrt_b64enc_finish New. Noteworthy changes in version 1.28 (2018-03-13) [C23/A23/R0] diff --git a/src/Makefile.am b/src/Makefile.am index 66c4414..42998e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -190,7 +190,7 @@ libgpg_error_la_SOURCES = gettext.h $(arch_sources) \ sysutils.c \ syscall-clamp.c \ logging.c \ - b64dec.c \ + b64dec.c b64enc.c \ argparse.c diff --git a/src/b64dec.c b/src/b64dec.c index a8a8351..1235406 100644 --- a/src/b64dec.c +++ b/src/b64dec.c @@ -2,7 +2,7 @@ * Copyright (C) 2008, 2011 Free Software Foundation, Inc. * Copyright (C) 2008, 2011, 2016 g10 Code GmbH * - * This file is part of GnuPG. + * 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 @@ -16,26 +16,18 @@ * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This file was originally a part of GnuPG. */ #include <config.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <assert.h> #include "gpgrt-int.h" -struct _gpgrt_b64state -{ - int idx; - int quad_count; - char *title; - unsigned char radbuf[4]; - int stop_seen:1; - int invalid_encoding:1; - gpg_error_t lasterr; -}; /* The reverse base-64 list used for base-64 decoding. */ static unsigned char const asctobin[128] = @@ -79,15 +71,15 @@ _gpgrt_b64dec_start (const char *title) if (title) { - t = strdup (title); + t = xtrystrdup (title); if (!t) return NULL; } - state = calloc (1, sizeof (struct _gpgrt_b64state)); + state = xtrycalloc (1, sizeof (struct _gpgrt_b64state)); if (!state) { - free (t); + xfree (t); return NULL; } @@ -99,13 +91,15 @@ _gpgrt_b64dec_start (const char *title) else state->idx = s_b64_0; + state->using_decoder = 1; + return state; } /* Do in-place decoding of base-64 data of LENGTH in BUFFER. Stores the new length of the buffer at R_NBYTES. */ -gpg_error_t +gpg_err_code_t _gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, size_t length, size_t *r_nbytes) { @@ -120,8 +114,8 @@ _gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, size_t length, if (state->stop_seen) { *r_nbytes = 0; - state->lasterr = gpg_error (GPG_ERR_EOF); - free (state->title); + state->lasterr = GPG_ERR_EOF; + xfree (state->title); state->title = NULL; return state->lasterr; } @@ -247,7 +241,7 @@ _gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, size_t length, state->stop_seen = 1; break; default: - assert (!"invalid state"); + gpgrt_assert (!"invalid state"); } } @@ -262,17 +256,22 @@ _gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, size_t length, /* Return an error code in case an encoding error has been found during decoding. */ -gpg_error_t +gpg_err_code_t _gpgrt_b64dec_finish (gpgrt_b64state_t state) { gpg_error_t err; - if (state->lasterr) + if (!state) + return 0; /* Already released. */ + + if (!state->using_decoder) + err = GPG_ERR_CONFLICT; /* State was allocated for the encoder. */ + else if (state->lasterr) err = state->lasterr; else { free (state->title); - err = state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0; + err = state->invalid_encoding? GPG_ERR_BAD_DATA : 0; } free (state); diff --git a/src/b64enc.c b/src/b64enc.c index 91960c7..571f4ec 100644 --- a/src/b64enc.c +++ b/src/b64enc.c @@ -2,9 +2,9 @@ * Copyright (C) 2001, 2003, 2004, 2008, 2010, * 2011 Free Software Foundation, Inc. * Copyright (C) 2001, 2003, 2004, 2008, 2010, - * 2011 g10 Code GmbH + * 2011, 2018 g10 Code GmbH * - * This file is part of GnuPG. + * 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 @@ -18,17 +18,20 @@ * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This file was originally a part of GnuPG. */ #include <config.h> #include <stdio.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> #include <errno.h> -#include <assert.h> -#include "i18n.h" -#include "util.h" +#include "gpgrt-int.h" + #define B64ENC_DID_HEADER 1 #define B64ENC_DID_TRAILER 2 @@ -36,9 +39,9 @@ #define B64ENC_USE_PGPCRC 32 /* The base-64 character list */ -static unsigned char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; +static unsigned char const bintoasc[64] = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"); /* Stuff required to create the OpenPGP CRC. This crc_table has been created using this code: @@ -92,7 +95,7 @@ static unsigned char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" } */ #define CRCINIT 0xB704CE -static const u32 crc_table[256] = { +static const uint32_t crc_table[256] = { 0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a, 0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf, 0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272, @@ -139,14 +142,28 @@ static const u32 crc_table[256] = { }; -static gpg_error_t -enc_start (struct b64state *state, FILE *fp, estream_t stream, - const char *title) +/* Prepare for Base-64 writing to STREAM. If TITLE is not NULL and + * not an empty string, that string will be used as the title for the + * armor lines, with TITLE being an empty string, we don't write the + * header lines and furthermore even don't write any linefeeds. If + * TITLE starts with "PGP " the OpenPGP CRC checksum will be written + * as well. With TITLE being NULL, we merely don't write header but + * make sure that lines are not too long. Note, that we don't write + * anything unless at least one byte is written using b64enc_write. + * On success an enoder object is returned which needs to be released + * using _gpgrt_b64dec_finish. On error NULL is returned an ERRNO is + * set. + */ +gpgrt_b64state_t +_gpgrt_b64enc_start (estream_t stream, const char *title) { - memset (state, 0, sizeof *state); - state->fp = fp; + gpgrt_b64state_t state; + + state = xtrycalloc (1, sizeof *state); + if (!state) + return NULL; + state->stream = stream; - state->lasterr = 0; if (title && !*title) state->flags |= B64ENC_NO_LINEFEEDS; else if (title) @@ -158,50 +175,21 @@ enc_start (struct b64state *state, FILE *fp, estream_t stream, } state->title = xtrystrdup (title); if (!state->title) - state->lasterr = gpg_error_from_syserror (); + { + xfree (state); + return NULL; + } } - return state->lasterr; -} - - -/* Prepare for base-64 writing to the stream FP. If TITLE is not NULL - and not an empty string, this string will be used as the title for - the armor lines, with TITLE being an empty string, we don't write - the header lines and furthermore even don't write any linefeeds. - If TITLE starts with "PGP " the OpenPGP CRC checksum will be - written as well. With TITLE being NULL, we merely don't write - header but make sure that lines are not too long. Note, that we - don't write any output unless at least one byte get written using - b64enc_write. */ -gpg_error_t -b64enc_start (struct b64state *state, FILE *fp, const char *title) -{ - return enc_start (state, fp, NULL, title); -} - -/* Same as b64enc_start but takes an estream. */ -gpg_error_t -b64enc_start_es (struct b64state *state, estream_t fp, const char *title) -{ - return enc_start (state, NULL, fp, title); -} - -static int -my_fputs (const char *string, struct b64state *state) -{ - if (state->stream) - return es_fputs (string, state->stream); - else - return fputs (string, state->fp); + return state; } -/* Write NBYTES from BUFFER to the Base 64 stream identified by - STATE. With BUFFER and NBYTES being 0, merely do a fflush on the - stream. */ -gpg_error_t -b64enc_write (struct b64state *state, const void *buffer, size_t nbytes) +/* Write NBYTES from BUFFER to the Base 64 stream identified by STATE. + * With BUFFER and NBYTES being 0, merely do a fflush on the stream. + */ +gpg_err_code_t +_gpgrt_b64enc_write (gpgrt_b64state_t state, const void *buffer, size_t nbytes) { unsigned char radbuf[4]; int idx, quad_count; @@ -213,7 +201,7 @@ b64enc_write (struct b64state *state, const void *buffer, size_t nbytes) if (!nbytes) { if (buffer) - if (state->stream? es_fflush (state->stream) : fflush (state->fp)) + if (_gpgrt_fflush (state->stream)) goto write_error; return 0; } @@ -222,12 +210,12 @@ b64enc_write (struct b64state *state, const void *buffer, size_t nbytes) { if (state->title) { - if ( my_fputs ("-----BEGIN ", state) == EOF - || my_fputs (state->title, state) == EOF - || my_fputs ("-----\n", state) == EOF) + if ( _gpgrt_fputs ("-----BEGIN ", state->stream) == EOF + || _gpgrt_fputs (state->title, state->stream) == EOF + || _gpgrt_fputs ("-----\n", state->stream) == EOF) goto write_error; if ( (state->flags & B64ENC_USE_PGPCRC) - && my_fputs ("\n", state) == EOF) + && _gpgrt_fputs ("\n", state->stream) == EOF) goto write_error; } @@ -236,16 +224,16 @@ b64enc_write (struct b64state *state, const void *buffer, size_t nbytes) idx = state->idx; quad_count = state->quad_count; - assert (idx < 4); + gpgrt_assert (idx < 4); memcpy (radbuf, state->radbuf, idx); if ( (state->flags & B64ENC_USE_PGPCRC) ) { size_t n; - u32 crc = state->crc; + uint32_t crc = state->crc; for (p=buffer, n=nbytes; n; p++, n-- ) - crc = ((u32)crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ *p]; + crc = ((uint32_t)crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ *p]; state->crc = (crc & 0x00ffffff); } @@ -260,27 +248,17 @@ b64enc_write (struct b64state *state, const void *buffer, size_t nbytes) tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; tmp[3] = bintoasc[radbuf[2]&077]; - if (state->stream) - { - for (idx=0; idx < 4; idx++) - es_putc (tmp[idx], state->stream); - idx = 0; - if (es_ferror (state->stream)) - goto write_error; - } - else - { - for (idx=0; idx < 4; idx++) - putc (tmp[idx], state->fp); - idx = 0; - if (ferror (state->fp)) - goto write_error; - } + for (idx=0; idx < 4; idx++) + _gpgrt_fputc (tmp[idx], state->stream); + idx = 0; + if (_gpgrt_ferror (state->stream)) + goto write_error; + if (++quad_count >= (64/4)) { quad_count = 0; if (!(state->flags & B64ENC_NO_LINEFEEDS) - && my_fputs ("\n", state) == EOF) + && _gpgrt_fputs ("\n", state->stream) == EOF) goto write_error; } } @@ -291,7 +269,7 @@ b64enc_write (struct b64state *state, const void *buffer, size_t nbytes) return 0; write_error: - state->lasterr = gpg_error_from_syserror (); + state->lasterr = _gpg_err_code_from_syserror (); if (state->title) { xfree (state->title); @@ -301,16 +279,28 @@ b64enc_write (struct b64state *state, const void *buffer, size_t nbytes) } -gpg_error_t -b64enc_finish (struct b64state *state) +gpg_err_code_t +_gpgrt_b64enc_finish (gpgrt_b64state_t state) { - gpg_error_t err = 0; + gpg_err_code_t err = 0; unsigned char radbuf[4]; int idx, quad_count; char tmp[4]; + if (!state) + return 0; /* Already released. */ + + if (state->using_decoder) + { + err = GPG_ERR_CONFLICT; /* State was created for the decoder. */ + goto cleanup; + } + if (state->lasterr) - return state->lasterr; + { + err = state->lasterr; + goto cleanup; + } if (!(state->flags & B64ENC_DID_HEADER)) goto cleanup; @@ -318,7 +308,7 @@ b64enc_finish (struct b64state *state) /* Flush the base64 encoding */ idx = state->idx; quad_count = state->quad_count; - assert (idx < 4); + gpgrt_assert (idx < 4); memcpy (radbuf, state->radbuf, idx); if (idx) @@ -336,26 +326,16 @@ b64enc_finish (struct b64state *state) tmp[2] = bintoasc[((radbuf[1] << 2) & 074) & 077]; tmp[3] = '='; } - if (state->stream) - { - for (idx=0; idx < 4; idx++) - es_putc (tmp[idx], state->stream); - if (es_ferror (state->stream)) - goto write_error; - } - else - { - for (idx=0; idx < 4; idx++) - putc (tmp[idx], state->fp); - if (ferror (state->fp)) - goto write_error; - } + for (idx=0; idx < 4; idx++) + _gpgrt_fputc (tmp[idx], state->stream); + if (_gpgrt_ferror (state->stream)) + goto write_error; if (++quad_count >= (64/4)) { quad_count = 0; if (!(state->flags & B64ENC_NO_LINEFEEDS) - && my_fputs ("\n", state) == EOF) + && _gpgrt_fputs ("\n", state->stream) == EOF) goto write_error; } } @@ -363,13 +343,13 @@ b64enc_finish (struct b64state *state) /* Finish the last line and write the trailer. */ if (quad_count && !(state->flags & B64ENC_NO_LINEFEEDS) - && my_fputs ("\n", state) == EOF) + && _gpgrt_fputs ("\n", state->stream) == EOF) goto write_error; if ( (state->flags & B64ENC_USE_PGPCRC) ) { /* Write the CRC. */ - my_fputs ("=", state); + _gpgrt_fputs ("=", state->stream); radbuf[0] = state->crc >>16; radbuf[1] = state->crc >> 8; radbuf[2] = state->crc; @@ -377,46 +357,30 @@ b64enc_finish (struct b64state *state) tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077]; tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; tmp[3] = bintoasc[radbuf[2]&077]; - if (state->stream) - { - for (idx=0; idx < 4; idx++) - es_putc (tmp[idx], state->stream); - if (es_ferror (state->stream)) - goto write_error; - } - else - { - for (idx=0; idx < 4; idx++) - putc (tmp[idx], state->fp); - if (ferror (state->fp)) - goto write_error; - } + for (idx=0; idx < 4; idx++) + _gpgrt_fputc (tmp[idx], state->stream); + if (_gpgrt_ferror (state->stream)) + goto write_error; + if (!(state->flags & B64ENC_NO_LINEFEEDS) - && my_fputs ("\n", state) == EOF) + && _gpgrt_fputs ("\n", state->stream) == EOF) goto write_error; } if (state->title) { - if ( my_fputs ("-----END ", state) == EOF - || my_fputs (state->title, state) == EOF - || my_fputs ("-----\n", state) == EOF) + if ( _gpgrt_fputs ("-----END ", state->stream) == EOF + || _gpgrt_fputs (state->title, state->stream) == EOF + || _gpgrt_fputs ("-----\n", state->stream) == EOF) goto write_error; } - goto cleanup; + cleanup: + xfree (state->title); + xfree (state); + return err; write_error: err = gpg_error_from_syserror (); - - cleanup: - if (state->title) - { - xfree (state->title); - state->title = NULL; - } - state->fp = NULL; - state->stream = NULL; - state->lasterr = err; - return err; + goto cleanup; } diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in index 33ef794..67bb12e 100644 --- a/src/gpg-error.def.in +++ b/src/gpg-error.def.in @@ -214,5 +214,9 @@ EXPORTS gpgrt_set_usage_outfnc @164 gpgrt_set_fixed_string_mapper @165 + gpgrt_b64enc_start @166 + gpgrt_b64enc_write @167 + gpgrt_b64enc_finish @168 + ;; end of file with public symbols for Windows. diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index c0656e2..a36e8b1 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -908,16 +908,22 @@ int gpgrt_vsnprintf (char *buf,size_t bufsize, /* - * Base64 decode functions. + * Base64 encode and decode functions. */ struct _gpgrt_b64state; typedef struct _gpgrt_b64state *gpgrt_b64state_t; +gpgrt_b64state_t gpgrt_b64enc_start (gpgrt_stream_t stream, const char *title); +gpg_err_code_t gpgrt_b64enc_write (gpgrt_b64state_t state, + const void *buffer, size_t nbytes); +gpg_err_code_t gpgrt_b64enc_finish (gpgrt_b64state_t state); + gpgrt_b64state_t gpgrt_b64dec_start (const char *title); -gpg_error_t gpgrt_b64dec_proc (gpgrt_b64state_t state, - void *buffer, size_t length, size_t *r_nbytes); -gpg_error_t gpgrt_b64dec_finish (gpgrt_b64state_t state); +gpg_error_t gpgrt_b64dec_proc (gpgrt_b64state_t state, + void *buffer, size_t length, + size_t *r_nbytes); +gpg_error_t gpgrt_b64dec_finish (gpgrt_b64state_t state); diff --git a/src/gpg-error.vers b/src/gpg-error.vers index c7de3c4..201b784 100644 --- a/src/gpg-error.vers +++ b/src/gpg-error.vers @@ -186,6 +186,11 @@ GPG_ERROR_1.0 { gpgrt_set_usage_outfnc; gpgrt_set_fixed_string_mapper; + gpgrt_b64enc_start; + gpgrt_b64enc_write; + gpgrt_b64enc_finish; + + local: *; }; diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h index 5d54a51..34e494c 100644 --- a/src/gpgrt-int.h +++ b/src/gpgrt-int.h @@ -480,10 +480,30 @@ int _gpgrt_w32_poll (gpgrt_poll_t *fds, size_t nfds, int timeout); * Local prototypes for the encoders. */ +struct _gpgrt_b64state +{ + int idx; + int quad_count; + estream_t stream; + char *title; + unsigned char radbuf[4]; + unsigned int crc; + gpg_err_code_t lasterr; + unsigned int flags; + int stop_seen:1; + int invalid_encoding:1; + int using_decoder:1; +}; + +gpgrt_b64state_t _gpgrt_b64enc_start (estream_t stream, const char *title); +gpg_err_code_t _gpgrt_b64enc_write (gpgrt_b64state_t state, + const void *buffer, size_t nbytes); +gpg_err_code_t _gpgrt_b64enc_finish (gpgrt_b64state_t state); + gpgrt_b64state_t _gpgrt_b64dec_start (const char *title); -gpg_error_t _gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, - size_t length, size_t *r_nbytes); -gpg_error_t _gpgrt_b64dec_finish (gpgrt_b64state_t state); +gpg_err_code_t _gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, + size_t length, size_t *r_nbytes); +gpg_err_code_t _gpgrt_b64dec_finish (gpgrt_b64state_t state); diff --git a/src/visibility.c b/src/visibility.c index 315bf32..6f8bb24 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -790,6 +790,24 @@ gpgrt_getcwd (void) gpgrt_b64state_t +gpgrt_b64enc_start (estream_t stream, const char *title) +{ + return _gpgrt_b64enc_start (stream, title); +} + +gpg_err_code_t +gpgrt_b64enc_write (gpgrt_b64state_t state, const void *buffer, size_t nbytes) +{ + return _gpgrt_b64enc_write (state, buffer, nbytes); +} + +gpg_err_code_t +gpgrt_b64enc_finish (gpgrt_b64state_t state) +{ + return _gpgrt_b64enc_finish (state); +} + +gpgrt_b64state_t gpgrt_b64dec_start (const char *title) { return _gpgrt_b64dec_start (title); diff --git a/src/visibility.h b/src/visibility.h index eae0f81..cfa32e5 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -161,6 +161,9 @@ MARK_VISIBLE (gpgrt_getcwd) MARK_VISIBLE (gpgrt_b64dec_start) MARK_VISIBLE (gpgrt_b64dec_proc) MARK_VISIBLE (gpgrt_b64dec_finish) +MARK_VISIBLE (gpgrt_b64enc_start) +MARK_VISIBLE (gpgrt_b64enc_write) +MARK_VISIBLE (gpgrt_b64enc_finish) MARK_VISIBLE (gpgrt_get_errorcount) MARK_VISIBLE (gpgrt_inc_errorcount) @@ -327,6 +330,9 @@ MARK_VISIBLE (gpgrt_set_usage_outfnc); #define gpgrt_get_syscall_clamp _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_set_alloc_func _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_b64enc_start _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_b64enc_write _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_b64enc_finish _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_b64dec_start _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_b64dec_proc _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_b64dec_finish _gpgrt_USE_UNDERSCORED_FUNCTION diff --git a/tests/Makefile.am b/tests/Makefile.am index cc3a2ad..b14fdc8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -27,7 +27,7 @@ endif gpg_error_lib = ../src/libgpg-error.la -TESTS = t-version t-strerror t-syserror t-lock t-printf t-poll t-b64dec \ +TESTS = t-version t-strerror t-syserror t-lock t-printf t-poll t-b64 \ t-argparse AM_CPPFLAGS = -I$(top_builddir)/src $(extra_includes) diff --git a/tests/t-b64.c b/tests/t-b64.c new file mode 100644 index 0000000..96e8fa4 --- /dev/null +++ b/tests/t-b64.c @@ -0,0 +1,373 @@ +/* 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 <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <string.h> +#if HAVE_STDLIB_H +#include <stdlib.h> +#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; +} diff --git a/tests/t-b64dec.c b/tests/t-b64dec.c deleted file mode 100644 index aae208b..0000000 --- a/tests/t-b64dec.c +++ /dev/null @@ -1,123 +0,0 @@ -/* t-b64dec.c - b64dec test. - Copyright (C) 2017 g10 Code GmbH - - This file is part of libgpg-error. - - 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. - - libgpg-error 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 libgpgme-error; if not, write to the Free - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ - -#if HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <string.h> -#if HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#include <gpg-error.h> - -static const char *test_b64_string = "bGliZ3BnLWVycm9yIGlzIGZyZWUgc29" - "mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXQgd" - "W5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljIEx" - "pY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb" - "247IGVpdGhlciB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXI" - "gb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4="; - -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."; - -#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\ - __FILE__,__LINE__, (a)); \ - errcount++; \ - } while(0) - -static int errcount; - -static gpg_error_t -test_b64dec_string (const char *string, const char *expected) -{ - 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; - } - - state = gpgrt_b64dec_start (""); - if (!state) - { - err = gpg_error_from_syserror (); - free (buffer); - 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 (strncmp (buffer, expected, len) == 0) - err = 0; - else - err = GPG_ERR_INTERNAL; - - free (buffer); - return err; -} - - - -int -main (int argc, char **argv) -{ - gpg_error_t err; - - (void)argc; - (void)argv; - - err = test_b64dec_string (test_b64_string, test_string); - - if (err) - { - fail (1); - return 1; - } - else - return 0; -} |