g13: Add functions to handle uint in a keyblob.

* g13/utils.c (append_tuple_uint): New.
(find_tuple_uint): New.
* g13/t-utils.c: New.
* g13/Makefile.am (noinst_PROGRAMS, TESTS): New.
(module_tests, t_common_ldadd): New.
(t_utils_SOURCES, t_utils_LDADD): New.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-02-10 20:44:19 +01:00
parent dc1dbc43a6
commit 4f152f3276
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
4 changed files with 318 additions and 4 deletions

View File

@ -23,6 +23,9 @@ EXTRA_DIST = ChangeLog-2011
bin_PROGRAMS = g13
sbin_PROGRAMS = g13-syshelp
noinst_PROGRAMS = $(module_tests)
TESTS = $(module_tests)
AM_CPPFLAGS = -I$(top_srcdir)/common
include $(top_srcdir)/am/cmacros.am
@ -61,3 +64,14 @@ g13_syshelp_SOURCES = \
g13_syshelp_LDADD = $(libcommon) \
$(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) \
$(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)
module_tests = t-utils
t_common_ldadd = $(libcommon) $(LIBGCRYPT_LIBS) \
$(LIBASSUAN_LIBS)
t_utils_SOURCES = t-utils.c utils.c
t_utils_LDADD = $(t_common_ldadd)
$(PROGRAMS) : $(libcommon) $(libcommonpth)

223
g13/t-utils.c Normal file
View File

@ -0,0 +1,223 @@
/* t-utils.c - Module test for utils.c
* Copyright (C) 2016 Werner Koch
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "util.h"
#include "keyblob.h"
#include "utils.h"
#define PGM "t-utils"
static int verbose;
static int debug;
static int errcount;
/* Test for the functions append_tuple_uint and find_tuple_unit. */
static void
test_tuple_uint (void)
{
static struct {
int tag;
int len;
char *data;
unsigned long long val;
gpg_err_code_t ec;
} tv[] = {
{ 1, 0, "", 0, GPG_ERR_ERANGE },
{ 2, 1, "\x00", 0, 0},
{ 3, 1, "\x7f", 127ull, 0},
{ 4, 1, "\x80", 0, GPG_ERR_ERANGE },
{ 5, 1, "\x81", 0, GPG_ERR_ERANGE },
{ 6, 2, "\x80\x01", 0, GPG_ERR_ERANGE },
{ 7, 2, "\x00\x80", 128ull, 0 },
{ 8, 1, "\x01", 1, 0 },
{ 9, 1, "\x40", 64, 0 },
{ 10, 2, "\x40\x00", 16384, 0 },
{ 11, 8, "\x7f\xff\xff\xff\xff\xff\xff\xff", 0x7fffffffffffffffull, 0 },
{ 12, 9, "\x00\xff\xff\xff\xff\xff\xff\xff\xff", 0xffffffffffffffffull, 0},
{ 13, 9, "\x01\xff\xff\xff\xff\xff\xff\xff\xff", 0, GPG_ERR_ERANGE }
};
int tidx;
gpg_error_t err;
membuf_t mb, mb2;
void *p;
const void *s;
size_t n;
tupledesc_t tuples;
tupledesc_t tuples2;
unsigned long long value;
int i;
init_membuf (&mb, 512);
init_membuf (&mb2, 512);
append_tuple (&mb, KEYBLOB_TAG_BLOBVERSION, "\x01", 1);
append_tuple (&mb2, KEYBLOB_TAG_BLOBVERSION, "\x01", 1);
for (tidx=0; tidx < DIM (tv); tidx++)
{
append_tuple (&mb, tv[tidx].tag, tv[tidx].data, tv[tidx].len);
if (!tv[tidx].ec)
append_tuple_uint (&mb2, tv[tidx].tag, tv[tidx].val);
}
p = get_membuf (&mb, &n);
if (!p)
{
err = gpg_error_from_syserror ();
fprintf (stderr, PGM ":%s: get_membuf failed: %s\n",
__func__, gpg_strerror (err));
exit (1);
}
err = create_tupledesc (&tuples, p, n);
if (err)
{
fprintf (stderr, PGM ":%s: create_tupledesc failed: %s\n",
__func__, gpg_strerror (err));
exit (1);
}
p = get_membuf (&mb2, &n);
if (!p)
{
err = gpg_error_from_syserror ();
fprintf (stderr, PGM ":%s: get_membuf failed: %s\n",
__func__, gpg_strerror (err));
exit (1);
}
err = create_tupledesc (&tuples2, p, n);
if (err)
{
fprintf (stderr, PGM ":%s: create_tupledesc failed: %s\n",
__func__, gpg_strerror (err));
exit (1);
}
for (tidx=0; tidx < DIM (tv); tidx++)
{
err = find_tuple_uint (tuples, tv[tidx].tag, &value);
if (tv[tidx].ec != gpg_err_code (err))
{
fprintf (stderr, PGM ":%s:tidx=%d: wrong error returned; "
"expected(%s) got(%s)\n",
__func__, tidx,
gpg_strerror (tv[tidx].ec), gpg_strerror (err));
errcount++;
}
else if (!err && tv[tidx].val != value)
{
fprintf (stderr, PGM ":%s:tidx=%d: wrong value returned; "
"expected(%llx) got(%llx)\n",
__func__, tidx, tv[tidx].val, value);
errcount++;
}
err = find_tuple_uint (tuples2, tv[tidx].tag, &value);
if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
{
if (!tv[tidx].ec)
{
fprintf (stderr, PGM ":%s:tidx=%d: find_tuple failed: %s\n",
__func__, tidx, gpg_strerror (err));
errcount++;
}
}
else if (tv[tidx].ec != gpg_err_code (err))
{
fprintf (stderr, PGM ":%s:tidx=%d: wrong error returned (2); "
"expected(%s) got(%s)\n",
__func__, tidx,
gpg_strerror (tv[tidx].ec), gpg_strerror (err));
errcount++;
}
else if (!err && tv[tidx].val != value)
{
fprintf (stderr, PGM ":%s:tidx=%d: wrong value returned (2); "
"expected(%llx) got(%llx)\n",
__func__, tidx, tv[tidx].val, value);
errcount++;
}
s = find_tuple (tuples2, tv[tidx].tag, &n);
if (!s)
;
else if (tv[tidx].len != n)
{
fprintf (stderr, PGM ":%s:tidx=%d: wrong string length returned; "
"expected(%d) got(%zu)\n",
__func__, tidx, tv[tidx].len, n);
errcount++;
}
else if (memcmp (tv[tidx].data, s, n))
{
fprintf (stderr, PGM ":%s:tidx=%d: wrong string returned:",
__func__, tidx);
for (i=0; i < n; i++)
fprintf (stderr, " %02x", ((unsigned char*)s)[i]);
fputc ('\n', stderr);
errcount++;
}
}
destroy_tupledesc (tuples);
destroy_tupledesc (tuples2);
}
int
main (int argc, char **argv)
{
int last_argc = -1;
gpgrt_init ();
if (argc)
{ argc--; argv++; }
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose += 2;
debug++;
argc--; argv++;
}
else if (!strncmp (*argv, "--", 2))
{
fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
exit (1);
}
}
test_tuple_uint ();
return !!errcount;
}

View File

@ -1,5 +1,6 @@
/* utils.c - Utility functions
* Copyright (C) 2009 Free Software Foundation, Inc.
* Copyright (C) 2009, 2015, 2016 Werner Koch
*
* This file is part of GnuPG.
*
@ -61,10 +62,45 @@ append_tuple (membuf_t *membuf, int tag, const void *value, size_t length)
}
/* Append the unsigned integer VALUE under TAG to MEMBUF. We make
* sure that the most significant bit is always cleared to explicitly
* flag the value as unsigned. */
void
append_tuple_uint (membuf_t *membuf, int tag, unsigned long long value)
{
unsigned char buf[16];
unsigned char *p;
unsigned int len;
p = buf + sizeof buf;
len = 0;
do
{
if (p == buf)
BUG () ;
*--p = (value & 0xff);
value >>= 8;
len++;
}
while (value);
/* Prepend a zero byte if the first byte has its MSB set. */
if ((*p & 0x80))
{
if (p == buf)
BUG () ;
*--p = 0;
len++;
}
append_tuple (membuf, tag, p, len);
}
/* Create a tuple object by moving the ownership of (DATA,DATALEN) to
a new object. Returns 0 on success and stores the new object at
R_TUPLEHD. The return object must be released using
destroy_tuples(). */
* a new object. Returns 0 on success and stores the new object at
* R_TUPLEHD. The return object must be released using
* destroy_tuples(). */
gpg_error_t
create_tupledesc (tupledesc_t *r_desc, void *data, size_t datalen)
{
@ -108,7 +144,7 @@ ref_tupledesc (tupledesc_t tupledesc)
/* Find the first tuple with tag TAG. On success return a pointer to
its value and store the length of the value at R_LENGTH. If no
tuple was return NULL. For future use by next_tupe, the last
tuple was found return NULL. For use by next_tuple, the last
position is stored in the descriptor. */
const void *
find_tuple (tupledesc_t tupledesc, unsigned int tag, size_t *r_length)
@ -147,6 +183,43 @@ find_tuple (tupledesc_t tupledesc, unsigned int tag, size_t *r_length)
}
/* Similar to find-tuple but expects an unsigned int value and stores
* that at R_VALUE. If the tag was not found GPG_ERR_NOT_FOUND is
* returned and 0 stored at R_VALUE. If the value cannot be converted
* to an unsigned integer GPG_ERR_ERANGE is returned. */
gpg_error_t
find_tuple_uint (tupledesc_t tupledesc, unsigned int tag,
unsigned long long *r_value)
{
const unsigned char *s;
size_t n;
unsigned long long value = 0;
*r_value = 0;
s = find_tuple (tupledesc, tag, &n);
if (!s)
return gpg_error (GPG_ERR_NOT_FOUND);
if (!n || (*s & 0x80)) /* No bytes or negative. */
return gpg_error (GPG_ERR_ERANGE);
if (n && !*s) /* Skip a leading zero. */
{
n--;
s++;
}
if (n > sizeof value)
return gpg_error (GPG_ERR_ERANGE);
for (; n; n--, s++)
{
value <<= 8;
value |= *s;
}
*r_value = value;
return 0;
}
const void *
next_tuple (tupledesc_t tupledesc, unsigned int *r_tag, size_t *r_length)
{

View File

@ -25,6 +25,8 @@
/* Append a new tuple to a memory buffer. */
void append_tuple (membuf_t *membuf,
int tag, const void *value, size_t length);
void append_tuple_uint (membuf_t *membuf, int tag,
unsigned long long value);
/* The tuple descriptor object. */
struct tupledesc_s;
@ -36,6 +38,8 @@ void destroy_tupledesc (tupledesc_t tupledesc);
tupledesc_t ref_tupledesc (tupledesc_t tupledesc);
const void *find_tuple (tupledesc_t tupledesc,
unsigned int tag, size_t *r_length);
gpg_error_t find_tuple_uint (tupledesc_t tupledesc, unsigned int tag,
unsigned long long *r_value);
const void *next_tuple (tupledesc_t tupledesc,
unsigned int *r_tag, size_t *r_length);