summaryrefslogtreecommitdiff
path: root/src/sexp.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2008-11-25 11:05:14 +0000
committerWerner Koch <wk@gnupg.org>2008-11-25 11:05:14 +0000
commit2e6ec80233084146b47cd5f10a9c5762cd30c6ae (patch)
treeff9c6882bcf6084555656271673b7ad1626ead0f /src/sexp.c
parent8cc2eb702eeed951907db225f25a1088db4e5c44 (diff)
downloadlibgcrypt-2e6ec80233084146b47cd5f10a9c5762cd30c6ae.tar.gz
Finished RSA X9.31 key generation.
Diffstat (limited to 'src/sexp.c')
-rw-r--r--src/sexp.c65
1 files changed, 62 insertions, 3 deletions
diff --git a/src/sexp.c b/src/sexp.c
index 721069ea..59a4e7ed 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -1,6 +1,6 @@
/* sexp.c - S-Expression handling
* Copyright (C) 1999, 2000, 2001, 2002, 2003,
- * 2004, 2006, 2007 Free Software Foundation, Inc.
+ * 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -191,7 +191,7 @@ normalize ( gcry_sexp_t list )
}
/* Create a new S-expression object by reading LENGTH bytes from
- BUFFER, assuming it is canonilized encoded or autodetected encoding
+ BUFFER, assuming it is canonical encoded or autodetected encoding
when AUTODETECT is set to 1. With FREEFNC not NULL, ownership of
the buffer is transferred to the newly created object. FREEFNC
should be the freefnc used to release BUFFER; there is no guarantee
@@ -492,6 +492,47 @@ gcry_sexp_length( const gcry_sexp_t list )
}
+/* Return the internal lengths offset of LIST. That is the size of
+ the buffer from the first ST_OPEN, which is retruned at R_OFF, to
+ the corresponding ST_CLOSE inclusive. */
+static size_t
+get_internal_buffer (const gcry_sexp_t list, size_t *r_off)
+{
+ const unsigned char *p;
+ DATALEN n;
+ int type;
+ int level = 0;
+
+ *r_off = 0;
+ if (list)
+ {
+ p = list->d;
+ while ( (type=*p) != ST_STOP )
+ {
+ p++;
+ if (type == ST_DATA)
+ {
+ memcpy (&n, p, sizeof n);
+ p += sizeof n + n;
+ }
+ else if (type == ST_OPEN)
+ {
+ if (!level)
+ *r_off = (p-1) - list->d;
+ level++;
+ }
+ else if ( type == ST_CLOSE )
+ {
+ level--;
+ if (!level)
+ return p - list->d;
+ }
+ }
+ }
+ return 0; /* Not a proper list. */
+}
+
+
/* Extract the CAR of the given list. May return NULL for bad lists
or memory failure. */
@@ -920,6 +961,9 @@ unquote_string (const char *string, size_t length, unsigned char *buf)
* %d - integer stored as string (no autoswitch to secure allocation)
* %b - memory buffer; this takes _two_ arguments: an integer with the
* length of the buffer and a pointer to the buffer.
+ * %S - Copy an gcry_sexp_t here. The S-expression needs to be a
+ * regular one, starting with a parenthesis.
+ * (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.
@@ -966,7 +1010,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
#define ARG_NEXT(storage, type) \
do \
{ \
- if (!arg_list) \
+ if (!arg_list) \
storage = va_arg (arg_ptr, type); \
else \
storage = *((type *) (arg_list[arg_counter++])); \
@@ -1310,6 +1354,21 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
memcpy (c.pos, buf, alen);
c.pos += alen;
}
+ else if (*p == 'S')
+ {
+ /* Insert a gcry_sexp_t. */
+ gcry_sexp_t asexp;
+ size_t alen, aoff;
+
+ ARG_NEXT (asexp, gcry_sexp_t);
+ alen = get_internal_buffer (asexp, &aoff);
+ if (alen)
+ {
+ MAKE_SPACE (alen);
+ memcpy (c.pos, asexp->d + aoff, alen);
+ c.pos += alen;
+ }
+ }
else
{
*erroff = p - buffer;