summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2018-03-22 17:20:52 +0100
committerWerner Koch <wk@gnupg.org>2018-03-22 17:38:24 +0100
commitffc8f805165a13d16ed227051c59d732117ec9d4 (patch)
tree61c75b91c4da65929381313489c7e00715015cea
parentb3df10d6620894bc4047af1e14239b258e440803 (diff)
downloadlibgpg-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--NEWS15
-rw-r--r--src/Makefile.am2
-rw-r--r--src/b64dec.c43
-rw-r--r--src/b64enc.c228
-rw-r--r--src/gpg-error.def.in4
-rw-r--r--src/gpg-error.h.in14
-rw-r--r--src/gpg-error.vers5
-rw-r--r--src/gpgrt-int.h26
-rw-r--r--src/visibility.c18
-rw-r--r--src/visibility.h6
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/t-b64.c373
-rw-r--r--tests/t-b64dec.c123
13 files changed, 567 insertions, 292 deletions
diff --git a/NEWS b/NEWS
index e21f534..de551f4 100644
--- a/NEWS
+++ b/NEWS
@@ -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;
-}