Page MenuHome GnuPG

No OneTemporary

diff --git a/src/ChangeLog b/src/ChangeLog
index 0b80d33e..044b0bd7 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,241 +1,245 @@
+2002-01-11 Werner Koch <wk@gnupg.org>
+
+ * sexp.c (gcry_sexp_canon_len): Fixed last change.
+
2002-01-01 Timo Schulz <ts@winpt.org>
* stdmem.c (_gcry_private_realloc): if pointer is NULL now realloc
behaves like malloc.
2001-12-20 Werner Koch <wk@gnupg.org>
* sexp.c (gcry_sexp_canon_len): Describe the error codes and
return an error if this is not a S-Exp; i.e. it does not start
with an open parenthesis.
2001-12-18 Werner Koch <wk@gnupg.org>
* sexp.c (gcry_sexp_canon_len): Fixed the test on NULL buffer.
* Makefile.am (DISTCLEANFILES): Include libgcrypt.sym
* sexp.c: Removed the commented test code because we now have a
text in ../tests/
2001-12-17 Werner Koch <wk@gnupg.org>
* sexp.c (gcry_sexp_canon_len): New.
2001-12-11 Werner Koch <wk@gnupg.org>
* gcrypt.h: Fixed AES128 macro, add enum for OFB mode.
2001-12-05 Werner Koch <wk@gnupg.org>
* misc.c (_gcry_log_printf): New.
* sexp.c (dump_string,gcry_sexp_dump): Use logging functions
instead of stderr.
2001-11-16 Werner Koch <wk@gnupg.org>
* gcrypt.h: New constant GCRYCTL_IS_ALGO_ENABLED.
2001-10-02 Werner Koch <wk@gnupg.org>
* gcrypt.h: Removed a couple of trailing commas.
2001-08-28 Werner Koch <wk@gnupg.org>
* sexp.c (sexp_sscan): Add an argument to enable the
arg_ptr. Changed all callers. Suggested by Tom Holroyd.
2001-08-03 Werner Koch <wk@gnupg.org>
* global.c (gcry_strerror): Updated list of error codes.
2001-07-23 Werner Koch <wk@gnupg.org>
* gcrypt.h: Replaced the last ulong. Noted by Rami Lehti.
2001-05-31 Werner Koch <wk@gnupg.org>
* gcrypt.h, mpi.h: Made some mpi functions public.
* wrapper.c: Removed.
* global.c: Renamed all g10_ prefixed functions which had wrappers
to gcry_xxx. So we now use the exported memory functions inernally.
Renamed all g10_ prefixed functions to _gcry_ prefixed ones.
* g10lib.h (_GCRYPT_IN_LIBGCRYPT): Replace defintion by a test on it.
2001-05-28 Werner Koch <wk@gnupg.org>
* libgcrypt.m4: Check GCRYPT_VERSION macro and not LIBGCRYPT_VERSION.
* mpi.h: Removed mpi_fromstr prototype.
2001-01-11 Werner Koch <wk@gnupg.org>
* Makefile.am (libgcrypt_la_SOURCES): Add mpi.h
2000-12-19 Werner Koch <wk@gnupg.org>
* types.h: Moved from ../include to here.
Major change:
Removed all GnuPG stuff and renamed this piece of software
to gcrypt.
2000-11-14 Werner Koch <wk@gnupg.org>
* mpi.h: Moved to ../mpi.
* Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency
problems.
2000-10-11 Werner Koch <wk@gnupg.org>
* mpi.h: Changed the way mpi_limb_t is defined.
2000-10-10 Werner Koch <wk@gnupg.org>
* Makefile.am: Take version-info from configure.
2000-10-09 Werner Koch <wk@gnupg.org>
* gcrypt.h: New cipher mode, new algo Arcfour and new error code
GCRYERR_INV_CIPHER_MODE.
* global.c (gcry_strerror): New errorcode.
Wed Oct 4 13:16:18 CEST 2000 Werner Koch <wk@openit.de>
* gcrypt.h (gcry_md_setkey): Replaced macro by function prototype.
Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de>
* gcrypt.h (GCRYCTL_GET_ALGO_USAGE): New.
* secmem.c (secmem_realloc): check for failed secmem_malloc. By
Matt Kraai.
Mon Jul 31 10:04:47 CEST 2000 Werner Koch <wk@openit.de>
* sexp.c: Removed the datalen fields from list tags.
(gcry_sexp_car_data,gcry_sexp_cdr_data,gcry_sexp_car_mpi,
gcry_sexp_cdr_mpi): Removed.
(gcry_sexp_nth,gcry_sexp_nth_data,gcry_sexp_nth_mpi): New.
Fri Jul 28 18:19:11 CEST 2000 Werner Koch <wk@openit.de>
* sexp.c (sexp_sscan): Fixed reallocation to secure memory.
(new_empty_list): Removed
(gcry_sexp_length): New.
(gcry_sexp_enum): Removed.
(normalize): New. Reworked the whole thing to use NULL for an empty list.
(make_space): New instead of the macro.
Tue Jul 25 17:44:15 CEST 2000 Werner Koch <wk@openit.de>
* sexp.c: Major rewrite.
(gcry_sexp_sscan): Reordered arguments. Moved functionality to ..
(sexp_sscan): .. this.
(gcry_sexp_build): New.
(gcry_sexp_new_name_mpi, gcry_sexp_new_name_data, gcry_sexp_new_data,
gcry_sexp_new_mpi): Removed.
Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@>
* gcrypt.h (gcry_md_start_debug, gcry_md_stop_debug): New.
(gcry_ctl_cmds): New control values
* sexp.c (gcry_sexp_sscan): Add hex format parsing.
* secmem.c (lock_pool): Check for ENOSYS return my mlock() on old SCOs.
(pool_is_mmapped): Made volatile.
(lock_pool): No more warning for QNX. By Sam Roberts.
(lock_pool,secmem_init): Additional check for dropped privs.
2000-03-21 09:18:48 Werner Koch (wk@habibti.gnupg.de)
* gcrypt.h (gcry_md_setkey): New.
(GCRY_MD_FLAG_HMAC): New.
Mon Jan 31 16:37:34 CET 2000 Werner Koch <wk@gnupg.de>
* Makefile.am: Add g10lib.h
Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de>
* sexp.c (gcry_sexp_sscan): Allow NULL for erroff.
Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de>
* sexp.c (gcry_sexp_alist): New.
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* secmem.c: Moved from ../util to here.
* secmem.h: New.
* stdmem.c: New. Based on the old ../util/memory.c.
* stdmem.h: New.
Wed Dec 8 21:58:32 CET 1999 Werner Koch <wk@gnupg.de>
* gcrypt.m4: New.
* gcrypt-config: New.
* mpi.h (mpi_get_nbit_info): Removed
(mpi_set_nbit_info): Removed.
(struct gcry_mpi): Removed the nbits field.
* misc.c (g10_log_verbosity): New.
* global.c (g10_xstrdup): New.
* mpiapi.c: Removed.
* mpi.h: Moved from ../include to here. Removed some obsolete
prototypes and the iobuf.h header.
* cipher.h: Moved from ../include to here. Removed the mpi.h header.
* g10lib.h: Moved from ../include to here.
Fri Nov 19 17:15:20 CET 1999 Werner Koch <wk@gnupg.de>
* sexp.c (dump_string): New. Taken from gnupg/util/miscutil.c.
(do_dump_list): s/print_string/dump_string/.
* testapi.c: New.
* mpiapi.c (gcry_mpi_randomize): Use new random API.
Sat Nov 13 17:44:23 CET 1999 Werner Koch <wk@gnupg.de>
* gloabl.c (gcry_control): Add cases for dumping random
and secmem stats.
Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de>
* pkapi.c: Removed.
* symapi.c: Removed.
* g10lib.h: Moved to ../include.
* mdapi.c: Removed.
Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* sexp.c: New.
Tue Dec 8 13:15:16 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* gcrypt.h: New
* mpiapi.c: New
- Copyright 1998,1999,2000,2001 Free Software Foundation, Inc.
+ Copyright 1998,1999,2000,2001,2002 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/src/sexp.c b/src/sexp.c
index 23129c15..085ebc96 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -1,1249 +1,1252 @@
/* sexp.c - S-Expression handling
- * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt 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 2 of the License, or
* (at your option) any later version.
*
* Libgcrypt 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <assert.h>
#define GCRYPT_NO_MPI_MACROS 1
#include "g10lib.h"
#include "memory.h"
typedef struct gcry_sexp *NODE;
typedef unsigned short DATALEN;
struct gcry_sexp {
byte d[1];
};
#define ST_STOP 0
#define ST_DATA 1 /* datalen follows */
#define ST_HINT 2 /* datalen follows */
#define ST_OPEN 3
#define ST_CLOSE 4
#define digitp(p) (*(p) >= '0' && *(p) <= '9')
#define hexdigitp(a) (digitp (a) \
|| (*(a) >= 'A' && *(a) <= 'F') \
|| (*(a) >= 'a' && *(a) <= 'f'))
/* the atoi macros assume that the buffer has only valid digits */
#define atoi_1(p) (*(p) - '0' )
#if 0
static void
dump_mpi( GCRY_MPI a )
{
char buffer[1000];
size_t n = 1000;
if( !a )
fputs("[no MPI]", stderr );
else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) )
fputs("[MPI too large to print]", stderr );
else
fputs( buffer, stderr );
}
#endif
static void
dump_string (const byte *p, size_t n, int delim )
{
for (; n; n--, p++ )
{
if ((*p & 0x80) || iscntrl( *p ) || *p == delim )
{
if( *p == '\n' )
log_printf ("\\n");
else if( *p == '\r' )
log_printf ("\\r");
else if( *p == '\f' )
log_printf ("\\f");
else if( *p == '\v' )
log_printf ("\\v");
else if( *p == '\b' )
log_printf ("\\b");
else if( !*p )
log_printf ("\\0");
else
log_printf ("\\x%02x", *p );
}
else
log_printf ("%c", *p);
}
}
void
gcry_sexp_dump (const GCRY_SEXP a)
{
const byte *p;
int indent = 0;
int type;
if (!a)
{
log_printf ( "[nil]\n");
return;
}
p = a->d;
while ( (type = *p) != ST_STOP )
{
p++;
switch ( type )
{
case ST_OPEN:
log_printf ("%*s[open]\n", 2*indent, "");
indent++;
break;
case ST_CLOSE:
if( indent )
indent--;
log_printf ("%*s[close]\n", 2*indent, "");
break;
case ST_DATA: {
DATALEN n;
memcpy ( &n, p, sizeof n );
p += sizeof n;
log_printf ("%*s[data=\"", 2*indent, "" );
dump_string (p, n, '\"' );
log_printf ("\"]\n");
p += n;
}
break;
default:
log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
break;
}
}
}
/****************
* Pass list through except when it is an empty list - in that case
* return NULL and release the passed list.
*/
static GCRY_SEXP
normalize ( GCRY_SEXP list )
{
char *p;
if ( !list )
return NULL;
p = list->d;
if ( *p == ST_STOP ) {
/* this is "" */
gcry_sexp_release ( list );
return NULL;
}
if( *p == ST_OPEN && p[1] == ST_CLOSE ) {
/* this is "()" */
gcry_sexp_release ( list );
return NULL;
}
return list;
}
/****************
* Release resource of the given SEXP object.
*/
void
gcry_sexp_release( GCRY_SEXP sexp )
{
gcry_free ( sexp );
}
/****************
* Make a pair from lists a and b, don't use a or b later on.
* Special behaviour: If one is a single element list we put the
* element straight into the new pair.
*/
GCRY_SEXP
gcry_sexp_cons( const GCRY_SEXP a, const GCRY_SEXP b )
{
/* NYI: Implementation should be quite easy with our new data representation */
BUG ();
return NULL;
}
/****************
* Make a list from all items in the array the end of the array is marked
* with a NULL. y a NULL
*/
GCRY_SEXP
gcry_sexp_alist( const GCRY_SEXP *array )
{
/* NYI: Implementaion should be quite easy with our new data representation */
BUG ();
return NULL;
}
/****************
* Make a list from all items, the end of list is indicated by a NULL
*/
GCRY_SEXP
gcry_sexp_vlist( const GCRY_SEXP a, ... )
{
/* NYI: Implementaion should be quite easy with our new data representation */
BUG ();
return NULL;
}
/****************
* Append n to the list a
* Returns: a new ist (which maybe a)
*/
GCRY_SEXP
gcry_sexp_append( const GCRY_SEXP a, const GCRY_SEXP n )
{
/* NYI: Implementaion should be quite easy with our new data representation */
BUG ();
return NULL;
}
GCRY_SEXP
gcry_sexp_prepend( const GCRY_SEXP a, const GCRY_SEXP n )
{
/* NYI: Implementaion should be quite easy with our new data representation */
BUG ();
return NULL;
}
/****************
* Locate token in a list. The token must be the car of a sublist.
* Returns: A new list with this sublist or NULL if not found.
*/
GCRY_SEXP
gcry_sexp_find_token( const GCRY_SEXP list, const char *tok, size_t toklen )
{
const byte *p;
DATALEN n;
if ( !list )
return NULL;
if( !toklen )
toklen = strlen(tok);
p = list->d;
while ( *p != ST_STOP ) {
if ( *p == ST_OPEN && p[1] == ST_DATA ) {
const byte *head = p;
p += 2;
memcpy ( &n, p, sizeof n ); p += sizeof n;
if ( n == toklen && !memcmp( p, tok, toklen ) ) { /* found it */
GCRY_SEXP newlist;
byte *d;
int level = 1;
/* look for the end of the list */
for ( p += n; level; p++ ) {
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--; /* compensate for later increment */
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
}
else if ( *p == ST_STOP ) {
BUG ();
}
} while ( level );
n = p - head;
newlist = gcry_xmalloc ( sizeof *newlist + n );
d = newlist->d;
memcpy ( d, head, n ); d += n;
*d++ = ST_STOP;
return normalize ( newlist );
}
p += n;
}
else if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n ); p += sizeof n;
p += n;
}
else
p++;
}
return NULL;
}
/****************
* return the length of the given list
*/
int
gcry_sexp_length( const GCRY_SEXP list )
{
const byte *p;
DATALEN n;
int type;
int length = 0;
int level = 0;
if ( !list )
return 0;
p = list->d;
while ( (type=*p) != ST_STOP ) {
p++;
if ( type == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
if ( !level )
length++;
}
else if ( type == ST_OPEN ) {
if ( !level )
length++;
level++;
}
else if ( type == ST_CLOSE ) {
level--;
}
}
return length;
}
/****************
* Extract the CAR of the given list
*/
GCRY_SEXP
gcry_sexp_nth( const GCRY_SEXP list, int number )
{
const byte *p;
DATALEN n;
GCRY_SEXP newlist;
byte *d;
int level = 0;
if ( !list || list->d[0] != ST_OPEN )
return NULL;
p = list->d;
while ( number > 0 ) {
p++;
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
if ( !level )
number--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
if ( !level )
number--;
}
else if ( *p == ST_STOP ) {
return NULL;
}
}
p++;
if ( *p == ST_DATA ) {
memcpy ( &n, p, sizeof n ); p += sizeof n;
newlist = gcry_xmalloc ( sizeof *newlist + n + 1 );
d = newlist->d;
memcpy ( d, p, n ); d += n;
*d++ = ST_STOP;
}
else if ( *p == ST_OPEN ) {
const byte *head = p;
level = 1;
do {
p++;
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
}
else if ( *p == ST_STOP ) {
BUG ();
}
} while ( level );
n = p + 1 - head;
newlist = gcry_xmalloc ( sizeof *newlist + n );
d = newlist->d;
memcpy ( d, head, n ); d += n;
*d++ = ST_STOP;
}
else
newlist = NULL;
return normalize (newlist);
}
GCRY_SEXP
gcry_sexp_car( const GCRY_SEXP list )
{
return gcry_sexp_nth ( list, 0 );
}
/****************
* Get data from the car. The returned value is valid as long as the list
* is not modified.
*/
const char *
gcry_sexp_nth_data( const GCRY_SEXP list, int number, size_t *datalen )
{
const byte *p;
DATALEN n;
int level = 0;
*datalen = 0;
if ( !list ) {
return NULL;
}
p = list->d;
if ( *p == ST_OPEN )
p++; /* yep, a list */
else if (number )
return NULL; /* not a list but an n > 0 element requested */
/* skip n elements */
while ( number > 0 ) {
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
if ( !level )
number--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
if ( !level )
number--;
}
else if ( *p == ST_STOP ) {
return NULL;
}
p++;
}
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
*datalen = n;
return p + sizeof n;
}
return NULL;
}
/****************
* Get a MPI from the car
*/
GCRY_MPI
gcry_sexp_nth_mpi( GCRY_SEXP list, int number, int mpifmt )
{
const byte *p;
DATALEN n;
int level = 0;
if ( !list )
return NULL;
if ( !mpifmt )
mpifmt = GCRYMPI_FMT_STD;
p = list->d;
if ( *p == ST_OPEN )
p++; /* yep, a list */
else if (number )
return NULL; /* not a list but an n > 0 element requested */
/* skip n elements */
while ( number > 0 ) {
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
if ( !level )
number--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
if ( !level )
number--;
}
else if ( *p == ST_STOP ) {
return NULL;
}
p++;
}
if ( *p == ST_DATA ) {
MPI a;
size_t nbytes;
memcpy ( &n, ++p, sizeof n );
p += sizeof n;
nbytes = n;
if( !gcry_mpi_scan( &a, mpifmt, p, &nbytes ) )
return a;
}
return NULL;
}
/****************
* Get the CDR
*/
GCRY_SEXP
gcry_sexp_cdr( const GCRY_SEXP list )
{
const byte *p;
const byte *head;
DATALEN n;
GCRY_SEXP newlist;
byte *d;
int level = 0;
int skip = 1;
if ( !list || list->d[0] != ST_OPEN )
return NULL;
p = list->d;
while ( skip > 0 ) {
p++;
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
if ( !level )
skip--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
if ( !level )
skip--;
}
else if ( *p == ST_STOP ) {
return NULL;
}
}
p++;
head = p;
level = 0;
do {
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
}
else if ( *p == ST_STOP ) {
return NULL;
}
p++;
} while ( level );
n = p - head;
newlist = gcry_xmalloc ( sizeof *newlist + n + 2 );
d = newlist->d;
*d++ = ST_OPEN;
memcpy ( d, head, n ); d += n;
*d++ = ST_CLOSE;
*d++ = ST_STOP;
return normalize (newlist);
}
GCRY_SEXP
gcry_sexp_cadr ( const GCRY_SEXP list )
{
GCRY_SEXP a, b;
a = gcry_sexp_cdr ( list );
b = gcry_sexp_car ( a );
gcry_sexp_release ( a );
return b;
}
static int
hextobyte( const byte *s )
{
int c=0;
if( *s >= '0' && *s <= '9' )
c = 16 * (*s - '0');
else if( *s >= 'A' && *s <= 'F' )
c = 16 * (10 + *s - 'A');
else if( *s >= 'a' && *s <= 'f' ) {
c = 16 * (10 + *s - 'a');
}
s++;
if( *s >= '0' && *s <= '9' )
c += *s - '0';
else if( *s >= 'A' && *s <= 'F' )
c += 10 + *s - 'A';
else if( *s >= 'a' && *s <= 'f' ) {
c += 10 + *s - 'a';
}
return c;
}
struct make_space_ctx {
GCRY_SEXP sexp;
size_t allocated;
byte *pos;
};
static void
make_space ( struct make_space_ctx *c, size_t n )
{
size_t used = c->pos - c->sexp->d;
if ( used + n + sizeof(DATALEN) + 1 >= c->allocated ) {
GCRY_SEXP newsexp;
byte *newhead;
c->allocated += 2*(n+sizeof(DATALEN)+1);
newsexp = gcry_xrealloc ( c->sexp, sizeof *newsexp + c->allocated - 1 );
newhead = newsexp->d;
c->pos = newhead + used;
c->sexp = newsexp;
}
}
/****************
* Scan the provided buffer and return the S expression in our internal
* format. Returns a newly allocated expression. If erroff is not NULL and
* a parsing error has occured, the offset into buffer will be returned.
* If ARGFLAG is true, the function supports some printf like
* expressions.
* These are:
* %m - MPI
* %s - string (no autoswitch to secure allocation)
* %d - integer stored as string (no autoswitch to secure allocation)
* all other format elements are currently not defined and return an error.
* this includes the "%%" sequence becauce the percent sign is not an
* allowed character.
* FIXME: We should find a way to store the secure-MPIS not in the string
* but as reference to somewhere - this can help us to save huge amounts
* of secure memory. The problem is, that if only one element is secure, all
* other elements are automagicaly copied to secure meory too, so the most
* common operation gcry_sexp_cdr_mpi() will always return a secure MPI
* regardless whether it is needed or not.
*/
static int
sexp_sscan( GCRY_SEXP *retsexp, size_t *erroff ,
const char *buffer, size_t length, va_list arg_ptr, int argflag )
{
static const char tokenchars[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789-./_:*+=";
const char *p;
size_t n;
const char *digptr=NULL;
const char *quoted=NULL;
const char *tokenp=NULL;
const char *hexfmt=NULL;
const char *base64=NULL;
const char *disphint=NULL;
const char *percent=NULL;
int hexcount=0;
int quoted_esc=0;
int datalen=0;
size_t dummy_erroff;
struct make_space_ctx c;
if( !erroff )
erroff = &dummy_erroff;
/* FIXME: replace all the returns by a jump to the leave label
* and invent better error codes. Make sure that everything is cleaned up*/
#define MAKE_SPACE(n) do { make_space ( &c, (n) ); } while (0)
#define STORE_LEN(p,n) do { \
DATALEN ashort = (n); \
memcpy ( (p), &ashort, sizeof(ashort) ); \
(p) += sizeof (ashort); \
} while (0)
/* We assume that the internal representation takes less memory
* than the provided one. However, we add space for one extra datalen
* so that the code which does the ST_CLOSE can use MAKE_SPACE */
c.allocated = length + sizeof(DATALEN);
c.sexp = gcry_xmalloc ( sizeof *c.sexp + c.allocated - 1 );
c.pos = c.sexp->d;
for(p=buffer,n=length; n; p++, n-- ) {
if( tokenp && !hexfmt ) {
if( strchr( tokenchars, *p ) )
continue;
datalen = p - tokenp;
MAKE_SPACE ( datalen );
*c.pos++ = ST_DATA;
STORE_LEN ( c.pos, datalen );
memcpy ( c.pos, tokenp, datalen );
c.pos += datalen;
tokenp = NULL;
}
if( quoted ) {
if( quoted_esc ) {
switch( *p ) {
case 'b': case 't': case 'v': case 'n': case 'f':
case 'r': case '"': case '\'': case '\\':
quoted_esc = 0;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7':
if( !(n > 2 && p[1] >= '0' && p[1] <= '7'
&& p[2] >= '0' && p[2] <= '7') ) {
*erroff = p - buffer;
return -6; /* invalid octal value */
}
p += 2; n -= 2;
quoted_esc = 0;
break;
case 'x':
if( !(n > 2 && isxdigit(p[1]) && isxdigit(p[2]) ) ) {
*erroff = p - buffer;
return -6; /* invalid hex value */
}
p += 2; n -= 2;
quoted_esc = 0;
break;
case '\r': /* ignore CR[,LF] */
if( n && p[1] == '\n' ) {
p++; n--;
}
quoted_esc = 0;
break;
case '\n': /* ignore LF[,CR] */
if( n && p[1] == '\r' ) {
p++; n--;
}
quoted_esc = 0;
break;
default:
*erroff = p - buffer;
return -6; /* invalid quoted string escape */
}
}
else if( *p == '\\' )
quoted_esc = 1;
else if( *p == '\"' ) {
/* fixme: add item */
quoted = NULL;
}
}
else if( hexfmt ) {
if( isxdigit( *p ) )
hexcount++;
else if( *p == '#' ) {
if( (hexcount & 1) ) {
*erroff = p - buffer;
return -12; /* odd number of hex digits */
}
datalen = hexcount/2;
MAKE_SPACE (datalen);
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, datalen);
for( hexfmt++; hexfmt < p; hexfmt++ ) {
if( isspace( *hexfmt ) )
continue;
*c.pos++ = hextobyte( hexfmt );
hexfmt++;
}
hexfmt = NULL;
}
else if( !isspace( *p ) ) {
*erroff = p - buffer;
return -11; /* invalid hex character */
}
}
else if( base64 ) {
if( *p == '|' )
base64 = NULL;
}
else if( digptr ) {
if( isdigit(*p) )
;
else if( *p == ':' ) {
datalen = atoi( digptr ); /* fixme: check for overflow */
digptr = NULL;
if( datalen > n-1 ) {
*erroff = p - buffer;
return -2; /* buffer too short */
}
/* make a new list entry */
MAKE_SPACE (datalen);
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, datalen);
memcpy (c.pos, p+1, datalen );
c.pos += datalen;
n -= datalen;
p += datalen;
}
else if( *p == '\"' ) {
digptr = NULL; /* we ignore the optional length */
quoted = p;
quoted_esc = 0;
}
else if( *p == '#' ) {
digptr = NULL; /* we ignore the optional length */
hexfmt = p;
hexcount = 0;
}
else if( *p == '|' ) {
digptr = NULL; /* we ignore the optional length */
base64 = p;
}
else {
*erroff = p - buffer;
return -1;
}
}
else if ( percent ) {
if ( *p == 'm' ) { /* insert an MPI */
GCRY_MPI m = va_arg (arg_ptr, GCRY_MPI);
size_t nm;
if ( gcry_mpi_print( GCRYMPI_FMT_STD, NULL, &nm, m ) )
BUG ();
MAKE_SPACE (nm);
if ( !gcry_is_secure ( c.sexp->d )
&& gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE ) ) {
/* we have to switch to secure allocation */
GCRY_SEXP newsexp;
byte *newhead;
newsexp = gcry_xmalloc_secure ( sizeof *newsexp
+ c.allocated - 1 );
newhead = newsexp->d;
memcpy ( newhead, c.sexp->d, (c.pos - c.sexp->d) );
c.pos = newhead + ( c.pos - c.sexp->d );
gcry_free ( c.sexp );
c.sexp = newsexp;
}
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, nm);
if ( gcry_mpi_print( GCRYMPI_FMT_STD, c.pos, &nm, m ) )
BUG ();
c.pos += nm;
}
else if ( *p == 's' ) { /* insert an string */
const char *astr = va_arg (arg_ptr, const char *);
size_t alen = strlen ( astr );
MAKE_SPACE (alen);
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, alen);
memcpy ( c.pos, astr, alen );
c.pos += alen;
}
else if ( *p == 'd' ) { /* insert an integer as string */
int aint = va_arg (arg_ptr, int);
size_t alen;
char buf[20];
sprintf ( buf, "%d", aint );
alen = strlen ( buf );
MAKE_SPACE (alen);
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, alen);
memcpy ( c.pos, buf, alen );
c.pos += alen;
}
else {
*erroff = p - buffer;
return -1; /* invalid format specifier */
}
percent = NULL;
}
else if( *p == '(' ) {
if( disphint ) {
*erroff = p - buffer;
return -9; /* open display hint */
}
MAKE_SPACE (0);
*c.pos++ = ST_OPEN;
}
else if( *p == ')' ) { /* walk up */
if( disphint ) {
*erroff = p - buffer;
return -9; /* open display hint */
}
MAKE_SPACE (0);
*c.pos++ = ST_CLOSE;
}
else if( *p == '\"' ) {
quoted = p;
quoted_esc = 0;
}
else if( *p == '#' ) {
hexfmt = p;
hexcount = 0;
}
else if( *p == '|' )
base64 = p;
else if( *p == '[' ) {
if( disphint ) {
*erroff = p - buffer;
return -8; /* nested display hints */
}
disphint = p;
}
else if( *p == ']' ) {
if( !disphint ) {
*erroff = p - buffer;
return -9; /* unmatched display hint close */
}
disphint = NULL;
}
else if( isdigit(*p) ) {
if( *p == '0' ) { /* a length may not begin with zero */
*erroff = p - buffer;
return -7;
}
digptr = p;
}
else if( strchr( tokenchars, *p ) )
tokenp = p;
else if( isspace(*p) )
;
else if( *p == '{' ) {
/* fixme: handle rescanning:
* we can do this by saving our current state
* and start over at p+1 -- Hmmm. At this point here
* we are in a well defined state, so we don't need to save
* it. Great.
*/
*erroff = p - buffer;
return -10; /* unexpected reserved punctuation */
}
else if( strchr( "&\\", *p ) ) { /*reserved punctuation*/
*erroff = p - buffer;
return -10; /* unexpected reserved punctuation */
}
else if( argflag && *p == '%' ) {
percent = p;
}
else { /* bad or unavailable*/
*erroff = p - buffer;
return -5;
}
}
MAKE_SPACE (0);
*c.pos++ = ST_STOP;
*retsexp = normalize ( c.sexp );
return 0;
#undef MAKE_SPACE
#undef STORE_LEN
}
int
gcry_sexp_build( GCRY_SEXP *retsexp, size_t *erroff, const char *format, ... )
{
int rc;
va_list arg_ptr ;
va_start( arg_ptr, format ) ;
rc = sexp_sscan( retsexp, erroff, format, strlen(format), arg_ptr, 1 );
va_end(arg_ptr);
return rc;
}
int
gcry_sexp_sscan( GCRY_SEXP *retsexp, size_t *erroff,
const char *buffer, size_t length )
{
va_list dummy_arg_ptr = 0;
return sexp_sscan( retsexp, erroff, buffer, length, dummy_arg_ptr, 0 );
}
/****************
* Print SEXP to buffer using the MODE. Returns the length of the
* SEXP in buffer or 0 if the buffer is too short (We have at least an
* empty list consisting of 2 bytes). If a buffer of NULL is provided,
* the required length is returned.
*/
size_t
gcry_sexp_sprint( const GCRY_SEXP list, int mode,
char *buffer, size_t maxlength )
{
static byte empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
const byte *s;
char *d;
DATALEN n;
char numbuf[20];
size_t len = 0;
s = list? list->d : empty;
d = buffer;
while ( *s != ST_STOP ) {
switch ( *s ) {
case ST_OPEN:
s++;
len++;
if ( buffer ) {
if ( len >= maxlength )
return 0;
*d++ = '(';
}
break;
case ST_CLOSE:
s++;
len++;
if ( mode != GCRYSEXP_FMT_CANON )
len++;
if ( buffer ) {
if ( len >= maxlength )
return 0;
*d++ = ')';
if ( mode != GCRYSEXP_FMT_CANON )
*d++ = '\n';
}
break;
case ST_DATA:
s++;
memcpy ( &n, s, sizeof n ); s += sizeof n;
sprintf (numbuf, "%u:", (unsigned int)n );
len += strlen (numbuf) + n;
if ( buffer ) {
if ( len >= maxlength )
return 0;
d = stpcpy ( d, numbuf );
memcpy ( d, s, n ); d += n;
}
s += n;
break;
default:
BUG ();
}
}
if (buffer) {
if ( len >= maxlength )
return 0;
*d++ = 0; /* for convenience we make a C string */
}
else
len++; /* we need one byte more for this */
return len;
}
/* Scan a cannocial encoded buffer with implicit length values and
return the actual length this S-expression uses. For a valid S-Exp
it should never return 0. If LENGTH is not zero, the maximum
length to scan is given - this can be used for syntax checks of
data passed from outside. erroce and erroff may both be passed as
NULL
Errorcodes (for historic reasons they are all negative):
-1 := invalid length specification
-2 := string too long
-3 := unmatched parenthesis
-4 := not a (canonical) S-expression
-5 := bad character
-6 := invalid hex octal value or bad quotation
-7 := a length may not begin with zero
-8 := nested display hints
-9 := unmatched display hint close
-10 := unexpected reserved punctuation
*/
size_t
gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
size_t *erroff, int *errcode)
{
const unsigned char *p;
const char *disphint=NULL;
unsigned int datalen = 0;
size_t dummy_erroff;
int dummy_errcode;
size_t count = 0;
int level = 0;
if (!erroff)
erroff = &dummy_erroff;
if (!errcode)
errcode = &dummy_errcode;
*errcode = 0;
*erroff = 0;
if (!buffer)
return 0;
if (*buffer != '(')
- return -4; /* not a canonical S-expression */
+ {
+ *errcode = -4; /* not a canonical S-expression */
+ return 0;
+ }
for (p=buffer; ; p++, count++ )
{
if (length && count >= length)
{
*erroff = count;
*errcode = -2; /* string too long */
return 0;
}
if (datalen)
{
if (*p == ':')
{
if (length && (count+datalen) >= length)
{
*erroff = count;
*errcode = -2; /* string too long */
return 0;
}
count += datalen;
p += datalen;
datalen = 0;
}
else if (digitp(p))
datalen = datalen*10 + atoi_1(p);
else
{
*erroff = count;
*errcode = -1;
return 0;
}
}
else if (*p == '(')
{
if (disphint)
{
*erroff = count;
*errcode = -9; /* open display hint */
return 0;
}
level++;
}
else if (*p == ')')
{ /* walk up */
if (!level)
{
*erroff = count;
*errcode = -3; /* unmatched parenthesis */
return 0;
}
if (disphint)
{
*erroff = count;
*errcode = -9; /* open display hint */
return 0;
}
if (!--level)
return ++count; /* ready */
}
else if (*p == '[')
{
if (disphint)
{
*erroff = count;
*errcode = -8; /* nested display hints */
return 0;
}
disphint = p;
}
else if (*p == ']')
{
if( !disphint )
{
*erroff = count;
*errcode = -9; /* unmatched display hint close */
return 0;
}
disphint = NULL;
}
else if (digitp (p) )
{
if (*p == '0')
{
*erroff = count;
*errcode = -7; /* a length may not begin with zero */
return 0;
}
datalen = atoi_1 (p);
}
else if (*p == '&' || *p == '\\')
{
*erroff = count;
*errcode = -10; /* unexpected reserved punctuation */
return 0;
}
else
{
*erroff = count;
*errcode = -5; /* bad character */
return 0;
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jan 1, 2:22 AM (10 h, 31 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
0a/93/83f174af6828388c72a6d3ebeb22

Event Timeline