Various minor changes.
authorWerner Koch <wk@gnupg.org>
Tue, 17 Oct 2006 17:44:49 +0000 (17:44 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 17 Oct 2006 17:44:49 +0000 (17:44 +0000)
Support for DSA2.

22 files changed:
AUTHORS
ChangeLog
NEWS
THANKS
TODO
acinclude.m4
cipher/ChangeLog
cipher/dsa.c
cipher/md.c
cipher/pubkey.c
doc/ChangeLog
doc/Makefile.am
doc/gcrypt.texi
src/ChangeLog
src/cipher.h
src/global.c
src/libgcrypt.m4
src/module.c
src/sexp.c
tests/ChangeLog
tests/keygen.c
tests/tsexp.c

diff --git a/AUTHORS b/AUTHORS
index f03d8bb..e421b56 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -74,9 +74,9 @@ bradh@frogmouth.net
  added SHA-224, changed cipher/sha256.c, added HMAC tests.)
 
 
-Hye-Shik Chang  <perky@FreeBSD.org>
-Wrote SEED cipher and put it into the Public domain.  See mail to
-gcrypt-devel@gnupg.org on 2006-07-12 <20060712143738.GA54909@FreeBSD.org>.
+LIBGCRYPT       Hye-Shik Chang   2006-09-07
+Assigns Past and Future Changes
+perky@freebsd.org
 (SEED cipher)
 
 
index 3737234..3707bcc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
        (AC_CONFIG_FILES): Add src/gcrypt.h.
        (AC_CONFIG_SRCDIR): Change to src/libgcrypt.vers.
 
+2006-10-02  Werner Koch  <wk@g10code.com>
+
+       * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Test on HOST and not
+       TARGET.  Hardwire for mingw32. Allow setting via command line when
+       cross compiling.
+
 2006-08-29  Werner Koch  <wk@g10code.com>
 
        * configure.ac (USE_SEED): New.
diff --git a/NEWS b/NEWS
index ea9c736..f3a6403 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,10 @@ Noteworthy changes in version 1.3.0 (unreleased)
 
  * gcry_mpi_rshift does not anymore truncate the shift count.
 
+ * Reserved algorithm ranges for use by applications.
+
+ * Support for DSA2.
+
  * Interface changes relative to the 1.2.0 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  gcry_fast_random_poll  NEW
diff --git a/THANKS b/THANKS
index 5aefc55..df111e4 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -60,6 +60,7 @@ Karsten Thygesen         karthy@kom.auc.dk
 Katsuhiro Kondou          kondou@nec.co.jp
 Kazu Yamamoto             kazu@iijlab.net
 Lars Kellogg-Stedman      lars@bu.edu
+Lee Fisher                 blibbet at gmail dot com
 Marco d'Itri               md@linux.it
 Mark Adler                madler@alumni.caltech.edu
 Mark Elbrecht             snowball3@bigfoot.com
diff --git a/TODO b/TODO
index 4ea299e..d5e6317 100644 (file)
--- a/TODO
+++ b/TODO
@@ -64,5 +64,6 @@ What's left to do                                 -*- outline -*-
 
 * gry_mpi_lshift is missing
 
+* Add OAEP
 
 
index d538210..7fb5c7d 100644 (file)
@@ -69,13 +69,18 @@ AC_DEFUN([GNUPG_CHECK_GNUMAKE],
 # Taken from GnuPG 1.2 and modified to use the libtool macros.
 AC_DEFUN([GNUPG_SYS_SYMBOL_UNDERSCORE],
 [tmp_do_check="no"
-case "${target}" in
+case "${host}" in
+    *-mingw32msvc*)
+        ac_cv_sys_symbol_underscore=yes
+        ;;
     i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp)
         ac_cv_sys_symbol_underscore=yes
         ;;
     *)
       if test "$cross_compiling" = yes; then
-         ac_cv_sys_symbol_underscore=yes
+        if test "x$ac_cv_sys_symbol_underscore" = x ; then
+           ac_cv_sys_symbol_underscore=yes
+        fi
       else
          tmp_do_check="yes"
       fi
index d4be562..58a29e4 100644 (file)
@@ -1,3 +1,16 @@
+2006-10-17  Werner Koch  <wk@g10code.com>
+
+       * dsa.c (_gcry_dsa_generate2): New.
+       (generate): New arg QBITS.  Add sanity checks for reasonable qbits
+       and nbits.
+       * pubkey.c (gcry_pk_genkey): Parse an qbits element.
+       (pubkey_generate): New arg QBITS.  Pass it to the DSA generation.
+
+2006-10-05  Werner Koch  <wk@g10code.com>
+
+       * md.c (gcry_md_algo_info) <get_asnoid>: Check that the algo is
+       available.
+
 2006-10-04  David Shaw  <dshaw@jabberwocky.com>  (wk)
  
        * tiger.c (round): Rename to tiger_round as gcc 4 has a built-in
index 5faf97b..4d477c6 100644 (file)
@@ -1,5 +1,6 @@
 /* dsa.c  -  DSA signature scheme
- * Copyright (C) 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 2000, 2001, 2002, 2003,
+ *               2006  Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
@@ -50,7 +51,9 @@ typedef struct
 static gcry_mpi_t gen_k (gcry_mpi_t q);
 static void test_keys (DSA_secret_key *sk, unsigned qbits);
 static int check_secret_key (DSA_secret_key *sk);
-static gpg_err_code_t generate (DSA_secret_key *sk, unsigned nbits,
+static gpg_err_code_t generate (DSA_secret_key *sk,
+                                unsigned int nbits,
+                                unsigned int qbits,
                                 gcry_mpi_t **ret_factors);
 static void sign (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input,
                   DSA_secret_key *skey);
@@ -173,7 +176,8 @@ test_keys( DSA_secret_key *sk, unsigned qbits )
            and an array with the n-1 factors of (p-1)
  */
 static gpg_err_code_t
-generate( DSA_secret_key *sk, unsigned nbits, gcry_mpi_t **ret_factors )
+generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
+          gcry_mpi_t **ret_factors )
 {
   gcry_mpi_t p;    /* the prime */
   gcry_mpi_t q;    /* the 160 bit prime factor */
@@ -181,22 +185,28 @@ generate( DSA_secret_key *sk, unsigned nbits, gcry_mpi_t **ret_factors )
   gcry_mpi_t y;    /* g^x mod p */
   gcry_mpi_t x;    /* the secret exponent */
   gcry_mpi_t h, e;  /* helper */
-  unsigned qbits;
   unsigned char *rndbuf;
 
-  if ( nbits >= 512 && nbits <= 1024 )
+  if (qbits)
+    ; /* Caller supplied qbits.  Use this value.  */
+  else if ( nbits >= 512 && nbits <= 1024 )
     qbits = 160;
   else if ( nbits == 2048 )
     qbits = 224;
   else if ( nbits == 3072 )
     qbits = 256;
-/*   else if ( nbits == 7680 ) */
-/*     qbits = 384; */
-/*   else if ( nbits == 15360 ) */
-/*     qbits = 512; */
+  else if ( nbits == 7680 )
+    qbits = 384;
+  else if ( nbits == 15360 )
+    qbits = 512;
   else
     return GPG_ERR_INV_VALUE;
 
+  if (qbits < 160 || qbits > 512 || (qbits%8) )
+    return GPG_ERR_INV_VALUE;
+  if (nbits < 2*qbits || nbits > 15360)
+    return GPG_ERR_INV_VALUE;
+
   p = _gcry_generate_elg_prime( 1, nbits, qbits, NULL, ret_factors );
   /* get q out of factors */
   q = mpi_copy((*ret_factors)[0]);
@@ -382,13 +392,40 @@ verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t hash, DSA_public_key *pkey )
  *********************************************/
 
 gcry_err_code_t
-_gcry_dsa_generate (int algo, unsigned nbits, unsigned long dummy,
+_gcry_dsa_generate (int algo, unsigned int nbits, unsigned long dummy,
                     gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
   gpg_err_code_t err;
   DSA_secret_key sk;
 
-  err = generate (&sk, nbits, retfactors);
+  err = generate (&sk, nbits, 0, retfactors);
+  if (!err)
+    {
+      skey[0] = sk.p;
+      skey[1] = sk.q;
+      skey[2] = sk.g;
+      skey[3] = sk.y;
+      skey[4] = sk.x;
+    }
+
+  return err;
+}
+
+
+/* We don't want to break our API.  Thus we use a hack in pubkey.c to
+   link directly to this function.  Note that we can't reuse the dummy
+   parameter because we can't be sure that applicaions accidently pass
+   a USE_E (that is for what dummy is used with RSA) to a DSA
+   generation. */
+gcry_err_code_t
+_gcry_dsa_generate2 (int algo, unsigned int nbits, unsigned int qbits,
+                     unsigned long dummy,
+                     gcry_mpi_t *skey, gcry_mpi_t **retfactors)
+{
+  gpg_err_code_t err;
+  DSA_secret_key sk;
+
+  err = generate (&sk, nbits, qbits, retfactors);
   if (!err)
     {
       skey[0] = sk.p;
index 7942e70..176c881 100644 (file)
@@ -1101,27 +1101,31 @@ gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes)
       break;
 
     case GCRYCTL_GET_ASNOID:
-      {
-       const char unsigned *asn;
-       size_t asnlen;
-
-       asn = md_asn_oid (algo, &asnlen, NULL);
-       if (buffer && (*nbytes >= asnlen))
+      /* We need to check that the algo is available because
+         md_asn_oid would otherwise raise an assertion. */
+      err = check_digest_algo (algo);
+      if (!err)
+        {
+          const char unsigned *asn;
+          size_t asnlen;
+          
+          asn = md_asn_oid (algo, &asnlen, NULL);
+          if (buffer && (*nbytes >= asnlen))
          {
            memcpy (buffer, asn, asnlen);
            *nbytes = asnlen;
          }
-       else if ((! buffer) && nbytes)
-         *nbytes = asnlen;
-       else
-         {
-           if (buffer)
-             err = GPG_ERR_TOO_SHORT;
-           else
-             err = GPG_ERR_INV_ARG;
-         }
-       break;
-      }
+          else if ((! buffer) && nbytes)
+            *nbytes = asnlen;
+          else
+            {
+              if (buffer)
+                err = GPG_ERR_TOO_SHORT;
+              else
+                err = GPG_ERR_INV_ARG;
+            }
+        }
+      break;
 
   default:
     err = GPG_ERR_INV_OP;
index 60aabdd..2d975e8 100644 (file)
@@ -467,7 +467,8 @@ pubkey_get_nenc (int algorithm)
 
 
 static gcry_err_code_t
-pubkey_generate (int algorithm, unsigned int nbits, unsigned long use_e,
+pubkey_generate (int algorithm, unsigned int nbits, unsigned int qbits,
+                 unsigned long use_e,
                  gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
   gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO;
@@ -479,8 +480,13 @@ pubkey_generate (int algorithm, unsigned int nbits, unsigned long use_e,
   pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
   if (pubkey)
     {
-      err = ((gcry_pk_spec_t *) pubkey->spec)->generate 
-        (algorithm, nbits, use_e, skey, retfactors);
+      /* Hack to pass QBITS to the DSA generation.  */
+      if (qbits && pubkey->spec == &_gcry_pubkey_spec_dsa)
+        err = _gcry_dsa_generate2
+          (algorithm, nbits, qbits, 0, skey, retfactors);
+      else
+        err = ((gcry_pk_spec_t *) pubkey->spec)->generate 
+          (algorithm, nbits, use_e, skey, retfactors);
       _gcry_module_release (pubkey);
     }
   ath_mutex_unlock (&pubkeys_registered_lock);
@@ -1862,6 +1868,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
   gcry_mpi_t skey[10], *factors = NULL;
   unsigned int nbits = 0;
   unsigned long use_e = 0;
+  unsigned int qbits;
   char *name_terminated;
 
   REGISTER_DEFAULT_PUBKEYS;
@@ -1941,6 +1948,28 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
   else
     use_e = 65537; /* Not given, use the value generated by old versions. */
 
+  /* Handle the optional qbits element. */
+  l2 = gcry_sexp_find_token (list, "qbits", 0);
+  if (l2)
+    {
+      char buf[50];
+
+      name = gcry_sexp_nth_data (l2, 1, &n);
+      if ((! name) || (n >= DIM (buf) - 1))
+        {
+          rc = GPG_ERR_INV_OBJ; /* No value or value too large. */
+          goto leave;
+        }
+      memcpy (buf, name, n);
+      buf[n] = 0;
+      qbits = (unsigned int)strtoul (buf, NULL, 0);
+      gcry_sexp_release (l2);
+      l2 = NULL;
+    }
+  else
+    qbits = 0;
+
+  /* Now parse the required nbits element. */
   l2 = gcry_sexp_find_token (list, "nbits", 0);
   gcry_sexp_release (list);
   list = l2;
@@ -1970,7 +1999,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
   nbits = (unsigned int) strtoul (name_terminated, NULL, 0);
   gcry_free (name_terminated);
 
-  rc = pubkey_generate (module->mod_id, nbits, use_e, skey, &factors);
+  rc = pubkey_generate (module->mod_id, nbits, qbits, use_e, skey, &factors);
   if (rc)
     goto leave;
 
index 70b6042..4ca27e8 100644 (file)
@@ -1,3 +1,7 @@
+2006-09-19  Werner Koch  <wk@g10code.com>
+
+       * Makefile.am (online): New target.
+
 2006-08-29  Werner Koch  <wk@g10code.com>
 
        * gcrypt.texi (Available ciphers): Add missing ciphers.
index 8ae6531..eeedf8b 100644 (file)
@@ -22,3 +22,12 @@ DISTCLEANFILES = gcrypt.cps
 info_TEXINFOS = gcrypt.texi
 gcrypt_TEXINFOS = lgpl.texi gpl.texi
 
+
+online: gcrypt.html gcrypt.pdf
+       set -e; \
+       echo "Uploading current manuals to www.gnupg.org ..."; \
+        user=werner ; \
+       (cd gcrypt.html && rsync -vr --exclude='.svn' .  \
+         $${user}@cvs.gnupg.org:webspace/manuals/gcrypt/ ); \
+        rsync -v gcrypt.pdf $${user}@cvs.gnupg.org:webspace/manuals/
+
index 0f44b16..d8f7f85 100644 (file)
@@ -2326,7 +2326,7 @@ Some functions operating on S-expressions support `flags', that
 influence the operation.  These flags have to be listed in a
 sub-S-expression named `flags'; the following flags are known:
 
-@table @var
+@table @code
 @item pkcs1
 Use PKCS#1 block type 2 padding.
 @item no-blinding
@@ -2694,7 +2694,8 @@ supported parameters are:
 @table @code
 @item nbits
 This is always required to specify the length of the key.  The argument
-is a string with a number in C-notation.
+is a string with a number in C-notation.  The value should be a multiple
+of 8.
 
 @item rsa-use-e
 This is only used with RSA to give a hint for the public exponent. The
@@ -2715,6 +2716,26 @@ Reserved
 If this parameter is not used, @acronym{Libgcrypt} uses for historic reasons
 65537.
 
+@item qbits
+This is only meanigful for DSA keys.  If it is given the DSA key is
+generated with a Q parameyer of this size.  If it is not given or zero 
+Q is deduced from NBITS in this way:
+@table @samp
+@item 512 <= N <= 1024
+Q = 160
+@item N = 2048
+Q = 224
+@item N = 3072
+Q = 256
+@item N = 7680
+Q = 384
+w@item N = 15360
+Q = 512
+@end table
+Note, that in this case only the values for N, as given in the table,
+are allowed.  When specifying Q all values of N in the range 512 to
+15680 are valid as long as they are multiples of 8.
+
 @end table
 @c end table of parameters
 
index 7fa1e83..2ff7e9b 100644 (file)
@@ -1,3 +1,11 @@
+2006-10-05  Werner Koch  <wk@g10code.com>
+
+       * module.c (_gcry_module_id_new): Don't assign modules in the range
+       the range of 1024..4096.
+       * gcrypt.h (GCRY_MD_USER, GCRY_MD_USER_LAST): New
+       (GCRY_PK_USER, GCRY_PK_USER_LAST): New.
+       (GCRY_CIPHER_USER, GCRY_CIPHER_USER_LAST): New.
+
 2006-10-12  Marcus Brinkmann  <marcus@g10code.de>
 
        * gcrypt.h.in: Replace socklen_t with gcry_socklen_t.
        * gcrypt.h.in: ... this file.
        * Makefile.am (EXTRA_DIST): Add gcrypt.h.in.
 
+2006-09-04  Werner Koch  <wk@g10code.com>
+
+       * gcrypt.h: Removed some trailing comma in enums.
+
 2006-08-29  Werner Koch  <wk@g10code.com>
 
+       * global.c (gcry_xrealloc): Pass secure flag to outofcore handler.
+
        * gcrypt.h (GCRY_CIPHER_SEED): New.
 
 2006-08-21  Werner Koch  <wk@g10code.com>
index 7af8f38..bdf8c80 100644 (file)
@@ -35,6 +35,12 @@ void _gcry_sha1_hash_buffer (char *outbuf, const char *buffer, size_t length);
 
 /*-- dsa.c --*/
 void _gcry_register_pk_dsa_progress (gcry_handler_progress_t cbc, void *cb_data);
+gcry_err_code_t _gcry_dsa_generate2 (int algo, unsigned int nbits,
+                                     unsigned int qbits,
+                                     unsigned long dummy,
+                                     gcry_mpi_t *skey,
+                                     gcry_mpi_t **retfactors);
+
 /*-- elgamal.c --*/
 void _gcry_register_pk_elg_progress (gcry_handler_progress_t cb, void *cb_data);
 /*-- primegen.c --*/
index 46a12be..d62c5be 100644 (file)
@@ -644,7 +644,8 @@ gcry_xrealloc( void *a, size_t n )
 
     while ( !(p = gcry_realloc( a, n )) ) {
        if( !outofcore_handler
-           || !outofcore_handler( outofcore_handler_value, n, 2 ) ) {
+           || !outofcore_handler( outofcore_handler_value, n,
+                                   gcry_is_secure(a)? 3:2 ) ) {
            _gcry_fatal_error(gpg_err_code_from_errno (errno), NULL );
        }
     }
index 20bd105..c5e8631 100644 (file)
@@ -89,7 +89,7 @@ AC_DEFUN([AM_PATH_LIBGCRYPT],
              AC_MSG_RESULT(okay)
            else
              ok=no
-             AC_MSG_RESULT([does not match (want=$req_libgcrypt_api got=$tmp)])
+             AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp])
            fi
         fi
      fi
index 69a7930..d99fbcf 100644 (file)
 #include <errno.h>
 #include "g10lib.h"
 
+/* Please match these numbers with the allocated algorithm
+   numbers.  */
 #define MODULE_ID_MIN 600
+#define MODULE_ID_LAST 65500
+#define MODULE_ID_USER 1024
+#define MODULE_ID_USER_LAST 4095
+
+#if MODULE_ID_MIN >= MODULE_ID_USER
+#error Need to implement a different search strategy
+#endif
 
 /* Internal function.  Generate a new, unique module ID for a module
    that should be inserted into the module chain starting at
 static gcry_err_code_t
 _gcry_module_id_new (gcry_module_t modules, unsigned int *id_new)
 {
-  /* FIXME, what should be the ID of the first module registered by
-     the user?  */
-  unsigned int id_min = MODULE_ID_MIN, id_max = (unsigned int) -1, mod_id;
+  unsigned int mod_id;
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   gcry_module_t module;
 
   /* Search for unused ID.  */
-  for (mod_id = id_min; mod_id < id_max; mod_id++)
+  for (mod_id = MODULE_ID_MIN; mod_id < MODULE_ID_LAST; mod_id++)
     {
+      if (mod_id == MODULE_ID_USER)
+        {
+          mod_id = MODULE_ID_USER_LAST;
+          continue;
+        }
+
       /* Search for a module with the current ID.  */
       for (module = modules; module; module = module->next)
        if (mod_id == module->mod_id)
@@ -49,7 +62,7 @@ _gcry_module_id_new (gcry_module_t modules, unsigned int *id_new)
        break;
     }
 
-  if (mod_id < id_max)
+  if (mod_id < MODULE_ID_LAST)
     /* Done.  */
     *id_new = mod_id;
   else
index 80fed53..38ab073 100644 (file)
@@ -190,7 +190,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
    when AUTODETECT is set to 1.  With FREEFNC not NULL, ownership of
-   the buffer is transferred to tyhe newle created object.  FREEFNC
+   the buffer is transferred to the newly created object.  FREEFNC
    should be the freefnc used to release BUFFER; there is no guarantee
    at which point this function is called; most likey you want to use
    free() or gcry_free(). 
@@ -239,7 +239,7 @@ gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length,
          have changed the internal represenation of S-expression to
          the canoncial format - which has the advantage of faster
          parsing - we will use this function as a closure in our
-         GCRYSEXP object and use the BUFFER directly */
+         GCRYSEXP object and use the BUFFER directly */
       freefnc (buffer);
     }
   return gcry_error (GPG_ERR_NO_ERROR);
index af66e6e..64bda5d 100644 (file)
@@ -1,3 +1,7 @@
+2006-10-17  Werner Koch  <wk@g10code.com>
+
+       * keygen.c (check_rsa_keys): Also create an 1536 bit DSA key.
+
 2006-08-03  Werner Koch  <wk@g10code.com>
 
        * t-mpi-bit.c: New.
index abe8881..0d73275 100644 (file)
@@ -123,12 +123,15 @@ check_rsa_keys (void)
   gcry_sexp_t keyparm, key;
   int rc;
 
+  /* Check that DSA generation works and that it can grok the qbits
+     argument. */
   if (verbose)
-    fprintf (stderr, "creating 2048 bit DSA key using old interface\n");
+    fprintf (stderr, "creating 1536 bit DSA key using old interface\n");
   rc = gcry_sexp_new (&keyparm, 
                       "(genkey\n"
                       " (dsa\n"
-                      "  (nbits 4:2048)\n"
+                      "  (nbits 4:1536)\n"
+                      "  (qbits 3:224)\n"
                       " ))", 0, 1);
   if (rc)
     die ("error creating S-expression: %s\n", gpg_strerror (rc));
@@ -144,7 +147,6 @@ check_rsa_keys (void)
               "=============================\n", buffer);
   }
   gcry_sexp_release (key);
-  exit (0);
 
   if (verbose)
     fprintf (stderr, "creating 1024 bit RSA key using old interface\n");
index 3ec8a60..5f3205c 100644 (file)
@@ -304,6 +304,32 @@ back_and_forth_one (int testno, const char *buffer, size_t length)
       return;
     }
   gcry_sexp_release (se1);
+
+  /* Again but with memory checking. */
+  p1 = gcry_xmalloc (n1+2);
+  *p1 = '\x55';
+  p1[n1+1] = '\xaa';
+  n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1);
+  if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
+    {
+      fail ("baf %d: length mismatch for canon\n", testno);
+      return;
+    }
+  if (*p1 != '\x55' || p1[n1+1] != '\xaa')
+    fail ("baf %d: memory corrupted (1)\n", testno);
+  rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL);
+  if (rc)
+    {
+      fail ("baf %d: gcry_sexp_create failed: %s\n",
+            testno, gpg_strerror (rc));
+      return;
+    }
+  if (*p1 != '\x55' || p1[n1+1] != '\xaa')
+    fail ("baf %d: memory corrupted (2)\n", testno);
+  gcry_sexp_release (se1);
+  if (*p1 != '\x55' || p1[n1+1] != '\xaa')
+    fail ("baf %d: memory corrupted (3)\n", testno);
+  gcry_free (p1);
   
   /* FIXME: we need a lot more tests */
 
@@ -318,6 +344,18 @@ back_and_forth (void)
   static struct { char *buf; int len; } tests[] = {
     { "(7:g34:fgh1::2:())", 0 },
     { "(7:g34:fgh1::2:())", 18 },
+    {
+"(protected-private-key \n"
+" (rsa \n"
+"  (n #00BE8A536204687149A48FF9F1715FF3530AD9A836D62102BF4065E5CF5953236DB94F1DF2FF4D525CD4CE7966DDC3C839968E8BAC2948934DF047CC65287CD79F6C23C93E55D7F9231E3942BD496DE383469977635A51ADF4AF747DB958CA02E9940DFC1DC0FC7FC755E7EB6618FEE6DA54B8A06E0CBF9D9257443F9992261435#)\n"
+"  (e #010001#)\n"
+"  (protected openpgp-s2k3-sha1-aes-cbc \n"
+"   (\n"
+"    (sha1 #C2A5673BD3882405# \"96\")\n"
+"    #8D08AAF6A9209ED69D71EB7E64D78715#)\n"
+"   #F7B0B535F8F8E22F4F3DA031224070303F82F9207D42952F1ACF21A4AB1C50304EBB25527992C7B265A9E9FF702826FB88759BDD55E4759E9FCA6C879538C9D043A9C60A326CB6681090BAA731289BD880A7D5774D9999F026E5E7963BFC8C0BDC9F061393CB734B4F259725C0A0A0B15BA39C39146EF6A1B3DC4DF30A22EBE09FD05AE6CB0C8C6532951A925F354F4E26A51964F5BBA50081690C421C8385C4074E9BAB9297D081B857756607EAE652415275A741C89E815558A50AC638EDC5F5030210B4395E3E1A40FF38DCCCB333A19EA88EFE7E4D51B54128C6DF27395646836679AC21B1B25C1DA6F0A7CE9F9BE078EFC7934FA9AE202CBB0AA06C20DFAF9A66FAB7E9073FBE96B9A7F25C3BA45EC3EECA65796AEE313BA148DE5314F30345B452B50B17C4D841A7F27397126E8C10BD0CE3B50A82C0425AAEE7798031671407B681F52916256F78CAF92A477AC27BCBE26DAFD1BCE386A853E2A036F8314BB2E8E5BB1F196434232EFB0288331C2AB16DBC5457CC295EB966CAC5CE73D5DA5D566E469F0EFA82F9A12B8693E0#)\n"
+"  )\n"
+" )\n", 0 },
     { NULL, 0 }
   };
   int idx;
@@ -390,9 +428,3 @@ main (int argc, char **argv)
   
   return error_count? 1:0;
 }
-
-
-
-
-
-