A whole bunch of changes to eventually support
authorWerner Koch <wk@gnupg.org>
Tue, 19 Aug 2008 15:55:46 +0000 (15:55 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 19 Aug 2008 15:55:46 +0000 (15:55 +0000)
FIPS restricted mode.  Also some documentation
improvements and other minor enhancements.
See the ChangeLogs. Stay tuned.

51 files changed:
BUGS [deleted file]
ChangeLog
Makefile.am
NEWS
cipher/ChangeLog
cipher/Makefile.am
cipher/ac.c
cipher/cipher.c
cipher/des.c
cipher/dsa.c
cipher/ecc.c
cipher/md.c
cipher/pubkey.c
cipher/rijndael.c
cipher/rsa.c
cipher/sha1.c
cipher/sha256.c
cipher/sha512.c
configure.ac
doc/ChangeLog
doc/Makefile.am
doc/gcrypt.texi
random/ChangeLog
random/Makefile.am
random/rand-internal.h
random/random-csprng.c [new file with mode: 0644]
random/random-fips.c [new file with mode: 0644]
random/random.c
random/random.h
src/ChangeLog
src/Makefile.am
src/ath.c
src/ath.h
src/cipher-proto.h [new file with mode: 0644]
src/cipher.h
src/g10lib.h
src/gcrypt-module.h
src/gcrypt.h.in
src/global.c
src/hmac256.c [new file with mode: 0644]
src/hmac256.h [new file with mode: 0644]
src/libgcrypt.def
src/libgcrypt.vers
src/misc.c
src/module.c
src/visibility.c
src/visibility.h
tests/ChangeLog
tests/basic.c
tests/benchmark.c
tests/register.c

diff --git a/BUGS b/BUGS
deleted file mode 100644 (file)
index e69de29..0000000
index 5e62403..384b339 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-08-18  Werner Koch  <wk@g10code.com>
+
+       * Makefile.am (EXTRA_DIST): Remove the unused BUGS file.
+
+2008-08-15  Werner Koch  <wk@g10code.com>
+
+       * configure.ac (AH_BOTTOM): Define GCRY_GPG_ERR_NOT_OPERATIONAL.
+
 2008-07-05  Werner Koch  <wk@g10code.com>
 
        * random/: New.
 2008-07-05  Werner Koch  <wk@g10code.com>
 
        * random/: New.
index 87eeff0..61ae90e 100644 (file)
@@ -24,7 +24,7 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-random-daemon \
 
 DIST_SUBDIRS = m4 mpi cipher random src doc tests
 SUBDIRS = mpi cipher random src doc tests
 
 DIST_SUBDIRS = m4 mpi cipher random src doc tests
 SUBDIRS = mpi cipher random src doc tests
-EXTRA_DIST = BUGS autogen.sh README.SVN
+EXTRA_DIST = autogen.sh README.SVN
 DISTCLEANFILES = 
 
 
 DISTCLEANFILES = 
 
 
diff --git a/NEWS b/NEWS
index 53eff08..60118e7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,25 @@
 Noteworthy changes in version 1.4.2
 ------------------------------------------------
 
 Noteworthy changes in version 1.4.2
 ------------------------------------------------
 
+ * The library may now be switched into a FIPS mode.
+
+ * More runtime selftests.
+
+ * A few macros have been replaced by functions for better type
+   checking.
+
+ * The thread initialiation structure now carries version information.
+
+ * Interface changes relative to the 1.3.0 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ GCRYCTL_OPERATIONAL_P   NEW.
+ GCRYCTL_FIPS_MODE_P     NEW.
+ GCRYCTL_FORCE_FIPS_MODE NEW.
+ gcry_cipher_setkey      NEW: Replaces macro.
+ gcry_cipher_setiv       NEW: Replaces macro.
+ gcry_cipher_setctr      NEW: Replaces macro.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 
 Noteworthy changes in version 1.4.1 (2008-04-25)
 ------------------------------------------------
 
 Noteworthy changes in version 1.4.1 (2008-04-25)
 ------------------------------------------------
index b5b5216..4549fc4 100644 (file)
@@ -1,3 +1,96 @@
+2008-08-19  Werner Koch  <wk@g10code.com>
+
+       * pubkey.c (sexp_elements_extract_ecc) [!USE_ECC]: Do not allow
+       allow "curve" parameter.
+
+2008-08-15  Werner Koch  <wk@g10code.com>
+
+       * pubkey.c (_gcry_pk_selftest): New.
+       * dsa.c (selftests_dsa, run_selftests): New.
+       * rsa.c (selftests_rsa, run_selftests): New.
+       * ecc.c (selftests_ecdsa, run_selftests): New.
+
+       * md.c (_gcry_md_selftest): New.
+       * sha1.c (run_selftests, selftests_sha1): New.
+       * sha256.c (selftests_sha224, selftests_sha256, run_selftests): New.
+       * sha512.c (selftests_sha384, selftests_sha512, run_selftests): New.
+
+       * des.c (selftest): Remove static variable form selftest.
+       (des_setkey): No on-the-fly self test in fips mode.
+       (tripledes_set3keys): Ditto.
+
+       * cipher.c (_gcry_cipher_setkey, _gcry_cipher_setiv): 
+
+       * dsa.c (generate): Bail out in fips mode if NBITS is less than 1024.
+       * rsa.c (generate): Return an error code if the the requested size
+       is less than 1024 and we are in fpis mode.
+       (_gcry_rsa_generate): Take care of that error code.
+
+       * ecc.c (generate_curve): In fips mode enable only NIST curves.
+
+       * cipher.c (_gcry_cipher_selftest): New.
+
+       * sha512.c (_gcry_digest_extraspec_sha384)
+       (_gcry_digest_extraspec_sha512): New.
+       * sha256.c (_gcry_digest_extraspec_sha224)
+       (_gcry_digest_extraspec_sha256): New.
+       * sha1.c (_gcry_digest_extraspec_sha1): New.
+       * ecc.c (_gcry_pubkey_extraspec_ecdsa): New.
+       * dsa.c (_gcry_pubkey_extraspec_dsa): New.
+       * rsa.c (_gcry_pubkey_extraspec_rsa): New.
+       * rijndael.c (_gcry_cipher_extraspec_aes)
+       (_gcry_cipher_extraspec_aes192, _gcry_cipher_extraspec_aes256): New.
+       * des.c (_gcry_cipher_extraspec_tripledes): New.
+
+       * cipher.c (gcry_cipher_register): Rename to _gcry_cipher_register.
+       Add arg EXTRASPEC.
+       (dummy_extra_spec): New.
+       (cipher_table_entry): Add extraspec field.
+       * md.c (_gcry_md_register): Rename to _gcry_md_register.  Add
+       arg EXTRASPEC.
+       (dummy_extra_spec): New.
+       (digest_table_entry): Add extraspec field.
+       * pubkey.c (gcry_pk_register): Rename to _gcry_pk_register.  Add
+       arg EXTRASPEC.
+       (dummy_extra_spec): New.
+       (pubkey_table_entry): Add extraspec field.
+
+       * ac.c: Let most public functions return GPG_ERR_UNSUPPORTED in
+       fips mode.
+
+       * pubkey.c (pubkey_table_entry): Add field FIPS_ALLOWED and mark
+       appropriate algorithms.
+       (dummy_generate, dummy_check_secret_key, dummy_encrypt) 
+       (dummy_decrypt, dummy_sign, dummy_verify, dummy_get_nbits): Signal
+       a fips error when used.
+       (gcry_pk_register): In fips mode do not allow to register new
+       algorithms.
+
+       * md.c (digest_table): Add field FIPS_ALLOWED and mark appropriate
+       algorithms.
+       (md_register_default): In fips mode register only fips algorithms.
+       (gcry_md_register): In fips mode do not allow to register new
+       algorithms.
+       (gcry_md_get): Signal a fips error if called.
+       (gcry_md_hash_buffer): Do not allow rmd160 when not in fips mode.
+       (md_start_debug): Disable in fips_mode.
+
+       * md.c (gcry_md_register_default): Rename to ..
+       (md_register_default): .. this.
+       (md_digest): Remove this commented fucntion.
+       * pubkey.c (gcry_pk_register_default): Rename to ..
+       (pk_register_default): .. this.
+
+       * cipher.c (cipher_table_entry): Add field FIPS_ALLOWED.
+       (gcry_cipher_register_default): Register only fips approved
+       algorithms.
+       (gcry_cipher_register): Do not allow to register new ciphers.
+       (cipher_setiv): Signal fips error.
+       
+       * cipher (gcry_cipher_register_default): Rename to ..
+       (cipher_register_default): .. this.
+       (REGISTER_DEFAULT_CIPHERS): Adjust for that change.
+
 2008-07-05  Werner Koch  <wk@g10code.com>
 
        * random-daemon.c, random.h, rndhw.c, rndunix.c, rand-internal.h
 2008-07-05  Werner Koch  <wk@g10code.com>
 
        * random-daemon.c, random.h, rndhw.c, rndunix.c, rand-internal.h
index 40ece5a..f1c313c 100644 (file)
@@ -36,6 +36,7 @@ libcipher_la_LIBADD = $(GCRYPT_MODULES)
 
 libcipher_la_SOURCES = \
 cipher.c pubkey.c ac.c md.c \
 
 libcipher_la_SOURCES = \
 cipher.c pubkey.c ac.c md.c \
+hmac-tests.c \
 bithelp.h  \
 primegen.c  \
 rmd.h
 bithelp.h  \
 primegen.c  \
 rmd.h
@@ -65,6 +66,7 @@ twofish.c \
 rfc2268.c \
 camellia.c camellia.h camellia-glue.c
 
 rfc2268.c \
 camellia.c camellia.h camellia-glue.c
 
+
 # We need to lower the optimization for this module.
 tiger.o: $(srcdir)/tiger.c
        `echo $(COMPILE) -c $(srcdir)/tiger.c | sed -e 's/-O[2-9s]*/-O1/g' `
 # We need to lower the optimization for this module.
 tiger.o: $(srcdir)/tiger.c
        `echo $(COMPILE) -c $(srcdir)/tiger.c | sed -e 's/-O[2-9s]*/-O1/g' `
index f65de09..04a3b28 100644 (file)
@@ -127,6 +127,9 @@ _gcry_ac_data_new (gcry_ac_data_t *data)
   gcry_ac_data_t data_new;
   gcry_error_t err;
 
   gcry_ac_data_t data_new;
   gcry_error_t err;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   data_new = gcry_malloc (sizeof (*data_new));
   if (! data_new)
     {
   data_new = gcry_malloc (sizeof (*data_new));
   if (! data_new)
     {
@@ -240,6 +243,9 @@ _gcry_ac_data_copy (gcry_ac_data_t *data_cp, gcry_ac_data_t data)
   gcry_ac_data_t data_new;
   gcry_error_t err;
 
   gcry_ac_data_t data_new;
   gcry_error_t err;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   /* Allocate data set.  */
   data_new = gcry_malloc (sizeof (*data_new));
   if (! data_new)
   /* Allocate data set.  */
   data_new = gcry_malloc (sizeof (*data_new));
   if (! data_new)
@@ -290,6 +296,9 @@ _gcry_ac_data_set (gcry_ac_data_t data, unsigned int flags,
   name_cp = NULL;
   mpi_cp = NULL;
 
   name_cp = NULL;
   mpi_cp = NULL;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   if (flags & ~(GCRY_AC_FLAG_DEALLOC | GCRY_AC_FLAG_COPY))
     {
       err = gcry_error (GPG_ERR_INV_ARG);
   if (flags & ~(GCRY_AC_FLAG_DEALLOC | GCRY_AC_FLAG_COPY))
     {
       err = gcry_error (GPG_ERR_INV_ARG);
@@ -370,6 +379,9 @@ _gcry_ac_data_get_name (gcry_ac_data_t data, unsigned int flags,
   gcry_error_t err;
   unsigned int i;
 
   gcry_error_t err;
   unsigned int i;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   if (flags & ~(GCRY_AC_FLAG_COPY))
     {
       err = gcry_error (GPG_ERR_INV_ARG);
   if (flags & ~(GCRY_AC_FLAG_COPY))
     {
       err = gcry_error (GPG_ERR_INV_ARG);
@@ -421,6 +433,9 @@ _gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int flags,
   name_cp = NULL;
   mpi_cp = NULL;
 
   name_cp = NULL;
   mpi_cp = NULL;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   if (flags & ~(GCRY_AC_FLAG_COPY))
     {
       err = gcry_error (GPG_ERR_INV_ARG);
   if (flags & ~(GCRY_AC_FLAG_COPY))
     {
       err = gcry_error (GPG_ERR_INV_ARG);
@@ -496,6 +511,9 @@ _gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp,
   arg_list = NULL;
   err = 0;
 
   arg_list = NULL;
   err = 0;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   /* Calculate size of S-expression representation.  */
 
   i = 0;
   /* Calculate size of S-expression representation.  */
 
   i = 0;
@@ -626,6 +644,9 @@ _gcry_ac_data_from_sexp (gcry_ac_data_t *data_set, gcry_sexp_t sexp,
   mpi = NULL;
   err = 0;
 
   mpi = NULL;
   err = 0;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   /* Process S-expression/identifiers.  */
 
   if (identifiers)
   /* Process S-expression/identifiers.  */
 
   if (identifiers)
@@ -795,6 +816,9 @@ _gcry_ac_data_dump (const char *prefix, gcry_ac_data_t data)
   if (! data)
     return;
 
   if (! data)
     return;
 
+  if (fips_mode ())
+    return;
+
   mpi_buffer = NULL;
 
   data_n = _gcry_ac_data_length (data);
   mpi_buffer = NULL;
 
   data_n = _gcry_ac_data_length (data);
@@ -859,6 +883,9 @@ _gcry_ac_io_init_va (gcry_ac_io_t *ac_io,
 {
   memset (ac_io, 0, sizeof (*ac_io));
 
 {
   memset (ac_io, 0, sizeof (*ac_io));
 
+  if (fips_mode ())
+    return;
+
   assert ((mode == GCRY_AC_IO_READABLE) || (mode == GCRY_AC_IO_WRITABLE));
   assert ((type == GCRY_AC_IO_STRING) || (type == GCRY_AC_IO_STRING));
 
   assert ((mode == GCRY_AC_IO_READABLE) || (mode == GCRY_AC_IO_WRITABLE));
   assert ((type == GCRY_AC_IO_STRING) || (type == GCRY_AC_IO_STRING));
 
@@ -1362,6 +1389,9 @@ _gcry_ac_open (gcry_ac_handle_t *handle,
   *handle = NULL;
   module = NULL;
 
   *handle = NULL;
   module = NULL;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   /* Get name.  */
   algorithm_name = _gcry_pk_aliased_algo_name (algorithm);
   if (! algorithm_name)
   /* Get name.  */
   algorithm_name = _gcry_pk_aliased_algo_name (algorithm);
   if (! algorithm_name)
@@ -1431,6 +1461,9 @@ _gcry_ac_key_init (gcry_ac_key_t *key, gcry_ac_handle_t handle,
 
   (void)handle;
 
 
   (void)handle;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   /* Allocate.  */
   key_new = gcry_malloc (sizeof (*key_new));
   if (! key_new)
   /* Allocate.  */
   key_new = gcry_malloc (sizeof (*key_new));
   if (! key_new)
@@ -1488,6 +1521,9 @@ _gcry_ac_key_pair_generate (gcry_ac_handle_t handle, unsigned int nbits,
 
   (void)misc_data;
 
 
   (void)misc_data;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   key_data_secret = NULL;
   key_data_public = NULL;
   key_secret = NULL;
   key_data_secret = NULL;
   key_data_public = NULL;
   key_secret = NULL;
@@ -1652,6 +1688,9 @@ _gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair,
 {
   gcry_ac_key_t key;
 
 {
   gcry_ac_key_t key;
 
+  if (fips_mode ())
+    return NULL;
+
   switch (which)
     {
     case GCRY_AC_KEY_SECRET:
   switch (which)
     {
     case GCRY_AC_KEY_SECRET:
@@ -1710,6 +1749,8 @@ _gcry_ac_key_pair_destroy (gcry_ac_key_pair_t key_pair)
 gcry_ac_data_t
 _gcry_ac_key_data_get (gcry_ac_key_t key)
 {
 gcry_ac_data_t
 _gcry_ac_key_data_get (gcry_ac_key_t key)
 {
+  if (fips_mode ())
+    return NULL;
   return key->data;
 }
 
   return key->data;
 }
 
@@ -1720,6 +1761,9 @@ _gcry_ac_key_test (gcry_ac_handle_t handle, gcry_ac_key_t key)
   gcry_sexp_t key_sexp;
   gcry_error_t err;
 
   gcry_sexp_t key_sexp;
   gcry_error_t err;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   key_sexp = NULL;
   err = ac_data_construct (ac_key_identifiers[key->type], 0, 0,
                           handle->algorithm_name, key->data, &key_sexp);
   key_sexp = NULL;
   err = ac_data_construct (ac_key_identifiers[key->type], 0, 0,
                           handle->algorithm_name, key->data, &key_sexp);
@@ -1744,6 +1788,9 @@ _gcry_ac_key_get_nbits (gcry_ac_handle_t handle,
   gcry_error_t err;
   unsigned int n;
 
   gcry_error_t err;
   unsigned int n;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   key_sexp = NULL;
 
   err = ac_data_construct (ac_key_identifiers[key->type],
   key_sexp = NULL;
 
   err = ac_data_construct (ac_key_identifiers[key->type],
@@ -1777,6 +1824,9 @@ _gcry_ac_key_get_grip (gcry_ac_handle_t handle,
   gcry_error_t err;
   unsigned char *ret;
 
   gcry_error_t err;
   unsigned char *ret;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   key_sexp = NULL;
   err = ac_data_construct (ac_key_identifiers[key->type], 0, 0,
                           handle->algorithm_name, key->data, &key_sexp);
   key_sexp = NULL;
   err = ac_data_construct (ac_key_identifiers[key->type], 0, 0,
                           handle->algorithm_name, key->data, &key_sexp);
@@ -1823,6 +1873,9 @@ _gcry_ac_data_encrypt (gcry_ac_handle_t handle,
   gcry_sexp_t sexp_key;
   gcry_error_t err;
 
   gcry_sexp_t sexp_key;
   gcry_error_t err;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   data_encrypted_new = NULL;
   sexp_request = NULL;
   sexp_reply = NULL;
   data_encrypted_new = NULL;
   sexp_request = NULL;
   sexp_reply = NULL;
@@ -1897,6 +1950,9 @@ _gcry_ac_data_decrypt (gcry_ac_handle_t handle,
   gcry_sexp_t sexp_key;
   gcry_error_t err;
 
   gcry_sexp_t sexp_key;
   gcry_error_t err;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   sexp_request = NULL;
   sexp_reply = NULL;
   sexp_value = NULL;
   sexp_request = NULL;
   sexp_reply = NULL;
   sexp_value = NULL;
@@ -1969,6 +2025,9 @@ _gcry_ac_data_sign (gcry_ac_handle_t handle,
   gcry_sexp_t sexp_key;
   gcry_error_t err;
 
   gcry_sexp_t sexp_key;
   gcry_error_t err;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   data_signed = NULL;
   data_value = NULL;
   sexp_request = NULL;
   data_signed = NULL;
   data_value = NULL;
   sexp_request = NULL;
@@ -2039,6 +2098,9 @@ _gcry_ac_data_verify (gcry_ac_handle_t handle,
   gcry_sexp_t sexp_key;
   gcry_error_t err;
 
   gcry_sexp_t sexp_key;
   gcry_error_t err;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   sexp_signature = NULL;
   data_value = NULL;
   sexp_data = NULL;
   sexp_signature = NULL;
   data_value = NULL;
   sexp_data = NULL;
@@ -2509,6 +2571,9 @@ _gcry_ac_data_encode (gcry_ac_em_t method,
                      gcry_ac_io_t *ac_io_read,
                      gcry_ac_io_t *ac_io_write)
 {
                      gcry_ac_io_t *ac_io_read,
                      gcry_ac_io_t *ac_io_write)
 {
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   return ac_data_dencode (method, DATA_ENCODE, flags, options,
                          ac_io_read, ac_io_write);
 }
   return ac_data_dencode (method, DATA_ENCODE, flags, options,
                          ac_io_read, ac_io_write);
 }
@@ -2522,6 +2587,9 @@ _gcry_ac_data_decode (gcry_ac_em_t method,
                      gcry_ac_io_t *ac_io_read,
                      gcry_ac_io_t *ac_io_write)
 {
                      gcry_ac_io_t *ac_io_read,
                      gcry_ac_io_t *ac_io_write)
 {
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   return ac_data_dencode (method, DATA_DECODE, flags, options,
                          ac_io_read, ac_io_write);
 }
   return ac_data_dencode (method, DATA_DECODE, flags, options,
                          ac_io_read, ac_io_write);
 }
@@ -2537,6 +2605,9 @@ _gcry_ac_mpi_to_os (gcry_mpi_t mpi, unsigned char *os, size_t os_n)
   gcry_mpi_t m;
   gcry_mpi_t d;
 
   gcry_mpi_t m;
   gcry_mpi_t d;
 
+  if (fips_mode ())
+    return;
+
   base = gcry_mpi_new (0);
   gcry_mpi_set_ui (base, 256);
 
   base = gcry_mpi_new (0);
   gcry_mpi_set_ui (base, 256);
 
@@ -2575,6 +2646,9 @@ _gcry_ac_mpi_to_os_alloc (gcry_mpi_t mpi, unsigned char **os, size_t *os_n)
   gcry_error_t err;
   unsigned int nbits;
 
   gcry_error_t err;
   unsigned int nbits;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   nbits = gcry_mpi_get_nbits (mpi);
   buffer_n = (nbits + 7) / 8;
   buffer = gcry_malloc (buffer_n);
   nbits = gcry_mpi_get_nbits (mpi);
   buffer_n = (nbits + 7) / 8;
   buffer = gcry_malloc (buffer_n);
@@ -2604,6 +2678,9 @@ _gcry_ac_os_to_mpi (gcry_mpi_t mpi, unsigned char *os, size_t os_n)
   gcry_mpi_t x;
   gcry_mpi_t a;
   
   gcry_mpi_t x;
   gcry_mpi_t a;
   
+  if (fips_mode ())
+    return;
+
   a = gcry_mpi_new (0);
   gcry_mpi_set_ui (a, 1);
   x = gcry_mpi_new (0);
   a = gcry_mpi_new (0);
   gcry_mpi_set_ui (a, 1);
   x = gcry_mpi_new (0);
@@ -2822,6 +2899,9 @@ _gcry_ac_data_encrypt_scheme (gcry_ac_handle_t handle,
 
   (void)flags;
 
 
   (void)flags;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   data_encrypted = NULL;
   mpi_encrypted = NULL;
   mpi_plain = NULL;
   data_encrypted = NULL;
   mpi_encrypted = NULL;
   mpi_plain = NULL;
@@ -2913,6 +2993,9 @@ _gcry_ac_data_decrypt_scheme (gcry_ac_handle_t handle,
 
   (void)flags;
 
 
   (void)flags;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   data_encrypted = NULL;
   mpi_encrypted = NULL;
   mpi_decrypted = NULL;
   data_encrypted = NULL;
   mpi_encrypted = NULL;
   mpi_decrypted = NULL;
@@ -3024,6 +3107,9 @@ _gcry_ac_data_sign_scheme (gcry_ac_handle_t handle,
 
   (void)flags;
 
 
   (void)flags;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   data_signed = NULL;
   mpi_signed = NULL;
   opts_em = NULL;
   data_signed = NULL;
   mpi_signed = NULL;
   opts_em = NULL;
@@ -3116,6 +3202,9 @@ _gcry_ac_data_verify_scheme (gcry_ac_handle_t handle,
 
   (void)flags;
 
 
   (void)flags;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   mpi_signature = NULL;
   elements_sig = NULL;
   data_signed = NULL;
   mpi_signature = NULL;
   elements_sig = NULL;
   data_signed = NULL;
@@ -3206,5 +3295,8 @@ _gcry_ac_data_verify_scheme (gcry_ac_handle_t handle,
 gcry_err_code_t
 _gcry_ac_init (void)
 {
 gcry_err_code_t
 _gcry_ac_init (void)
 {
+  if (fips_mode ())
+    return GPG_ERR_NOT_SUPPORTED;
+
   return 0;
 }
   return 0;
 }
index 66470ee..e328435 100644 (file)
@@ -1,6 +1,6 @@
 /* cipher.c  - cipher dispatcher
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
 /* cipher.c  - cipher dispatcher
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
- *               2005, 2007 Free Software Foundation, Inc.
+ *               2005, 2007, 2008 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  *
  * This file is part of Libgcrypt.
  *
 #define NEED_16BYTE_ALIGNED_CONTEXT 1
 #endif
 
 #define NEED_16BYTE_ALIGNED_CONTEXT 1
 #endif
 
+/* A dummy extraspec so that we do not need to tests the extraspec
+   field from the module specification against NULL and instead
+   directly test the respective fields of extraspecs.  */
+static cipher_extra_spec_t dummy_extra_spec;
+
 /* This is the list of the default ciphers, which are included in
    libgcrypt.  */
 static struct cipher_table_entry
 {
   gcry_cipher_spec_t *cipher;
 /* This is the list of the default ciphers, which are included in
    libgcrypt.  */
 static struct cipher_table_entry
 {
   gcry_cipher_spec_t *cipher;
+  cipher_extra_spec_t *extraspec;
   unsigned int algorithm;
   unsigned int algorithm;
+  int fips_allowed;
 } cipher_table[] =
   {
 #if USE_BLOWFISH
 } cipher_table[] =
   {
 #if USE_BLOWFISH
-    { &_gcry_cipher_spec_blowfish,   GCRY_CIPHER_BLOWFISH },
+    { &_gcry_cipher_spec_blowfish,
+      &dummy_extra_spec,                  GCRY_CIPHER_BLOWFISH },
 #endif
 #if USE_DES
 #endif
 #if USE_DES
-    { &_gcry_cipher_spec_des,        GCRY_CIPHER_DES },
-    { &_gcry_cipher_spec_tripledes,  GCRY_CIPHER_3DES },
+    { &_gcry_cipher_spec_des,       
+      &dummy_extra_spec,                  GCRY_CIPHER_DES },
+    { &_gcry_cipher_spec_tripledes,
+      &_gcry_cipher_extraspec_tripledes,  GCRY_CIPHER_3DES, 1 },
 #endif
 #if USE_ARCFOUR
 #endif
 #if USE_ARCFOUR
-    { &_gcry_cipher_spec_arcfour,    GCRY_CIPHER_ARCFOUR },
+    { &_gcry_cipher_spec_arcfour,    
+      &dummy_extra_spec,                  GCRY_CIPHER_ARCFOUR },
 #endif
 #if USE_CAST5
 #endif
 #if USE_CAST5
-    { &_gcry_cipher_spec_cast5,      GCRY_CIPHER_CAST5 },
+    { &_gcry_cipher_spec_cast5,      
+      &dummy_extra_spec,                  GCRY_CIPHER_CAST5 },
 #endif
 #if USE_AES
 #endif
 #if USE_AES
-    { &_gcry_cipher_spec_aes,        GCRY_CIPHER_AES},
-    { &_gcry_cipher_spec_aes192,     GCRY_CIPHER_AES192},
-    { &_gcry_cipher_spec_aes256,     GCRY_CIPHER_AES256},
+    { &_gcry_cipher_spec_aes,        
+      &_gcry_cipher_extraspec_aes,        GCRY_CIPHER_AES,    1 },
+    { &_gcry_cipher_spec_aes192,     
+      &_gcry_cipher_extraspec_aes192,     GCRY_CIPHER_AES192, 1 },
+    { &_gcry_cipher_spec_aes256,     
+      &_gcry_cipher_extraspec_aes256,     GCRY_CIPHER_AES256, 1 },
 #endif
 #if USE_TWOFISH
 #endif
 #if USE_TWOFISH
-    { &_gcry_cipher_spec_twofish,    GCRY_CIPHER_TWOFISH },
-    { &_gcry_cipher_spec_twofish128, GCRY_CIPHER_TWOFISH128 },
+    { &_gcry_cipher_spec_twofish,
+      &dummy_extra_spec,                  GCRY_CIPHER_TWOFISH },
+    { &_gcry_cipher_spec_twofish128,     
+      &dummy_extra_spec,                  GCRY_CIPHER_TWOFISH128 },
 #endif
 #if USE_SERPENT
 #endif
 #if USE_SERPENT
-    { &_gcry_cipher_spec_serpent128, GCRY_CIPHER_SERPENT128 },
-    { &_gcry_cipher_spec_serpent192, GCRY_CIPHER_SERPENT192 },
-    { &_gcry_cipher_spec_serpent256, GCRY_CIPHER_SERPENT256 },
+    { &_gcry_cipher_spec_serpent128, 
+      &dummy_extra_spec,                  GCRY_CIPHER_SERPENT128 },
+    { &_gcry_cipher_spec_serpent192,
+      &dummy_extra_spec,                  GCRY_CIPHER_SERPENT192 },
+    { &_gcry_cipher_spec_serpent256, 
+      &dummy_extra_spec,                  GCRY_CIPHER_SERPENT256 },
 #endif
 #if USE_RFC2268
 #endif
 #if USE_RFC2268
-    { &_gcry_cipher_spec_rfc2268_40, GCRY_CIPHER_RFC2268_40 },
+    { &_gcry_cipher_spec_rfc2268_40,
+      &dummy_extra_spec,                  GCRY_CIPHER_RFC2268_40 },
 #endif
 #if USE_SEED
 #endif
 #if USE_SEED
-    { &_gcry_cipher_spec_seed,       GCRY_CIPHER_SEED },
+    { &_gcry_cipher_spec_seed, 
+      &dummy_extra_spec,                  GCRY_CIPHER_SEED },
 #endif
 #if USE_CAMELLIA
 #endif
 #if USE_CAMELLIA
-    { &_gcry_cipher_spec_camellia128, GCRY_CIPHER_CAMELLIA128 },
-    { &_gcry_cipher_spec_camellia192, GCRY_CIPHER_CAMELLIA192 },
-    { &_gcry_cipher_spec_camellia256, GCRY_CIPHER_CAMELLIA256 },
+    { &_gcry_cipher_spec_camellia128,
+      &dummy_extra_spec,                  GCRY_CIPHER_CAMELLIA128 },
+    { &_gcry_cipher_spec_camellia192, 
+      &dummy_extra_spec,                  GCRY_CIPHER_CAMELLIA192 },
+    { &_gcry_cipher_spec_camellia256,
+      &dummy_extra_spec,                  GCRY_CIPHER_CAMELLIA256 },
 #endif
     { NULL                    }
   };
 #endif
     { NULL                    }
   };
@@ -104,7 +129,7 @@ static int default_ciphers_registered;
       ath_mutex_lock (&ciphers_registered_lock);   \
       if (! default_ciphers_registered)            \
         {                                          \
       ath_mutex_lock (&ciphers_registered_lock);   \
       if (! default_ciphers_registered)            \
         {                                          \
-          gcry_cipher_register_default ();         \
+          cipher_register_default ();              \
           default_ciphers_registered = 1;          \
         }                                          \
       ath_mutex_unlock (&ciphers_registered_lock); \
           default_ciphers_registered = 1;          \
         }                                          \
       ath_mutex_unlock (&ciphers_registered_lock); \
@@ -251,7 +276,7 @@ dummy_decrypt_stream (void *c,
    CIPHER_TABLE.  Note, that this function gets only used by the macro
    REGISTER_DEFAULT_CIPHERS which protects it using a mutex. */
 static void
    CIPHER_TABLE.  Note, that this function gets only used by the macro
    REGISTER_DEFAULT_CIPHERS which protects it using a mutex. */
 static void
-gcry_cipher_register_default (void)
+cipher_register_default (void)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   int i;
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   int i;
@@ -269,9 +294,13 @@ gcry_cipher_register_default (void)
       if (! cipher_table[i].cipher->stdecrypt)
        cipher_table[i].cipher->stdecrypt = dummy_decrypt_stream;
 
       if (! cipher_table[i].cipher->stdecrypt)
        cipher_table[i].cipher->stdecrypt = dummy_decrypt_stream;
 
+      if ( fips_mode () && !cipher_table[i].fips_allowed )
+        continue;
+
       err = _gcry_module_add (&ciphers_registered,
                              cipher_table[i].algorithm,
                              (void *) cipher_table[i].cipher,
       err = _gcry_module_add (&ciphers_registered,
                              cipher_table[i].algorithm,
                              (void *) cipher_table[i].cipher,
+                             (void *) cipher_table[i].extraspec,
                              NULL);
     }
 
                              NULL);
     }
 
@@ -340,16 +369,23 @@ gcry_cipher_lookup_oid (const char *oid)
    CIPHER.  On success, a new algorithm ID is stored in ALGORITHM_ID
    and a pointer representhing this module is stored in MODULE.  */
 gcry_error_t
    CIPHER.  On success, a new algorithm ID is stored in ALGORITHM_ID
    and a pointer representhing this module is stored in MODULE.  */
 gcry_error_t
-gcry_cipher_register (gcry_cipher_spec_t *cipher,
-                     int *algorithm_id,
-                     gcry_module_t *module)
+_gcry_cipher_register (gcry_cipher_spec_t *cipher,
+                       cipher_extra_spec_t *extraspec,
+                       int *algorithm_id,
+                       gcry_module_t *module)
 {
   gcry_err_code_t err = 0;
   gcry_module_t mod;
 
 {
   gcry_err_code_t err = 0;
   gcry_module_t mod;
 
+  /* We do not support module loading in fips mode.  */
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   ath_mutex_lock (&ciphers_registered_lock);
   err = _gcry_module_add (&ciphers_registered, 0,
   ath_mutex_lock (&ciphers_registered_lock);
   err = _gcry_module_add (&ciphers_registered, 0,
-                         (void *) cipher, &mod);
+                         (void *)cipher, 
+                         (void *)(extraspec? extraspec : &dummy_extra_spec), 
+                          &mod);
   ath_mutex_unlock (&ciphers_registered_lock);
 
   if (! err)
   ath_mutex_unlock (&ciphers_registered_lock);
 
   if (! err)
@@ -529,8 +565,9 @@ disable_cipher_algo (int algorithm)
 }
 
 
 }
 
 
-/* Return 0 if the cipher algorithm with indentifier ALGORITHM is
-   available. Returns a basic error code value if it is not available.  */
+/* Return 0 if the cipher algorithm with identifier ALGORITHM is
+   available. Returns a basic error code value if it is not
+   available.  */
 static gcry_err_code_t
 check_cipher_algo (int algorithm)
 {
 static gcry_err_code_t
 check_cipher_algo (int algorithm)
 {
@@ -572,7 +609,7 @@ cipher_get_keylen (int algorithm)
   if (cipher)
     {
       len = ((gcry_cipher_spec_t *) cipher->spec)->keylen;
   if (cipher)
     {
       len = ((gcry_cipher_spec_t *) cipher->spec)->keylen;
-      if (! len)
+      if (!len)
        log_bug ("cipher %d w/o key length\n", algorithm);
       _gcry_module_release (cipher);
     }
        log_bug ("cipher %d w/o key length\n", algorithm);
       _gcry_module_release (cipher);
     }
@@ -793,7 +830,7 @@ gcry_cipher_close (gcry_cipher_hd_t h)
 {
   size_t off;
 
 {
   size_t off;
 
-  if (! h)
+  if (!h)
     return;
 
   if ((h->magic != CTX_MAGIC_SECURE)
     return;
 
   if ((h->magic != CTX_MAGIC_SECURE)
@@ -824,16 +861,18 @@ gcry_cipher_close (gcry_cipher_hd_t h)
 /* Set the key to be used for the encryption context C to KEY with
    length KEYLEN.  The length should match the required length. */
 static gcry_error_t
 /* Set the key to be used for the encryption context C to KEY with
    length KEYLEN.  The length should match the required length. */
 static gcry_error_t
-cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned keylen)
+cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen)
 {
   gcry_err_code_t ret;
 
   ret = (*c->cipher->setkey) (&c->context.c, key, keylen);
 {
   gcry_err_code_t ret;
 
   ret = (*c->cipher->setkey) (&c->context.c, key, keylen);
-  if (! ret)
-    /* Duplicate initial context.  */
-    memcpy ((void *) ((char *) &c->context.c + c->cipher->contextsize),
-           (void *) &c->context.c,
-           c->cipher->contextsize);
+  if (!ret)
+    {
+      /* Duplicate initial context.  */
+      memcpy ((void *) ((char *) &c->context.c + c->cipher->contextsize),
+              (void *) &c->context.c,
+              c->cipher->contextsize);
+    }
 
   return gcry_error (ret);
 }
 
   return gcry_error (ret);
 }
@@ -848,8 +887,11 @@ cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen )
   if (iv) 
     {
       if (ivlen != c->cipher->blocksize)
   if (iv) 
     {
       if (ivlen != c->cipher->blocksize)
-        log_info ("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
-                  ivlen, (unsigned int)c->cipher->blocksize);
+        {
+          log_info ("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
+                    ivlen, (unsigned int)c->cipher->blocksize);
+          fips_signal_error ("IV length does not match blocklength");
+        }
       if (ivlen > c->cipher->blocksize)
         ivlen = c->cipher->blocksize;
       memcpy (c->u_iv.iv, iv, ivlen);
       if (ivlen > c->cipher->blocksize)
         ivlen = c->cipher->blocksize;
       memcpy (c->u_iv.iv, iv, ivlen);
@@ -876,12 +918,13 @@ static void
 do_ecb_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
                 unsigned int nblocks )
 {
 do_ecb_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
                 unsigned int nblocks )
 {
-    unsigned int n;
-
-    for(n=0; n < nblocks; n++ ) {
-       c->cipher->encrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf );
-       inbuf  += c->cipher->blocksize;
-       outbuf += c->cipher->blocksize;
+  unsigned int n;
+  
+  for (n=0; n < nblocks; n++ )
+    {
+      c->cipher->encrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf );
+      inbuf  += c->cipher->blocksize;
+      outbuf += c->cipher->blocksize;
     }
 }
 
     }
 }
 
@@ -889,12 +932,13 @@ static void
 do_ecb_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
                 unsigned int nblocks )
 {
 do_ecb_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
                 unsigned int nblocks )
 {
-    unsigned n;
+  unsigned int n;
 
 
-    for(n=0; n < nblocks; n++ ) {
-       c->cipher->decrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf );
-       inbuf  += c->cipher->blocksize;
-       outbuf += c->cipher->blocksize;
+  for (n=0; n < nblocks; n++ ) 
+    {
+      c->cipher->decrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf );
+      inbuf  += c->cipher->blocksize;
+      outbuf += c->cipher->blocksize;
     }
 }
 
     }
 }
 
@@ -994,7 +1038,7 @@ do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
       for (n=0; n < nblocks; n++ ) 
         {
           /* Because outbuf and inbuf might be the same, we have to
       for (n=0; n < nblocks; n++ ) 
         {
           /* Because outbuf and inbuf might be the same, we have to
-           * save the original ciphertext block.  We use lastiv for
+           * save the original ciphertext block.  We use LASTIV for
            * this here because it is not used otherwise. */
           memcpy (c->lastiv, inbuf, blocksize);
           c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
            * this here because it is not used otherwise. */
           memcpy (c->lastiv, inbuf, blocksize);
           c->cipher->decrypt ( &c->context.c, outbuf, inbuf );
@@ -1400,10 +1444,12 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
   gcry_err_code_t err;
 
   if (!in)
   gcry_err_code_t err;
 
   if (!in)
-    /* Caller requested in-place encryption. */
-    /* Actually cipher_encrypt() does not need to know about it, but
-     * we may change it in the future to get better performance.  */
-    err = cipher_encrypt (h, out, out, outsize);
+    {
+      /* Caller requested in-place encryption. */
+      /* Actually cipher_encrypt() does not need to know about it, but
+       * we may change it in the future to get better performance.  */
+      err = cipher_encrypt (h, out, out, outsize);
+    }
   else if (outsize < ((h->flags & GCRY_CIPHER_CBC_MAC) ?
                       h->cipher->blocksize : inlen))
     err = GPG_ERR_TOO_SHORT;
   else if (outsize < ((h->flags & GCRY_CIPHER_CBC_MAC) ?
                       h->cipher->blocksize : inlen))
     err = GPG_ERR_TOO_SHORT;
@@ -1485,10 +1531,12 @@ gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
   gcry_err_code_t err = 0;
 
   if (!in)
   gcry_err_code_t err = 0;
 
   if (!in)
-    /* Caller requested in-place encryption. */
-    /* Actually cipher_encrypt() does not need to know about it, but
-     * we may change it in the future to get better performance.  */
-    err = cipher_decrypt (h, out, out, outsize);
+    {
+      /* Caller requested in-place encryption. */
+      /* Actually cipher_encrypt() does not need to know about it, but
+       * we may change it in the future to get better performance.  */
+      err = cipher_decrypt (h, out, out, outsize);
+    }
   else if (outsize < inlen)
     err = GPG_ERR_TOO_SHORT;
   else if (((h->mode == GCRY_CIPHER_MODE_ECB)
   else if (outsize < inlen)
     err = GPG_ERR_TOO_SHORT;
   else if (((h->mode == GCRY_CIPHER_MODE_ECB)
@@ -1510,7 +1558,7 @@ gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
  * the corresponding flag is set.
  */
 static void
  * the corresponding flag is set.
  */
 static void
-cipher_sync( gcry_cipher_hd_t c )
+cipher_sync (gcry_cipher_hd_t c)
 {
   if ((c->flags & GCRY_CIPHER_ENABLE_SYNC) && c->unused)
     {
 {
   if ((c->flags & GCRY_CIPHER_ENABLE_SYNC) && c->unused)
     {
@@ -1524,24 +1572,58 @@ cipher_sync( gcry_cipher_hd_t c )
 
 
 gcry_error_t
 
 
 gcry_error_t
+_gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen)
+{
+  return cipher_setkey (hd, (void*)key, keylen);
+}
+
+
+gcry_error_t
+_gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen)
+{
+  cipher_setiv (hd, iv, ivlen);
+  return 0;
+}
+
+/* Set counter for CTR mode.  (CTR,CTRLEN) must denote a buffer of
+   block size length, or (NULL,0) to set the CTR to the all-zero
+   block. */
+gpg_error_t
+_gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen)
+{
+  if (ctr && ctrlen == hd->cipher->blocksize)
+    memcpy (hd->ctr, ctr, hd->cipher->blocksize);
+  else if (!ctr || !ctrlen)
+    memset (hd->ctr, 0, hd->cipher->blocksize);
+  else
+    return gpg_error (GPG_ERR_INV_ARG);
+  return 0;
+}
+
+
+gcry_error_t
 gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
 {
   gcry_err_code_t rc = GPG_ERR_NO_ERROR;
 
   switch (cmd)
     {
 gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
 {
   gcry_err_code_t rc = GPG_ERR_NO_ERROR;
 
   switch (cmd)
     {
-    case GCRYCTL_SET_KEY:
+    case GCRYCTL_SET_KEY:  /* Deprecated; use gcry_cipher_setkey.  */
       rc = cipher_setkey( h, buffer, buflen );
       break;
       rc = cipher_setkey( h, buffer, buflen );
       break;
-    case GCRYCTL_SET_IV:
+
+    case GCRYCTL_SET_IV:   /* Deprecated; use gcry_cipher_setiv.  */
       cipher_setiv( h, buffer, buflen );
       break;
       cipher_setiv( h, buffer, buflen );
       break;
+
     case GCRYCTL_RESET:
       cipher_reset (h);
       break;
     case GCRYCTL_RESET:
       cipher_reset (h);
       break;
+
     case GCRYCTL_CFB_SYNC:
       cipher_sync( h );
       break;
     case GCRYCTL_CFB_SYNC:
       cipher_sync( h );
       break;
+
     case GCRYCTL_SET_CBC_CTS:
       if (buflen)
        if (h->flags & GCRY_CIPHER_CBC_MAC)
     case GCRYCTL_SET_CBC_CTS:
       if (buflen)
        if (h->flags & GCRY_CIPHER_CBC_MAC)
@@ -1551,6 +1633,7 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
       else
        h->flags &= ~GCRY_CIPHER_CBC_CTS;
       break;
       else
        h->flags &= ~GCRY_CIPHER_CBC_CTS;
       break;
+
     case GCRYCTL_SET_CBC_MAC:
       if (buflen)
        if (h->flags & GCRY_CIPHER_CBC_CTS)
     case GCRYCTL_SET_CBC_MAC:
       if (buflen)
        if (h->flags & GCRY_CIPHER_CBC_CTS)
@@ -1560,15 +1643,16 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
       else
        h->flags &= ~GCRY_CIPHER_CBC_MAC;
       break;
       else
        h->flags &= ~GCRY_CIPHER_CBC_MAC;
       break;
+
     case GCRYCTL_DISABLE_ALGO:
     case GCRYCTL_DISABLE_ALGO:
-      /* this one expects a NULL handle and buffer pointing to an
-       * integer with the algo number.
-       */
+      /* This command expects NULL for H and BUFFER to point to an
+         integer with the algo number.  */
       if( h || !buffer || buflen != sizeof(int) )
        return gcry_error (GPG_ERR_CIPHER_ALGO);
       disable_cipher_algo( *(int*)buffer );
       break;
       if( h || !buffer || buflen != sizeof(int) )
        return gcry_error (GPG_ERR_CIPHER_ALGO);
       disable_cipher_algo( *(int*)buffer );
       break;
-    case GCRYCTL_SET_CTR:
+
+    case GCRYCTL_SET_CTR: /* Deprecated; use gcry_cipher_setctr.  */
       if (buffer && buflen == h->cipher->blocksize)
        memcpy (h->ctr, buffer, h->cipher->blocksize);
       else if (buffer == NULL || buflen == 0)
       if (buffer && buflen == h->cipher->blocksize)
        memcpy (h->ctr, buffer, h->cipher->blocksize);
       else if (buffer == NULL || buflen == 0)
@@ -1585,11 +1669,16 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
 }
 
 
 }
 
 
-/****************
- * Return information about the cipher handle.
+/* Return information about the cipher handle H.  CMD is the kind of
+   information requested.  BUFFER and NBYTES are reserved for now.
+
+   There are no values for CMD yet defined.  
+
+   The fucntion always returns GPG_ERR_INV_OP.
+   
  */
 gcry_error_t
  */
 gcry_error_t
-gcry_cipher_infogcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
+gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
 
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
 
@@ -1606,27 +1695,29 @@ gcry_cipher_info( gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
   return gcry_error (err);
 }
 
   return gcry_error (err);
 }
 
-/****************
- * Return information about the given cipher algorithm
- * WHAT select the kind of information returned:
- *  GCRYCTL_GET_KEYLEN:
- *     Return the length of the key, if the algorithm
- *     supports multiple key length, the maximum supported value
- *     is returnd.  The length is return as number of octets.
- *     buffer and nbytes must be zero.
- *     The keylength is returned in _bytes_.
- *  GCRYCTL_GET_BLKLEN:
- *     Return the blocklength of the algorithm counted in octets.
- *     buffer and nbytes must be zero.
- *  GCRYCTL_TEST_ALGO:
- *     Returns 0 when the specified algorithm is available for use.
- *     buffer and nbytes must be zero.
- *
- * Note:  Because this function is in most cases used to return an
- * integer value, we can make it easier for the caller to just look at
- * the return value.  The caller will in all cases consult the value
- * and thereby detecting whether a error occured or not (i.e. while checking
- * the block size)
+/* Return information about the given cipher algorithm ALGO.
+
+   WHAT select the kind of information returned:
+
+    GCRYCTL_GET_KEYLEN:
+       Return the length of the key.  If the algorithm ALGO
+       supports multiple key lengths, the maximum supported key length
+       is returned.  The key length is returned as number of octets.
+       BUFFER and NBYTES must be zero.
+
+    GCRYCTL_GET_BLKLEN:
+       Return the blocklength of the algorithm ALGO counted in octets.
+       BUFFER and NBYTES must be zero.
+
+    GCRYCTL_TEST_ALGO:
+       Returns 0 if the specified algorithm ALGO is available for use.
+       BUFFER and NBYTES must be zero.
+  
+   Note: Because this function is in most cases used to return an
+   integer value, we can make it easier for the caller to just look at
+   the return value.  The caller will in all cases consult the value
+   and thereby detecting whether a error occured or not (i.e. while
+   checking the block size)
  */
 gcry_error_t
 gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes)
  */
 gcry_error_t
 gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes)
@@ -1681,17 +1772,30 @@ gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes)
 }
 
 
 }
 
 
+/* This function returns length of the key for algorithm ALGO.  If the
+   algorithm supports multiple key lengths, the maximum supported key
+   length is returned.  On error 0 is returned.  The key length is
+   returned as number of octets.
+
+   This is a convenience functions which should be preferred over
+   gcry_cipher_algo_info because it allows for proper type
+   checking.  */
 size_t
 gcry_cipher_get_algo_keylen (int algo) 
 {
   size_t n;
 
 size_t
 gcry_cipher_get_algo_keylen (int algo) 
 {
   size_t n;
 
-  if (gcry_cipher_algo_infoalgo, GCRYCTL_GET_KEYLEN, NULL, &n))
+  if (gcry_cipher_algo_info (algo, GCRYCTL_GET_KEYLEN, NULL, &n))
     n = 0;
   return n;
 }
 
     n = 0;
   return n;
 }
 
+/* This functions returns the blocklength of the algorithm ALGO
+   counted in octets.  On error 0 is returned.
 
 
+   This is a convenience functions which should be preferred over
+   gcry_cipher_algo_info because it allows for proper type
+   checking.  */
 size_t
 gcry_cipher_get_algo_blklen (int algo) 
 {
 size_t
 gcry_cipher_get_algo_blklen (int algo) 
 {
@@ -1702,7 +1806,7 @@ gcry_cipher_get_algo_blklen (int algo)
   return n;
 }
 
   return n;
 }
 
-
+/* Explicitly initialize this module.  */
 gcry_err_code_t
 _gcry_cipher_init (void)
 {
 gcry_err_code_t
 _gcry_cipher_init (void)
 {
@@ -1730,3 +1834,41 @@ gcry_cipher_list (int *list, int *list_length)
 
   return err;
 }
 
   return err;
 }
+
+
+/* Run the selftests for cipher algorithm ALGO with optional reporting
+   function REPORT.  */
+gpg_error_t
+_gcry_cipher_selftest (int algo, selftest_report_func_t report)
+{
+  gcry_module_t module = NULL;
+  cipher_extra_spec_t *extraspec = NULL;
+  gcry_err_code_t ec = 0;
+
+  REGISTER_DEFAULT_CIPHERS;
+
+  ath_mutex_lock (&ciphers_registered_lock);
+  module = _gcry_module_lookup_id (ciphers_registered, algo);
+  if (module && !(module->flags & FLAG_MODULE_DISABLED))
+    extraspec = module->extraspec;
+  ath_mutex_unlock (&ciphers_registered_lock);
+  if (extraspec && extraspec->selftest)
+    ec = extraspec->selftest (algo, report);
+  else
+    {
+      ec = GPG_ERR_CIPHER_ALGO;
+      if (report)
+        report ("cipher", algo, "module", 
+                module && !(module->flags & FLAG_MODULE_DISABLED)?
+                "no selftest available" :
+                module? "algorithm disabled" : "algorithm not found");
+    }
+
+  if (module)
+    {
+      ath_mutex_lock (&ciphers_registered_lock);
+      _gcry_module_release (module);
+      ath_mutex_unlock (&ciphers_registered_lock);
+    }
+  return gpg_error (ec);
+}
index 81b5337..dcc4a6b 100644 (file)
  *     char *error_msg;
  *
  *     * To perform a selftest of this DES/Triple-DES implementation use the
  *     char *error_msg;
  *
  *     * To perform a selftest of this DES/Triple-DES implementation use the
- *      function selftest(). It will return an error string if their are
+ *      function selftest(). It will return an error string if there are
  *      some problems with this library. *
  *
  *     if ( (error_msg = selftest()) )
  *      some problems with this library. *
  *
  *     if ( (error_msg = selftest()) )
@@ -310,7 +310,7 @@ static byte encrypt_rotate_tab[16] =
 
 /*
  * Table with weak DES keys sorted in ascending order.
 
 /*
  * Table with weak DES keys sorted in ascending order.
- * In DES their are 64 known keys wich are weak. They are weak
+ * In DES their are 64 known keys which are weak. They are weak
  * because they produce only one, two or four different
  * subkeys in the subkey scheduling process.
  * The keys in this table have all their parity bits cleared.
  * because they produce only one, two or four different
  * subkeys in the subkey scheduling process.
  * The keys in this table have all their parity bits cleared.
@@ -584,7 +584,7 @@ des_setkey (struct _des_ctx *ctx, const byte * key)
   static const char *selftest_failed;
   int i;
 
   static const char *selftest_failed;
   int i;
 
-  if (! initialized)
+  if (!fips_mode () && !initialized)
     {
       initialized = 1;
       selftest_failed = selftest ();
     {
       initialized = 1;
       selftest_failed = selftest ();
@@ -691,7 +691,7 @@ tripledes_set3keys (struct _tripledes_ctx *ctx,
   static const char *selftest_failed;
   int i;
 
   static const char *selftest_failed;
   int i;
 
-  if (! initialized)
+  if (!fips_mode () && !initialized)
     {
       initialized = 1;
       selftest_failed = selftest ();
     {
       initialized = 1;
       selftest_failed = selftest ();
@@ -956,7 +956,6 @@ selftest (void)
 
     byte               result[8];
     int                i;
 
     byte               result[8];
     int                i;
-    static char        error[80];
     tripledes_ctx      des3;
 
     for (i=0; i<sizeof(testdata)/sizeof(*testdata); ++i)
     tripledes_ctx      des3;
 
     for (i=0; i<sizeof(testdata)/sizeof(*testdata); ++i)
@@ -966,19 +965,11 @@ selftest (void)
         
         tripledes_ecb_encrypt (des3, testdata[i].plain, result);
         if (memcmp (testdata[i].cipher, result, 8))
         
         tripledes_ecb_encrypt (des3, testdata[i].plain, result);
         if (memcmp (testdata[i].cipher, result, 8))
-          {
-            sprintf (error, "Triple-DES SSLeay test pattern no. %d "
-                     "failed on encryption.", i+1);
-            return error;
-          }
+          return "Triple-DES SSLeay test failed on encryption.";
 
         tripledes_ecb_decrypt (des3, testdata[i].cipher, result);
         if (memcmp (testdata[i].plain, result, 8))
 
         tripledes_ecb_decrypt (des3, testdata[i].cipher, result);
         if (memcmp (testdata[i].plain, result, 8))
-          {
-            sprintf (error, "Triple-DES SSLeay test pattern no. %d "
-                     "failed on decryption.", i+1);
-            return error;
-          }
+          return  "Triple-DES SSLeay test failed on decryption.";;
       }
   }
 
       }
   }
 
@@ -992,14 +983,14 @@ selftest (void)
     unsigned char *p;
     gcry_md_hd_t h;
 
     unsigned char *p;
     gcry_md_hd_t h;
 
-    if (gcry_md_open (&h, GCRY_MD_SHA1, 0))
+    if (_gcry_md_open (&h, GCRY_MD_SHA1, 0))
       return "SHA1 not available";
 
     for (i = 0; i < 64; ++i)
       return "SHA1 not available";
 
     for (i = 0; i < 64; ++i)
-      gcry_md_write (h, weak_keys[i], 8);
-    p = gcry_md_read (h, GCRY_MD_SHA1);
+      _gcry_md_write (h, weak_keys[i], 8);
+    p = _gcry_md_read (h, GCRY_MD_SHA1);
     i = memcmp (p, weak_keys_chksum, 20);
     i = memcmp (p, weak_keys_chksum, 20);
-    gcry_md_close (h);
+    _gcry_md_close (h);
     if (i)
       return "weak key table defect";
 
     if (i)
       return "weak key table defect";
 
@@ -1088,6 +1079,59 @@ do_des_decrypt( void *context, byte *outbuf, const byte *inbuf )
   _gcry_burn_stack (32);
 }
 
   _gcry_burn_stack (32);
 }
 
+
+
+\f
+/* 
+     Self-test section.
+ */
+
+
+/* Complete selftest for TripleDES with all modes and driver code.  */
+static gpg_err_code_t
+selftest_fips (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = selftest ();
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("cipher", GCRY_CIPHER_3DES, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+
+/* Run a full self-test for ALGO and return 0 on success.  */
+static gpg_err_code_t
+run_selftests (int algo, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_CIPHER_3DES:
+      ec = selftest_fips (report);
+      break;
+    default:
+      ec = GPG_ERR_CIPHER_ALGO;
+      break;
+        
+    }
+  return ec;
+}
+
+
+\f
 gcry_cipher_spec_t _gcry_cipher_spec_des =
   {
     "DES", NULL, NULL, 8, 64, sizeof (struct _des_ctx),
 gcry_cipher_spec_t _gcry_cipher_spec_des =
   {
     "DES", NULL, NULL, 8, 64, sizeof (struct _des_ctx),
@@ -1109,3 +1153,8 @@ gcry_cipher_spec_t _gcry_cipher_spec_tripledes =
     "3DES", NULL, oids_tripledes, 8, 192, sizeof (struct _tripledes_ctx),
     do_tripledes_setkey, do_tripledes_encrypt, do_tripledes_decrypt
   };
     "3DES", NULL, oids_tripledes, 8, 192, sizeof (struct _tripledes_ctx),
     do_tripledes_setkey, do_tripledes_encrypt, do_tripledes_decrypt
   };
+
+cipher_extra_spec_t _gcry_cipher_extraspec_tripledes = 
+  {
+    run_selftests
+  };
index bf5bf6d..ccfd686 100644 (file)
@@ -1,6 +1,6 @@
 /* dsa.c  -  DSA signature scheme
  * Copyright (C) 1998, 2000, 2001, 2002, 2003,
 /* dsa.c  -  DSA signature scheme
  * Copyright (C) 1998, 2000, 2001, 2002, 2003,
- *               2006  Free Software Foundation, Inc.
+ *               2006, 2008  Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  *
  * This file is part of Libgcrypt.
  *
@@ -207,6 +207,9 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
   if (nbits < 2*qbits || nbits > 15360)
     return GPG_ERR_INV_VALUE;
 
   if (nbits < 2*qbits || nbits > 15360)
     return GPG_ERR_INV_VALUE;
 
+  if (nbits < 1024 && fips_mode ())
+    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]);
   p = _gcry_generate_elg_prime( 1, nbits, qbits, NULL, ret_factors );
   /* get q out of factors */
   q = mpi_copy((*ret_factors)[0]);
@@ -531,6 +534,57 @@ _gcry_dsa_get_nbits (int algo, gcry_mpi_t *pkey)
   return mpi_get_nbits (pkey[0]);
 }
 
   return mpi_get_nbits (pkey[0]);
 }
 
+
+\f
+/* 
+     Self-test section.
+ */
+
+
+static gpg_err_code_t
+selftests_dsa (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = NULL; /*selftest ();*/
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("pubkey", GCRY_PK_DSA, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Run a full self-test for ALGO and return 0 on success.  */
+static gpg_err_code_t
+run_selftests (int algo, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_PK_DSA:
+      ec = selftests_dsa (report);
+      break;
+    default:
+      ec = GPG_ERR_PUBKEY_ALGO;
+      break;
+        
+    }
+  return ec;
+}
+
+
+
+\f
 static const char *dsa_names[] =
   {
     "dsa",
 static const char *dsa_names[] =
   {
     "dsa",
@@ -551,4 +605,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_dsa =
     _gcry_dsa_verify,
     _gcry_dsa_get_nbits,
   };
     _gcry_dsa_verify,
     _gcry_dsa_get_nbits,
   };
+pk_extra_spec_t _gcry_pubkey_extraspec_dsa = 
+  {
+    run_selftests
+  };
 
 
index b93e809..d1da75a 100644 (file)
@@ -1,5 +1,5 @@
 /* ecc.c  -  Elliptic Curve Cryptography
 /* ecc.c  -  Elliptic Curve Cryptography
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
 
    This file is part of Libgcrypt.
   
 
    This file is part of Libgcrypt.
   
@@ -128,6 +128,7 @@ static const struct
 {
   const char *desc;           /* Description of the curve.  */
   unsigned int nbits;         /* Number of bits.  */
 {
   const char *desc;           /* Description of the curve.  */
   unsigned int nbits;         /* Number of bits.  */
+  unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
   const char  *p;             /* Order of the prime field.  */
   const char *a, *b;          /* The coefficients. */
   const char *n;              /* The order of the base point.  */
   const char  *p;             /* Order of the prime field.  */
   const char *a, *b;          /* The coefficients. */
   const char *n;              /* The order of the base point.  */
@@ -135,7 +136,7 @@ static const struct
 } domain_parms[] =
   {
     {
 } domain_parms[] =
   {
     {
-      "NIST P-192", 192,
+      "NIST P-192", 192, 1,
       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
@@ -145,7 +146,7 @@ static const struct
       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
     },
     {
       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
     },
     {
-      "NIST P-224", 224,
+      "NIST P-224", 224, 1,
       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
@@ -155,7 +156,7 @@ static const struct
       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
     },
     {
       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
     },
     {
-      "NIST P-256", 256,
+      "NIST P-256", 256, 1,
       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
@@ -165,7 +166,7 @@ static const struct
       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
     },
     {
       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
     },
     {
-      "NIST P-384", 384,
+      "NIST P-384", 384, 1,
       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
       "ffffffff0000000000000000ffffffff",
       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
       "ffffffff0000000000000000ffffffff",
       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
@@ -181,7 +182,7 @@ static const struct
       "0a60b1ce1d7e819d7a431d7c90ea0e5f"
     },
     {
       "0a60b1ce1d7e819d7a431d7c90ea0e5f"
     },
     {
-      "NIST P-521", 521,
+      "NIST P-521", 521, 1,
       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
@@ -197,7 +198,7 @@ static const struct
       "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
     },
 
       "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
     },
 
-    { "brainpoolP160r1", 160,
+    { "brainpoolP160r1", 160, 0, 
       "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
       "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
       "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
       "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
@@ -206,7 +207,7 @@ static const struct
       "0x1667cb477a1a8ec338f94741669c976316da6321"
     },
 
       "0x1667cb477a1a8ec338f94741669c976316da6321"
     },
 
-    { "brainpoolP192r1", 192,
+    { "brainpoolP192r1", 192, 0, 
       "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
       "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
       "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
       "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
@@ -215,7 +216,7 @@ static const struct
       "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
     },
 
       "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
     },
 
-    { "brainpoolP224r1", 224,
+    { "brainpoolP224r1", 224, 0,
       "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
       "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
       "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
       "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
@@ -224,7 +225,7 @@ static const struct
       "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
     },
 
       "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
     },
 
-    { "brainpoolP256r1", 256, 
+    { "brainpoolP256r1", 256, 0,
       "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
       "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
       "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
       "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
@@ -233,7 +234,7 @@ static const struct
       "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
     },
 
       "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
     },
 
-    { "brainpoolP320r1", 320, 
+    { "brainpoolP320r1", 320, 0,
       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
       "fcd412b1f1b32e27",
       "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
       "fcd412b1f1b32e27",
       "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
@@ -248,7 +249,7 @@ static const struct
       "d35245d1692e8ee1"
     },
 
       "d35245d1692e8ee1"
     },
 
-    { "brainpoolP384r1", 384, 
+    { "brainpoolP384r1", 384, 0,
       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
       "acd3a729901d1a71874700133107ec53",
       "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
       "acd3a729901d1a71874700133107ec53",
       "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
@@ -263,7 +264,7 @@ static const struct
       "0e4646217791811142820341263c5315"
     },
 
       "0e4646217791811142820341263c5315"
     },
 
-    { "brainpoolP512r1", 512,
+    { "brainpoolP512r1", 512, 0,
       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
       "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
       "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
       "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
       "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
@@ -278,7 +279,7 @@ static const struct
       "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
     },
 
       "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
     },
 
-    { NULL, 0, NULL, NULL, NULL, NULL }
+    { NULL, 0, 0, NULL, NULL, NULL, NULL }
   };
 
 
   };
 
 
@@ -478,6 +479,13 @@ generate_curve (unsigned int nbits, const char *name,
   if (!domain_parms[idx].desc)
     return GPG_ERR_INV_VALUE;
 
   if (!domain_parms[idx].desc)
     return GPG_ERR_INV_VALUE;
 
+  /* In fips mode we only support NIST curves.  Note that it is
+     possible to bypass this check by specifying the curve parameters
+     directly.  */
+  if (fips_mode () && !domain_parms[idx].fips )
+    return GPG_ERR_NOT_SUPPORTED; 
+  
+
   *r_nbits = domain_parms[idx].nbits;
   curve->p = scanval (domain_parms[idx].p);
   curve->a = scanval (domain_parms[idx].a);
   *r_nbits = domain_parms[idx].nbits;
   curve->p = scanval (domain_parms[idx].p);
   curve->a = scanval (domain_parms[idx].a);
@@ -1175,6 +1183,56 @@ ecc_get_nbits (int algo, gcry_mpi_t *pkey)
 }
 
 
 }
 
 
+\f
+/* 
+     Self-test section.
+ */
+
+
+static gpg_err_code_t
+selftests_ecdsa (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = NULL; /*selftest ();*/
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("pubkey", GCRY_PK_ECDSA, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Run a full self-test for ALGO and return 0 on success.  */
+static gpg_err_code_t
+run_selftests (int algo, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_PK_ECDSA:
+      ec = selftests_ecdsa (report);
+      break;
+    default:
+      ec = GPG_ERR_PUBKEY_ALGO;
+      break;
+        
+    }
+  return ec;
+}
+
+
+
+\f
 static const char *ecdsa_names[] =
   {
     "ecdsa",
 static const char *ecdsa_names[] =
   {
     "ecdsa",
@@ -1195,4 +1253,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
     ecc_verify,
     ecc_get_nbits
   };
     ecc_verify,
     ecc_get_nbits
   };
+pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = 
+  {
+    run_selftests
+  };
 
 
index e1cb27d..2cc25b7 100644 (file)
@@ -1,5 +1,6 @@
 /* md.c  -  message digest dispatcher
 /* md.c  -  message digest dispatcher
- * Copyright (C) 1998, 1999, 2002, 2003, 2006 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2002, 2003, 2006,
+ *               2008 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  *
  * This file is part of Libgcrypt.
  *
@@ -14,8 +15,7 @@
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
  */
 
 #include <config.h>
 
 #include "rmd.h"
 
 
 #include "rmd.h"
 
+/* A dummy extraspec so that we do not need to tests the extraspec
+   field from the module specification against NULL and instead
+   directly test the respective fields of extraspecs.  */
+static md_extra_spec_t dummy_extra_spec;
+
+
+/* This is the list of the digest implementations included in
+   libgcrypt.  */
 static struct digest_table_entry
 {
   gcry_md_spec_t *digest;
 static struct digest_table_entry
 {
   gcry_md_spec_t *digest;
+  md_extra_spec_t *extraspec;
   unsigned int algorithm;
   unsigned int algorithm;
+  int fips_allowed;
 } digest_table[] =
   {
 #if USE_CRC    
 } digest_table[] =
   {
 #if USE_CRC    
-    { &_gcry_digest_spec_crc32, GCRY_MD_CRC32 },
-    { &_gcry_digest_spec_crc32_rfc1510, GCRY_MD_CRC32_RFC1510 },
-    { &_gcry_digest_spec_crc24_rfc2440, GCRY_MD_CRC24_RFC2440 },
+    /* We allow the CRC algorithms even in FIPS mode because they are
+       actually no cryptographic primitives.  */
+    { &_gcry_digest_spec_crc32,   
+      &dummy_extra_spec,                 GCRY_MD_CRC32, 1 },
+    { &_gcry_digest_spec_crc32_rfc1510,  
+      &dummy_extra_spec,                 GCRY_MD_CRC32_RFC1510, 1 },
+    { &_gcry_digest_spec_crc24_rfc2440,
+      &dummy_extra_spec,                 GCRY_MD_CRC24_RFC2440, 1 },
 #endif
 #if USE_MD4
 #endif
 #if USE_MD4
-    { &_gcry_digest_spec_md4, GCRY_MD_MD4 },
+    { &_gcry_digest_spec_md4,
+      &dummy_extra_spec,                 GCRY_MD_MD4 },
 #endif
 #if USE_MD5
 #endif
 #if USE_MD5
-    { &_gcry_digest_spec_md5, GCRY_MD_MD5 },
+    { &_gcry_digest_spec_md5,
+      &dummy_extra_spec,                 GCRY_MD_MD5 },
 #endif
 #if USE_RMD160
 #endif
 #if USE_RMD160
-    { &_gcry_digest_spec_rmd160, GCRY_MD_RMD160 },
+    { &_gcry_digest_spec_rmd160,
+      &dummy_extra_spec,                 GCRY_MD_RMD160 },
 #endif
 #if USE_SHA1
 #endif
 #if USE_SHA1
-    { &_gcry_digest_spec_sha1, GCRY_MD_SHA1 },
+    { &_gcry_digest_spec_sha1, 
+      &_gcry_digest_extraspec_sha1,      GCRY_MD_SHA1, 1 },
 #endif
 #if USE_SHA256
 #endif
 #if USE_SHA256
-    { &_gcry_digest_spec_sha256, GCRY_MD_SHA256 },
-    { &_gcry_digest_spec_sha224, GCRY_MD_SHA224 },
+    { &_gcry_digest_spec_sha256,
+      &_gcry_digest_extraspec_sha256,    GCRY_MD_SHA256, 1 },
+    { &_gcry_digest_spec_sha224,
+      &_gcry_digest_extraspec_sha224,    GCRY_MD_SHA224, 1 },
 #endif
 #if USE_SHA512
 #endif
 #if USE_SHA512
-    { &_gcry_digest_spec_sha512, GCRY_MD_SHA512 },
-    { &_gcry_digest_spec_sha384, GCRY_MD_SHA384 },
+    { &_gcry_digest_spec_sha512,
+      &_gcry_digest_extraspec_sha512,    GCRY_MD_SHA512, 1 },
+    { &_gcry_digest_spec_sha384,
+      &_gcry_digest_extraspec_sha384,    GCRY_MD_SHA384, 1 },
 #endif
 #if USE_TIGER
 #endif
 #if USE_TIGER
-    { &_gcry_digest_spec_tiger, GCRY_MD_TIGER },
+    { &_gcry_digest_spec_tiger,
+      &dummy_extra_spec,                 GCRY_MD_TIGER },
 #endif
 #if USE_WHIRLPOOL
 #endif
 #if USE_WHIRLPOOL
-    { &_gcry_digest_spec_whirlpool, GCRY_MD_WHIRLPOOL },
+    { &_gcry_digest_spec_whirlpool,
+      &dummy_extra_spec,                 GCRY_MD_WHIRLPOOL },
 #endif
     { NULL },
   };
 #endif
     { NULL },
   };
@@ -115,7 +140,7 @@ struct gcry_md_context
       ath_mutex_lock (&digests_registered_lock);   \
       if (! default_digests_registered)            \
         {                                          \
       ath_mutex_lock (&digests_registered_lock);   \
       if (! default_digests_registered)            \
         {                                          \
-          gcry_md_register_default ();             \
+          md_register_default ();                  \
           default_digests_registered = 1;          \
         }                                          \
       ath_mutex_unlock (&digests_registered_lock); \
           default_digests_registered = 1;          \
         }                                          \
       ath_mutex_unlock (&digests_registered_lock); \
@@ -145,16 +170,22 @@ static void md_stop_debug ( gcry_md_hd_t a );
 /* Internal function.  Register all the ciphers included in
    CIPHER_TABLE.  Returns zero on success or an error code.  */
 static void
 /* Internal function.  Register all the ciphers included in
    CIPHER_TABLE.  Returns zero on success or an error code.  */
 static void
-gcry_md_register_default (void)
+md_register_default (void)
 {
   gcry_err_code_t err = 0;
   int i;
   
 {
   gcry_err_code_t err = 0;
   int i;
   
-  for (i = 0; (! err) && digest_table[i].digest; i++)
-    err = _gcry_module_add (&digests_registered,
-                           digest_table[i].algorithm,
-                           (void *) digest_table[i].digest,
-                           NULL);
+  for (i = 0; !err && digest_table[i].digest; i++)
+    {
+      if ( fips_mode () && !digest_table[i].fips_allowed )
+        continue;
+
+      err = _gcry_module_add (&digests_registered,
+                              digest_table[i].algorithm,
+                              (void *) digest_table[i].digest,
+                              (void *) digest_table[i].extraspec,
+                              NULL);
+    }
 
   if (err)
     BUG ();
 
   if (err)
     BUG ();
@@ -217,16 +248,23 @@ gcry_md_lookup_oid (const char *oid)
    DIGEST.  On success, a new algorithm ID is stored in ALGORITHM_ID
    and a pointer representhing this module is stored in MODULE.  */
 gcry_error_t
    DIGEST.  On success, a new algorithm ID is stored in ALGORITHM_ID
    and a pointer representhing this module is stored in MODULE.  */
 gcry_error_t
-gcry_md_register (gcry_md_spec_t *digest,
-                 unsigned int *algorithm_id,
-                 gcry_module_t *module)
+_gcry_md_register (gcry_md_spec_t *digest,
+                   md_extra_spec_t *extraspec,
+                   unsigned int *algorithm_id,
+                   gcry_module_t *module)
 {
   gcry_err_code_t err = 0;
   gcry_module_t mod;
 
 {
   gcry_err_code_t err = 0;
   gcry_module_t mod;
 
+  /* We do not support module loading in fips mode.  */
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   ath_mutex_lock (&digests_registered_lock);
   err = _gcry_module_add (&digests_registered, 0,
   ath_mutex_lock (&digests_registered_lock);
   err = _gcry_module_add (&digests_registered, 0,
-                         (void *) digest, &mod);
+                         (void *) digest, 
+                         (void *)(extraspec? extraspec : &dummy_extra_spec), 
+                          &mod);
   ath_mutex_unlock (&digests_registered_lock);
   
   if (! err)
   ath_mutex_unlock (&digests_registered_lock);
   
   if (! err)
@@ -448,7 +486,7 @@ md_open (gcry_md_hd_t *h, int algo, int secure, int hmac)
 
   if (! err)
     {
 
   if (! err)
     {
-      /* FIXME: should we really do that? - yes [-wk] */
+      /* Hmmm, should we really do that? - yes [-wk] */
       _gcry_fast_random_poll ();
 
       if (algo)
       _gcry_fast_random_poll ();
 
       if (algo)
@@ -560,8 +598,7 @@ md_enable (gcry_md_hd_t hd, int algorithm)
 gcry_error_t
 gcry_md_enable (gcry_md_hd_t hd, int algorithm)
 {
 gcry_error_t
 gcry_md_enable (gcry_md_hd_t hd, int algorithm)
 {
-  gcry_err_code_t err = md_enable (hd, algorithm);
-  return gcry_error (err);
+  return gcry_error (md_enable (hd, algorithm));
 }
 
 static gcry_err_code_t
 }
 
 static gcry_err_code_t
@@ -655,7 +692,9 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
 gcry_error_t
 gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd)
 {
 gcry_error_t
 gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd)
 {
-  gcry_err_code_t err = md_copy (hd, handle);
+  gcry_err_code_t err;
+
+  err = md_copy (hd, handle);
   if (err)
     *handle = NULL;
   return gcry_error (err);
   if (err)
     *handle = NULL;
   return gcry_error (err);
@@ -669,7 +708,9 @@ void
 gcry_md_reset (gcry_md_hd_t a)
 {
   GcryDigestEntry *r;
 gcry_md_reset (gcry_md_hd_t a)
 {
   GcryDigestEntry *r;
-  
+
+  /* Note: We allow this even in fips non operational mode.  */
+
   a->bufpos = a->ctx->finalized = 0;
 
   for (r = a->ctx->list; r; r = r->next)
   a->bufpos = a->ctx->finalized = 0;
 
   for (r = a->ctx->list; r; r = r->next)
@@ -713,6 +754,7 @@ md_close (gcry_md_hd_t a)
 void
 gcry_md_close (gcry_md_hd_t hd)
 {
 void
 gcry_md_close (gcry_md_hd_t hd)
 {
+  /* Note: We allow this even in fips non operational mode.  */
   md_close (hd);
 }
 
   md_close (hd);
 }
 
@@ -771,7 +813,9 @@ md_final (gcry_md_hd_t a)
 
       if (err)
        _gcry_fatal_error (err, NULL);
 
       if (err)
        _gcry_fatal_error (err, NULL);
-      md_write (om, (a->ctx->macpads)+(a->ctx->macpads_Bsize), a->ctx->macpads_Bsize);
+      md_write (om, 
+                (a->ctx->macpads)+(a->ctx->macpads_Bsize), 
+                a->ctx->macpads_Bsize);
       md_write (om, p, dlen);
       md_final (om);
       /* Replace our digest with the mac (they have the same size). */
       md_write (om, p, dlen);
       md_final (om);
       /* Replace our digest with the mac (they have the same size). */
@@ -847,7 +891,7 @@ gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen)
 {
   gcry_err_code_t rc = GPG_ERR_NO_ERROR;
 
 {
   gcry_err_code_t rc = GPG_ERR_NO_ERROR;
 
-  if (! hd->ctx->macpads)
+  if (!hd->ctx->macpads)
     rc = GPG_ERR_CONFLICT;
   else
     {
     rc = GPG_ERR_CONFLICT;
   else
     {
@@ -905,64 +949,16 @@ md_read( gcry_md_hd_t a, int algo )
 byte *
 gcry_md_read (gcry_md_hd_t hd, int algo)
 {
 byte *
 gcry_md_read (gcry_md_hd_t hd, int algo)
 {
+  /* This function is expected to always return a digest, thus we
+     can't return an error which we actually should do in
+     non-operational state.  */
   gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0);
   return md_read (hd, algo);
 }
 
   gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0);
   return md_read (hd, algo);
 }
 
-/****************
- * This function combines md_final and md_read but keeps the context
- * intact.  This function can be used to calculate intermediate
- * digests.  The digest is copied into buffer and the digestlength is
- * returned.  If buffer is NULL only the needed size for buffer is returned.
- * buflen gives the max size of buffer. If the buffer is too shourt to
- * hold the complete digest, the buffer is filled with as many bytes are
- * possible and this value is returned.
- */
-#if 0
-static int
-md_digest( gcry_md_hd_t a, int algo, byte *buffer, int buflen )
-{
-  struct md_digest_list_s *r = NULL;
-  char *context;
-  char *digest;
-
-  if( a->bufpos )
-    md_write( a, NULL, 0 );
-
-  if( !algo ) {  /* return digest for the first algorithm */
-    if( (r=a->ctx->list) && r->next )
-      log_debug("more than algorithm in md_digest(0)\n");
-  }
-  else {
-    for(r=a->ctx->list; r; r = r->next )
-      if( r->algo == algo )
-       break;
-  }
-  if( !r )
-    BUG();
-
-  if( !buffer )
-    return r->mdlen;
-
-  /* I don't want to change the interface, so I simply work on a copy
-   * of the context (extra overhead - should be fixed)*/
-  context = a->ctx->secure ? gcry_xmalloc_secure( r->contextsize )
-    : gcry_xmalloc( r->contextsize );
-  memcpy( context, r->context.c, r->contextsize );
-  (*r->digest->final)( context );
-  digest = (*r->digest->read)( context );
-
-  if( buflen > r->mdlen )
-    buflen = r->mdlen;
-  memcpy( buffer, digest, buflen );
-
-  gcry_free(context);
-  return buflen;
-}
-#endif
 
 /*
 
 /*
- * Read out an intermediate digest.  Not yet fucntional.
+ * Read out an intermediate digest.  Not yet functional.
  */
 gcry_err_code_t
 gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen)
  */
 gcry_err_code_t
 gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen)
@@ -973,6 +969,7 @@ gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen)
   (void)buflen;
 
   /*md_digest ... */
   (void)buflen;
 
   /*md_digest ... */
+  fips_signal_error ("unimplemented function called");
   return GPG_ERR_INTERNAL;
 }
 
   return GPG_ERR_INTERNAL;
 }
 
@@ -989,7 +986,7 @@ gcry_md_hash_buffer (int algo, void *digest,
 {
   if (algo == GCRY_MD_SHA1)
     _gcry_sha1_hash_buffer (digest, buffer, length);
 {
   if (algo == GCRY_MD_SHA1)
     _gcry_sha1_hash_buffer (digest, buffer, length);
-  else if (algo == GCRY_MD_RMD160)
+  else if (algo == GCRY_MD_RMD160 && !fips_mode () )
     _gcry_rmd160_hash_buffer (digest, buffer, length);
   else
     {
     _gcry_rmd160_hash_buffer (digest, buffer, length);
   else
     {
@@ -1013,7 +1010,10 @@ md_get_algo (gcry_md_hd_t a)
   GcryDigestEntry *r = a->ctx->list;
 
   if (r && r->next)
   GcryDigestEntry *r = a->ctx->list;
 
   if (r && r->next)
-    log_error("WARNING: more than algorithm in md_get_algo()\n");
+    {
+      fips_signal_error ("possible usage error");
+      log_error ("WARNING: more than algorithm in md_get_algo()\n");
+    }
   return r ? r->module->mod_id : 0;
 }
 
   return r ? r->module->mod_id : 0;
 }
 
@@ -1158,6 +1158,9 @@ md_start_debug ( gcry_md_hd_t md, const char *suffix )
 {
   static int idx=0;
   char buf[50];
 {
   static int idx=0;
   char buf[50];
+
+  if (fips_mode ())
+    return;
   
   if ( md->ctx->debug )
     {
   
   if ( md->ctx->debug )
     {
@@ -1244,6 +1247,8 @@ gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes)
   return gcry_error (err);
 }
 
   return gcry_error (err);
 }
 
+
+/* Explicitly initialize this module.  */
 gcry_err_code_t
 _gcry_md_init (void)
 {
 gcry_err_code_t
 _gcry_md_init (void)
 {
@@ -1296,3 +1301,41 @@ gcry_md_list (int *list, int *list_length)
 
   return err;
 }
 
   return err;
 }
+
+
+/* Run the selftests for digest algorithm ALGO with optional reporting
+   function REPORT.  */
+gpg_error_t
+_gcry_md_selftest (int algo, selftest_report_func_t report)
+{
+  gcry_module_t module = NULL;
+  cipher_extra_spec_t *extraspec = NULL;
+  gcry_err_code_t ec = 0;
+
+  REGISTER_DEFAULT_DIGESTS;
+
+  ath_mutex_lock (&digests_registered_lock);
+  module = _gcry_module_lookup_id (digests_registered, algo);
+  if (module && !(module->flags & FLAG_MODULE_DISABLED))
+    extraspec = module->extraspec;
+  ath_mutex_unlock (&digests_registered_lock);
+  if (extraspec && extraspec->selftest)
+    ec = extraspec->selftest (algo, report);
+  else
+    {
+      ec = GPG_ERR_DIGEST_ALGO;
+      if (report)
+        report ("digest", algo, "module", 
+                module && !(module->flags & FLAG_MODULE_DISABLED)?
+                "no selftest available" :
+                module? "algorithm disabled" : "algorithm not found");
+    }
+
+  if (module)
+    {
+      ath_mutex_lock (&digests_registered_lock);
+      _gcry_module_release (module);
+      ath_mutex_unlock (&digests_registered_lock);
+    }
+  return gpg_error (ec);
+}
index 5a39f3e..ad5f89b 100644 (file)
@@ -1,6 +1,6 @@
 /* pubkey.c  - pubkey dispatcher
 /* pubkey.c  - pubkey dispatcher
- * Copyright (C) 1998, 1999, 2000, 2002, 2003,
- *               2005, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, 
+ *               2007, 2008 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  *
  * This file is part of Libgcrypt.
  *
@@ -15,8 +15,7 @@
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
  */
 
 #include <config.h>
@@ -41,26 +40,41 @@ static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash,
                                     int (*cmp) (void *, gcry_mpi_t),
                                       void *opaque);
 
                                     int (*cmp) (void *, gcry_mpi_t),
                                       void *opaque);
 
+
+/* A dummy extraspec so that we do not need to tests the extraspec
+   field from the module specification against NULL and instead
+   directly test the respective fields of extraspecs.  */
+static pk_extra_spec_t dummy_extra_spec;
+
+
 /* This is the list of the default public-key ciphers included in
 /* This is the list of the default public-key ciphers included in
-   libgcrypt.  */
+   libgcrypt.  FIPS_ALLOWED indicated whether the algorithm is used in
+   FIPS mode. */
 static struct pubkey_table_entry
 {
   gcry_pk_spec_t *pubkey;
 static struct pubkey_table_entry
 {
   gcry_pk_spec_t *pubkey;
+  pk_extra_spec_t *extraspec;
   unsigned int algorithm;
   unsigned int algorithm;
+  int fips_allowed; 
 } pubkey_table[] =
   {
 #if USE_RSA
 } pubkey_table[] =
   {
 #if USE_RSA
-    { &_gcry_pubkey_spec_rsa, GCRY_PK_RSA   },
+    { &_gcry_pubkey_spec_rsa,
+      &_gcry_pubkey_extraspec_rsa,   GCRY_PK_RSA, 1},
 #endif
 #if USE_ELGAMAL
 #endif
 #if USE_ELGAMAL
-    { &_gcry_pubkey_spec_elg, GCRY_PK_ELG   },
-    { &_gcry_pubkey_spec_elg, GCRY_PK_ELG_E },
+    { &_gcry_pubkey_spec_elg,
+      &dummy_extra_spec,             GCRY_PK_ELG   },
+    { &_gcry_pubkey_spec_elg,
+      &dummy_extra_spec,             GCRY_PK_ELG_E },
 #endif
 #if USE_DSA
 #endif
 #if USE_DSA
-    { &_gcry_pubkey_spec_dsa, GCRY_PK_DSA   },
+    { &_gcry_pubkey_spec_dsa,
+      &_gcry_pubkey_extraspec_dsa,   GCRY_PK_DSA, 1   },
 #endif
 #if USE_ECC
 #endif
 #if USE_ECC
-    { &_gcry_pubkey_spec_ecdsa, GCRY_PK_ECDSA },
+    { &_gcry_pubkey_spec_ecdsa,
+      &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDSA, 0 },
 #endif
     { NULL, 0 },
   };
 #endif
     { NULL, 0 },
   };
@@ -82,7 +96,7 @@ static int default_pubkeys_registered;
       ath_mutex_lock (&pubkeys_registered_lock);   \
       if (! default_pubkeys_registered)            \
         {                                          \
       ath_mutex_lock (&pubkeys_registered_lock);   \
       if (! default_pubkeys_registered)            \
         {                                          \
-          gcry_pk_register_default ();         \
+          pk_register_default ();                  \
           default_pubkeys_registered = 1;          \
         }                                          \
       ath_mutex_unlock (&pubkeys_registered_lock); \
           default_pubkeys_registered = 1;          \
         }                                          \
       ath_mutex_unlock (&pubkeys_registered_lock); \
@@ -101,6 +115,7 @@ dummy_generate (int algorithm, unsigned int nbits, unsigned long dummy,
   (void)dummy;
   (void)skey;
   (void)retfactors;
   (void)dummy;
   (void)skey;
   (void)retfactors;
+  fips_signal_error ("using dummy public key function");
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -109,6 +124,7 @@ dummy_check_secret_key (int algorithm, gcry_mpi_t *skey)
 {
   (void)algorithm;
   (void)skey;
 {
   (void)algorithm;
   (void)skey;
+  fips_signal_error ("using dummy public key function");
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -121,6 +137,7 @@ dummy_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
   (void)data;
   (void)pkey;
   (void)flags;
   (void)data;
   (void)pkey;
   (void)flags;
+  fips_signal_error ("using dummy public key function");
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -133,6 +150,7 @@ dummy_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
   (void)data;
   (void)skey;
   (void)flags;
   (void)data;
   (void)skey;
   (void)flags;
+  fips_signal_error ("using dummy public key function");
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -144,6 +162,7 @@ dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
   (void)resarr;
   (void)data;
   (void)skey;
   (void)resarr;
   (void)data;
   (void)skey;
+  fips_signal_error ("using dummy public key function");
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -158,6 +177,7 @@ dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
   (void)pkey;
   (void)cmp;
   (void)opaquev;
   (void)pkey;
   (void)cmp;
   (void)opaquev;
+  fips_signal_error ("using dummy public key function");
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -166,13 +186,14 @@ dummy_get_nbits (int algorithm, gcry_mpi_t *pkey)
 {
   (void)algorithm;
   (void)pkey;
 {
   (void)algorithm;
   (void)pkey;
+  fips_signal_error ("using dummy public key function");
   return 0;
 }
 
 /* Internal function.  Register all the pubkeys included in
    PUBKEY_TABLE.  Returns zero on success or an error code.  */
 static void
   return 0;
 }
 
 /* Internal function.  Register all the pubkeys included in
    PUBKEY_TABLE.  Returns zero on success or an error code.  */
 static void
-gcry_pk_register_default (void)
+pk_register_default (void)
 {
   gcry_err_code_t err = 0;
   int i;
 {
   gcry_err_code_t err = 0;
   int i;
@@ -191,9 +212,12 @@ gcry_pk_register_default (void)
       pubkey_use_dummy (verify);
       pubkey_use_dummy (get_nbits);
 #undef pubkey_use_dummy
       pubkey_use_dummy (verify);
       pubkey_use_dummy (get_nbits);
 #undef pubkey_use_dummy
+
       err = _gcry_module_add (&pubkeys_registered,
                              pubkey_table[i].algorithm,
       err = _gcry_module_add (&pubkeys_registered,
                              pubkey_table[i].algorithm,
-                             (void *) pubkey_table[i].pubkey, NULL);
+                             (void *) pubkey_table[i].pubkey, 
+                             (void *) pubkey_table[i].extraspec, 
+                              NULL);
     }
 
   if (err)
     }
 
   if (err)
@@ -231,16 +255,23 @@ gcry_pk_lookup_name (const char *name)
    PUBKEY.  On success, a new algorithm ID is stored in ALGORITHM_ID
    and a pointer representhing this module is stored in MODULE.  */
 gcry_error_t
    PUBKEY.  On success, a new algorithm ID is stored in ALGORITHM_ID
    and a pointer representhing this module is stored in MODULE.  */
 gcry_error_t
-gcry_pk_register (gcry_pk_spec_t *pubkey,
-                 unsigned int *algorithm_id,
-                 gcry_module_t *module)
+_gcry_pk_register (gcry_pk_spec_t *pubkey,
+                   pk_extra_spec_t *extraspec,
+                   unsigned int *algorithm_id,
+                   gcry_module_t *module)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   gcry_module_t mod;
 
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   gcry_module_t mod;
 
+  /* We do not support module loading in fips mode.  */
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   ath_mutex_lock (&pubkeys_registered_lock);
   err = _gcry_module_add (&pubkeys_registered, 0,
   ath_mutex_lock (&pubkeys_registered_lock);
   err = _gcry_module_add (&pubkeys_registered, 0,
-                         (void *) pubkey, &mod);
+                         (void *) pubkey, 
+                         (void *)(extraspec? extraspec : &dummy_extra_spec), 
+                          &mod);
   ath_mutex_unlock (&pubkeys_registered_lock);
 
   if (! err)
   ath_mutex_unlock (&pubkeys_registered_lock);
 
   if (! err)
@@ -498,6 +529,13 @@ pubkey_get_nenc (int algorithm)
 }
 
 
 }
 
 
+/* Generate a new public key with algorithm ALGORITHM of size NBITS
+   and return it at SKEY. The use of the arguments QBITS, USE_E,
+   XVALUE and CURVE+_NAME depend onthe ALGORITHM.  RETFACTOR is used
+   by some algorithms to return certain additional information which
+   are in general not required.  
+
+   The function returns ther error code number or 0 on success. */
 static gcry_err_code_t
 pubkey_generate (int algorithm, unsigned int nbits, unsigned int qbits,
                  unsigned long use_e, gcry_mpi_t xvalue,
 static gcry_err_code_t
 pubkey_generate (int algorithm, unsigned int nbits, unsigned int qbits,
                  unsigned long use_e, gcry_mpi_t xvalue,
@@ -582,7 +620,10 @@ pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
   gcry_err_code_t rc;
   int i;
 
   gcry_err_code_t rc;
   int i;
 
-  if (DBG_CIPHER)
+  /* Note: In fips mode DBG_CIPHER will enver evaluate to true but as
+     an extra failsafe protection we explicitly test for fips mode
+     here. */ 
+  if (DBG_CIPHER && !fips_mode ())
     {
       log_debug ("pubkey_encrypt: algo=%d\n", algorithm);
       for(i = 0; i < pubkey_get_npkey (algorithm); i++)
     {
       log_debug ("pubkey_encrypt: algo=%d\n", algorithm);
       for(i = 0; i < pubkey_get_npkey (algorithm); i++)
@@ -604,7 +645,7 @@ pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
  ready:
   ath_mutex_unlock (&pubkeys_registered_lock);
 
  ready:
   ath_mutex_unlock (&pubkeys_registered_lock);
 
-  if (!rc && DBG_CIPHER)
+  if (!rc && DBG_CIPHER && !fips_mode ())
     {
       for(i = 0; i < pubkey_get_nenc (algorithm); i++)
        log_mpidump("  encr:", resarr[i] );
     {
       for(i = 0; i < pubkey_get_nenc (algorithm); i++)
        log_mpidump("  encr:", resarr[i] );
@@ -630,7 +671,7 @@ pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
   int i;
 
   *result = NULL; /* so the caller can always do a mpi_free */
   int i;
 
   *result = NULL; /* so the caller can always do a mpi_free */
-  if (DBG_CIPHER)
+  if (DBG_CIPHER && !fips_mode ())
     {
       log_debug ("pubkey_decrypt: algo=%d\n", algorithm);
       for(i = 0; i < pubkey_get_nskey (algorithm); i++)
     {
       log_debug ("pubkey_decrypt: algo=%d\n", algorithm);
       for(i = 0; i < pubkey_get_nskey (algorithm); i++)
@@ -654,7 +695,7 @@ pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
  ready:
   ath_mutex_unlock (&pubkeys_registered_lock);
 
  ready:
   ath_mutex_unlock (&pubkeys_registered_lock);
 
-  if (! rc && DBG_CIPHER)
+  if (!rc && DBG_CIPHER && !fips_mode ())
     log_mpidump (" plain:", *result);
 
   return rc;
     log_mpidump (" plain:", *result);
 
   return rc;
@@ -676,7 +717,7 @@ pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
   gcry_err_code_t rc;
   int i;
 
   gcry_err_code_t rc;
   int i;
 
-  if (DBG_CIPHER)
+  if (DBG_CIPHER && !fips_mode ())
     {
       log_debug ("pubkey_sign: algo=%d\n", algorithm);
       for(i = 0; i < pubkey_get_nskey (algorithm); i++)
     {
       log_debug ("pubkey_sign: algo=%d\n", algorithm);
       for(i = 0; i < pubkey_get_nskey (algorithm); i++)
@@ -699,7 +740,7 @@ pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
  ready:
   ath_mutex_unlock (&pubkeys_registered_lock);
 
  ready:
   ath_mutex_unlock (&pubkeys_registered_lock);
 
-  if (! rc && DBG_CIPHER)
+  if (!rc && DBG_CIPHER && !fips_mode ())
     for (i = 0; i < pubkey_get_nsig (algorithm); i++)
       log_mpidump ("   sig:", resarr[i]);
 
     for (i = 0; i < pubkey_get_nsig (algorithm); i++)
       log_mpidump ("   sig:", resarr[i]);
 
@@ -720,7 +761,7 @@ pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
   gcry_err_code_t rc;
   int i;
 
   gcry_err_code_t rc;
   int i;
 
-  if (DBG_CIPHER)
+  if (DBG_CIPHER && !fips_mode ())
     {
       log_debug ("pubkey_verify: algo=%d\n", algorithm);
       for (i = 0; i < pubkey_get_npkey (algorithm); i++)
     {
       log_debug ("pubkey_verify: algo=%d\n", algorithm);
       for (i = 0; i < pubkey_get_npkey (algorithm); i++)
@@ -844,6 +885,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names,
   list = gcry_sexp_find_token (key_sexp, "curve", 5);
   if (list)
     {
   list = gcry_sexp_find_token (key_sexp, "curve", 5);
   if (list)
     {
+#if USE_ECC
       char *curve;
       gcry_mpi_t params[6];
 
       char *curve;
       gcry_mpi_t params[6];
 
@@ -868,6 +910,10 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names,
           else
             mpi_free (params[idx]);
         }
           else
             mpi_free (params[idx]);
         }
+#else /* !USE_ECC */
+      err = GPG_ERR_INV_OBJ; /* "curve" given but ECC not supported. */
+      goto leave;
+#endif /* !USE_ECC */
     }
 
   /* Check that all parameters are known.  */
     }
 
   /* Check that all parameters are known.  */
@@ -1322,7 +1368,8 @@ sexp_data_to_mpi (gcry_sexp_t input, unsigned int nbits, gcry_mpi_t *ret_mpi,
         rc = GPG_ERR_INV_OBJ;
     }
   else if (is_pkcs1 && lvalue && for_encryption)
         rc = GPG_ERR_INV_OBJ;
     }
   else if (is_pkcs1 && lvalue && for_encryption)
-    { /* Create pkcs#1 block type 2 padding. */
+    { 
+      /* Create pkcs#1 block type 2 padding. */
       unsigned char *frame = NULL;
       size_t nframe = (nbits+7) / 8;
       const void * value;
       unsigned char *frame = NULL;
       size_t nframe = (nbits+7) / 8;
       const void * value;
@@ -1388,7 +1435,8 @@ sexp_data_to_mpi (gcry_sexp_t input, unsigned int nbits, gcry_mpi_t *ret_mpi,
       gcry_free(frame);
     }
   else if (is_pkcs1 && lhash && !for_encryption)
       gcry_free(frame);
     }
   else if (is_pkcs1 && lhash && !for_encryption)
-    { /* Create pkcs#1 block type 1 padding. */
+    { 
+      /* Create pkcs#1 block type 1 padding. */
       if (gcry_sexp_length (lhash) != 3)
         rc = GPG_ERR_INV_OBJ;
       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
       if (gcry_sexp_length (lhash) != 3)
         rc = GPG_ERR_INV_OBJ;
       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
@@ -1489,7 +1537,7 @@ sexp_data_to_mpi (gcry_sexp_t input, unsigned int nbits, gcry_mpi_t *ret_mpi,
               n += valuelen;
               assert (n == nframe);
       
               n += valuelen;
               assert (n == nframe);
       
-              /* convert it into an MPI, FIXME: error checking?  */
+              /* Convert it into an MPI.  FIXME: error checking?  */
               gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe);
             }
           
               gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe);
             }
           
@@ -1542,10 +1590,11 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
   gcry_pk_spec_t *pubkey = NULL;
   gcry_module_t module = NULL;
 
   gcry_pk_spec_t *pubkey = NULL;
   gcry_module_t module = NULL;
 
+  *r_ciph = NULL;
+
   REGISTER_DEFAULT_PUBKEYS;
 
   REGISTER_DEFAULT_PUBKEYS;
 
-  *r_ciph = NULL;
-  /* get the key */
+  /* Get the key. */
   rc = sexp_to_key (s_pkey, 0, &pkey, &module);
   if (rc)
     goto leave;
   rc = sexp_to_key (s_pkey, 0, &pkey, &module);
   if (rc)
     goto leave;
@@ -1610,7 +1659,7 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
     
     /* And now the ugly part: We don't have a function to pass an
      * array to a format string, so we have to do it this way :-(.  */
     
     /* And now the ugly part: We don't have a function to pass an
      * array to a format string, so we have to do it this way :-(.  */
-    /* FIXME: There is now such a format spefier, so we can could
+    /* FIXME: There is now such a format specifier, so we can
        change the code to be more clear. */
     arg_list = malloc (nelem * sizeof *arg_list);
     if (!arg_list)
        change the code to be more clear. */
     arg_list = malloc (nelem * sizeof *arg_list);
     if (!arg_list)
@@ -1685,9 +1734,10 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
   gcry_module_t module_enc = NULL, module_key = NULL;
   gcry_pk_spec_t *pubkey = NULL;
 
   gcry_module_t module_enc = NULL, module_key = NULL;
   gcry_pk_spec_t *pubkey = NULL;
 
+  *r_plain = NULL;
+
   REGISTER_DEFAULT_PUBKEYS;
 
   REGISTER_DEFAULT_PUBKEYS;
 
-  *r_plain = NULL;
   rc = sexp_to_key (s_skey, 1, &skey, &module_key);
   if (rc)
     goto leave;
   rc = sexp_to_key (s_skey, 1, &skey, &module_key);
   if (rc)
     goto leave;
@@ -1780,9 +1830,10 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
   int i;
   gcry_err_code_t rc;
 
   int i;
   gcry_err_code_t rc;
 
+  *r_sig = NULL;
+
   REGISTER_DEFAULT_PUBKEYS;
 
   REGISTER_DEFAULT_PUBKEYS;
 
-  *r_sig = NULL;
   rc = sexp_to_key (s_skey, 1, &skey, &module);
   if (rc)
     goto leave;
   rc = sexp_to_key (s_skey, 1, &skey, &module);
   if (rc)
     goto leave;
@@ -2026,11 +2077,11 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
   gcry_mpi_t xvalue = NULL;
   char *curve = NULL;
 
   gcry_mpi_t xvalue = NULL;
   char *curve = NULL;
 
-  REGISTER_DEFAULT_PUBKEYS;
-
   skey[0] = NULL;
   *r_key = NULL;
 
   skey[0] = NULL;
   *r_key = NULL;
 
+  REGISTER_DEFAULT_PUBKEYS;
+
   list = gcry_sexp_find_token (s_parms, "genkey", 0);
   if (!list)
     {
   list = gcry_sexp_find_token (s_parms, "genkey", 0);
   if (!list)
     {
@@ -2398,6 +2449,12 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
   if (gcry_md_open (&md, GCRY_MD_SHA1, 0))
     goto fail;
 
   if (gcry_md_open (&md, GCRY_MD_SHA1, 0))
     goto fail;
 
+#if USE_ECC
+# ifdef __GNUC__
+#  warning needs to be fixed for ECC.
+# endif
+#endif
+
   for (idx = 0, s = elems; *s; s++, idx++)
     {
       const char *data;
   for (idx = 0, s = elems; *s; s++, idx++)
     {
       const char *data;
@@ -2418,8 +2475,8 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
         }
   
       /* PKCS-15 says that for RSA only the modulus should be hashed -
         }
   
       /* PKCS-15 says that for RSA only the modulus should be hashed -
-         however, it is not clear wether this is meant to has the raw
-         bytes assuming this is an unsigned integer or whether the DER
+         however, it is not clear wether this is meant to use the raw
+         bytes (assuming this is an unsigned integer) or whether the DER
          required 0 should be prefixed. We hash the raw bytes.  For
          non-RSA we hash S-expressions. */
       gcry_md_write (md, data, datalen);
          required 0 should be prefixed. We hash the raw bytes.  For
          non-RSA we hash S-expressions. */
       gcry_md_write (md, data, datalen);
@@ -2475,14 +2532,16 @@ gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
 }
 
 
 }
 
 
-/*
-   Return information about the given algorithm
-   WHAT select the kind of information returned:
+/* Return information about the given algorithm
+
+   WHAT selects the kind of information returned:
+
     GCRYCTL_TEST_ALGO:
         Returns 0 when the specified algorithm is available for use.
         Buffer must be NULL, nbytes  may have the address of a variable
         with the required usage of the algorithm. It may be 0 for don't
         care or a combination of the GCRY_PK_USAGE_xxx flags;
     GCRYCTL_TEST_ALGO:
         Returns 0 when the specified algorithm is available for use.
         Buffer must be NULL, nbytes  may have the address of a variable
         with the required usage of the algorithm. It may be 0 for don't
         care or a combination of the GCRY_PK_USAGE_xxx flags;
+
     GCRYCTL_GET_ALGO_USAGE:
         Return the usage glafs for the give algo.  An invalid alog
         does return 0.  Disabled algos are ignored here becuase we
     GCRYCTL_GET_ALGO_USAGE:
         Return the usage glafs for the give algo.  An invalid alog
         does return 0.  Disabled algos are ignored here becuase we
@@ -2570,6 +2629,7 @@ gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes)
 }
 
 
 }
 
 
+/* Explicitly initialize this module.  */
 gcry_err_code_t
 _gcry_pk_init (void)
 {
 gcry_err_code_t
 _gcry_pk_init (void)
 {
@@ -2627,6 +2687,46 @@ gcry_pk_list (int *list, int *list_length)
   return err;
 }
 
   return err;
 }
 
+
+/* Run the selftests for pubkey algorithm ALGO with optional reporting
+   function REPORT.  */
+gpg_error_t
+_gcry_pk_selftest (int algo, selftest_report_func_t report)
+{
+  gcry_module_t module = NULL;
+  cipher_extra_spec_t *extraspec = NULL;
+  gcry_err_code_t ec = 0;
+
+  REGISTER_DEFAULT_PUBKEYS;
+
+  ath_mutex_lock (&pubkeys_registered_lock);
+  module = _gcry_module_lookup_id (pubkeys_registered, algo);
+  if (module && !(module->flags & FLAG_MODULE_DISABLED))
+    extraspec = module->extraspec;
+  ath_mutex_unlock (&pubkeys_registered_lock);
+  if (extraspec && extraspec->selftest)
+    ec = extraspec->selftest (algo, report);
+  else
+    {
+      ec = GPG_ERR_PUBKEY_ALGO;
+      if (report)
+        report ("pubkey", algo, "module", 
+                module && !(module->flags & FLAG_MODULE_DISABLED)?
+                "no selftest available" :
+                module? "algorithm disabled" : "algorithm not found");
+    }
+
+  if (module)
+    {
+      ath_mutex_lock (&pubkeys_registered_lock);
+      _gcry_module_release (module);
+      ath_mutex_unlock (&pubkeys_registered_lock);
+    }
+  return gpg_error (ec);
+}
+
+
+/* This function is only used by ac.c!  */
 gcry_err_code_t
 _gcry_pk_get_elements (int algo, char **enc, char **sig)
 {
 gcry_err_code_t
 _gcry_pk_get_elements (int algo, char **enc, char **sig)
 {
index 7f3fc7b..b54e069 100644 (file)
  *
  * This code is placed in the public domain.
  *------------------------------------------
  *
  * This code is placed in the public domain.
  *------------------------------------------
+ *
+ * The SP800-38a document is available at:
+ *   http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ *
  */
 
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h> /* for memcmp() */
  */
 
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h> /* for memcmp() */
+#include <assert.h>
 
 #include "types.h"  /* for byte and u32 typedefs */
 #include "g10lib.h"
 
 #include "types.h"  /* for byte and u32 typedefs */
 #include "g10lib.h"
@@ -98,14 +103,21 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
   byte tk[MAXKC][4];
   int KC;
   
   byte tk[MAXKC][4];
   int KC;
   
-  if (!initialized)
+  /* The on-the-fly self tests are only run in non-fips mode. In fips
+     mode explicit self-tests are required.  Actually the on-the-fly
+     self-tests are not fully thread-safe and it might happen that a
+     failed self-test won't get noticed in another thread.  
+
+     FIXME: We might want to have a central registry of succeeded
+     self-tests. */
+  if (!fips_mode () && !initialized)
     {
       initialized = 1;
       selftest_failed = selftest ();
     {
       initialized = 1;
       selftest_failed = selftest ();
-      if( selftest_failed )
+      if (selftest_failed)
         log_error ("%s\n", selftest_failed );
     }
         log_error ("%s\n", selftest_failed );
     }
-  if( selftest_failed )
+  if (selftest_failed)
     return GPG_ERR_SELFTEST_FAILED;
 
   ctx->decryption_prepared = 0;
     return GPG_ERR_SELFTEST_FAILED;
 
   ctx->decryption_prepared = 0;
@@ -774,85 +786,368 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv,
 
 
 \f
 
 
 \f
-/* Test a single encryption and decryption with each key size. */
+/* Run the self-tests for AES 128.  Returns NULL on success. */
 static const char*
 static const char*
-selftest (void)
+selftest_basic_128 (void)
 {
   RIJNDAEL_context ctx;
 {
   RIJNDAEL_context ctx;
-  byte scratch[16];       
-
-  /* The test vectors are from the AES supplied ones; more or less 
-   * randomly taken from ecb_tbl.txt (I=42,81,14)
-   */
-  static byte plaintext[16] = {
-    0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33,
-    0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A
-  };
-  static byte key[16] = {
-    0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0,
-    0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA
-  };
-  static const byte ciphertext[16] = {
-    0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2,
-    0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD
-  };
-
-  static byte plaintext_192[16] = {
-    0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4,
-    0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72
-  };
-  static byte key_192[24] = {
-    0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C,
-    0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16,
-    0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20
-  };
-  static const byte ciphertext_192[16] = {
-    0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC,
-    0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA
-  };
-    
-  static byte plaintext_256[16] = {
-    0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
-    0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21
-  };
-  static byte key_256[32] = {
-    0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10,
-    0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A,
-    0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24,
-    0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E
-  };
-  static const byte ciphertext_256[16] = {
-    0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71,
-    0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3
-  };
+  unsigned char scratch[16];      
 
 
-  rijndael_setkey (&ctx, key, sizeof(key));
-  rijndael_encrypt (&ctx, scratch, plaintext);
-  if (memcmp (scratch, ciphertext, sizeof (ciphertext)))
-    return "Rijndael-128 test encryption failed.";
+  /* The test vectors are from the AES supplied ones; more or less
+     randomly taken from ecb_tbl.txt (I=42,81,14) */
+  static const unsigned char plaintext_128[16] = 
+    {
+      0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33,
+      0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A
+    };
+  static const unsigned char key_128[16] =
+    {
+      0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0,
+      0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA
+    };
+  static const unsigned char ciphertext_128[16] =
+    {
+      0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2,
+      0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD
+    };
+  
+  rijndael_setkey (&ctx, key_128, sizeof (key_128));
+  rijndael_encrypt (&ctx, scratch, plaintext_128);
+  if (memcmp (scratch, ciphertext_128, sizeof (ciphertext_128)))
+     return "AES-128 test encryption failed.";
   rijndael_decrypt (&ctx, scratch, scratch);
   rijndael_decrypt (&ctx, scratch, scratch);
-  if (memcmp (scratch, plaintext, sizeof (plaintext)))
-    return "Rijndael-128 test decryption failed.";
+  if (memcmp (scratch, plaintext_128, sizeof (plaintext_128)))
+    return "AES-128 test decryption failed.";
+  
+  return NULL;
+}
 
 
+/* Run the self-tests for AES 192.  Returns NULL on success. */
+static const char*
+selftest_basic_192 (void)
+{
+  RIJNDAEL_context ctx;
+  unsigned char scratch[16];      
+  
+  static unsigned char plaintext_192[16] = 
+    {
+      0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4,
+      0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72
+    };
+  static unsigned char key_192[24] = 
+    {
+      0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C,
+      0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16,
+      0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20
+    };
+  static const unsigned char ciphertext_192[16] =
+    {
+      0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC,
+      0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA
+    };
+    
   rijndael_setkey (&ctx, key_192, sizeof(key_192));
   rijndael_encrypt (&ctx, scratch, plaintext_192);
   if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192)))
   rijndael_setkey (&ctx, key_192, sizeof(key_192));
   rijndael_encrypt (&ctx, scratch, plaintext_192);
   if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192)))
-    return "Rijndael-192 test encryption failed.";
+    return "AES-192 test encryption failed.";
   rijndael_decrypt (&ctx, scratch, scratch);
   if (memcmp (scratch, plaintext_192, sizeof (plaintext_192)))
   rijndael_decrypt (&ctx, scratch, scratch);
   if (memcmp (scratch, plaintext_192, sizeof (plaintext_192)))
-    return "Rijndael-192 test decryption failed.";
-    
+    return "AES-192 test decryption failed.";
+  
+  return NULL;
+}
+
+
+/* Run the self-tests for AES 256.  Returns NULL on success. */
+static const char*
+selftest_basic_256 (void)
+{
+  RIJNDAEL_context ctx;
+  unsigned char scratch[16];      
+
+  static unsigned char plaintext_256[16] = 
+    {
+      0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
+      0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21
+    };
+  static unsigned char key_256[32] = 
+    {
+      0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10,
+      0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A,
+      0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24,
+      0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E
+    };
+  static const unsigned char ciphertext_256[16] = 
+    {
+      0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71,
+      0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3
+    };
+
   rijndael_setkey (&ctx, key_256, sizeof(key_256));
   rijndael_encrypt (&ctx, scratch, plaintext_256);
   if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256)))
   rijndael_setkey (&ctx, key_256, sizeof(key_256));
   rijndael_encrypt (&ctx, scratch, plaintext_256);
   if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256)))
-    return "Rijndael-256 test encryption failed.";
+    return "AES-256 test encryption failed.";
   rijndael_decrypt (&ctx, scratch, scratch);
   if (memcmp (scratch, plaintext_256, sizeof (plaintext_256)))
   rijndael_decrypt (&ctx, scratch, scratch);
   if (memcmp (scratch, plaintext_256, sizeof (plaintext_256)))
-    return "Rijndael-256 test decryption failed.";
+    return "AES-256 test decryption failed.";
     
   return NULL;
 }
 
     
   return NULL;
 }
 
+/* Run all the self-tests and return NULL on success.  This function
+   is used for the on-the-fly self-tests. */
+static const char *
+selftest (void)
+{
+  const char *r;
+
+  if ( (r = selftest_basic_128 ())
+       || (r = selftest_basic_192 ())
+       || (r = selftest_basic_256 ()) )
+    return r;
+
+  return r;
+}
+
+
+/* SP800-38a.pdf for AES-128.  */
+static const char *
+selftest_fips_128_38a (int requested_mode)
+{
+  struct tv
+  {
+    int mode;
+    const unsigned char key[16];
+    const unsigned char iv[16];
+    struct 
+    {
+      const unsigned char input[16];
+      const unsigned char output[16];
+    } data[4];
+  } tv[2] =
+    {
+      {
+        GCRY_CIPHER_MODE_CFB,  /* F.3.13, CFB128-AES128 */
+        { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+          0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+        { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+          0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+        {
+          { { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+              0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
+            { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20,
+              0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } },
+          
+          { { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+              0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 },
+            { 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f,
+              0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b } },
+          
+          { { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 
+              0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef },
+            { 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40,
+              0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf } },
+          
+          { { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+              0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+            { 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e,
+              0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6 } }
+        }
+      },
+      {
+        GCRY_CIPHER_MODE_OFB,
+        { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+          0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+        { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+          0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+        {
+          { { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+              0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
+            { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20,
+              0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } },
+
+          { { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+              0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 },
+            { 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
+              0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25 } },
+          
+          { { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+              0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef },
+            { 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
+              0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc } },
+
+          { { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+              0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+            { 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
+              0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e } },
+        }
+      }
+    };
+  unsigned char scratch[16];
+  gpg_error_t err;
+  int tvi, idx;
+  gcry_cipher_hd_t hdenc = NULL;
+  gcry_cipher_hd_t hddec = NULL;
+
+#define Fail(a) do {           \
+    _gcry_cipher_close (hdenc);  \
+    _gcry_cipher_close (hddec);  \
+    return a;                    \
+  } while (0)
+
+  assert (sizeof tv[0].data[0].input == sizeof scratch);
+  assert (sizeof tv[0].data[0].output == sizeof scratch);
+
+  for (tvi=0; tvi < DIM (tv); tvi++)
+    if (tv[tvi].mode == requested_mode)
+      break;
+  if (tvi == DIM (tv))
+    Fail ("no test data for this mode");
+
+  err = _gcry_cipher_open (&hdenc, GCRY_CIPHER_AES, tv[tvi].mode, 0);
+  if (err)
+    Fail ("open");
+  err = _gcry_cipher_open (&hddec, GCRY_CIPHER_AES, tv[tvi].mode, 0);
+  if (err)
+    Fail ("open");
+  err = _gcry_cipher_setkey (hdenc, tv[tvi].key,  sizeof tv[tvi].key);
+  if (!err)
+    err = _gcry_cipher_setkey (hddec, tv[tvi].key, sizeof tv[tvi].key);
+  if (err)
+    Fail ("set key");
+  err = _gcry_cipher_setiv (hdenc, tv[tvi].iv, sizeof tv[tvi].iv);
+  if (!err)
+    err = _gcry_cipher_setiv (hddec, tv[tvi].iv, sizeof tv[tvi].iv);
+  if (err)
+    Fail ("set IV");
+  for (idx=0; idx < DIM (tv[tvi].data); idx++)
+    {
+      err = _gcry_cipher_encrypt (hdenc, scratch, sizeof scratch,
+                                  tv[tvi].data[idx].input,
+                                  sizeof tv[tvi].data[idx].input);
+      if (err)
+        Fail ("encrypt command");
+      if (memcmp (scratch, tv[tvi].data[idx].output, sizeof scratch))
+        Fail ("encrypt mismatch");
+      err = _gcry_cipher_decrypt (hddec, scratch, sizeof scratch,
+                                  tv[tvi].data[idx].output,
+                                  sizeof tv[tvi].data[idx].output);
+      if (err)
+        Fail ("decrypt command");
+      if (memcmp (scratch, tv[tvi].data[idx].input, sizeof scratch))
+        Fail ("decrypt mismatch");
+    }
+
+#undef Fail
+  _gcry_cipher_close (hdenc);
+  _gcry_cipher_close (hddec); 
+  return NULL;
+}
+
+
+/* Complete selftest for AES-128 with all modes and driver code.  */
+static gpg_err_code_t
+selftest_fips_128 (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = selftest_basic_128 ();
+  if (errtxt)
+    goto failed;
+
+  what = "cfb";
+  errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_CFB);
+  if (errtxt)
+    goto failed;
+
+  what = "ofb";
+  errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_OFB);
+  if (errtxt)
+    goto failed;
+
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("cipher", GCRY_CIPHER_AES128, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+/* Complete selftest for AES-192 with all modes and driver code.  */
+static gpg_err_code_t
+selftest_fips_192 (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+
+  what = "low-level";
+  errtxt = selftest_basic_192 ();
+  if (errtxt)
+    goto failed;
+
+
+
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("cipher", GCRY_CIPHER_AES192, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Complete selftest for AES-256 with all modes and driver code.  */
+static gpg_err_code_t
+selftest_fips_256 (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = selftest_basic_256 ();
+  if (errtxt)
+    goto failed;
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("cipher", GCRY_CIPHER_AES256, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+
+/* Run a full self-test for ALGO and return 0 on success.  */
+static gpg_err_code_t
+run_selftests (int algo, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_CIPHER_AES128:
+      ec = selftest_fips_128 (report);
+      break;
+    case GCRY_CIPHER_AES192:
+      ec = selftest_fips_192 (report);
+      break;
+    case GCRY_CIPHER_AES256:
+      ec = selftest_fips_256 (report);
+      break;
+    default:
+      ec = GPG_ERR_CIPHER_ALGO;
+      break;
+        
+    }
+  return ec;
+}
+
+
 \f
 
 static const char *rijndael_names[] =
 \f
 
 static const char *rijndael_names[] =
@@ -875,6 +1170,10 @@ gcry_cipher_spec_t _gcry_cipher_spec_aes =
     "AES", rijndael_names, rijndael_oids, 16, 128, sizeof (RIJNDAEL_context),
     rijndael_setkey, rijndael_encrypt, rijndael_decrypt
   };
     "AES", rijndael_names, rijndael_oids, 16, 128, sizeof (RIJNDAEL_context),
     rijndael_setkey, rijndael_encrypt, rijndael_decrypt
   };
+cipher_extra_spec_t _gcry_cipher_extraspec_aes = 
+  {
+    run_selftests
+  };
 
 static const char *rijndael192_names[] =
   {
 
 static const char *rijndael192_names[] =
   {
@@ -896,6 +1195,10 @@ gcry_cipher_spec_t _gcry_cipher_spec_aes192 =
     "AES192", rijndael192_names, rijndael192_oids, 16, 192, sizeof (RIJNDAEL_context),
     rijndael_setkey, rijndael_encrypt, rijndael_decrypt
   };
     "AES192", rijndael192_names, rijndael192_oids, 16, 192, sizeof (RIJNDAEL_context),
     rijndael_setkey, rijndael_encrypt, rijndael_decrypt
   };
+cipher_extra_spec_t _gcry_cipher_extraspec_aes192 = 
+  {
+    run_selftests
+  };
 
 static const char *rijndael256_names[] =
   {
 
 static const char *rijndael256_names[] =
   {
@@ -918,3 +1221,8 @@ gcry_cipher_spec_t _gcry_cipher_spec_aes256 =
     sizeof (RIJNDAEL_context),
     rijndael_setkey, rijndael_encrypt, rijndael_decrypt
   };
     sizeof (RIJNDAEL_context),
     rijndael_setkey, rijndael_encrypt, rijndael_decrypt
   };
+
+cipher_extra_spec_t _gcry_cipher_extraspec_aes256 = 
+  {
+    run_selftests
+  };
index 0971eaa..370a8f7 100644 (file)
@@ -1,6 +1,6 @@
 /* rsa.c  -  RSA function
  * Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn)
 /* rsa.c  -  RSA function
  * Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn)
- * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2000, 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  *
  * This file is part of Libgcrypt.
  *
@@ -53,8 +53,8 @@ typedef struct
 
 
 static void test_keys (RSA_secret_key *sk, unsigned nbits);
 
 
 static void test_keys (RSA_secret_key *sk, unsigned nbits);
-static void generate (RSA_secret_key *sk,
-                      unsigned int nbits, unsigned long use_e);
+static gpg_err_code_t generate (RSA_secret_key *sk,
+                                unsigned int nbits, unsigned long use_e);
 static int  check_secret_key (RSA_secret_key *sk);
 static void public (gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *skey);
 static void secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey);
 static int  check_secret_key (RSA_secret_key *sk);
 static void public (gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *skey);
 static void secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey);
@@ -111,7 +111,7 @@ check_exponent (void *arg, gcry_mpi_t a)
  *       > 2 Try starting at this value until a working exponent is found.
  * Returns: 2 structures filled with all needed values
  */
  *       > 2 Try starting at this value until a working exponent is found.
  * Returns: 2 structures filled with all needed values
  */
-static void
+static gpg_err_code_t
 generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e)
 {
   gcry_mpi_t p, q; /* the two primes */
 generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e)
 {
   gcry_mpi_t p, q; /* the two primes */
@@ -124,7 +124,10 @@ generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e)
   gcry_mpi_t g;
   gcry_mpi_t f;
 
   gcry_mpi_t g;
   gcry_mpi_t f;
 
-  /* make sure that nbits is even so that we generate p, q of equal size */
+  if ( nbits < 1024 && fips_mode ())
+    return GPG_ERR_INV_VALUE;
+
+  /* Make sure that nbits is even so that we generate p, q of equal size. */
   if ( (nbits&1) )
     nbits++; 
 
   if ( (nbits&1) )
     nbits++; 
 
@@ -232,6 +235,8 @@ generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e)
 
   /* now we can test our keys (this should never fail!) */
   test_keys( sk, nbits - 64 );
 
   /* now we can test our keys (this should never fail!) */
   test_keys( sk, nbits - 64 );
+
+  return 0;
 }
 
 
 }
 
 
@@ -441,34 +446,37 @@ _gcry_rsa_generate (int algo, unsigned int nbits, unsigned long use_e,
                     gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
   RSA_secret_key sk;
                     gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
   RSA_secret_key sk;
-  gpg_err_code_t rc;
+  gpg_err_code_t ec;
   int i;
 
   (void)algo;
 
   int i;
 
   (void)algo;
 
-  generate (&sk, nbits, use_e);
-  skey[0] = sk.n;
-  skey[1] = sk.e;
-  skey[2] = sk.d;
-  skey[3] = sk.p;
-  skey[4] = sk.q;
-  skey[5] = sk.u;
-  
-  /* Make an empty list of factors.  */
-  *retfactors = gcry_calloc ( 1, sizeof **retfactors );
-  if (!*retfactors)
+  ec = generate (&sk, nbits, use_e);
+  if (!ec)
     {
     {
-      rc = gpg_err_code_from_errno (errno);
-      for (i=0; i <= 5; i++)
+      skey[0] = sk.n;
+      skey[1] = sk.e;
+      skey[2] = sk.d;
+      skey[3] = sk.p;
+      skey[4] = sk.q;
+      skey[5] = sk.u;
+  
+      /* Make an empty list of factors.  */
+      *retfactors = gcry_calloc ( 1, sizeof **retfactors );
+      if (!*retfactors)
         {
         {
-          gcry_mpi_release (skey[i]);
-          skey[i] = NULL;
+          ec = gpg_err_code_from_syserror ();
+          for (i=0; i <= 5; i++)
+            {
+              gcry_mpi_release (skey[i]);
+              skey[i] = NULL;
+            }
         }
         }
+      else
+        ec = 0;
     }
     }
-  else
-    rc = 0;
   
   
-  return rc;
+  return ec;
 }
 
 
 }
 
 
@@ -537,6 +545,9 @@ _gcry_rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
 
   y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n));
 
 
   y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n));
 
+  /* We use blinding by default to mitigate timing attacks which can
+     be practically mounted over the network as shown by Brumley and
+     Boney in 2003.  */ 
   if (! (flags & PUBKEY_FLAG_NO_BLINDING))
     {
       /* Initialize blinding.  */
   if (! (flags & PUBKEY_FLAG_NO_BLINDING))
     {
       /* Initialize blinding.  */
@@ -650,6 +661,58 @@ _gcry_rsa_get_nbits (int algo, gcry_mpi_t *pkey)
   return mpi_get_nbits (pkey[0]);
 }
 
   return mpi_get_nbits (pkey[0]);
 }
 
+
+
+\f
+/* 
+     Self-test section.
+ */
+
+
+static gpg_err_code_t
+selftests_rsa (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = NULL; /*selftest ();*/
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("pubkey", GCRY_PK_RSA, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Run a full self-test for ALGO and return 0 on success.  */
+static gpg_err_code_t
+run_selftests (int algo, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_PK_RSA:
+      ec = selftests_rsa (report);
+      break;
+    default:
+      ec = GPG_ERR_PUBKEY_ALGO;
+      break;
+        
+    }
+  return ec;
+}
+
+
+
+\f
 static const char *rsa_names[] =
   {
     "rsa",
 static const char *rsa_names[] =
   {
     "rsa",
@@ -671,3 +734,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_rsa =
     _gcry_rsa_verify,
     _gcry_rsa_get_nbits,
   };
     _gcry_rsa_verify,
     _gcry_rsa_get_nbits,
   };
+pk_extra_spec_t _gcry_pubkey_extraspec_rsa = 
+  {
+    run_selftests
+  };
+
index 2c1bda2..caf1c9a 100644 (file)
@@ -373,6 +373,56 @@ _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length)
 }
 
 
 }
 
 
+\f
+/* 
+     Self-test section.
+ */
+
+
+static gpg_err_code_t
+selftests_sha1 (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = NULL; /*selftest ();*/
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("digest", GCRY_MD_SHA1, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Run a full self-test for ALGO and return 0 on success.  */
+static gpg_err_code_t
+run_selftests (int algo, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_MD_SHA1:
+      ec = selftests_sha1 (report);
+      break;
+    default:
+      ec = GPG_ERR_DIGEST_ALGO;
+      break;
+        
+    }
+  return ec;
+}
+
+
+
+\f
 static unsigned char asn[15] = /* Object ID is 1.3.14.3.2.26 */
   { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
     0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
 static unsigned char asn[15] = /* Object ID is 1.3.14.3.2.26 */
   { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
     0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
@@ -398,3 +448,8 @@ gcry_md_spec_t _gcry_digest_spec_sha1 =
     sha1_init, sha1_write, sha1_final, sha1_read,
     sizeof (SHA1_CONTEXT)
   };
     sha1_init, sha1_write, sha1_final, sha1_read,
     sizeof (SHA1_CONTEXT)
   };
+md_extra_spec_t _gcry_digest_extraspec_sha1 = 
+  {
+    run_selftests
+  };
+
index bc439c3..b0a5629 100644 (file)
@@ -1,5 +1,5 @@
 /* sha256.c - SHA256 hash function
 /* sha256.c - SHA256 hash function
- *     Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ *     Copyright (C) 2003, 2006, 2008 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  *
  * This file is part of Libgcrypt.
  *
@@ -14,8 +14,7 @@
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 
  */
 
 
@@ -313,6 +312,81 @@ sha256_read (void *context)
   return hd->buf;
 }
 
   return hd->buf;
 }
 
+
+\f
+/* 
+     Self-test section.
+ */
+
+
+static gpg_err_code_t
+selftests_sha224 (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = NULL; /*selftest ();*/
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("digest", GCRY_MD_SHA224, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+static gpg_err_code_t
+selftests_sha256 (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = NULL; /*selftest ();*/
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("digest", GCRY_MD_SHA256, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Run a full self-test for ALGO and return 0 on success.  */
+static gpg_err_code_t
+run_selftests (int algo, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_MD_SHA224:
+      ec = selftests_sha224 (report);
+      break;
+    case GCRY_MD_SHA256:
+      ec = selftests_sha256 (report);
+      break;
+    default:
+      ec = GPG_ERR_DIGEST_ALGO;
+      break;
+        
+    }
+  return ec;
+}
+
+
+
+\f
 static byte asn224[19] = /* Object ID is 2.16.840.1.101.3.4.2.4 */
   { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
     0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
 static byte asn224[19] = /* Object ID is 2.16.840.1.101.3.4.2.4 */
   { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
     0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
@@ -347,6 +421,10 @@ gcry_md_spec_t _gcry_digest_spec_sha224 =
     sha224_init, sha256_write, sha256_final, sha256_read,
     sizeof (SHA256_CONTEXT)
   };
     sha224_init, sha256_write, sha256_final, sha256_read,
     sizeof (SHA256_CONTEXT)
   };
+md_extra_spec_t _gcry_digest_extraspec_sha224 = 
+  {
+    run_selftests
+  };
 
 gcry_md_spec_t _gcry_digest_spec_sha256 =
   {
 
 gcry_md_spec_t _gcry_digest_spec_sha256 =
   {
@@ -354,3 +432,7 @@ gcry_md_spec_t _gcry_digest_spec_sha256 =
     sha256_init, sha256_write, sha256_final, sha256_read,
     sizeof (SHA256_CONTEXT)
   };
     sha256_init, sha256_write, sha256_final, sha256_read,
     sizeof (SHA256_CONTEXT)
   };
+md_extra_spec_t _gcry_digest_extraspec_sha256 = 
+  {
+    run_selftests
+  };
index b70b175..e1ba517 100644 (file)
@@ -1,7 +1,5 @@
 /* sha512.c - SHA384 and SHA512 hash functions
 /* sha512.c - SHA384 and SHA512 hash functions
- *     Copyright (C) 2003 Free Software Foundation, Inc.
- *
- * Please see below for more legal information!
+ *     Copyright (C) 2003, 2008 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  *
  * This file is part of Libgcrypt.
  *
@@ -15,9 +13,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 
  */
 
 
@@ -362,12 +359,87 @@ sha512_read (void *context)
   return hd->buf;
 }
 
   return hd->buf;
 }
 
-static byte sha512_asn[] =     /* Object ID is 2.16.840.1.101.3.4.2.3 */
+
+\f
+/* 
+     Self-test section.
+ */
+
+
+static gpg_err_code_t
+selftests_sha384 (selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = NULL; /*selftest ();*/
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("digest", GCRY_MD_SHA384, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+static gpg_err_code_t
+selftests_sha512 (selftest_report_func_t report)
 {
 {
-  0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-  0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
-  0x00, 0x04, 0x40
-};
+  const char *what;
+  const char *errtxt;
+  
+  what = "low-level";
+  errtxt = NULL; /*selftest ();*/
+  if (errtxt)
+    goto failed;
+
+  /* FIXME:  need more tests.  */
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("digest", GCRY_MD_SHA512, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Run a full self-test for ALGO and return 0 on success.  */
+static gpg_err_code_t
+run_selftests (int algo, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_MD_SHA384:
+      ec = selftests_sha384 (report);
+      break;
+    case GCRY_MD_SHA512:
+      ec = selftests_sha512 (report);
+      break;
+    default:
+      ec = GPG_ERR_DIGEST_ALGO;
+      break;
+        
+    }
+  return ec;
+}
+
+
+
+\f
+static byte sha512_asn[] =     /* Object ID is 2.16.840.1.101.3.4.2.3 */
+  {
+    0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+    0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
+    0x00, 0x04, 0x40
+  };
 
 static gcry_md_oid_spec_t oid_spec_sha512[] =
   {
 
 static gcry_md_oid_spec_t oid_spec_sha512[] =
   {
@@ -379,18 +451,23 @@ static gcry_md_oid_spec_t oid_spec_sha512[] =
     { NULL }
   };
 
     { NULL }
   };
 
-gcry_md_spec_t _gcry_digest_spec_sha512 = {
-  "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64,
-  sha512_init, sha512_write, sha512_final, sha512_read,
-  sizeof (SHA512_CONTEXT),
-};
+gcry_md_spec_t _gcry_digest_spec_sha512 = 
+  {
+    "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64,
+    sha512_init, sha512_write, sha512_final, sha512_read,
+    sizeof (SHA512_CONTEXT),
+  };
+md_extra_spec_t _gcry_digest_extraspec_sha512 = 
+  {
+    run_selftests
+  };
 
 static byte sha384_asn[] =     /* Object ID is 2.16.840.1.101.3.4.2.2 */
 
 static byte sha384_asn[] =     /* Object ID is 2.16.840.1.101.3.4.2.2 */
-{
-  0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-  0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
-  0x00, 0x04, 0x30
-};
+  {
+    0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+    0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
+    0x00, 0x04, 0x30
+  };
 
 static gcry_md_oid_spec_t oid_spec_sha384[] =
   {
 
 static gcry_md_oid_spec_t oid_spec_sha384[] =
   {
@@ -402,8 +479,13 @@ static gcry_md_oid_spec_t oid_spec_sha384[] =
     { NULL },
   };
 
     { NULL },
   };
 
-gcry_md_spec_t _gcry_digest_spec_sha384 = {
-  "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48,
-  sha384_init, sha512_write, sha512_final, sha512_read,
-  sizeof (SHA512_CONTEXT),
-};
+gcry_md_spec_t _gcry_digest_spec_sha384 = 
+  {
+    "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48,
+    sha384_init, sha512_write, sha512_final, sha512_read,
+    sizeof (SHA512_CONTEXT),
+  };
+md_extra_spec_t _gcry_digest_extraspec_sha384 = 
+  {
+    run_selftests
+  };
index c81903f..04d9184 100644 (file)
@@ -86,6 +86,10 @@ AH_BOTTOM([
    properly prefixed.  */
 #define CAMELLIA_EXT_SYM_PREFIX _gcry_
 
    properly prefixed.  */
 #define CAMELLIA_EXT_SYM_PREFIX _gcry_
 
+/* This error code is only available with gpg-error 1.7.  Thus
+   we define it here with the usual gcry prefix.  */
+#define GCRY_GPG_ERR_NOT_OPERATIONAL  176
+
 
 #endif /*_GCRYPT_CONFIG_H_INCLUDED*/
 ])
 
 #endif /*_GCRYPT_CONFIG_H_INCLUDED*/
 ])
index b9cb198..193ac2e 100644 (file)
@@ -1,3 +1,21 @@
+2008-08-18  Werner Koch  <wk@g10code.com>
+
+       * gcrypt.texi (Top): Remove the detailmenu.
+       (Public Key Cryptographi (II)): Move into a section of the PK
+       interface description.
+       (Hashing): Move after the encryption chapters.
+
+2008-08-15  Werner Koch  <wk@g10code.com>
+
+       * gcrypt.texi (Controlling the library): Remove
+       GCRYCTL_DUMP_CONFIG because it is not implemented.
+       (Initializing the library): Describe initialization steps with
+       regard to secure memory.
+
+       * gcrypt.texi (Working with cipher handles): Adjust for
+       implementation changes of gcry_cipher_setkey, gcry_cipher_setiv and
+       gcry_cipher_setctr.
+
 2008-01-04  Werner Koch  <wk@g10code.com>
 
        * gcrypt.texi (Controlling the library): Add remark that the
 2008-01-04  Werner Koch  <wk@g10code.com>
 
        * gcrypt.texi (Controlling the library): Add remark that the
index 0589891..d715e63 100644 (file)
 # License along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
 # License along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
-EXTRA_DIST = README.apichanges HACKING 
+EXTRA_DIST = README.apichanges HACKING \
+            libgcrypt-modules.eps \
+            libgcrypt-modules.png \
+             libgcrypt-modules.pdf
 
 DISTCLEANFILES = gcrypt.cps
 
 
 DISTCLEANFILES = gcrypt.cps
 
+BUILT_SOURCES = libgcrypt-modules.eps \
+                libgcrypt-modules.png \
+                libgcrypt-modules.pdf
+
 info_TEXINFOS = gcrypt.texi
 info_TEXINFOS = gcrypt.texi
-gcrypt_TEXINFOS = lgpl.texi gpl.texi
+gcrypt_TEXINFOS = lgpl.texi gpl.texi libgcrypt-modules.fig
+
+
+.fig.png:
+       fig2dev -L png `test -f '$<' || echo '$(srcdir)/'`$< $@
+
+.fig.jpg:
+       fig2dev -L jpg `test -f '$<' || echo '$(srcdir)/'`$< $@
+
+.fig.eps:
+       fig2dev -L eps `test -f '$<' || echo '$(srcdir)/'`$< $@
+
+.fig.pdf:
+       fig2dev -L pdf `test -f '$<' || echo '$(srcdir)/'`$< $@
 
 
 online: gcrypt.html gcrypt.pdf gcrypt.info
 
 
 online: gcrypt.html gcrypt.pdf gcrypt.info
index b6d3621..d281ae8 100644 (file)
@@ -12,7 +12,7 @@ This manual is for Libgcrypt
 (version @value{VERSION}, @value{UPDATED}),
 which is GNU's library of cryptographic building blocks.
 
 (version @value{VERSION}, @value{UPDATED}),
 which is GNU's library of cryptographic building blocks.
 
-Copyright @copyright{} 2000, 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
+Copyright @copyright{} 2000, 2002, 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -66,17 +66,18 @@ section entitled ``Copying''.
 * Generalities::                 General library functions and data types.
 * Handler Functions::            Working with handler functions.
 * Symmetric cryptography::       How to use symmetric cryptography.
 * Generalities::                 General library functions and data types.
 * Handler Functions::            Working with handler functions.
 * Symmetric cryptography::       How to use symmetric cryptography.
+* Public Key cryptography::      How to use public key cryptography.
 * Hashing::                      How to use hashing.
 * Hashing::                      How to use hashing.
-* Public Key cryptography (I)::  How to use public key cryptography.
-* Public Key cryptography (II):: How to use public key cryptography, alternatively.
 * Random Numbers::               How to work with random numbers.
 * S-expressions::                How to manage S-expressions.
 * MPI library::                  How to work with multi-precision-integers.
 * Prime numbers::                How to use the Prime number related functions.
 * Utilities::                    Utility functions.
 * Random Numbers::               How to work with random numbers.
 * S-expressions::                How to manage S-expressions.
 * MPI library::                  How to work with multi-precision-integers.
 * Prime numbers::                How to use the Prime number related functions.
 * Utilities::                    Utility functions.
+* Architecture::                 How Libgcrypt works internally.
 
 Appendices
 
 
 Appendices
 
+* FIPS Restrictions::           Restrictions in FIPS mode.
 * Library Copying::             The GNU Lesser General Public License
                                 says how you can copy and share Libgcrypt.
 * Copying::                     The GNU General Public License says how you
 * Library Copying::             The GNU Lesser General Public License
                                 says how you can copy and share Libgcrypt.
 * Copying::                     The GNU General Public License says how you
@@ -87,86 +88,6 @@ Indices
 * Concept Index::               Index of concepts and programs.
 * Function and Data Index::     Index of functions, variables and data types.
 
 * Concept Index::               Index of concepts and programs.
 * Function and Data Index::     Index of functions, variables and data types.
 
-@detailmenu
- --- The Detailed Node Listing ---
-
-Introduction
-* Getting Started::             How to use this manual.
-* Features::                    A glance at Libgcrypt's features.
-* Overview::                    Overview about the library.
-
-Preparation
-* Header::                              What header file you need to include.
-* Building sources::                    How to build sources using the library.
-* Building sources using Automake::     How to build sources with the help of Automake.
-* Initializing the library::            How to initialize the library.
-* Multi-Threading::                     How Libgcrypt can be used in a MT environment.
-
-Generalities
-* Controlling the library::     Controlling Libgcrypt's behavior.
-* Modules::                     Description of extension modules.
-* Error Handling::              Error codes and such.
-
-Handler Functions
-* Progress handler::            Using a progress handler function.
-* Allocation handler::          Using special memory allocation functions.
-* Error handler::               Using error handler functions.
-* Logging handler::             Using a special logging function.
-
-Symmetric cryptography
-* Available ciphers::           List of ciphers supported by the library.
-* Cipher modules::              How to work with cipher modules.
-* Available cipher modes::      List of cipher modes supported by the library.
-* Working with cipher handles:: How to perform operations related to cipher handles.
-* General cipher functions::    General cipher functions independent of cipher handles.
-
-Hashing
-* Available hash algorithms::           List of hash algorithms supported by the library.
-* Hash algorithm modules::              How to work with hash algorithm modules.
-* Working with hash algorithms::        List of functions related to hashing.
-
-Public Key cryptography (I)
-* Used S-expressions::                    Introduction into the used S-expression.
-* Available algorithms::                  Algorithms supported by the library.
-* Public key modules::                    How to work with public key modules.
-* Cryptographic Functions::               Functions for performing the cryptographic actions.
-* General public-key related Functions::  General functions, not implementing any cryptography.
-
-Public Key cryptography (II)
-* Available asymmetric algorithms:: List of algorithms supported by the library.
-* Working with sets of data::       How to work with sets of data.
-* Working with handles::            How to use handles.
-* Working with keys::               How to work with keys.
-* Using cryptographic functions::   How to perform cryptographic operations.
-* Handle-independent functions::    General functions independent of handles.
-
-Random Numbers
-* Quality of random numbers::   Libgcrypt uses different quality levels.
-* Retrieving random numbers::   How to retrieve random numbers.
-
-S-expressions
-* Data types for S-expressions::   Data types related with S-expressions.
-* Working with S-expressions::     How to work with S-expressions.
-
-MPI library
-* Data types::                  MPI related data types.
-* Basic functions::             First steps with MPI numbers.
-* MPI formats::                 External representation of MPIs.
-* Calculations::                Performing MPI calculations.
-* Comparisons::                 How to compare MPI values.
-* Bit manipulations::           How to access single bits of MPI values.
-* Miscellaneous::               Miscellaneous MPI functions.
-
-Prime numbers
-* Generation::                  Generation of new prime numbers.
-* Checking::                    Checking if a given number is prime.
-
-Utilities
-* Memory allocation::           Functions related with memory allocation.
-
-@end detailmenu
-
-
 @end menu
 
 @ifhtml
 @end menu
 
 @ifhtml
@@ -220,10 +141,9 @@ a similar job.
 @item It's Free Software
 Anybody can use, modify, and redistribute it under the terms of the GNU
 Lesser General Public License (@pxref{Library Copying}).  Note, that
 @item It's Free Software
 Anybody can use, modify, and redistribute it under the terms of the GNU
 Lesser General Public License (@pxref{Library Copying}).  Note, that
-some parts (which are not needed on a GNU or GNU/Linux system) are
-subject to the terms of the GNU General Public License
-(@pxref{Copying}); please see the README file of the distribution for of
-list of these parts.
+some parts (which are in general not needed by applications) are subject
+to the terms of the GNU General Public License (@pxref{Copying}); please
+see the README file of the distribution for of list of these parts.
 
 @item It encapsulates the low level cryptography
 Libgcrypt provides a high level interface to cryptographic
 
 @item It encapsulates the low level cryptography
 Libgcrypt provides a high level interface to cryptographic
@@ -264,6 +184,7 @@ of the library are verified.
 * Building sources using Automake::  How to build sources with the help of Automake.
 * Initializing the library::    How to initialize the library.
 * Multi-Threading::             How Libgcrypt can be used in a MT environment.
 * Building sources using Automake::  How to build sources with the help of Automake.
 * Initializing the library::    How to initialize the library.
 * Multi-Threading::             How Libgcrypt can be used in a MT environment.
+* FIPS mode::                   How to enable the FIPS mode.
 @end menu
 
 
 @end menu
 
 
@@ -295,10 +216,10 @@ Certain parts of gcrypt.h may be excluded by defining these macros:
 Do not define the shorthand macros @code{mpi_*} for @code{gcry_mpi_*}.
 
 @item GCRYPT_NO_DEPRECATED
 Do not define the shorthand macros @code{mpi_*} for @code{gcry_mpi_*}.
 
 @item GCRYPT_NO_DEPRECATED
-Do not include defintions for deprecated features.
+Do not include defintions for deprecated features.  This is useful to
+make sure that no deprecated features are used.
 @end table
 
 @end table
 
-
 @node Building sources
 @section Building sources
 
 @node Building sources
 @section Building sources
 
@@ -394,10 +315,10 @@ after program startup.
 
 @deftypefun const char *gcry_check_version (const char *@var{req_version})
 
 
 @deftypefun const char *gcry_check_version (const char *@var{req_version})
 
-The function @code{gcry_check_version} initializes the sub-systems
-used by Libgcrypt and must be invoked before any other function in the
-library, with the exception of the @code{GCRYCTL_SET_THREAD_CBS}
-command (called via the @code{gcry_control} function), see
+The function @code{gcry_check_version} initializes some subsystems used
+by Libgcrypt and must be invoked before any other function in the
+library, with the exception of the @code{GCRYCTL_SET_THREAD_CBS} command
+(called via the @code{gcry_control} function).
 @xref{Multi-Threading}.
 
 Furthermore, this function returns the version number of the library.
 @xref{Multi-Threading}.
 
 Furthermore, this function returns the version number of the library.
@@ -406,6 +327,94 @@ required version number @var{req_version}, if this value is not a null
 pointer.
 @end deftypefun
 
 pointer.
 @end deftypefun
 
+Libgcrypt uses a concept known as secure memory, which is a region of
+memory set aside for storing sensitive data.  Because such memory is a
+scare resource, it needs to be setup in advanced to a fixed size.
+Further, most operating systems have special requirements on how that
+secure memory can be used.  For example, it might be required to install
+an application as ``setuid(root)'' to allow allocating such memory.
+Libgcrypt requires a sequence of initialization steps to make sure that
+this works correctly.  The following examples show the necessary steps.
+
+If you don't have a need for secure memory, for example if your
+application does not use secret keys or other confidential data or it
+runs in a controlled environment where key material floating around in
+memory is not a problem, you should initialize Libgcrypt this way:
+
+@example
+  /* Version check should be the very first call because it
+     makes sure that important subsystems are intialized. */
+  if (!gcry_check_version (GCRYPT_VERSION))
+    @{
+      fputs ("libgcrypt version mismatch\n", stderr);
+      exit (2);
+    @}
+        
+  /* Disable secure memory.  */
+  gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+
+  /* ... If required, other initialization goes here.  */
+
+  /* Tell Libgcrypt that initialization has completed. */
+  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+@end example
+
+
+If you have to protect your keys or other information in memory against
+being swapped out to disk and to enable an automatic overwrite of used
+and freed memory, you need to initialize Libgcrypt this way:
+
+@example
+  /* Version check should be the very first call because it
+     makes sure that important subsystems are intialized. */
+  if (!gcry_check_version (GCRYPT_VERSION))
+    @{
+      fputs ("libgcrypt version mismatch\n", stderr);
+      exit (2);
+    @}
+
+@anchor{sample-use-suspend-secmem}
+  /* We don't want to see any warnings, e.g. because we have not yet
+     parsed program options which might be used to suppress such
+     warnings. */
+  gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
+
+  /* ... If required, other initialization goes here.  Note that the
+     process might still be running with increased privileges and that 
+     the secure memory has not been intialized.  */
+
+  /* Allocate a pool of 16k secure memory.  This make the secure memory
+     available and also drops privileges where needed.  */
+  gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
+
+@anchor{sample-use-resume-secmem}
+  /* It is now okay to let Libgcrypt complain when there was/is a problem
+     with the secure memory. */
+  gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
+
+  /* ... If required, other initialization goes here.  */
+
+  /* Tell Libgcrypt that initialization has completed. */
+  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+@end example
+
+It is important that these initialization steps are not done by a
+library but by the actual application.  A library using Libgcrypt might
+want to check for finished initialization using:
+
+@example
+  if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P))
+    @{
+      fputs ("libgcrypt has not been initialized\n", stderr);
+      abort ();
+    @}       
+@end example
+
+Instead of terminating the process, the library may instead print a
+warning and try to initialize Libgcrypt itself.  See also the section on
+multi-threading below for more pitfalls.
+
+
 
 @node Multi-Threading
 @section Multi-Threading
 
 @node Multi-Threading
 @section Multi-Threading
@@ -500,6 +509,45 @@ Note that these macros need to be terminated with a semicolon.  Keep
 in mind that these are convenient macros for C programmers; C++
 programmers might have to wrap these macros in an ``extern C'' body.
 
 in mind that these are convenient macros for C programmers; C++
 programmers might have to wrap these macros in an ``extern C'' body.
 
+
+
+@node FIPS mode
+@section FIPS Mode
+
+Libgcrypt may be used in a FIPS 140 mode.  Note, that this does not
+necessary mean that Libcgrypt is n appoved FIPS 140-2 module.  Check the
+NIST database at @url{http://csrc.nist.gov/groups/STM/cmvp/} to see what
+versions of Libgcrypt are approved.
+
+Because FIPS 140 has certain restrictions on the use of cryptography
+which are not always wanted, Libgcrypt needs to be put into FIPS mode
+explicitly.  Three alternative mechanisms are provided to switch
+Libgcrypt into this mode:
+
+@itemize
+@item 
+If the file @file{/proc/fips140} exists and contains the string value
+@code{1}, Libgcrypt is put into FIPS mode at initialization time.
+Obviously this works only on systems with a @code{proc} file system
+(ie.e GNU/Linux).
+
+@item 
+If the file @file{/etc/gcrypt/fips140.force} exists, Libgcrypt is put
+into FIPS mode at initialization time.  Note that this filename is
+hardwired and does not depend on any configuration options.
+
+@item 
+If the applications requests FIPS mode using the control command
+@code{GCRYCTL_FORCE_FIPS_MODE}.  This may be done at any time.
+
+@end itemize
+
+Note that once Libgcrypt has been put into FIPS mode, it is not possible
+to switch back to standard mode without terminating the process first.
+
+
+
+
 @c **********************************************************
 @c *******************  General  ****************************
 @c **********************************************************
 @c **********************************************************
 @c *******************  General  ****************************
 @c **********************************************************
@@ -541,49 +589,72 @@ your application.
 This option can only be used at initialization time.
 
 
 This option can only be used at initialization time.
 
 
-@item GCRYCTL_DUMP_RANDOM_STATS
-This command dumps PRNG related statistics to the librarys logging
-stream.
+@item GCRYCTL_DUMP_RANDOM_STATS; Arguments: none
+This command dumps randum number generator related statistics to the
+library's logging stream.
 
 
-@item GCRYCTL_DUMP_MEMORY_STATS
-This command dumps memory manamgent related statistics to the librarys
+@item GCRYCTL_DUMP_MEMORY_STATS; Arguments: none
+This command dumps memory managment related statistics to the library's
 logging stream.
 
 logging stream.
 
-@item GCRYCTL_DUMP_SECMEM_STATS
+@item GCRYCTL_DUMP_SECMEM_STATS; Arguments: none
 This command dumps secure memory manamgent related statistics to the
 This command dumps secure memory manamgent related statistics to the
-librarys logging stream.
+library's logging stream.
 
 
-@item GCRYCTL_DUMP_CONFIG; Arguments: none
-This command dumps information pertaining to the configuration of
-libgcrypt to the logging stream.  It may be used before the
-intialization has been finished but not before a gcry_version_check.
-
-@item GCRYCTL_DROP_PRIVS
+@item GCRYCTL_DROP_PRIVS; Arguments: none
 This command disables the use of secure memory and drops the priviliges
 This command disables the use of secure memory and drops the priviliges
-of the current process.  FIXME.
+of the current process.  This command has not much use; the suggested way
+to disable secure memory is to use @code{GCRYCTL_DISABLE_SECMEM} right
+after initialization.
 
 
-@item GCRYCTL_DISABLE_SECMEM
+@item GCRYCTL_DISABLE_SECMEM; Arguments: none
 This command disables the use of secure memory. 
 
 Many applications do not require secure memory, so they should disable
 it right away.  There won't be a problem if not disabling it unless one
 makes use of a feature which requires secure memory - in that case the
 This command disables the use of secure memory. 
 
 Many applications do not require secure memory, so they should disable
 it right away.  There won't be a problem if not disabling it unless one
 makes use of a feature which requires secure memory - in that case the
-process will abort because the secmem is not initialized.
-
-
-@item GCRYCTL_INIT_SECMEM
-@item GCRYCTL_TERM_SECMEM
-@item GCRYCTL_DISABLE_SECMEM_WARN
-@item GCRYCTL_SUSPEND_SECMEM_WARN
-@item GCRYCTL_RESUME_SECMEM_WARN
+process will abort because the secmem is not initialized.  This command
+should be executed right after @code{gcry_check_version}.
+
+@item GCRYCTL_INIT_SECMEM; Arguments: int nbytes
+This command is used to allocate a pool of secure memory and thus
+enabling the use of secure memory.  It also drops all extra privileges
+the process has (i.e. if it is run as setuid (root)).  If the argument
+@var{nbytes} is 0, secure memory will be disabled.  The minimum amount
+of secure memory allocated is currently 16384 bytes; you may thus use a
+value of 1 to request that default size.
+
+@item GCRYCTL_TERM_SECMEM; Arguments: none
+This command zeroises the secure memory and destroys the handler.  The
+secure memory pool may not be used anymore after running this command.
+If the secure memory pool as already been destroyed, this command has no
+effect.  Applications might want to run this command from their exit
+handler to make sure that the secure memory gets properly destroyed.
+This command is not necessary thread-safe but that should not be needed
+in cleanup code.  It may be called from a signal handler.
+
+@item GCRYCTL_DISABLE_SECMEM_WARN; Arguments: none
+Disable warning messages about problems with the secure memory
+subsystem. This command should be run right after
+@code{gcry_check_version}.
+
+@item GCRYCTL_SUSPEND_SECMEM_WARN; Arguments: none
+Postpone warning messages from the secure memory subsystem. 
+@xref{sample-use-suspend-secmem,,the initialization example}, on how to
+use it. 
+
+@item GCRYCTL_RESUME_SECMEM_WARN; Arguments: none
+Resume warning messages from the secure memory subsystem.
+@xref{sample-use-resume-secmem,,the initialization example}, on how to
+use it.
 
 @item GCRYCTL_USE_SECURE_RNDPOOL; Arguments: none
 
 @item GCRYCTL_USE_SECURE_RNDPOOL; Arguments: none
-
 This command tells the PRNG to store random numbers in secure memory.
 This command tells the PRNG to store random numbers in secure memory.
-FIXME: what about initialization time?
+This command should be run right after @code{gcry_check_version} and not
+later than the command GCRYCTL_INIT_SECMEM.  Note that in FIPS mode the
+secure memory is always used.
 
 @item GCRYCTL_SET_RANDOM_SEED_FILE; Arguments: const char *filename
 
 @item GCRYCTL_SET_RANDOM_SEED_FILE; Arguments: const char *filename
-
 This command specifies the file, which is to be used as seed file for
 the PRNG.  If the seed file is registered prior to initialization of the
 PRNG, the seed file's content (if it exists and seems to be valid) is
 This command specifies the file, which is to be used as seed file for
 the PRNG.  If the seed file is registered prior to initialization of the
 PRNG, the seed file's content (if it exists and seems to be valid) is
@@ -593,7 +664,6 @@ file with the following command.
 
 
 @item GCRYCTL_UPDATE_RANDOM_SEED_FILE; Arguments: none
 
 
 @item GCRYCTL_UPDATE_RANDOM_SEED_FILE; Arguments: none
-
 Write out the PRNG pool's content into the registered seed file.
 
 Multiple instances of the applications sharing the same random seed file
 Write out the PRNG pool's content into the registered seed file.
 
 Multiple instances of the applications sharing the same random seed file
@@ -613,36 +683,86 @@ not an issue when using Linux (rndlinux driver), because this one
 guarantees to read full 16 bytes from /dev/urandom and thus there is no
 way for an attacker without kernel access to conrol these 16 bytes.
 
 guarantees to read full 16 bytes from /dev/urandom and thus there is no
 way for an attacker without kernel access to conrol these 16 bytes.
 
-@item GCRYCTL_SET_VERBOSITY
-
-
-@item GCRYCTL_SET_DEBUG_FLAGS
-@item GCRYCTL_CLEAR_DEBUG_FLAGS
-@item GCRYCTL_DISABLE_INTERNAL_LOCKING
-@item GCRYCTL_ANY_INITIALIZATION_P
-@item GCRYCTL_INITIALIZATION_FINISHED_P
-@item GCRYCTL_INITIALIZATION_FINISHED
+@item GCRYCTL_SET_VERBOSITY; Arguments: int level
+This command sets the verbosity of the logging.  A level of 0 disables
+all extra logging whereas positive numbers enable more verbose logging.
+The level may be changed at any time but be aware that no memory
+syncronization is done so the effect of this command might not
+immediately show up in other threads.
+
+@item GCRYCTL_SET_DEBUG_FLAGS; Arguments: unsigned int flags
+Set the debug flag bits as given by the argument.  Be aware that that no
+memory syncronization is done so the effect of this command might not
+immediately show up in other threads.  The debug flags are not
+considered part of the API and thus may change without notice.  As of
+now bit 0 enables debugging of cipher functions and bit 1 debugging of
+multi-precision-integers.
+
+@item GCRYCTL_CLEAR_DEBUG_FLAGS; Arguments: unsigned int flags
+Set the debug flag bits as given by the argument.  Be aware that that no
+memory syncronization is done so the effect of this command might not
+immediately show up in other threads.
+
+@item GCRYCTL_DISABLE_INTERNAL_LOCKING; Arguments: none
+This command does nothing.  It exists only for backward compatibility.
+
+@item GCRYCTL_ANY_INITIALIZATION_P; Arguments: none
+This command returns true if the library has been basically initialized.
+Such a basic initialization happens implicitly with many commands to get
+certain internal subsystems running.  The common and suggested way to
+do this basic intialization is by calling gcry_check_version.
+
+@item GCRYCTL_INITIALIZATION_FINISHED; Arguments: none
+This command tells the libray that the application has finished the
+intialization.
+
+@item GCRYCTL_INITIALIZATION_FINISHED_P; Arguments: none
+This command returns true if the command@*
+GCRYCTL_INITIALIZATION_FINISHED has already been run.
 
 @item GCRYCTL_SET_THREAD_CBS; Arguments: struct ath_ops *ath_ops
 
 @item GCRYCTL_SET_THREAD_CBS; Arguments: struct ath_ops *ath_ops
+This command registers a thread-callback structure.
+@xref{Multi-Threading}.
 
 
-This command registers a thread-callback structure.  See section ``multi
-threading'' for more information on this command.
-
-@item GCRYCTL_FAST_POLL
-
+@item GCRYCTL_FAST_POLL; Arguments: none
 Run a fast random poll.
 
 Run a fast random poll.
 
-
 @item GCRYCTL_SET_RNDEGD_SOCKET; Arguments: const char *filename
 @item GCRYCTL_SET_RNDEGD_SOCKET; Arguments: const char *filename
-
 This command may be used to override the default name of the EGD socket
 to connect to.  It may be used only during initialization as it is not
 thread safe.  Changing the socket name again is not supported.  The
 function may return an error if the given filename is too long for a
 local socket name.
 
 This command may be used to override the default name of the EGD socket
 to connect to.  It may be used only during initialization as it is not
 thread safe.  Changing the socket name again is not supported.  The
 function may return an error if the given filename is too long for a
 local socket name.
 
-EGD is an alternative random gatherer, used only on a few systems.
-
+EGD is an alternative random gatherer, used only on systems lacking a
+proper random device.
+
+@item GCRYCTL_PRINT_CONFIG; Arguments: FILE *stream
+This command dumps information pertaining to the configuration of the
+library to the given stream.  If NULL is given for @var{stream}, the log
+system is used.  This command may be used before the intialization has
+been finished but not before a gcry_version_check.
+
+@item GCRYCTL_OPERATIONAL_P; Arguments: none
+This command returns true if the library is in an operational state.
+This information makes only sense in FIPS mode.  In contrast to other
+functions, this is a pure test function and won't put the library into
+FIPS mode or change the internal state.  This command may be used before
+the intialization has been finished but not before a gcry_version_check.
+
+@item GCRYCTL_FIPS_MODE_P; Arguments: none
+This command returns true if the library is in FIPS mode.  Note, that
+this is no indication about the current state of the library.  This
+command may be used before the intialization has been finished but not
+before a gcry_version_check.
+
+@item GCRYCTL_FORCE_FIPS_MODE; Arguments: none
+Running this command puts the library into FIPS mode.  If the library
+has already been initialized or is already in FIPS mode, a selftest is
+triggered and thus the library will be put into operational state.  This
+command may even be used before a call to gcry_check_version and that is
+actually the recommended way to let an application switch the library
+into FIPS mode.
 
 
 @end table
 
 
 @end table
@@ -855,7 +975,7 @@ value will be @code{0}.  In this case the error source part is of
 course @code{GPG_ERR_SOURCE_UNKNOWN}.
 
 The list of error sources that might occur in applications using
 course @code{GPG_ERR_SOURCE_UNKNOWN}.
 
 The list of error sources that might occur in applications using
-@acronym{Libgctypt} is:
+@acronym{Libgcrypt} is:
 
 @table @code
 @item GPG_ERR_SOURCE_UNKNOWN
 
 @table @code
 @item GPG_ERR_SOURCE_UNKNOWN
@@ -980,6 +1100,16 @@ This value means a verification failed because the signature is bad.
 This value means a verification failed because the public key is not
 available.
 
 This value means a verification failed because the public key is not
 available.
 
+@item GPG_ERR_NOT_OPERATIONAL
+This value means that the library is not yet in state which allows to
+use this function.  This error code is in particular returned if
+Libgcrypt is operated in FIPS mode and the internal state of the
+library does not yet or not anymore allow the use of a service.
+
+This error code is only available with newer libgpg-error versions, thus
+you might see ``invalid error code'' when passing this to
+@code{gpg_strerror}.  The numeric value of this error code is 176.
+
 @item GPG_ERR_USER_1
 @item GPG_ERR_USER_2
 @item ...
 @item GPG_ERR_USER_1
 @item GPG_ERR_USER_2
 @item ...
@@ -1486,7 +1616,7 @@ This function releases the context created by @code{gcry_cipher_open}.
 In order to use a handle for performing cryptographic operations, a
 `key' has to be set first:
 
 In order to use a handle for performing cryptographic operations, a
 `key' has to be set first:
 
-@deftypefun gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t @var{h}, void *@var{k}, size_t @var{l})
+@deftypefun gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t @var{h}, const void *@var{k}, size_t @var{l})
 
 Set the key @var{k} used for encryption or decryption in the context
 denoted by the handle @var{h}.  The length @var{l} of the key @var{k}
 
 Set the key @var{k} used for encryption or decryption in the context
 denoted by the handle @var{h}.  The length @var{l} of the key @var{k}
@@ -1495,8 +1625,6 @@ be in the allowed range for algorithms with variable key size.  The
 function checks this and returns an error if there is a problem.  A
 caller should always check for an error.
 
 function checks this and returns an error if there is a problem.  A
 caller should always check for an error.
 
-Note that this is currently implemented as a macro but may be changed
-to a function in the future.
 @end deftypefun
 
 Most crypto modes requires an initialization vector (IV), which
 @end deftypefun
 
 Most crypto modes requires an initialization vector (IV), which
@@ -1504,23 +1632,21 @@ usually is a non-secret random string acting as a kind of salt value.
 The CTR mode requires a counter, which is also similar to a salt
 value.  To set the IV or CTR, use these functions:
 
 The CTR mode requires a counter, which is also similar to a salt
 value.  To set the IV or CTR, use these functions:
 
-@deftypefun gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t @var{h}, void *@var{k}, size_t @var{l})
+@deftypefun gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t @var{h}, const void *@var{k}, size_t @var{l})
 
 Set the initialization vector used for encryption or decryption. The
 vector is passed as the buffer @var{K} of length @var{l} and copied to
 internal data structures.  The function checks that the IV matches the
 
 Set the initialization vector used for encryption or decryption. The
 vector is passed as the buffer @var{K} of length @var{l} and copied to
 internal data structures.  The function checks that the IV matches the
-requirement of the selected algorithm and mode.  Note that this is
-implemented as a macro.
+requirement of the selected algorithm and mode. 
 @end deftypefun
 
 @end deftypefun
 
-@deftypefun gcry_error_t gcry_cipher_setctr (gcry_cipher_hd_t @var{h}, void *@var{c}, size_t @var{l})
+@deftypefun gcry_error_t gcry_cipher_setctr (gcry_cipher_hd_t @var{h}, const void *@var{c}, size_t @var{l})
 
 Set the counter vector used for encryption or decryption. The counter
 is passed as the buffer @var{c} of length @var{l} and copied to
 internal data structures.  The function checks that the counter
 matches the requirement of the selected algorithm (i.e., it must be
 
 Set the counter vector used for encryption or decryption. The counter
 is passed as the buffer @var{c} of length @var{l} and copied to
 internal data structures.  The function checks that the counter
 matches the requirement of the selected algorithm (i.e., it must be
-the same size as the block size).  Note that this is implemented as a
-macro.
+the same size as the block size).  
 @end deftypefun
 
 @deftypefun gcry_error_t gcry_cipher_reset (gcry_cipher_hd_t @var{h})
 @end deftypefun
 
 @deftypefun gcry_error_t gcry_cipher_reset (gcry_cipher_hd_t @var{h})
@@ -1674,1878 +1800,1883 @@ with it.
 
 
 @c **********************************************************
 
 
 @c **********************************************************
-@c *******************  Hash Functions  *********************
+@c *******************  Public Key  *************************
 @c **********************************************************
 @c **********************************************************
-@node Hashing
-@chapter Hashing
+@node Public Key cryptography
+@chapter Public Key cryptography
 
 
-Libgcrypt provides an easy and consistent to use interface
-for hashing.  Hashing is buffered and several hash algorithms can be
-updated at once.  It is possible to calculate a MAC using the same
-routines.  The programming model follows an open/process/close
-paradigm and is in that similar to other building blocks provided by
-Libgcrypt.
-
-For convenience reasons, a few cyclic redundancy check value operations
-are also supported.
+Public key cryptography, also known as asymmetric cryptography, is an
+easy way for key management and to provide digital signatures.
+Libgcrypt provides two completely different interfaces to
+public key cryptography, this chapter explains the one based on
+S-expressions.
 
 @menu
 
 @menu
-* Available hash algorithms::   List of hash algorithms supported by the library.
-* Hash algorithm modules::      How to work with hash algorithm modules.
-* Working with hash algorithms::  List of functions related to hashing.
+* Available algorithms::        Algorithms supported by the library.
+* Used S-expressions::          Introduction into the used S-expression.
+* Public key modules::          How to work with public key modules.
+* Cryptographic Functions::     Functions for performing the cryptographic actions.
+* General public-key related Functions::  General functions, not implementing any cryptography.
+
+* AC Interface::                Alternative interface to public key functions.
 @end menu
 
 @end menu
 
-@node Available hash algorithms
-@section Available hash algorithms
+@node Available algorithms
+@section Available algorithms
 
 
-@c begin table of hash algorithms
-@table @code
-@item GCRY_MD_NONE
-This is not a real algorithm but used by some functions as an error
-return value.  This constant is guaranteed to have the value @code{0}.
+Libgcrypt supports the RSA (Rivest-Shamir-Adleman) algorithms as well
+as DSA (Digital Signature Algorithm) and Elgamal.  The versatile
+interface allows to add more algorithms in the future.
 
 
-@item GCRY_MD_SHA1
-This is the SHA-1 algorithm which yields a message digest of 20 bytes.
+@node Used S-expressions
+@section Used S-expressions
 
 
-@item GCRY_MD_RMD160
-This is the 160 bit version of the RIPE message digest (RIPE-MD-160).
-Like SHA-1 it also yields a digest of 20 bytes.
+Libgcrypt's API for asymmetric cryptography is based on data structures
+called S-expressions (see
+@uref{http://people.csail.mit.edu/@/rivest/@/sexp.html}) and does not work
+with contexts as most of the other building blocks of Libgcrypt do.
 
 
-@item GCRY_MD_MD5
-This is the well known MD5 algorithm, which yields a message digest of
-16 bytes. 
+The following information are stored in S-expressions:
 
 
-@item GCRY_MD_MD4
-This is the MD4 algorithm, which yields a message digest of 16 bytes.
+@table @asis
+@item keys
 
 
-@item GCRY_MD_MD2
-This is an reserved identifier for MD-2; there is no implementation yet.
+@item plain text data
 
 
-@item GCRY_MD_TIGER
-This is the TIGER/192 algorithm which yields a message digest of 24 bytes.
+@item encrypted data
 
 
-@item GCRY_MD_HAVAL
-This is an reserved for the HAVAL algorithm with 5 passes and 160
-bit. It yields a message digest of 20 bytes.  Note that there is no
-implementation yet available.
+@item signatures
 
 
-@item GCRY_MD_SHA224
-This is the SHA-224 algorithm which yields a message digest of 28 bytes.
-See Change Notice 1 for FIPS 180-2 for the specification.
+@end table
 
 
-@item GCRY_MD_SHA256
-This is the SHA-256 algorithm which yields a message digest of 32 bytes.
-See FIPS 180-2 for the specification.
+@noindent
+To describe how Libgcrypt expect keys, we use examples. Note that
+words in
+@ifnottex
+uppercase
+@end ifnottex
+@iftex
+italics
+@end iftex
+indicate parameters whereas lowercase words are literals.
 
 
-@item GCRY_MD_SHA384
-This is the SHA-384 algorithm which yields a message digest of 48 bytes.
-See FIPS 180-2 for the specification.
+Note that all MPI (multi-precision-integers) values are expected to be in
+@code{GCRYMPI_FMT_USG} format.  An easy way to create S-expressions is
+by using @code{gcry_sexp_build} which allows to pass a string with
+printf-like escapes to insert MPI values.
 
 
-@item GCRY_MD_SHA512
-This is the SHA-384 algorithm which yields a message digest of 64 bytes.
-See FIPS 180-2 for the specification.
+@menu
+* RSA key parameters::  Parameters used with an RSA key.
+* DSA key parameters::  Parameters used with a DSA key.
+* ECC key parameters::  Parameters used with ECC keys.
+@end menu
 
 
-@item GCRY_MD_CRC32
-This is the ISO 3309 and ITU-T V.42 cyclic redundancy check.  It
-yields an output of 4 bytes.
+@node RSA key parameters
+@subsection RSA key parameters
 
 
-@item GCRY_MD_CRC32_RFC1510
-This is the above cyclic redundancy check function, as modified by RFC
-1510.  It yields an output of 4 bytes.
+@noindent
+An RSA private key is described by this S-expression:
 
 
-@item GCRY_MD_CRC24_RFC2440
-This is the OpenPGP cyclic redundancy check function.  It yields an
-output of 3 bytes.
+@example
+(private-key
+  (rsa
+    (n @var{n-mpi})
+    (e @var{e-mpi})
+    (d @var{d-mpi})
+    (p @var{p-mpi})
+    (q @var{q-mpi})
+    (u @var{u-mpi})))
+@end example
 
 
-@item GCRY_MD_WHIRLPOOL
-This is the Whirlpool algorithm which yields a message digest of 64
-bytes.
+@noindent
+An RSA public key is described by this S-expression:
 
 
-@end table
-@c end table of hash algorithms
+@example
+(public-key
+  (rsa
+    (n @var{n-mpi})
+    (e @var{e-mpi})))
+@end example
 
 
-@node Hash algorithm modules
-@section Hash algorithm modules
 
 
-Libgcrypt makes it possible to load additional `message
-digest modules'; these digests can be used just like the message digest
-algorithms that are built into the library directly.  For an
-introduction into extension modules, see @xref{Modules}.
-
-@deftp {Data type} gcry_md_spec_t
-This is the `module specification structure' needed for registering
-message digest modules, which has to be filled in by the user before
-it can be used to register a module.  It contains the following
-members:
-
-@table @code
-@item const char *name
-The primary name of this algorithm.
-@item unsigned char *asnoid
-Array of bytes that form the ASN OID.
-@item int asnlen
-Length of bytes in `asnoid'.
-@item gcry_md_oid_spec_t *oids
-A list of OIDs that are to be associated with the algorithm.  The
-list's last element must have it's `oid' member set to NULL.  See
-below for an explanation of this type.  See below for an explanation
-of this type.
-@item int mdlen
-Length of the message digest algorithm.  See below for an explanation
-of this type.
-@item gcry_md_init_t init
-The function responsible for initializing a handle.  See below for an
-explanation of this type.
-@item gcry_md_write_t write
-The function responsible for writing data into a message digest
-context.  See below for an explanation of this type.
-@item gcry_md_final_t final
-The function responsible for `finalizing' a message digest context.
-See below for an explanation of this type.
-@item gcry_md_read_t read
-The function responsible for reading out a message digest result.  See
-below for an explanation of this type.
-@item size_t contextsize
-The size of the algorithm-specific `context', that should be
-allocated for each handle.
+@table @var
+@item n-mpi
+RSA public modulus @math{n}.
+@item e-mpi
+RSA public exponent @math{e}.
+@item d-mpi
+RSA secret exponent @math{d = e^{-1} \bmod (p-1)(q-1)}.
+@item p-mpi
+RSA secret prime @math{p}.
+@item q-mpi
+RSA secret prime @math{q} with @math{p < q}.
+@item u-mpi
+Multiplicative inverse @math{u = p^{-1} \bmod q}.
 @end table
 @end table
-@end deftp
 
 
-@deftp {Data type} gcry_md_oid_spec_t
-This type is used for associating a user-provided algorithm
-implementation with certain OIDs.  It contains the following members:
+For signing and decryption the parameters @math{(p, q, u)} are optional
+but greatly improve the performance.  Either all of these optional
+parameters must be given or none of them.  They are mandatory for
+gcry_pk_testkey.
 
 
-@table @code
-@item const char *oidstring
-Textual representation of the OID.
-@end table
-@end deftp
+Note that OpenSSL uses slighly different parameters: @math{q < p} and 
+ @math{u = q^{-1} \bmod p}.  To use these parameters you will need to
+swap the values and recompute @math{u}.  Here is example code to do this:
 
 
-@deftp {Data type} gcry_md_init_t
-Type for the `init' function, defined as: void (*gcry_md_init_t) (void
-*c)
-@end deftp
+@example
+  if (gcry_mpi_cmp (p, q) > 0)
+    @{
+      gcry_mpi_swap (p, q);
+      gcry_mpi_invm (u, p, q);
+    @}
+@end example
 
 
-@deftp {Data type} gcry_md_write_t
-Type for the `write' function, defined as: void (*gcry_md_write_t)
-(void *c, unsigned char *buf, size_t nbytes)
-@end deftp
 
 
-@deftp {Data type} gcry_md_final_t
-Type for the `final' function, defined as: void (*gcry_md_final_t)
-(void *c)
-@end deftp
 
 
-@deftp {Data type} gcry_md_read_t
-Type for the `read' function, defined as: unsigned char
-*(*gcry_md_read_t) (void *c)
-@end deftp
 
 
-@deftypefun gcry_error_t gcry_md_register (gcry_md_spec_t *@var{digest}, unsigned int *algorithm_id, gcry_module_t *@var{module})
+@node DSA key parameters
+@subsection DSA key parameters
 
 
-Register a new digest module whose specification can be found in
-@var{digest}.  On success, a new algorithm ID is stored in
-@var{algorithm_id} and a pointer representing this module is stored
-in @var{module}.
-@end deftypefun
+@noindent
+A DSA private key is described by this S-expression:
 
 
-@deftypefun void gcry_md_unregister (gcry_module_t @var{module})
-Unregister the digest identified by @var{module}, which must have been
-registered with gcry_md_register.
-@end deftypefun
+@example
+(private-key
+  (dsa
+    (p @var{p-mpi})
+    (q @var{q-mpi})
+    (g @var{g-mpi})
+    (y @var{y-mpi})
+    (x @var{x-mpi})))
+@end example
 
 
-@deftypefun gcry_error_t gcry_md_list (int *@var{list}, int *@var{list_length})
-Get a list consisting of the IDs of the loaded message digest modules.
-If @var{list} is zero, write the number of loaded message digest
-modules to @var{list_length} and return.  If @var{list} is non-zero,
-the first *@var{list_length} algorithm IDs are stored in @var{list},
-which must be of according size.  In case there are less message
-digests modules than *@var{list_length}, *@var{list_length} is updated
-to the correct number.
-@end deftypefun
+@table @var
+@item p-mpi
+DSA prime @math{p}.
+@item q-mpi
+DSA group order @math{q} (which is a prime divisor of @math{p-1}).
+@item g-mpi
+DSA group generator @math{g}.
+@item y-mpi
+DSA public key value @math{y = g^x \bmod p}.
+@item x-mpi
+DSA secret exponent x.
+@end table
 
 
-@node Working with hash algorithms
-@section Working with hash algorithms
+The public key is similar with "private-key" replaced by "public-key"
+and no @var{x-mpi}.
 
 
-To use most of these function it is necessary to create a context;
-this is done using:
 
 
-@deftypefun gcry_error_t gcry_md_open (gcry_md_hd_t *@var{hd}, int @var{algo}, unsigned int @var{flags})
+@node ECC key parameters
+@subsection ECC key parameters
 
 
-Create a message digest object for algorithm @var{algo}.  @var{flags}
-may be given as an bitwise OR of constants described below.  @var{algo}
-may be given as @code{0} if the algorithms to use are later set using
-@code{gcry_md_enable}. @var{hd} is guaranteed to either receive a valid
-handle or NULL.
+@noindent
+An ECC private key is described by this S-expression:
 
 
-For a list of supported algorithms, see @xref{Available hash
-algorithms}.
+@example
+(private-key
+  (ecc
+    (p @var{p-mpi})
+    (a @var{a-mpi})
+    (b @var{b-mpi})
+    (g @var{g-point})
+    (n @var{n-mpi})
+    (q @var{q-point})
+    (d @var{d-mpi})))
+@end example
 
 
-The flags allowed for @var{mode} are:
+@table @var
+@item p-mpi
+Prime specifying the field @math{GF(p)}.
+@item a-mpi
+@itemx b-mpi
+The two coefficients of the Weierstrass equation @math{y^2 = x^3 + ax + b}
+@item g-point
+Base point @math{g}.
+@item n-mpi
+Order of @math{g}
+@item q-point
+The point representing the public key @math{Q = dP}.
+@item d-mpi
+The private key @math{d}
+@end table
 
 
-@c begin table of hash flags
-@table @code
-@item GCRY_MD_FLAG_SECURE
-Allocate all buffers and the resulting digest in "secure memory".  Use
-this is the hashed data is highly confidential.
+All point values are encoded in standard format; Libgcrypt does
+currently only support uncompressed points, thus the first byte needs to
+be @code{0x04}.
 
 
-@item GCRY_MD_FLAG_HMAC
-Turn the algorithm into a HMAC message authentication algorithm.  This
-only works if just one algorithm is enabled for the handle.  Note that the function
-@code{gcry_md_setkey} must be used to set the MAC key.  If you want CBC
-message authentication codes based on a cipher, see @xref{Working with
-cipher handles}.
+The public key is similar with "private-key" replaced by "public-key"
+and no @var{d-mpi}.
 
 
-@end table
-@c begin table of hash flags
+If the domain parameters are well-known, the name of this curve may be
+used.  For example
 
 
-You may use the function @code{gcry_md_is_enabled} to later check
-whether an algorithm has been enabled.
+@example
+(private-key
+  (ecc
+    (curve "NIST P-192")
+    (q @var{q-point})
+    (d @var{d-mpi})))
+@end example
 
 
-@end deftypefun
-@c end function gcry_md_open
+The @code{curve} parameter may be given in any case and is used to replace
+missing parameters.
 
 
-If you want to calculate several hash algorithms at the same time, you
-have to use the following function right after the @code{gcry_md_open}:
+@noindent
+Currently implemented curves are:
+@table @code
+@item NIST P-192
+@itemx 1.2.840.10045.3.1.1
+@itemx prime192v1
+@itemx secp192r1
+The NIST 192 bit curve, its OID, X9.62 and SECP aliases.
 
 
-@deftypefun gcry_error_t gcry_md_enable (gcry_md_hd_t @var{h}, int @var{algo})
+@item NIST P-224
+@itemx secp224r1
+The NIST 224 bit curve and its SECP alias.
 
 
-Add the message digest algorithm @var{algo} to the digest object
-described by handle @var{h}.  Duplicated enabling of algorithms is
-detected and ignored.
-@end deftypefun
+@item NIST P-256
+@itemx 1.2.840.10045.3.1.7
+@itemx prime256v1
+@itemx secp256r1
+The NIST 256 bit curve, its OID, X9.62 and SECP aliases.
 
 
-If the flag @code{GCRY_MD_FLAG_HMAC} was used, the key for the MAC must
-be set using the function:
+@item NIST P-384
+@itemx secp384r1
+The NIST 384 bit curve and its SECP alias.
 
 
-@deftypefun gcry_error_t gcry_md_setkey (gcry_md_hd_t @var{h}, const void *@var{key}, size_t @var{keylen})
+@item NIST P-521
+@itemx secp521r1
+The NIST 521 bit curve and its SECP alias.
 
 
-For use with the HMAC feature, set the MAC key to the value of @var{key}
-of length @var{keylen}.
-@end deftypefun
+@end table
+As usual the OIDs may optionally be prefixed with the string @code{OID.}
+or @code{oid.}.
 
 
 
 
-After you are done with the hash calculation, you should release the
-resources by using:
 
 
-@deftypefun void gcry_md_close (gcry_md_hd_t @var{h})
+@node Public key modules
+@section Public key modules
 
 
-Release all resources of hash context @var{h}.  @var{h} should not be
-used after a call to this function.  A @code{NULL} passed as @var{h} is
-ignored.
-
-@end deftypefun
+Libgcrypt makes it possible to load additional `public key
+modules'; these public key algorithms can be used just like the
+algorithms that are built into the library directly.  For an
+introduction into extension modules, see @xref{Modules}.
 
 
-Often you have to do several hash operations using the same algorithm.
-To avoid the overhead of creating and releasing context, a reset function
-is provided:
+@deftp {Data type} gcry_pk_spec_t
+This is the `module specification structure' needed for registering
+public key modules, which has to be filled in by the user before it
+can be used to register a module.  It contains the following members:
 
 
-@deftypefun void gcry_md_reset (gcry_md_hd_t @var{h})
+@table @code
+@item const char *name
+The primary name of this algorithm.
+@item char **aliases
+A list of strings that are `aliases' for the algorithm.  The list
+must be terminated with a NULL element.
+@item const char *elements_pkey
+String containing the one-letter names of the MPI values contained in
+a public key.
+@item const char *element_skey
+String containing the one-letter names of the MPI values contained in
+a secret key.
+@item const char *elements_enc
+String containing the one-letter names of the MPI values that are the
+result of an encryption operation using this algorithm.
+@item const char *elements_sig
+String containing the one-letter names of the MPI values that are the
+result of a sign operation using this algorithm.
+@item const char *elements_grip
+String containing the one-letter names of the MPI values that are to
+be included in the `key grip'.
+@item int use
+The bitwise-OR of the following flags, depending on the abilities of
+the algorithm:
+@table @code
+@item GCRY_PK_USAGE_SIGN
+The algorithm supports signing and verifying of data.
+@item GCRY_PK_USAGE_ENCR
+The algorithm supports the encryption and decryption of data.
+@end table
+@item gcry_pk_generate_t generate
+The function responsible for generating a new key pair.  See below for
+a description of this type.
+@item gcry_pk_check_secret_key_t check_secret_key
+The function responsible for checking the sanity of a provided secret
+key.  See below for a description of this type.
+@item gcry_pk_encrypt_t encrypt
+The function responsible for encrypting data.  See below for a
+description of this type.
+@item gcry_pk_decrypt_t decrypt
+The function responsible for decrypting data.  See below for a
+description of this type.
+@item gcry_pk_sign_t sign
+The function responsible for signing data.  See below for a description
+of this type.
+@item gcry_pk_verify_t verify
+The function responsible for verifying that the provided signature
+matches the provided data.  See below for a description of this type.
+@item gcry_pk_get_nbits_t get_nbits
+The function responsible for returning the number of bits of a provided
+key.  See below for a description of this type.
+@end table
+@end deftp
 
 
-Reset the current context to its initial state.  This is effectively
-identical to a close followed by an open and enabling all currently
-active algorithms.
-@end deftypefun
+@deftp {Data type} gcry_pk_generate_t
+Type for the `generate' function, defined as: gcry_err_code_t
+(*gcry_pk_generate_t) (int algo, unsigned int nbits, unsigned long
+use_e, gcry_mpi_t *skey, gcry_mpi_t **retfactors)
+@end deftp
 
 
+@deftp {Data type} gcry_pk_check_secret_key_t
+Type for the `check_secret_key' function, defined as: gcry_err_code_t
+(*gcry_pk_check_secret_key_t) (int algo, gcry_mpi_t *skey)
+@end deftp
 
 
-Often it is necessary to start hashing some data and then continue to
-hash different data.  To avoid hashing the same data several times (which
-might not even be possible if the data is received from a pipe), a
-snapshot of the current hash context can be taken and turned into a new
-context:
+@deftp {Data type} gcry_pk_encrypt_t
+Type for the `encrypt' function, defined as: gcry_err_code_t
+(*gcry_pk_encrypt_t) (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
+gcry_mpi_t *pkey, int flags)
+@end deftp
 
 
-@deftypefun gcry_error_t gcry_md_copy (gcry_md_hd_t *@var{handle_dst}, gcry_md_hd_t @var{handle_src})
+@deftp {Data type} gcry_pk_decrypt_t
+Type for the `decrypt' function, defined as: gcry_err_code_t
+(*gcry_pk_decrypt_t) (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
+gcry_mpi_t *skey, int flags)
+@end deftp
 
 
-Create a new digest object as an exact copy of the object described by
-handle @var{handle_src} and store it in @var{handle_dst}.  The context
-is not reset and you can continue to hash data using this context and
-independently using the original context.
-@end deftypefun
+@deftp {Data type} gcry_pk_sign_t
+Type for the `sign' function, defined as: gcry_err_code_t
+(*gcry_pk_sign_t) (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
+gcry_mpi_t *skey)
+@end deftp
 
 
+@deftp {Data type} gcry_pk_verify_t
+Type for the `verify' function, defined as: gcry_err_code_t
+(*gcry_pk_verify_t) (int algo, gcry_mpi_t hash, gcry_mpi_t *data,
+gcry_mpi_t *pkey, int (*cmp) (void *, gcry_mpi_t), void *opaquev)
+@end deftp
 
 
-Now that we have prepared everything to calculate hashes, it is time to
-see how it is actually done.  There are two ways for this, one to
-update the hash with a block of memory and one macro to update the hash
-by just one character.  Both methods can be used on the same hash context.
+@deftp {Data type} gcry_pk_get_nbits_t
+Type for the `get_nbits' function, defined as: unsigned
+(*gcry_pk_get_nbits_t) (int algo, gcry_mpi_t *pkey)
+@end deftp
 
 
-@deftypefun void gcry_md_write (gcry_md_hd_t @var{h}, const void *@var{buffer}, size_t @var{length})
+@deftypefun gcry_error_t gcry_pk_register (gcry_pk_spec_t *@var{pubkey}, unsigned int *algorithm_id, gcry_module_t *@var{module})
 
 
-Pass @var{length} bytes of the data in @var{buffer} to the digest object
-with handle @var{h} to update the digest values. This
-function should be used for large blocks of data.
+Register a new public key module whose specification can be found in
+@var{pubkey}.  On success, a new algorithm ID is stored in
+@var{algorithm_id} and a pointer representing this module is stored
+in @var{module}.
 @end deftypefun
 
 @end deftypefun
 
-@deftypefun void gcry_md_putc (gcry_md_hd_t @var{h}, int @var{c})
-
-Pass the byte in @var{c} to the digest object with handle @var{h} to
-update the digest value.  This is an efficient function, implemented as
-a macro to buffer the data before an actual update. 
+@deftypefun void gcry_pk_unregister (gcry_module_t @var{module})
+Unregister the public key module identified by @var{module}, which
+must have been registered with gcry_pk_register.
 @end deftypefun
 
 @end deftypefun
 
-The semantics of the hash functions do not provide for reading out intermediate
-message digests because the calculation must be finalized first.  This
-finalization may for example include the number of bytes hashed in the
-message digest or some padding.
-
-@deftypefun void gcry_md_final (gcry_md_hd_t @var{h})
-
-Finalize the message digest calculation.  This is not really needed
-because @code{gcry_md_read} does this implicitly.  After this has been
-done no further updates (by means of @code{gcry_md_write} or
-@code{gcry_md_putc} are allowed.  Only the first call to this function
-has an effect. It is implemented as a macro.
+@deftypefun gcry_error_t gcry_pk_list (int *@var{list}, int *@var{list_length})
+Get a list consisting of the IDs of the loaded pubkey modules.  If
+@var{list} is zero, write the number of loaded pubkey modules to
+@var{list_length} and return.  If @var{list} is non-zero, the first
+*@var{list_length} algorithm IDs are stored in @var{list}, which must
+be of according size.  In case there are less pubkey modules than
+*@var{list_length}, *@var{list_length} is updated to the correct
+number.
 @end deftypefun
 
 @end deftypefun
 
-The way to read out the calculated message digest is by using the
-function:
+@node Cryptographic Functions
+@section Cryptographic Functions
 
 
-@deftypefun unsigned char *gcry_md_read (gcry_md_hd_t @var{h}, int @var{algo})
+@noindent
+Note that we will in future allow to use keys without p,q and u
+specified and may also support other parameters for performance
+reasons. 
 
 
-@code{gcry_md_read} returns the message digest after finalizing the
-calculation.  This function may be used as often as required but it will
-always return the same value for one handle.  The returned message digest
-is allocated within the message context and therefore valid until the
-handle is released or reseted (using @code{gcry_md_close} or
-@code{gcry_md_reset}.  @var{algo} may be given as 0 to return the only
-enabled message digest or it may specify one of the enabled algorithms.
-The function does return @code{NULL} if the requested algorithm has not
-been enabled.
-@end deftypefun
+@noindent
 
 
-Because it is often necessary to get the message digest of one block of
-memory, a fast convenience function is available for this task: 
+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:
 
 
-@deftypefun void gcry_md_hash_buffer (int @var{algo}, void *@var{digest}, const void *@var{buffer}, size_t @var{length});
+@table @code
+@item pkcs1
+Use PKCS#1 block type 2 padding.
+@item no-blinding
+Do not use a technique called `blinding', which is used by default in
+order to prevent leaking of secret information.  Blinding is only
+implemented by RSA, but it might be implemented by other algorithms in
+the future as well, when necessary.
+@end table
 
 
-@code{gcry_md_hash_buffer} is a shortcut function to calculate a message
-digest of a buffer.  This function does not require a context and
-immediately returns the message digest of the @var{length} bytes at
-@var{buffer}.  @var{digest} must be allocated by the caller, large
-enough to hold the message digest yielded by the the specified algorithm
-@var{algo}.  This required size may be obtained by using the function
-@code{gcry_md_get_algo_dlen}.
+@noindent
+Now that we know the key basics, we can carry on and explain how to
+encrypt and decrypt data.  In almost all cases the data is a random
+session key which is in turn used for the actual encryption of the real
+data.  There are 2 functions to do this:
 
 
-Note that this function will abort the process if an unavailable
-algorithm is used.
-@end deftypefun
+@deftypefun gcry_error_t gcry_pk_encrypt (@w{gcry_sexp_t *@var{r_ciph},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{pkey}})
 
 
-@c ***********************************
-@c ***** MD info functions ***********
-@c ***********************************
+Obviously a public key must be provided for encryption.  It is
+expected as an appropriate S-expression (see above) in @var{pkey}.
+The data to be encrypted can either be in the simple old format, which
+is a very simple S-expression consisting only of one MPI, or it may be
+a more complex S-expression which also allows to specify flags for
+operation, like e.g. padding rules.
 
 
-Hash algorithms are identified by internal algorithm numbers (see
-@code{gcry_md_open} for a list).  However, in most applications they are
-used by names, so two functions are available to map between string
-representations and hash algorithm identifiers.
+@noindent
+If you don't want to let Libgcrypt handle the padding, you must pass an
+appropriate MPI using this expression for @var{data}:
 
 
-@deftypefun const char *gcry_md_algo_name (int @var{algo})
+@example 
+(data
+  (flags raw)
+  (value @var{mpi}))
+@end example
 
 
-Map the digest algorithm id @var{algo} to a string representation of the
-algorithm name.  For unknown algorithms this function returns the
-string @code{"?"}.  This function should not be used to test for the
-availability of an algorithm.
-@end deftypefun
+@noindent
+This has the same semantics as the old style MPI only way.  @var{MPI} is
+the actual data, already padded appropriate for your protocol.  Most
+systems however use PKCS#1 padding and so you can use this S-expression
+for @var{data}:
 
 
-@deftypefun int gcry_md_map_name (const char *@var{name})
+@example 
+(data
+  (flags pkcs1)
+  (value @var{block}))
+@end example
 
 
-Map the algorithm with @var{name} to a digest algorithm identifier.
-Returns 0 if the algorithm name is not known.  Names representing
-@acronym{ASN.1} object identifiers are recognized if the @acronym{IETF}
-dotted format is used and the OID is prefixed with either "@code{oid.}"
-or "@code{OID.}".  For a list of supported OIDs, see the source code at
-@file{cipher/md.c}. This function should not be used to test for the
-availability of an algorithm.
-@end deftypefun
-
-@deftypefun gcry_error_t gcry_md_get_asnoid (int @var{algo}, void *@var{buffer}, size_t *@var{length})
+@noindent
+Here, the "flags" list has the "pkcs1" flag which let the function know
+that it should provide PKCS#1 block type 2 padding.  The actual data to
+be encrypted is passed as a string of octets in @var{block}.  The
+function checks that this data actually can be used with the given key,
+does the padding and encrypts it.
 
 
-Return an DER encoded ASN.1 OID for the algorithm @var{algo} in the
-user allocated @var{buffer}. @var{length} must point to variable with
-the available size of @var{buffer} and receives after return the
-actual size of the returned OID.  The returned error code may be
-@code{GPG_ERR_TOO_SHORT} if the provided buffer is to short to receive
-the OID; it is possible to call the function with @code{NULL} for
-@var{buffer} to have it only return the required size.  The function
-returns 0 on success.
+If the function could successfully perform the encryption, the return
+value will be 0 and a a new S-expression with the encrypted result is
+allocated and assigned to the variable at the address of @var{r_ciph}.
+The caller is responsible to release this value using
+@code{gcry_sexp_release}.  In case of an error, an error code is
+returned and @var{r_ciph} will be set to @code{NULL}.
 
 
-@end deftypefun
+@noindent
+The returned S-expression has this format when used with RSA:
 
 
+@example
+(enc-val
+  (rsa
+    (a @var{a-mpi})))
+@end example
 
 
-To test whether an algorithm is actually available for use, the
-following macro should be used:
+@noindent
+Where @var{a-mpi} is an MPI with the result of the RSA operation.  When
+using the Elgamal algorithm, the return value will have this format:
 
 
-@deftypefun gcry_error_t gcry_md_test_algo (int @var{algo}) 
+@example
+(enc-val
+  (elg
+    (a @var{a-mpi})
+    (b @var{b-mpi})))
+@end example
 
 
-The macro returns 0 if the algorithm @var{algo} is available for use.
+@noindent
+Where @var{a-mpi} and @var{b-mpi} are MPIs with the result of the
+Elgamal encryption operation.
 @end deftypefun
 @end deftypefun
+@c end gcry_pk_encrypt
 
 
-If the length of a message digest is not known, it can be retrieved
-using the following function:
-
-@deftypefun unsigned int gcry_md_get_algo_dlen (int @var{algo})
+@deftypefun gcry_error_t gcry_pk_decrypt (@w{gcry_sexp_t *@var{r_plain},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{skey}})
 
 
-Retrieve the length in bytes of the digest yielded by algorithm
-@var{algo}.  This is often used prior to @code{gcry_md_read} to allocate
-sufficient memory for the digest.
-@end deftypefun
+Obviously a private key must be provided for decryption.  It is expected
+as an appropriate S-expression (see above) in @var{skey}.  The data to
+be decrypted must match the format of the result as returned by
+@code{gcry_pk_encrypt}, but should be enlarged with a @code{flags}
+element:
 
 
+@example
+(enc-val
+  (flags)
+  (elg
+    (a @var{a-mpi})
+    (b @var{b-mpi})))
+@end example
 
 
-In some situations it might be hard to remember the algorithm used for
-the ongoing hashing. The following function might be used to get that
-information:
+@noindent
+Note that this function currently does not know of any padding
+methods and the caller must do any un-padding on his own.
 
 
-@deftypefun int gcry_md_get_algo (gcry_md_hd_t @var{h})
+@noindent
+The function returns 0 on success or an error code.  The variable at the
+address of @var{r_plain} will be set to NULL on error or receive the
+decrypted value on success.  The format of @var{r_plain} is a
+simple S-expression part (i.e. not a valid one) with just one MPI if
+there was no @code{flags} element in @var{data}; if at least an empty
+@code{flags} is passed in @var{data}, the format is:
 
 
-Retrieve the algorithm used with the handle @var{h}.  Note that this
-does not work reliable if more than one algorithm is enabled in @var{h}.
+@example
+(value @var{plaintext})
+@end example
 @end deftypefun
 @end deftypefun
+@c end gcry_pk_decrypt
 
 
-The following macro might also be useful:
 
 
-@deftypefun int gcry_md_is_secure (gcry_md_hd_t @var{h})
+Another operation commonly performed using public key cryptography is
+signing data.  In some sense this is even more important than
+encryption because digital signatures are an important instrument for
+key management.  Libgcrypt supports digital signatures using
+2 functions, similar to the encryption functions:
 
 
-This function returns true when the digest object @var{h} is allocated
-in "secure memory"; i.e. @var{h} was created with the
-@code{GCRY_MD_FLAG_SECURE}.
-@end deftypefun
+@deftypefun gcry_error_t gcry_pk_sign (@w{gcry_sexp_t *@var{r_sig},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{skey}})
 
 
-@deftypefun int gcry_md_is_enabled (gcry_md_hd_t @var{h}, int @var{algo})
+This function creates a digital signature for @var{data} using the
+private key @var{skey} and place it into the variable at the address of
+@var{r_sig}.  @var{data} may either be the simple old style S-expression
+with just one MPI or a modern and more versatile S-expression which
+allows to let Libgcrypt handle padding:
 
 
-This function returns true when the algorithm @var{algo} has been
-enabled for the digest object @var{h}.
-@end deftypefun
+@example 
+ (data
+  (flags pkcs1)
+  (hash @var{hash-algo} @var{block}))
+@end example
 
 
+@noindent
+This example requests to sign the data in @var{block} after applying
+PKCS#1 block type 1 style padding.  @var{hash-algo} is a string with the
+hash algorithm to be encoded into the signature, this may be any hash
+algorithm name as supported by Libgcrypt.  Most likely, this will be
+"sha1", "rmd160" or "md5".  It is obvious that the length of @var{block}
+must match the size of that message digests; the function checks that
+this and other constraints are valid.
 
 
+@noindent
+If PKCS#1 padding is not required (because the caller does already
+provide a padded value), either the old format or better the following
+format should be used:
 
 
-Tracking bugs related to hashing is often a cumbersome task which
-requires to add a lot of printf statements into the code.
-Libgcrypt provides an easy way to avoid this.  The actual data
-hashed can be written to files on request.
+@example
+(data
+  (flags raw)
+  (value @var{mpi}))
+@end example
 
 
-@deftypefun void gcry_md_debug (gcry_md_hd_t @var{h}, const char *@var{suffix})
+@noindent
+Here, the data to be signed is directly given as an @var{MPI}.
 
 
-Enable debugging for the digest object with handle @var{h}.  This
-creates create files named @file{dbgmd-<n>.<string>} while doing the
-actual hashing.  @var{suffix} is the string part in the filename.  The
-number is a counter incremented for each new hashing.  The data in the
-file is the raw data as passed to @code{gcry_md_write} or
-@code{gcry_md_putc}.  If @code{NULL} is used for @var{suffix}, the
-debugging is stopped and the file closed.  This is only rarely required
-because @code{gcry_md_close} implicitly stops debugging.
-@end deftypefun
+@noindent
+The signature is returned as a newly allocated S-expression in
+@var{r_sig} using this format for RSA:
 
 
+@example
+(sig-val
+  (rsa
+    (s @var{s-mpi})))
+@end example
 
 
-The following two deprecated macros are used for debugging by old code.
-They shopuld be replaced by @code{gcry_md_debug}.
+Where @var{s-mpi} is the result of the RSA sign operation.  For DSA the
+S-expression returned is:
 
 
-@deftypefun void gcry_md_start_debug (gcry_md_hd_t @var{h}, const char *@var{suffix})
+@example
+(sig-val
+  (dsa
+    (r @var{r-mpi})
+    (s @var{s-mpi})))
+@end example
 
 
-Enable debugging for the digest object with handle @var{h}.  This
-creates create files named @file{dbgmd-<n>.<string>} while doing the
-actual hashing.  @var{suffix} is the string part in the filename.  The
-number is a counter incremented for each new hashing.  The data in the
-file is the raw data as passed to @code{gcry_md_write} or
-@code{gcry_md_putc}.
+Where @var{r-mpi} and @var{s-mpi} are the result of the DSA sign
+operation.  For Elgamal signing (which is slow, yields large numbers
+and probably is not as secure as the other algorithms), the same format is
+used with "elg" replacing "dsa".
 @end deftypefun
 @end deftypefun
+@c end gcry_pk_sign
 
 
+@noindent
+The operation most commonly used is definitely the verification of a
+signature.  Libgcrypt provides this function:
 
 
-@deftypefun void gcry_md_stop_debug (gcry_md_hd_t @var{h}, int @var{reserved})
+@deftypefun gcry_error_t gcry_pk_verify (@w{gcry_sexp_t @var{sig}}, @w{gcry_sexp_t @var{data}}, @w{gcry_sexp_t @var{pkey}})
 
 
-Stop debugging on handle @var{h}.  @var{reserved} should be specified as
-0.  This function is usually not required because @code{gcry_md_close}
-does implicitly stop debugging.
-@end deftypefun
+This is used to check whether the signature @var{sig} matches the
+@var{data}.  The public key @var{pkey} must be provided to perform this
+verification.  This function is similar in its parameters to
+@code{gcry_pk_sign} with the exceptions that the public key is used
+instead of the private key and that no signature is created but a
+signature, in a format as created by @code{gcry_pk_sign}, is passed to
+the function in @var{sig}.
 
 
+@noindent
+The result is 0 for success (i.e. the data matches the signature), or an
+error code where the most relevant code is @code{GCRYERR_BAD_SIGNATURE}
+to indicate that the signature does not match the provided data.
 
 
-@c **********************************************************
-@c *******************  Public Key  *************************
-@c **********************************************************
-@node Public Key cryptography (I)
-@chapter Public Key cryptography (I)
+@end deftypefun
+@c end gcry_pk_verify
 
 
-Public key cryptography, also known as asymmetric cryptography, is an
-easy way for key management and to provide digital signatures.
-Libgcrypt provides two completely different interfaces to
-public key cryptography, this chapter explains the one based on
-S-expressions.
+@node General public-key related Functions
+@section General public-key related Functions
 
 
-@menu
-* Available algorithms::        Algorithms supported by the library.
-* Used S-expressions::          Introduction into the used S-expression.
-* Public key modules::          How to work with public key modules.
-* Cryptographic Functions::     Functions for performing the cryptographic actions.
-* General public-key related Functions::  General functions, not implementing any cryptography.
-@end menu
+@noindent
+A couple of utility functions are available to retrieve the length of
+the key, map algorithm identifiers and perform sanity checks:
 
 
-@node Available algorithms
-@section Available algorithms
+@deftypefun {const char *} gcry_pk_algo_name (int @var{algo})
 
 
-Libgcrypt supports the RSA (Rivest-Shamir-Adleman) algorithms as well
-as DSA (Digital Signature Algorithm) and Elgamal.  The versatile
-interface allows to add more algorithms in the future.
+Map the public key algorithm id @var{algo} to a string representation of
+the algorithm name.  For unknown algorithms this functions returns the
+string @code{"?"}.  This function should not be used to test for the
+availability of an algorithm.
+@end deftypefun
 
 
-@node Used S-expressions
-@section Used S-expressions
+@deftypefun int gcry_pk_map_name (const char *@var{name})
 
 
-Libgcrypt's API for asymmetric cryptography is based on data structures
-called S-expressions (see
-@uref{http://people.csail.mit.edu/@/rivest/@/sexp.html}) and does not work
-with contexts as most of the other building blocks of Libgcrypt do.
+Map the algorithm @var{name} to a public key algorithm Id.  Returns 0 if
+the algorithm name is not known.
+@end deftypefun
 
 
-The following information are stored in S-expressions:
+@deftypefun int gcry_pk_test_algo (int @var{algo})
 
 
-@table @asis
-@item keys
+Return 0 if the public key algorithm @var{algo} is available for use.
+Note that this is implemented as a macro.
+@end deftypefun
 
 
-@item plain text data
 
 
-@item encrypted data
+@deftypefun {unsigned int} gcry_pk_get_nbits (gcry_sexp_t @var{key})
 
 
-@item signatures
+Return what is commonly referred as the key length for the given
+public or private in @var{key}.
+@end deftypefun
 
 
-@end table
+@deftypefun {unsigned char *} gcry_pk_get_keygrip (@w{gcry_sexp_t @var{key}}, @w{unsigned char *@var{array}})
 
 
-@noindent
-To describe how Libgcrypt expect keys, we use examples. Note that
-words in
-@ifnottex
-uppercase
-@end ifnottex
-@iftex
-italics
-@end iftex
-indicate parameters whereas lowercase words are literals.
-
-Note that all MPI (big integer) values are expected to be in
-@code{GCRYMPI_FMT_USG} format.  An easy way to create S-expressions is
-by using @code{gcry_sexp_build} which allows to pass a string with
-printf-like escapes to insert MPI values.
+Return the so called "keygrip" which is the SHA-1 hash of the public key
+parameters expressed in a way depended on the algorithm.  @var{array}
+must either provide space for 20 bytes or be @code{NULL}. In the latter
+case a newly allocated array of that size is returned.  On success a
+pointer to the newly allocated space or to @var{array} is returned.
+@code{NULL} is returned to indicate an error which is most likely an
+unknown algorithm or one where a "keygrip" has not yet been defined.
+The function accepts public or secret keys in @var{key}.
+@end deftypefun
 
 
-@menu
-* RSA key parameters::  Parameters used with an RSA key.
-* DSA key parameters::  Parameters used with a DSA key.
-* ECC key parameters::  Parameters used with ECC keys.
-@end menu
+@deftypefun gcry_error_t gcry_pk_testkey (gcry_sexp_t @var{key})
 
 
-@node RSA key parameters
-@subsection RSA key parameters
+Return zero if the private key @var{key} is `sane', an error code otherwise.
+Note that it is not possible to check the `saneness' of a public key.
 
 
-@noindent
-An RSA private key is described by this S-expression:
+@end deftypefun
 
 
-@example
-(private-key
-  (rsa
-    (n @var{n-mpi})
-    (e @var{e-mpi})
-    (d @var{d-mpi})
-    (p @var{p-mpi})
-    (q @var{q-mpi})
-    (u @var{u-mpi})))
-@end example
 
 
-@noindent
-An RSA public key is described by this S-expression:
+@deftypefun gcry_error_t gcry_pk_algo_info (@w{int @var{algo}}, @w{int @var{what}}, @w{void *@var{buffer}}, @w{size_t *@var{nbytes}})
 
 
-@example
-(public-key
-  (rsa
-    (n @var{n-mpi})
-    (e @var{e-mpi})))
-@end example
+Depending on the value of @var{what} return various information about
+the public key algorithm with the id @var{algo}.  Note that the
+function returns @code{-1} on error and the actual error code must be
+retrieved using the function @code{gcry_errno}.  The currently defined
+values for @var{what} are:
 
 
+@table @code
+@item GCRYCTL_TEST_ALGO:
+Return 0 if the specified algorithm is available for use.
+@var{buffer} must be @code{NULL}, @var{nbytes} may be passed as
+@code{NULL} or point to a variable with the required usage of the
+algorithm. This may be 0 for "don't care" or the bit-wise OR of these
+flags:
 
 
-@table @var
-@item n-mpi
-RSA public modulus @math{n}.
-@item e-mpi
-RSA public exponent @math{e}.
-@item d-mpi
-RSA secret exponent @math{d = e^{-1} \bmod (p-1)(q-1)}.
-@item p-mpi
-RSA secret prime @math{p}.
-@item q-mpi
-RSA secret prime @math{q} with @math{p < q}.
-@item u-mpi
-Multiplicative inverse @math{u = p^{-1} \bmod q}.
+@table @code
+@item GCRY_PK_USAGE_SIGN 
+Algorithm is usable for signing.
+@item GCRY_PK_USAGE_ENCR 
+Algorithm is usable for encryption.
 @end table
 
 @end table
 
-For signing and decryption the parameters @math{(p, q, u)} are optional
-but greatly improve the performance.  Either all of these optional
-parameters must be given or none of them.  They are mandatory for
-gcry_pk_testkey.
-
-Note that OpenSSL uses slighly different parameters: @math{q < p} and 
- @math{u = q^{-1} \bmod p}.  To use these parameters you will need to
-swap the values and recompute @math{u}.  Here is example code to do this:
+Unless you need to test for the allowed usage, it is in general better
+to use the macro gcry_pk_test_algo instead.
 
 
-@example
-  if (gcry_mpi_cmp (p, q) > 0)
-    @{
-      gcry_mpi_swap (p, q);
-      gcry_mpi_invm (u, p, q);
-    @}
-@end example
+@item GCRYCTL_GET_ALGO_USAGE:
+Return the usage flags for the given algorithm.  An invalid algorithm
+return 0.  Disabled algorithms are ignored here because we
+want to know whether the algorithm is at all capable of a certain usage.
 
 
+@item GCRYCTL_GET_ALGO_NPKEY
+Return the number of elements the public key for algorithm @var{algo}
+consist of.  Return 0 for an unknown algorithm.
 
 
+@item GCRYCTL_GET_ALGO_NSKEY
+Return the number of elements the private key for algorithm @var{algo}
+consist of.  Note that this value is always larger than that of the
+public key.  Return 0 for an unknown algorithm.
 
 
+@item GCRYCTL_GET_ALGO_NSIGN
+Return the number of elements a signature created with the algorithm
+@var{algo} consists of.  Return 0 for an unknown algorithm or for an
+algorithm not capable of creating signatures.
 
 
-@node DSA key parameters
-@subsection DSA key parameters
+@item GCRYCTL_GET_ALGO_NENC
+Return the number of elements a encrypted message created with the algorithm
+@var{algo} consists of.  Return 0 for an unknown algorithm or for an
+algorithm not capable of encryption.
+@end table
 
 @noindent
 
 @noindent
-A DSA private key is described by this S-expression:
+Please note that parameters not required should be passed as @code{NULL}.
+@end deftypefun
+@c end gcry_pk_algo_info
 
 
-@example
-(private-key
-  (dsa
-    (p @var{p-mpi})
-    (q @var{q-mpi})
-    (g @var{g-mpi})
-    (y @var{y-mpi})
-    (x @var{x-mpi})))
-@end example
 
 
-@table @var
-@item p-mpi
-DSA prime @math{p}.
-@item q-mpi
-DSA group order @math{q} (which is a prime divisor of @math{p-1}).
-@item g-mpi
-DSA group generator @math{g}.
-@item y-mpi
-DSA public key value @math{y = g^x \bmod p}.
-@item x-mpi
-DSA secret exponent x.
-@end table
+@deftypefun gcry_error_t gcry_pk_ctl (@w{int @var{cmd}}, @w{void *@var{buffer}}, @w{size_t @var{buflen}})
 
 
-The public key is similar with "private-key" replaced by "public-key"
-and no @var{x-mpi}.
+This is a general purpose function to perform certain control
+operations.  @var{cmd} controls what is to be done. The return value is
+0 for success or an error code.  Currently supported values for
+@var{cmd} are:
 
 
+@table @code
+@item GCRYCTL_DISABLE_ALGO
+Disable the algorithm given as an algorithm id in @var{buffer}.
+@var{buffer} must point to an @code{int} variable with the algorithm id
+and @var{buflen} must have the value @code{sizeof (int)}.
 
 
-@node ECC key parameters
-@subsection ECC key parameters
+@end table
+@end deftypefun
+@c end gcry_pk_ctl
 
 @noindent
 
 @noindent
-An ECC private key is described by this S-expression:
-
-@example
-(private-key
-  (ecc
-    (p @var{p-mpi})
-    (a @var{a-mpi})
-    (b @var{b-mpi})
-    (g @var{g-point})
-    (n @var{n-mpi})
-    (q @var{q-point})
-    (d @var{d-mpi})))
-@end example
-
-@table @var
-@item p-mpi
-Prime specifying the field @math{GF(p)}.
-@item a-mpi
-@itemx b-mpi
-The two coefficients of the Weierstrass equation @math{y^2 = x^3 + ax + b}
-@item g-point
-Base point @math{g}.
-@item n-mpi
-Order of @math{g}
-@item q-point
-The point representing the public key @math{Q = dP}.
-@item d-mpi
-The private key @math{d}
-@end table
+Libgcrypt also provides a function for generating public key
+pairs:
 
 
-All point values are encoded in standard format; Libgcrypt does
-currently only support uncompressed points, thus the first byte needs to
-be @code{0x04}.
+@deftypefun gcry_error_t gcry_pk_genkey (@w{gcry_sexp_t *@var{r_key}}, @w{gcry_sexp_t @var{parms}})
 
 
-The public key is similar with "private-key" replaced by "public-key"
-and no @var{d-mpi}.
+This function create a new public key pair using information given in
+the S-expression @var{parms} and stores the private and the public key
+in one new S-expression at the address given by @var{r_key}.  In case of
+an error, @var{r_key} is set to @code{NULL}.  The return code is 0 for
+success or an error code otherwise.
 
 
-If the domain parameters are well-known, the name of this curve may be
-used.  For example
+@noindent
+Here is an example for @var{parms} for creating a 1024 bit RSA key:
 
 @example
 
 @example
-(private-key
-  (ecc
-    (curve "NIST P-192")
-    (q @var{q-point})
-    (d @var{d-mpi})))
+(genkey
+  (rsa
+    (nbits 4:1024)))
 @end example
 
 @end example
 
-The @code{curve} parameter may be given in any case and is used to replace
-missing parameters.
-
 @noindent
 @noindent
-Currently implemented curves are:
+To create an Elgamal key, substitute "elg" for "rsa" and to create a DSA
+key use "dsa".  Valid ranges for the key length depend on the
+algorithms; all commonly used key lengths are supported.  Currently
+supported parameters are:
+
 @table @code
 @table @code
-@item NIST P-192
-@itemx 1.2.840.10045.3.1.1
-@itemx prime192v1
-@itemx secp192r1
-The NIST 192 bit curve, its OID, X9.62 and SECP aliases.
+@item nbits
+This is always required to specify the length of the key.  The argument
+is a string with a number in C-notation.  The value should be a multiple
+of 8.
 
 
-@item NIST P-224
-@itemx secp224r1
-The NIST 224 bit curve and its SECP alias.
+@item curve @var{name}
+For ECC a named curve may be used instead of giving the number of
+requested bits.  This allows to request a specific curve to override a
+default selection Libgcrypt would have taken if @code{nbits} has been
+given.  The available names are listed with the description of the ECC
+public key parameters.
 
 
-@item NIST P-256
-@itemx 1.2.840.10045.3.1.7
-@itemx prime256v1
-@itemx secp256r1
-The NIST 256 bit curve, its OID, X9.62 and SECP aliases.
+@item rsa-use-e
+This is only used with RSA to give a hint for the public exponent. The
+value will be used as a base to test for a usable exponent. Some values
+are special:
 
 
-@item NIST P-384
-@itemx secp384r1
-The NIST 384 bit curve and its SECP alias.
+@table @samp
+@item 0
+Use a secure and fast value.  This is currently the number 41.
+@item 1
+Use a secure value as required by some specification.  This is currently
+the number 65537.
+@item 2
+Reserved
+@end table
 
 
-@item NIST P-521
-@itemx secp521r1
-The NIST 521 bit curve and its SECP alias.
+@noindent
+If this parameter is not used, 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
+@item N = 15360
+Q = 512
 @end table
 @end table
-As usual the OIDs may optionally be prefixed with the string @code{OID.}
-or @code{oid.}.
+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
 
 
+@noindent
+The key pair is returned in a format depending on the algorithm.  Both
+private and public keys are returned in one container and may be
+accompanied by some miscellaneous information.
 
 
-@node Public key modules
-@section Public key modules
+@noindent
+As an example, here is what the Elgamal key generation returns:
 
 
-Libgcrypt makes it possible to load additional `public key
-modules'; these public key algorithms can be used just like the
-algorithms that are built into the library directly.  For an
-introduction into extension modules, see @xref{Modules}.
+@example
+(key-data
+  (public-key
+    (elg
+      (p @var{p-mpi})
+      (g @var{g-mpi})
+      (y @var{y-mpi})))
+  (private-key
+    (elg
+      (p @var{p-mpi})
+      (g @var{g-mpi})
+      (y @var{y-mpi})
+      (x @var{x-mpi})))
+  (misc-key-info
+    (pm1-factors @var{n1 n2 ... nn})))
+@end example
 
 
-@deftp {Data type} gcry_pk_spec_t
-This is the `module specification structure' needed for registering
-public key modules, which has to be filled in by the user before it
-can be used to register a module.  It contains the following members:
+@noindent
+As you can see, some of the information is duplicated, but this provides
+an easy way to extract either the public or the private key.  Note that
+the order of the elements is not defined, e.g. the private key may be
+stored before the public key. @var{n1 n2 ... nn} is a list of prime
+numbers used to composite @var{p-mpi}; this is in general not a very
+useful information.
+@end deftypefun
+@c end gcry_pk_genkey
 
 
-@table @code
-@item const char *name
-The primary name of this algorithm.
-@item char **aliases
-A list of strings that are `aliases' for the algorithm.  The list
-must be terminated with a NULL element.
-@item const char *elements_pkey
-String containing the one-letter names of the MPI values contained in
-a public key.
-@item const char *element_skey
-String containing the one-letter names of the MPI values contained in
-a secret key.
-@item const char *elements_enc
-String containing the one-letter names of the MPI values that are the
-result of an encryption operation using this algorithm.
-@item const char *elements_sig
-String containing the one-letter names of the MPI values that are the
-result of a sign operation using this algorithm.
-@item const char *elements_grip
-String containing the one-letter names of the MPI values that are to
-be included in the `key grip'.
-@item int use
-The bitwise-OR of the following flags, depending on the abilities of
-the algorithm:
-@table @code
-@item GCRY_PK_USAGE_SIGN
-The algorithm supports signing and verifying of data.
-@item GCRY_PK_USAGE_ENCR
-The algorithm supports the encryption and decryption of data.
-@end table
-@item gcry_pk_generate_t generate
-The function responsible for generating a new key pair.  See below for
-a description of this type.
-@item gcry_pk_check_secret_key_t check_secret_key
-The function responsible for checking the sanity of a provided secret
-key.  See below for a description of this type.
-@item gcry_pk_encrypt_t encrypt
-The function responsible for encrypting data.  See below for a
-description of this type.
-@item gcry_pk_decrypt_t decrypt
-The function responsible for decrypting data.  See below for a
-description of this type.
-@item gcry_pk_sign_t sign
-The function responsible for signing data.  See below for a description
-of this type.
-@item gcry_pk_verify_t verify
-The function responsible for verifying that the provided signature
-matches the provided data.  See below for a description of this type.
-@item gcry_pk_get_nbits_t get_nbits
-The function responsible for returning the number of bits of a provided
-key.  See below for a description of this type.
-@end table
-@end deftp
+@node AC Interface
+@section Alternative Public Key Interface
 
 
-@deftp {Data type} gcry_pk_generate_t
-Type for the `generate' function, defined as: gcry_err_code_t
-(*gcry_pk_generate_t) (int algo, unsigned int nbits, unsigned long
-use_e, gcry_mpi_t *skey, gcry_mpi_t **retfactors)
-@end deftp
+This section documents the alternative interface to asymmetric
+cryptography (ac) that is not based on S-expressions, but on native C
+data structures.  As opposed to the pk interface described in the
+former chapter, this one follows an open/use/close paradigm like other
+building blocks of the library.
 
 
-@deftp {Data type} gcry_pk_check_secret_key_t
-Type for the `check_secret_key' function, defined as: gcry_err_code_t
-(*gcry_pk_check_secret_key_t) (int algo, gcry_mpi_t *skey)
-@end deftp
+@strong{This interface has a few known problems; most noteworthy an
+inherent tendency to leak memory.  It might not be available in
+forthcoming versions Libgcrypt.}
 
 
-@deftp {Data type} gcry_pk_encrypt_t
-Type for the `encrypt' function, defined as: gcry_err_code_t
-(*gcry_pk_encrypt_t) (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
-gcry_mpi_t *pkey, int flags)
-@end deftp
 
 
-@deftp {Data type} gcry_pk_decrypt_t
-Type for the `decrypt' function, defined as: gcry_err_code_t
-(*gcry_pk_decrypt_t) (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
-gcry_mpi_t *skey, int flags)
-@end deftp
+@menu
+* Available asymmetric algorithms::  List of algorithms supported by the library.
+* Working with sets of data::   How to work with sets of data.
+* Working with IO objects::     How to work with IO objects.
+* Working with handles::        How to use handles.
+* Working with keys::           How to work with keys.
+* Using cryptographic functions::  How to perform cryptographic operations.
+* Handle-independent functions::  General functions independent of handles.
+@end menu
 
 
-@deftp {Data type} gcry_pk_sign_t
-Type for the `sign' function, defined as: gcry_err_code_t
-(*gcry_pk_sign_t) (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
-gcry_mpi_t *skey)
-@end deftp
+@node Available asymmetric algorithms
+@subsection Available asymmetric algorithms
 
 
-@deftp {Data type} gcry_pk_verify_t
-Type for the `verify' function, defined as: gcry_err_code_t
-(*gcry_pk_verify_t) (int algo, gcry_mpi_t hash, gcry_mpi_t *data,
-gcry_mpi_t *pkey, int (*cmp) (void *, gcry_mpi_t), void *opaquev)
-@end deftp
+Libgcrypt supports the RSA (Rivest-Shamir-Adleman)
+algorithms as well as DSA (Digital Signature Algorithm) and Elgamal.
+The versatile interface allows to add more algorithms in the future.
 
 
-@deftp {Data type} gcry_pk_get_nbits_t
-Type for the `get_nbits' function, defined as: unsigned
-(*gcry_pk_get_nbits_t) (int algo, gcry_mpi_t *pkey)
-@end deftp
+@deftp {Data type} gcry_ac_id_t
 
 
-@deftypefun gcry_error_t gcry_pk_register (gcry_pk_spec_t *@var{pubkey}, unsigned int *algorithm_id, gcry_module_t *@var{module})
+The following constants are defined for this type:
 
 
-Register a new public key module whose specification can be found in
-@var{pubkey}.  On success, a new algorithm ID is stored in
-@var{algorithm_id} and a pointer representing this module is stored
-in @var{module}.
-@end deftypefun
+@table @code
+@item GCRY_AC_RSA
+Rivest-Shamir-Adleman
+@item GCRY_AC_DSA
+Digital Signature Algorithm
+@item GCRY_AC_ELG
+Elgamal
+@item GCRY_AC_ELG_E
+Elgamal, encryption only.
+@end table
+@end deftp
 
 
-@deftypefun void gcry_pk_unregister (gcry_module_t @var{module})
-Unregister the public key module identified by @var{module}, which
-must have been registered with gcry_pk_register.
-@end deftypefun
+@node Working with sets of data
+@subsection Working with sets of data
 
 
-@deftypefun gcry_error_t gcry_pk_list (int *@var{list}, int *@var{list_length})
-Get a list consisting of the IDs of the loaded pubkey modules.  If
-@var{list} is zero, write the number of loaded pubkey modules to
-@var{list_length} and return.  If @var{list} is non-zero, the first
-*@var{list_length} algorithm IDs are stored in @var{list}, which must
-be of according size.  In case there are less pubkey modules than
-*@var{list_length}, *@var{list_length} is updated to the correct
-number.
-@end deftypefun
+In the context of this interface the term `data set' refers to a list
+of `named MPI values' that is used by functions performing
+cryptographic operations; a named MPI value is a an MPI value,
+associated with a label.
 
 
-@node Cryptographic Functions
-@section Cryptographic Functions
+Such data sets are used for representing keys, since keys simply
+consist of a variable amount of numbers.  Furthermore some functions
+return data sets to the caller that are to be provided to other
+functions.
 
 
-@noindent
-Note that we will in future allow to use keys without p,q and u
-specified and may also support other parameters for performance
-reasons. 
+This section documents the data types, symbols and functions that are
+relevant for working with data sets.
 
 
-@noindent
+@deftp {Data type} gcry_ac_data_t
+A single data set.
+@end deftp
 
 
-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:
+The following flags are supported:
 
 @table @code
 
 @table @code
-@item pkcs1
-Use PKCS#1 block type 2 padding.
-@item no-blinding
-Do not use a technique called `blinding', which is used by default in
-order to prevent leaking of secret information.  Blinding is only
-implemented by RSA, but it might be implemented by other algorithms in
-the future as well, when necessary.
-@end table
-
-@noindent
-Now that we know the key basics, we can carry on and explain how to
-encrypt and decrypt data.  In almost all cases the data is a random
-session key which is in turn used for the actual encryption of the real
-data.  There are 2 functions to do this:
-
-@deftypefun gcry_error_t gcry_pk_encrypt (@w{gcry_sexp_t *@var{r_ciph},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{pkey}})
+@item GCRY_AC_FLAG_DEALLOC
+Used for storing data in a data set.  If given, the data will be
+released by the library.  Note that whenever one of the ac functions
+is about to release objects because of this flag, the objects are
+expected to be stored in memory allocated through the Libgcrypt memory
+management.  In other words: gcry_free() is used instead of free().
 
 
-Obviously a public key must be provided for encryption.  It is
-expected as an appropriate S-expression (see above) in @var{pkey}.
-The data to be encrypted can either be in the simple old format, which
-is a very simple S-expression consisting only of one MPI, or it may be
-a more complex S-expression which also allows to specify flags for
-operation, like e.g. padding rules.
+@item GCRY_AC_FLAG_COPY
+Used for storing/retrieving data in/from a data set.  If given, the
+library will create copies of the provided/contained data, which will
+then be given to the user/associated with the data set.
+@end table
 
 
-@noindent
-If you don't want to let Libgcrypt handle the padding, you must pass an
-appropriate MPI using this expression for @var{data}:
+@deftypefun gcry_error_t gcry_ac_data_new (gcry_ac_data_t *@var{data})
+Creates a new, empty data set and stores it in @var{data}.
+@end deftypefun
 
 
-@example 
-(data
-  (flags raw)
-  (value @var{mpi}))
-@end example
+@deftypefun void gcry_ac_data_destroy (gcry_ac_data_t @var{data})
+Destroys the data set @var{data}.
+@end deftypefun
 
 
-@noindent
-This has the same semantics as the old style MPI only way.  @var{MPI} is
-the actual data, already padded appropriate for your protocol.  Most
-systems however use PKCS#1 padding and so you can use this S-expression
-for @var{data}:
+@deftypefun gcry_error_t gcry_ac_data_set (gcry_ac_data_t @var{data}, unsigned int @var{flags}, char *@var{name}, gcry_mpi_t @var{mpi})
+Add the value @var{mpi} to @var{data} with the label @var{name}.  If
+@var{flags} contains GCRY_AC_FLAG_COPY, the data set will contain
+copies of @var{name} and @var{mpi}.  If @var{flags} contains
+GCRY_AC_FLAG_DEALLOC or GCRY_AC_FLAG_COPY, the values
+contained in the data set will be deallocated when they are to be
+removed from the data set.
+@end deftypefun
 
 
-@example 
-(data
-  (flags pkcs1)
-  (value @var{block}))
-@end example
+@deftypefun gcry_error_t gcry_ac_data_copy (gcry_ac_data_t *@var{data_cp}, gcry_ac_data_t @var{data})
+Create a copy of the data set @var{data} and store it in
+@var{data_cp}.  FIXME: exact semantics undefined.
+@end deftypefun
 
 
-@noindent
-Here, the "flags" list has the "pkcs1" flag which let the function know
-that it should provide PKCS#1 block type 2 padding.  The actual data to
-be encrypted is passed as a string of octets in @var{block}.  The
-function checks that this data actually can be used with the given key,
-does the padding and encrypts it.
+@deftypefun unsigned int gcry_ac_data_length (gcry_ac_data_t @var{data})
+Returns the number of named MPI values inside of the data set
+@var{data}.
+@end deftypefun
 
 
-If the function could successfully perform the encryption, the return
-value will be 0 and a a new S-expression with the encrypted result is
-allocated and assigned to the variable at the address of @var{r_ciph}.
-The caller is responsible to release this value using
-@code{gcry_sexp_release}.  In case of an error, an error code is
-returned and @var{r_ciph} will be set to @code{NULL}.
+@deftypefun gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t @var{data}, unsigned int @var{flags}, char *@var{name}, gcry_mpi_t *@var{mpi})
+Store the value labelled with @var{name} found in @var{data} in
+@var{mpi}.  If @var{flags} contains GCRY_AC_FLAG_COPY, store a copy of
+the @var{mpi} value contained in the data set.  @var{mpi} may be NULL
+(this might be useful for checking the existence of an MPI with
+extracting it).
+@end deftypefun
 
 
-@noindent
-The returned S-expression has this format when used with RSA:
+@deftypefun gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t @var{data}, unsigned int flags, unsigned int @var{index}, const char **@var{name}, gcry_mpi_t *@var{mpi})
+Stores in @var{name} and @var{mpi} the named @var{mpi} value contained
+in the data set @var{data} with the index @var{idx}.  If @var{flags}
+contains GCRY_AC_FLAG_COPY, store copies of the values contained in
+the data set. @var{name} or @var{mpi} may be NULL.
+@end deftypefun
 
 
-@example
-(enc-val
-  (rsa
-    (a @var{a-mpi})))
-@end example
+@deftypefun void gcry_ac_data_clear (gcry_ac_data_t @var{data})
+Destroys any values contained in the data set @var{data}.
+@end deftypefun
 
 
-@noindent
-Where @var{a-mpi} is an MPI with the result of the RSA operation.  When
-using the Elgamal algorithm, the return value will have this format:
+@deftypefun gcry_error_t gcry_ac_data_to_sexp (gcry_ac_data_t @var{data}, gcry_sexp_t *@var{sexp}, const char **@var{identifiers})
+This function converts the data set @var{data} into a newly created
+S-Expression, which is to be stored in @var{sexp}; @var{identifiers}
+is a NULL terminated list of C strings, which specifies the structure
+of the S-Expression.
 
 
-@example
-(enc-val
-  (elg
-    (a @var{a-mpi})
-    (b @var{b-mpi})))
-@end example
+Example:
 
 
-@noindent
-Where @var{a-mpi} and @var{b-mpi} are MPIs with the result of the
-Elgamal encryption operation.
+If @var{identifiers} is a list of pointers to the strings ``foo'' and
+``bar'' and if @var{data} is a data set containing the values ``val1 =
+0x01'' and ``val2 = 0x02'', then the resulting S-Expression will look
+like this: (foo (bar ((val1 0x01) (val2 0x02))).
 @end deftypefun
 @end deftypefun
-@c end gcry_pk_encrypt
 
 
-@deftypefun gcry_error_t gcry_pk_decrypt (@w{gcry_sexp_t *@var{r_plain},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{skey}})
-
-Obviously a private key must be provided for decryption.  It is expected
-as an appropriate S-expression (see above) in @var{skey}.  The data to
-be decrypted must match the format of the result as returned by
-@code{gcry_pk_encrypt}, but should be enlarged with a @code{flags}
-element:
+@deftypefun gcry_error gcry_ac_data_from_sexp (gcry_ac_data_t *@var{data}, gcry_sexp_t @var{sexp}, const char **@var{identifiers})
+This function converts the S-Expression @var{sexp} into a newly
+created data set, which is to be stored in @var{data};
+@var{identifiers} is a NULL terminated list of C strings, which
+specifies the structure of the S-Expression.  If the list of
+identifiers does not match the structure of the S-Expression, the
+function fails.
+@end deftypefun
 
 
-@example
-(enc-val
-  (flags)
-  (elg
-    (a @var{a-mpi})
-    (b @var{b-mpi})))
-@end example
+@node Working with IO objects
+@subsection Working with IO objects
 
 
-@noindent
-Note that this function currently does not know of any padding
-methods and the caller must do any un-padding on his own.
+Note: IO objects are currently only used in the context of message
+encoding/decoding and encryption/signature schemes.
 
 
-@noindent
-The function returns 0 on success or an error code.  The variable at the
-address of @var{r_plain} will be set to NULL on error or receive the
-decrypted value on success.  The format of @var{r_plain} is a
-simple S-expression part (i.e. not a valid one) with just one MPI if
-there was no @code{flags} element in @var{data}; if at least an empty
-@code{flags} is passed in @var{data}, the format is:
+@deftp {Data type} {gcry_ac_io_t}
+@code{gcry_ac_io_t} is the type to be used for IO objects.
+@end deftp
 
 
-@example
-(value @var{plaintext})
-@end example
-@end deftypefun
-@c end gcry_pk_decrypt
+IO objects provide an uniform IO layer on top of different underlying
+IO mechanisms; either they can be used for providing data to the
+library (mode is GCRY_AC_IO_READABLE) or they can be used for
+retrieving data from the library (mode is GCRY_AC_IO_WRITABLE).
 
 
+IO object need to be initialized by calling on of the following
+functions:
 
 
-Another operation commonly performed using public key cryptography is
-signing data.  In some sense this is even more important than
-encryption because digital signatures are an important instrument for
-key management.  Libgcrypt supports digital signatures using
-2 functions, similar to the encryption functions:
+@deftypefun void gcry_ac_io_init (gcry_ac_io_t *@var{ac_io}, gcry_ac_io_mode_t @var{mode}, gcry_ac_io_type_t @var{type}, ...);
+Initialize @var{ac_io} according to @var{mode}, @var{type} and the
+variable list of arguments.  The list of variable arguments to specify
+depends on the given @var{type}.
+@end deftypefun
 
 
-@deftypefun gcry_error_t gcry_pk_sign (@w{gcry_sexp_t *@var{r_sig},} @w{gcry_sexp_t @var{data},} @w{gcry_sexp_t @var{skey}})
+@deftypefun void gcry_ac_io_init_va (gcry_ac_io_t *@var{ac_io}, gcry_ac_io_mode_t @var{mode}, gcry_ac_io_type_t @var{type}, va_list @var{ap});
+Initialize @var{ac_io} according to @var{mode}, @var{type} and the
+variable list of arguments @var{ap}.  The list of variable arguments
+to specify depends on the given @var{type}.
+@end deftypefun
 
 
-This function creates a digital signature for @var{data} using the
-private key @var{skey} and place it into the variable at the address of
-@var{r_sig}.  @var{data} may either be the simple old style S-expression
-with just one MPI or a modern and more versatile S-expression which
-allows to let Libgcrypt handle padding:
+The following types of IO objects exist:
 
 
-@example 
- (data
-  (flags pkcs1)
-  (hash @var{hash-algo} @var{block}))
-@end example
+@table @code
+@item GCRY_AC_IO_STRING
+In case of GCRY_AC_IO_READABLE the IO object will provide data from a
+memory string.  Arguments to specify at initialization time:
+@table @code
+@item unsigned char *
+Pointer to the beginning of the memory string
+@item size_t
+Size of the memory string
+@end table
+In case of GCRY_AC_IO_WRITABLE the object will store retrieved data in
+a newly allocated memory string.  Arguments to specify at
+initialization time:
+@table @code
+@item unsigned char **
+Pointer to address, at which the pointer to the newly created memory
+string is to be stored
+@item size_t *
+Pointer to address, at which the size of the newly created memory
+string is to be stored
+@end table
 
 
-@noindent
-This example requests to sign the data in @var{block} after applying
-PKCS#1 block type 1 style padding.  @var{hash-algo} is a string with the
-hash algorithm to be encoded into the signature, this may be any hash
-algorithm name as supported by Libgcrypt.  Most likely, this will be
-"sha1", "rmd160" or "md5".  It is obvious that the length of @var{block}
-must match the size of that message digests; the function checks that
-this and other constraints are valid.
+@item GCRY_AC_IO_CALLBACK
+In case of GCRY_AC_IO_READABLE the object will forward read requests
+to a provided callback function.  Arguments to specify at
+initialization time:
+@table @code
+@item gcry_ac_data_read_cb_t
+Callback function to use
+@item void *
+Opaque argument to provide to the callback function
+@end table
+In case of GCRY_AC_IO_WRITABLE the object will forward write requests
+to a provided callback function.  Arguments to specify at
+initialization time:
+@table @code
+@item gcry_ac_data_write_cb_t
+Callback function to use
+@item void *
+Opaque argument to provide to the callback function
+@end table
+@end table
 
 
-@noindent
-If PKCS#1 padding is not required (because the caller does already
-provide a padded value), either the old format or better the following
-format should be used:
+@node Working with handles
+@subsection Working with handles
 
 
-@example
-(data
-  (flags raw)
-  (value @var{mpi}))
-@end example
+In order to use an algorithm, an according handle must be created.
+This is done using the following function:
 
 
-@noindent
-Here, the data to be signed is directly given as an @var{MPI}.
+@deftypefun gcry_error_t gcry_ac_open (gcry_ac_handle_t *@var{handle}, int @var{algorithm}, int @var{flags})
 
 
-@noindent
-The signature is returned as a newly allocated S-expression in
-@var{r_sig} using this format for RSA:
+Creates a new handle for the algorithm @var{algorithm} and stores it
+in @var{handle}.  @var{flags} is not used currently.
 
 
-@example
-(sig-val
-  (rsa
-    (s @var{s-mpi})))
-@end example
+@var{algorithm} must be a valid algorithm ID, see @xref{Available
+asymmetric algorithms}, for a list of supported algorithms and the
+according constants.  Besides using the listed constants directly, the
+functions @code{gcry_pk_name_to_id} may be used to convert the textual
+name of an algorithm into the according numeric ID.
+@end deftypefun
 
 
-Where @var{s-mpi} is the result of the RSA sign operation.  For DSA the
-S-expression returned is:
+@deftypefun void gcry_ac_close (gcry_ac_handle_t @var{handle})
+Destroys the handle @var{handle}.
+@end deftypefun
 
 
-@example
-(sig-val
-  (dsa
-    (r @var{r-mpi})
-    (s @var{s-mpi})))
-@end example
+@node Working with keys
+@subsection Working with keys
 
 
-Where @var{r-mpi} and @var{s-mpi} are the result of the DSA sign
-operation.  For Elgamal signing (which is slow, yields large numbers
-and probably is not as secure as the other algorithms), the same format is
-used with "elg" replacing "dsa".
-@end deftypefun
-@c end gcry_pk_sign
+@deftp {Data type} gcry_ac_key_type_t
+Defined constants:
 
 
-@noindent
-The operation most commonly used is definitely the verification of a
-signature.  Libgcrypt provides this function:
+@table @code
+@item GCRY_AC_KEY_SECRET
+Specifies a secret key.
+@item GCRY_AC_KEY_PUBLIC
+Specifies a public key.
+@end table
+@end deftp
 
 
-@deftypefun gcry_error_t gcry_pk_verify (@w{gcry_sexp_t @var{sig}}, @w{gcry_sexp_t @var{data}}, @w{gcry_sexp_t @var{pkey}})
+@deftp {Data type} gcry_ac_key_t
+This type represents a single `key', either a secret one or a public
+one.
+@end deftp
 
 
-This is used to check whether the signature @var{sig} matches the
-@var{data}.  The public key @var{pkey} must be provided to perform this
-verification.  This function is similar in its parameters to
-@code{gcry_pk_sign} with the exceptions that the public key is used
-instead of the private key and that no signature is created but a
-signature, in a format as created by @code{gcry_pk_sign}, is passed to
-the function in @var{sig}.
+@deftp {Data type} gcry_ac_key_pair_t
+This type represents a `key pair' containing a secret and a public key.
+@end deftp
 
 
-@noindent
-The result is 0 for success (i.e. the data matches the signature), or an
-error code where the most relevant code is @code{GCRYERR_BAD_SIGNATURE}
-to indicate that the signature does not match the provided data.
+Key data structures can be created in two different ways; a new key
+pair can be generated, resulting in ready-to-use key.  Alternatively a
+key can be initialized from a given data set.
 
 
+@deftypefun gcry_error_t gcry_ac_key_init (gcry_ac_key_t *@var{key}, gcry_ac_handle_t @var{handle}, gcry_ac_key_type_t @var{type}, gcry_ac_data_t @var{data})
+Creates a new key of type @var{type}, consisting of the MPI values
+contained in the data set @var{data} and stores it in @var{key}.
 @end deftypefun
 @end deftypefun
-@c end gcry_pk_verify
 
 
-@node General public-key related Functions
-@section General public-key related Functions
+@deftypefun gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t @var{handle}, unsigned int @var{nbits}, void *@var{key_spec}, gcry_ac_key_pair_t *@var{key_pair}, gcry_mpi_t **@var{misc_data})
 
 
-@noindent
-A couple of utility functions are available to retrieve the length of
-the key, map algorithm identifiers and perform sanity checks:
+Generates a new key pair via the handle @var{handle} of @var{NBITS}
+bits and stores it in @var{key_pair}.
 
 
-@deftypefun {const char *} gcry_pk_algo_name (int @var{algo})
+In case non-standard settings are wanted, a pointer to a structure of
+type @code{gcry_ac_key_spec_<algorithm>_t}, matching the selected
+algorithm, can be given as @var{key_spec}.  @var{misc_data} is not
+used yet.  Such a structure does only exist for RSA.  A description
+of the members of the supported structures follows.
 
 
-Map the public key algorithm id @var{algo} to a string representation of
-the algorithm name.  For unknown algorithms this functions returns the
-string @code{"?"}.  This function should not be used to test for the
-availability of an algorithm.
-@end deftypefun
+@table @code
+@item gcry_ac_key_spec_rsa_t
+@table @code
+@item gcry_mpi_t e
+Generate the key pair using a special @code{e}.  The value of @code{e}
+has the following meanings:
+@table @code
+@item = 0
+Let Libgcrypt decide what exponent should be used.
+@item = 1
+Request the use of a ``secure'' exponent; this is required by some
+specification to be 65537.
+@item > 2
+Try starting at this value until a working exponent is found.  Note
+that the current implementation leaks some information about the
+private key because the incrementation used is not randomized.  Thus,
+this function will be changed in the future to return a random
+exponent of the given size.
+@end table
+@end table
+@end table
 
 
-@deftypefun int gcry_pk_map_name (const char *@var{name})
+Example code:
+@example
+@{
+  gcry_ac_key_pair_t key_pair;
+  gcry_ac_key_spec_rsa_t rsa_spec;
 
 
-Map the algorithm @var{name} to a public key algorithm Id.  Returns 0 if
-the algorithm name is not known.
-@end deftypefun
+  rsa_spec.e = gcry_mpi_new (0);
+  gcry_mpi_set_ui (rsa_spec.e, 1);
 
 
-@deftypefun int gcry_pk_test_algo (int @var{algo})
+  err = gcry_ac_open  (&handle, GCRY_AC_RSA, 0);
+  assert (! err);
 
 
-Return 0 if the public key algorithm @var{algo} is available for use.
-Note that this is implemented as a macro.
+  err = gcry_ac_key_pair_generate (handle, 1024, &rsa_spec, &key_pair, NULL);
+  assert (! err);
+@}
+@end example
 @end deftypefun
 
 
 @end deftypefun
 
 
-@deftypefun {unsigned int} gcry_pk_get_nbits (gcry_sexp_t @var{key})
-
-Return what is commonly referred as the key length for the given
-public or private in @var{key}.
+@deftypefun gcry_ac_key_t gcry_ac_key_pair_extract (gcry_ac_key_pair_t @var{key_pair}, gcry_ac_key_type_t @var{which})
+Returns the key of type @var{which} out of the key pair
+@var{key_pair}.
 @end deftypefun
 
 @end deftypefun
 
-@deftypefun {unsigned char *} gcry_pk_get_keygrip (@w{gcry_sexp_t @var{key}}, @w{unsigned char *@var{array}})
-
-Return the so called "keygrip" which is the SHA-1 hash of the public key
-parameters expressed in a way depended on the algorithm.  @var{array}
-must either provide space for 20 bytes or be @code{NULL}. In the latter
-case a newly allocated array of that size is returned.  On success a
-pointer to the newly allocated space or to @var{array} is returned.
-@code{NULL} is returned to indicate an error which is most likely an
-unknown algorithm or one where a "keygrip" has not yet been defined.
-The function accepts public or secret keys in @var{key}.
+@deftypefun void gcry_ac_key_destroy (gcry_ac_key_t @var{key})
+Destroys the key @var{key}.
 @end deftypefun
 
 @end deftypefun
 
-@deftypefun gcry_error_t gcry_pk_testkey (gcry_sexp_t @var{key})
+@deftypefun void gcry_ac_key_pair_destroy (gcry_ac_key_pair_t @var{key_pair})
+Destroys the key pair @var{key_pair}.
+@end deftypefun
 
 
-Return zero if the private key @var{key} is `sane', an error code otherwise.
-Note that it is not possible to check the `saneness' of a public key.
+@deftypefun gcry_ac_data_t gcry_ac_key_data_get (gcry_ac_key_t @var{key})
+Returns the data set contained in the key @var{key}.
+@end deftypefun
 
 
+@deftypefun gcry_error_t gcry_ac_key_test (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key})
+Verifies that the private key @var{key} is sane via @var{handle}.
 @end deftypefun
 
 @end deftypefun
 
+@deftypefun gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, unsigned int *@var{nbits})
+Stores the number of bits of the key @var{key} in @var{nbits} via @var{handle}.
+@end deftypefun
 
 
-@deftypefun gcry_error_t gcry_pk_algo_info (@w{int @var{algo}}, @w{int @var{what}}, @w{void *@var{buffer}}, @w{size_t *@var{nbytes}})
+@deftypefun gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, unsigned char *@var{key_grip})
+Writes the 20 byte long key grip of the key @var{key} to
+@var{key_grip} via @var{handle}.
+@end deftypefun
 
 
-Depending on the value of @var{what} return various information about
-the public key algorithm with the id @var{algo}.  Note that the
-function returns @code{-1} on error and the actual error code must be
-retrieved using the function @code{gcry_errno}.  The currently defined
-values for @var{what} are:
+@node Using cryptographic functions
+@subsection Using cryptographic functions
 
 
-@table @code
-@item GCRYCTL_TEST_ALGO:
-Return 0 when the specified algorithm is available for use.
-@var{buffer} must be @code{NULL}, @var{nbytes} may be passed as
-@code{NULL} or point to a variable with the required usage of the
-algorithm. This may be 0 for "don't care" or the bit-wise OR of these
-flags:
+The following flags might be relevant:
 
 @table @code
 
 @table @code
-@item GCRY_PK_USAGE_SIGN 
-Algorithm is usable for signing.
-@item GCRY_PK_USAGE_ENCR 
-Algorithm is usable for encryption.
+@item GCRY_AC_FLAG_NO_BLINDING
+Disable any blinding, which might be supported by the chosen
+algorithm; blinding is the default.
 @end table
 
 @end table
 
-@item GCRYCTL_GET_ALGO_USAGE:
-Return the usage flags for the given algorithm.  An invalid algorithm
-return 0.  Disabled algorithms are ignored here because we
-want to know whether the algorithm is at all capable of a certain usage.
+There exist two kinds of cryptographic functions available through the
+ac interface: primitives, and high-level functions.
 
 
-@item GCRYCTL_GET_ALGO_NPKEY
-Return the number of elements the public key for algorithm @var{algo}
-consist of.  Return 0 for an unknown algorithm.
+Primitives deal with MPIs (data sets) directly; what they provide is
+direct access to the cryptographic operations provided by an algorithm
+implementation.
 
 
-@item GCRYCTL_GET_ALGO_NSKEY
-Return the number of elements the private key for algorithm @var{algo}
-consist of.  Note that this value is always larger than that of the
-public key.  Return 0 for an unknown algorithm.
+High-level functions deal with octet strings, according to a specified
+``scheme''.  Schemes make use of ``encoding methods'', which are
+responsible for converting the provided octet strings into MPIs, which
+are then forwared to the cryptographic primitives.  Since schemes are
+to be used for a special purpose in order to achieve a particular
+security goal, there exist ``encryption schemes'' and ``signature
+schemes''.  Encoding methods can be used seperately or implicitly
+through schemes.
 
 
-@item GCRYCTL_GET_ALGO_NSIGN
-Return the number of elements a signature created with the algorithm
-@var{algo} consists of.  Return 0 for an unknown algorithm or for an
-algorithm not capable of creating signatures.
+What follows is a description of the cryptographic primitives.
 
 
-@item GCRYCTL_GET_ALGO_NENC
-Return the number of elements a encrypted message created with the algorithm
-@var{algo} consists of.  Return 0 for an unknown algorithm or for an
-algorithm not capable of encryption.
-@end table
+@deftypefun gcry_error_t gcry_ac_data_encrypt (gcry_ac_handle_t @var{handle}, unsigned int @var{flags}, gcry_ac_key_t @var{key}, gcry_mpi_t @var{data_plain}, gcry_ac_data_t *@var{data_encrypted})
+Encrypts the plain text MPI value @var{data_plain} with the key public
+@var{key} under the control of the flags @var{flags} and stores the
+resulting data set into @var{data_encrypted}.
+@end deftypefun
 
 
-@noindent
-Please note that parameters not required should be passed as @code{NULL}.
+@deftypefun gcry_error_t gcry_ac_data_decrypt (gcry_ac_handle_t @var{handle}, unsigned int @var{flags}, gcry_ac_key_t @var{key}, gcry_mpi_t *@var{data_plain}, gcry_ac_data_t @var{data_encrypted})
+Decrypts the encrypted data contained in the data set
+@var{data_encrypted} with the secret key KEY under the control of the
+flags @var{flags} and stores the resulting plain text MPI value in
+@var{DATA_PLAIN}.
+@end deftypefun
+
+@deftypefun gcry_error_t gcry_ac_data_sign (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, gcry_mpi_t @var{data}, gcry_ac_data_t *@var{data_signature})
+Signs the data contained in @var{data} with the secret key @var{key}
+and stores the resulting signature in the data set
+@var{data_signature}.
 @end deftypefun
 @end deftypefun
-@c end gcry_pk_algo_info
 
 
+@deftypefun gcry_error_t gcry_ac_data_verify (gcry_ac_handle_t @var{handle}, gcry_ac_key_t @var{key}, gcry_mpi_t @var{data}, gcry_ac_data_t @var{data_signature})
+Verifies that the signature contained in the data set
+@var{data_signature} is indeed the result of signing the data
+contained in @var{data} with the secret key belonging to the public
+key @var{key}.
+@end deftypefun
 
 
-@deftypefun gcry_error_t gcry_pk_ctl (@w{int @var{cmd}}, @w{void *@var{buffer}}, @w{size_t @var{buflen}})
+What follows is a description of the high-level functions.
 
 
-This is a general purpose function to perform certain control
-operations.  @var{cmd} controls what is to be done. The return value is
-0 for success or an error code.  Currently supported values for
-@var{cmd} are:
+The type ``gcry_ac_em_t'' is used for specifying encoding methods; the
+following methods are supported:
 
 @table @code
 
 @table @code
-@item GCRYCTL_DISABLE_ALGO
-Disable the algorithm given as an algorithm id in @var{buffer}.
-@var{buffer} must point to an @code{int} variable with the algorithm id
-and @var{buflen} must have the value @code{sizeof (int)}.
+@item GCRY_AC_EME_PKCS_V1_5
+PKCS-V1_5 Encoding Method for Encryption.  Options must be provided
+through a pointer to a correctly initialized object of type
+gcry_ac_eme_pkcs_v1_5_t.
 
 
-@end table
-@end deftypefun
-@c end gcry_pk_ctl
+@item GCRY_AC_EMSA_PKCS_V1_5
+PKCS-V1_5 Encoding Method for Signatures with Appendix.  Options must
+be provided through a pointer to a correctly initialized object of
+type gcry_ac_emsa_pkcs_v1_5_t.
+@end table
 
 
-@noindent
-Libgcrypt also provides a function for generating public key
-pairs:
+Option structure types:
 
 
-@deftypefun gcry_error_t gcry_pk_genkey (@w{gcry_sexp_t *@var{r_key}}, @w{gcry_sexp_t @var{parms}})
+@table @code
+@item gcry_ac_eme_pkcs_v1_5_t
+@table @code
+@item gcry_ac_key_t key
+@item gcry_ac_handle_t handle
+@end table
+@item gcry_ac_emsa_pkcs_v1_5_t
+@table @code
+@item gcry_md_algo_t md
+@item size_t em_n
+@end table
+@end table
 
 
-This function create a new public key pair using information given in
-the S-expression @var{parms} and stores the private and the public key
-in one new S-expression at the address given by @var{r_key}.  In case of
-an error, @var{r_key} is set to @code{NULL}.  The return code is 0 for
-success or an error code otherwise.
+Encoding methods can be used directly through the following functions:
 
 
-@noindent
-Here is an example for @var{parms} for creating a 1024 bit RSA key:
+@deftypefun gcry_error_t gcry_ac_data_encode (gcry_ac_em_t @var{method}, unsigned int @var{flags}, void *@var{options}, unsigned char *@var{m}, size_t @var{m_n}, unsigned char **@var{em}, size_t *@var{em_n})
+Encodes the message contained in @var{m} of size @var{m_n} according
+to @var{method}, @var{flags} and @var{options}.  The newly created
+encoded message is stored in @var{em} and @var{em_n}.
+@end deftypefun
 
 
-@example
-(genkey
-  (rsa
-    (nbits 4:1024)))
-@end example
+@deftypefun gcry_error_t gcry_ac_data_decode (gcry_ac_em_t @var{method}, unsigned int @var{flags}, void *@var{options}, unsigned char *@var{em}, size_t @var{em_n}, unsigned char **@var{m}, size_t *@var{m_n})
+Decodes the message contained in @var{em} of size @var{em_n} according
+to @var{method}, @var{flags} and @var{options}.  The newly created
+decoded message is stored in @var{m} and @var{m_n}.
+@end deftypefun
 
 
-@noindent
-To create an Elgamal key, substitute "elg" for "rsa" and to create a DSA
-key use "dsa".  Valid ranges for the key length depend on the
-algorithms; all commonly used key lengths are supported.  Currently
-supported parameters are:
+The type ``gcry_ac_scheme_t'' is used for specifying schemes; the
+following schemes are supported:
 
 @table @code
 
 @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.  The value should be a multiple
-of 8.
-
-@item curve @var{name}
-For ECC a named curve may be used instead of giving the number of
-requested bits.  This allows to request a specific curve to override a
-default selection Libgcrypt would have taken if @code{nbits} has been
-given.  The available names are listed with the description of the ECC
-public key parameters.
+@item GCRY_AC_ES_PKCS_V1_5
+PKCS-V1_5 Encryption Scheme.  No options can be provided.
+@item GCRY_AC_SSA_PKCS_V1_5
+PKCS-V1_5 Signature Scheme (with Appendix).  Options can be provided
+through a pointer to a correctly initialized object of type
+gcry_ac_ssa_pkcs_v1_5_t.
+@end table
 
 
-@item rsa-use-e
-This is only used with RSA to give a hint for the public exponent. The
-value will be used as a base to test for a usable exponent. Some values
-are special:
+Option structure types:
 
 
-@table @samp
-@item 0
-Use a secure and fast value.  This is currently the number 41.
-@item 1
-Use a secure value as required by some specification.  This is currently
-the number 65537.
-@item 2
-Reserved
+@table @code
+@item gcry_ac_ssa_pkcs_v1_5_t
+@table @code
+@item gcry_md_algo_t md
+@end table
 @end table
 
 @end table
 
-@noindent
-If this parameter is not used, Libgcrypt uses for historic reasons
-65537.
+The functions implementing schemes:
 
 
-@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
-@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.
+@deftypefun gcry_error_t gcry_ac_data_encrypt_scheme (gcry_ac_handle_t @var{handle}, gcry_ac_scheme_t @var{scheme}, unsigned int @var{flags}, void *@var{opts}, gcry_ac_key_t @var{key}, gcry_ac_io_t *@var{io_message}, gcry_ac_io_t *@var{io_cipher})
+Encrypts the plain text readable from @var{io_message} through
+@var{handle} with the public key @var{key} according to @var{scheme},
+@var{flags} and @var{opts}.  If @var{opts} is not NULL, it has to be a
+pointer to a structure specific to the chosen scheme (gcry_ac_es_*_t).
+The encrypted message is written to @var{io_cipher}.
+@end deftypefun
 
 
-@end table
-@c end table of parameters
+@deftypefun gcry_error_t gcry_ac_data_decrypt_scheme (gcry_ac_handle_t @var{handle}, gcry_ac_scheme_t @var{scheme}, unsigned int @var{flags}, void *@var{opts}, gcry_ac_key_t @var{key}, gcry_ac_io_t *@var{io_cipher}, gcry_ac_io_t *@var{io_message})
+Decrypts the cipher text readable from @var{io_cipher} through
+@var{handle} with the secret key @var{key} according to @var{scheme},
+@var{flags} and @var{opts}.  If @var{opts} is not NULL, it has to be a
+pointer to a structure specific to the chosen scheme (gcry_ac_es_*_t).
+The decrypted message is written to @var{io_message}.
+@end deftypefun
 
 
-@noindent
-The key pair is returned in a format depending on the algorithm.  Both
-private and public keys are returned in one container and may be
-accompanied by some miscellaneous information.
+@deftypefun gcry_error_t gcry_ac_data_sign_scheme (gcry_ac_handle_t @var{handle}, gcry_ac_scheme_t @var{scheme}, unsigned int @var{flags}, void *@var{opts}, gcry_ac_key_t @var{key}, gcry_ac_io_t *@var{io_message}, gcry_ac_io_t *@var{io_signature})
+Signs the message readable from @var{io_message} through @var{handle}
+with the secret key @var{key} according to @var{scheme}, @var{flags}
+and @var{opts}.  If @var{opts} is not NULL, it has to be a pointer to
+a structure specific to the chosen scheme (gcry_ac_ssa_*_t).  The
+signature is written to @var{io_signature}.
+@end deftypefun
 
 
-@noindent
-As an example, here is what the Elgamal key generation returns:
+@deftypefun gcry_error_t gcry_ac_data_verify_scheme (gcry_ac_handle_t @var{handle}, gcry_ac_scheme_t @var{scheme}, unsigned int @var{flags}, void *@var{opts}, gcry_ac_key_t @var{key}, gcry_ac_io_t *@var{io_message}, gcry_ac_io_t *@var{io_signature})
+Verifies through @var{handle} that the signature readable from
+@var{io_signature} is indeed the result of signing the message
+readable from @var{io_message} with the secret key belonging to the
+public key @var{key} according to @var{scheme} and @var{opts}.  If
+@var{opts} is not NULL, it has to be an anonymous structure
+(gcry_ac_ssa_*_t) specific to the chosen scheme.
+@end deftypefun
 
 
-@example
-(key-data
-  (public-key
-    (elg
-      (p @var{p-mpi})
-      (g @var{g-mpi})
-      (y @var{y-mpi})))
-  (private-key
-    (elg
-      (p @var{p-mpi})
-      (g @var{g-mpi})
-      (y @var{y-mpi})
-      (x @var{x-mpi})))
-  (misc-key-info
-    (pm1-factors @var{n1 n2 ... nn})))
-@end example
+@node Handle-independent functions
+@subsection Handle-independent functions
 
 
-@noindent
-As you can see, some of the information is duplicated, but this provides
-an easy way to extract either the public or the private key.  Note that
-the order of the elements is not defined, e.g. the private key may be
-stored before the public key. @var{n1 n2 ... nn} is a list of prime
-numbers used to composite @var{p-mpi}; this is in general not a very
-useful information.
+These two functions are deprecated; do not use them for new code.
+
+@deftypefun gcry_error_t gcry_ac_id_to_name (gcry_ac_id_t @var{algorithm}, const char **@var{name})
+Stores the textual representation of the algorithm whose id is given
+in @var{algorithm} in @var{name}.  Deprecated; use @code{gcry_pk_algo_name}.
 @end deftypefun
 @end deftypefun
-@c end gcry_pk_genkey
 
 
-@node Public Key cryptography (II)
-@chapter Public Key cryptography (II)
+@deftypefun gcry_error_t gcry_ac_name_to_id (const char *@var{name}, gcry_ac_id_t *@var{algorithm})
+Stores the numeric ID of the algorithm whose textual representation is
+contained in @var{name} in @var{algorithm}. Deprecated; use
+@code{gcry_pk_map_name}.
+@end deftypefun
 
 
-This chapter documents the alternative interface to asymmetric
-cryptography (ac) that is not based on S-expressions, but on native C
-data structures.  As opposed to the pk interface described in the
-former chapter, this one follows an open/use/close paradigm like other
-building blocks of the library.
+@c **********************************************************
+@c *******************  Hash Functions  *********************
+@c **********************************************************
+@node Hashing
+@chapter Hashing
 
 
-@strong{This interface has a few known problems; most noteworthy an
-inherent tendency to leak memory.  It might not be available in
-forthcoming versions Libgcrypt.}
+Libgcrypt provides an easy and consistent to use interface
+for hashing.  Hashing is buffered and several hash algorithms can be
+updated at once.  It is possible to calculate a MAC using the same
+routines.  The programming model follows an open/process/close
+paradigm and is in that similar to other building blocks provided by
+Libgcrypt.
 
 
+For convenience reasons, a few cyclic redundancy check value operations
+are also supported.
 
 @menu
 
 @menu
-* Available asymmetric algorithms::  List of algorithms supported by the library.
-* Working with sets of data::   How to work with sets of data.
-* Working with IO objects::     How to work with IO objects.
-* Working with handles::        How to use handles.
-* Working with keys::           How to work with keys.
-* Using cryptographic functions::  How to perform cryptographic operations.
-* Handle-independent functions::  General functions independent of handles.
+* Available hash algorithms::   List of hash algorithms supported by the library.
+* Hash algorithm modules::      How to work with hash algorithm modules.
+* Working with hash algorithms::  List of functions related to hashing.
 @end menu
 
 @end menu
 
-@node Available asymmetric algorithms
-@section Available asymmetric algorithms
+@node Available hash algorithms
+@section Available hash algorithms
 
 
-Libgcrypt supports the RSA (Rivest-Shamir-Adleman)
-algorithms as well as DSA (Digital Signature Algorithm) and Elgamal.
-The versatile interface allows to add more algorithms in the future.
+@c begin table of hash algorithms
+@table @code
+@item GCRY_MD_NONE
+This is not a real algorithm but used by some functions as an error
+return value.  This constant is guaranteed to have the value @code{0}.
 
 
-@deftp {Data type} gcry_ac_id_t
+@item GCRY_MD_SHA1
+This is the SHA-1 algorithm which yields a message digest of 20 bytes.
 
 
-The following constants are defined for this type:
+@item GCRY_MD_RMD160
+This is the 160 bit version of the RIPE message digest (RIPE-MD-160).
+Like SHA-1 it also yields a digest of 20 bytes.
 
 
-@table @code
-@item GCRY_AC_RSA
-Rivest-Shamir-Adleman
-@item GCRY_AC_DSA
-Digital Signature Algorithm
-@item GCRY_AC_ELG
-Elgamal
-@item GCRY_AC_ELG_E
-Elgamal, encryption only.
-@end table
-@end deftp
+@item GCRY_MD_MD5
+This is the well known MD5 algorithm, which yields a message digest of
+16 bytes. 
 
 
-@node Working with sets of data
-@section Working with sets of data
+@item GCRY_MD_MD4
+This is the MD4 algorithm, which yields a message digest of 16 bytes.
 
 
-In the context of this interface the term `data set' refers to a list
-of `named MPI values' that is used by functions performing
-cryptographic operations; a named MPI value is a an MPI value,
-associated with a label.
+@item GCRY_MD_MD2
+This is an reserved identifier for MD-2; there is no implementation yet.
 
 
-Such data sets are used for representing keys, since keys simply
-consist of a variable amount of numbers.  Furthermore some functions
-return data sets to the caller that are to be provided to other
-functions.
+@item GCRY_MD_TIGER
+This is the TIGER/192 algorithm which yields a message digest of 24 bytes.
 
 
-This section documents the data types, symbols and functions that are
-relevant for working with data sets.
+@item GCRY_MD_HAVAL
+This is an reserved for the HAVAL algorithm with 5 passes and 160
+bit. It yields a message digest of 20 bytes.  Note that there is no
+implementation yet available.
 
 
-@deftp {Data type} gcry_ac_data_t
-A single data set.
-@end deftp
+@item GCRY_MD_SHA224
+This is the SHA-224 algorithm which yields a message digest of 28 bytes.
+See Change Notice 1 for FIPS 180-2 for the specification.
 
 
-The following flags are supported:
+@item GCRY_MD_SHA256
+This is the SHA-256 algorithm which yields a message digest of 32 bytes.
+See FIPS 180-2 for the specification.
 
 
-@table @code
-@item GCRY_AC_FLAG_DEALLOC
-Used for storing data in a data set.  If given, the data will be
-released by the library.  Note that whenever one of the ac functions
-is about to release objects because of this flag, the objects are
-expected to be stored in memory allocated through the Libgcrypt memory
-management.  In other words: gcry_free() is used instead of free().
+@item GCRY_MD_SHA384
+This is the SHA-384 algorithm which yields a message digest of 48 bytes.
+See FIPS 180-2 for the specification.
 
 
-@item GCRY_AC_FLAG_COPY
-Used for storing/retrieving data in/from a data set.  If given, the
-library will create copies of the provided/contained data, which will
-then be given to the user/associated with the data set.
-@end table
+@item GCRY_MD_SHA512
+This is the SHA-384 algorithm which yields a message digest of 64 bytes.
+See FIPS 180-2 for the specification.
 
 
-@deftypefun gcry_error_t gcry_ac_data_new (gcry_ac_data_t *@var{data})
-Creates a new, empty data set and stores it in @var{data}.
-@end deftypefun
+@item GCRY_MD_CRC32
+This is the ISO 3309 and ITU-T V.42 cyclic redundancy check.  It
+yields an output of 4 bytes.
 
 
-@deftypefun void gcry_ac_data_destroy (gcry_ac_data_t @var{data})
-Destroys the data set @var{data}.
-@end deftypefun
+@item GCRY_MD_CRC32_RFC1510
+This is the above cyclic redundancy check function, as modified by RFC
+1510.  It yields an output of 4 bytes.
 
 
-@deftypefun gcry_error_t gcry_ac_data_set (gcry_ac_data_t @var{data}, unsigned int @var{flags}, char *@var{name}, gcry_mpi_t @var{mpi})
-Add the value @var{mpi} to @var{data} with the label @var{name}.  If
-@var{flags} contains GCRY_AC_FLAG_COPY, the data set will contain
-copies of @var{name} and @var{mpi}.  If @var{flags} contains
-GCRY_AC_FLAG_DEALLOC or GCRY_AC_FLAG_COPY, the values
-contained in the data set will be deallocated when they are to be
-removed from the data set.
-@end deftypefun
+@item GCRY_MD_CRC24_RFC2440
+This is the OpenPGP cyclic redundancy check function.  It yields an
+output of 3 bytes.
 
 
-@deftypefun gcry_error_t gcry_ac_data_copy (gcry_ac_data_t *@var{data_cp}, gcry_ac_data_t @var{data})
-Create a copy of the data set @var{data} and store it in
-@var{data_cp}.  FIXME: exact semantics undefined.
-@end deftypefun
+@item GCRY_MD_WHIRLPOOL
+This is the Whirlpool algorithm which yields a message digest of 64
+bytes.
 
 
-@deftypefun unsigned int gcry_ac_data_length (gcry_ac_data_t @var{data})
-Returns the number of named MPI values inside of the data set
-@var{data}.
-@end deftypefun
+@end table
+@c end table of hash algorithms
 
 
-@deftypefun gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t @var{data}, unsigned int @var{flags}, char *@var{name}, gcry_mpi_t *@var{mpi})
-Store the value labelled with @var{name} found in @var{data} in
-@var{mpi}.  If @var{flags} contains GCRY_AC_FLAG_COPY, store a copy of
-the @var{mpi} value contained in the data set.  @var{mpi} may be NULL
-(this might be useful for checking the existence of an MPI with
-extracting it).
-@end deftypefun
+@node Hash algorithm modules
+@section Hash algorithm modules
 
 
-@deftypefun gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t @var{data}, unsigned int flags, unsigned int @var{index}, const char **@var{name}, gcry_mpi_t *@var{mpi})
-Stores in @var{name} and @var{mpi} the named @var{mpi} value contained
-in the data set @var{data} with the index @var{idx}.  If @var{flags}
-contains GCRY_AC_FLAG_COPY, store copies of the values contained in
-the data set. @var{name} or @var{mpi} may be NULL.
-@end deftypefun
+Libgcrypt makes it possible to load additional `message
+digest modules'; these digests can be used just like the message digest
+algorithms that are built into the library directly.  For an
+introduction into extension modules, see @xref{Modules}.
 
 
-@deftypefun void gcry_ac_data_clear (gcry_ac_data_t @var{data})
-Destroys any values contained in the data set @var{data}.
-@end deftypefun
+@deftp {Data type} gcry_md_spec_t
+This is the `module specification structure' needed for registering
+message digest modules, which has to be filled in by the user before
+it can be used to register a module.  It contains the following
+members:
 
 
-@deftypefun gcry_error_t gcry_ac_data_to_sexp (gcry_ac_data_t @var{data}, gcry_sexp_t *@var{sexp}, const char **@var{identifiers})
-This function converts the data set @var{data} into a newly created
-S-Expression, which is to be stored in @var{sexp}; @var{identifiers}
-is a NULL terminated list of C strings, which specifies the structure
-of the S-Expression.
+@table @code
+@item const char *name
+The primary name of this algorithm.
+@item unsigned char *asnoid
+Array of bytes that form the ASN OID.
+@item int asnlen
+Length of bytes in `asnoid'.
+@item gcry_md_oid_spec_t *oids
+A list of OIDs that are to be associated with the algorithm.  The
+list's last element must have it's `oid' member set to NULL.  See
+below for an explanation of this type.  See below for an explanation
+of this type.
+@item int mdlen
+Length of the message digest algorithm.  See below for an explanation
+of this type.
+@item gcry_md_init_t init
+The function responsible for initializing a handle.  See below for an
+explanation of this type.
+@item gcry_md_write_t write
+The function responsible for writing data into a message digest
+context.  See below for an explanation of this type.
+@item gcry_md_final_t final
+The function responsible for `finalizing' a message digest context.
+See below for an explanation of this type.
+@item gcry_md_read_t read
+The function responsible for reading out a message digest result.  See
+below for an explanation of this type.
+@item size_t contextsize
+The size of the algorithm-specific `context', that should be
+allocated for each handle.
+@end table
+@end deftp
 
 
-Example:
+@deftp {Data type} gcry_md_oid_spec_t
+This type is used for associating a user-provided algorithm
+implementation with certain OIDs.  It contains the following members:
 
 
-If @var{identifiers} is a list of pointers to the strings ``foo'' and
-``bar'' and if @var{data} is a data set containing the values ``val1 =
-0x01'' and ``val2 = 0x02'', then the resulting S-Expression will look
-like this: (foo (bar ((val1 0x01) (val2 0x02))).
-@end deftypefun
+@table @code
+@item const char *oidstring
+Textual representation of the OID.
+@end table
+@end deftp
 
 
-@deftypefun gcry_error gcry_ac_data_from_sexp (gcry_ac_data_t *@var{data}, gcry_sexp_t @var{sexp}, const char **@var{identifiers})
-This function converts the S-Expression @var{sexp} into a newly
-created data set, which is to be stored in @var{data};
-@var{identifiers} is a NULL terminated list of C strings, which
-specifies the structure of the S-Expression.  If the list of
-identifiers does not match the structure of the S-Expression, the
-function fails.
-@end deftypefun
+@deftp {Data type} gcry_md_init_t
+Type for the `init' function, defined as: void (*gcry_md_init_t) (void
+*c)
+@end deftp
 
 
-@node Working with IO objects
-@section Working with IO objects
+@deftp {Data type} gcry_md_write_t
+Type for the `write' function, defined as: void (*gcry_md_write_t)
+(void *c, unsigned char *buf, size_t nbytes)
+@end deftp
 
 
-Note: IO objects are currently only used in the context of message
-encoding/decoding and encryption/signature schemes.
+@deftp {Data type} gcry_md_final_t
+Type for the `final' function, defined as: void (*gcry_md_final_t)
+(void *c)
+@end deftp
 
 
-@deftp {Data type} {gcry_ac_io_t}
-@code{gcry_ac_io_t} is the type to be used for IO objects.
+@deftp {Data type} gcry_md_read_t
+Type for the `read' function, defined as: unsigned char
+*(*gcry_md_read_t) (void *c)
 @end deftp
 
 @end deftp
 
-IO objects provide an uniform IO layer on top of different underlying
-IO mechanisms; either they can be used for providing data to the
-library (mode is GCRY_AC_IO_READABLE) or they can be used for
-retrieving data from the library (mode is GCRY_AC_IO_WRITABLE).
+@deftypefun gcry_error_t gcry_md_register (gcry_md_spec_t *@var{digest}, unsigned int *algorithm_id, gcry_module_t *@var{module})
 
 
-IO object need to be initialized by calling on of the following
-functions:
+Register a new digest module whose specification can be found in
+@var{digest}.  On success, a new algorithm ID is stored in
+@var{algorithm_id} and a pointer representing this module is stored
+in @var{module}.
+@end deftypefun
 
 
-@deftypefun void gcry_ac_io_init (gcry_ac_io_t *@var{ac_io}, gcry_ac_io_mode_t @var{mode}, gcry_ac_io_type_t @var{type}, ...);
-Initialize @var{ac_io} according to @var{mode}, @var{type} and the
-variable list of arguments.  The list of variable arguments to specify
-depends on the given @var{type}.
+@deftypefun void gcry_md_unregister (gcry_module_t @var{module})
+Unregister the digest identified by @var{module}, which must have been
+registered with gcry_md_register.
 @end deftypefun
 
 @end deftypefun
 
-@deftypefun void gcry_ac_io_init_va (gcry_ac_io_t *@var{ac_io}, gcry_ac_io_mode_t @var{mode}, gcry_ac_io_type_t @var{type}, va_list @var{ap});
-Initialize @var{ac_io} according to @var{mode}, @var{type} and the
-variable list of arguments @var{ap}.  The list of variable arguments
-to specify depends on the given @var{type}.
+@deftypefun gcry_error_t gcry_md_list (int *@var{list}, int *@var{list_length})
+Get a list consisting of the IDs of the loaded message digest modules.
+If @var{list} is zero, write the number of loaded message digest
+modules to @var{list_length} and return.  If @var{list} is non-zero,
+the first *@var{list_length} algorithm IDs are stored in @var{list},
+which must be of according size.  In case there are less message
+digests modules than *@var{list_length}, *@var{list_length} is updated
+to the correct number.
 @end deftypefun
 
 @end deftypefun
 
-The following types of IO objects exist:
+@node Working with hash algorithms
+@section Working with hash algorithms
 
 
-@table @code
-@item GCRY_AC_IO_STRING
-In case of GCRY_AC_IO_READABLE the IO object will provide data from a
-memory string.  Arguments to specify at initialization time:
-@table @code
-@item unsigned char *
-Pointer to the beginning of the memory string
-@item size_t
-Size of the memory string
-@end table
-In case of GCRY_AC_IO_WRITABLE the object will store retrieved data in
-a newly allocated memory string.  Arguments to specify at
-initialization time:
-@table @code
-@item unsigned char **
-Pointer to address, at which the pointer to the newly created memory
-string is to be stored
-@item size_t *
-Pointer to address, at which the size of the newly created memory
-string is to be stored
-@end table
+To use most of these function it is necessary to create a context;
+this is done using:
 
 
-@item GCRY_AC_IO_CALLBACK
-In case of GCRY_AC_IO_READABLE the object will forward read requests
-to a provided callback function.  Arguments to specify at
-initialization time:
-@table @code
-@item gcry_ac_data_read_cb_t
-Callback function to use
-@item void *
-Opaque argument to provide to the callback function
-@end table
-In case of GCRY_AC_IO_WRITABLE the object will forward write requests
-to a provided callback function.  Arguments to specify at
-initialization time:
+@deftypefun gcry_error_t gcry_md_open (gcry_md_hd_t *@var{hd}, int @var{algo}, unsigned int @var{flags})
+
+Create a message digest object for algorithm @var{algo}.  @var{flags}
+may be given as an bitwise OR of constants described below.  @var{algo}
+may be given as @code{0} if the algorithms to use are later set using
+@code{gcry_md_enable}. @var{hd} is guaranteed to either receive a valid
+handle or NULL.
+
+For a list of supported algorithms, see @xref{Available hash
+algorithms}.
+
+The flags allowed for @var{mode} are:
+
+@c begin table of hash flags
 @table @code
 @table @code
-@item gcry_ac_data_write_cb_t
-Callback function to use
-@item void *
-Opaque argument to provide to the callback function
-@end table
+@item GCRY_MD_FLAG_SECURE
+Allocate all buffers and the resulting digest in "secure memory".  Use
+this is the hashed data is highly confidential.
+
+@item GCRY_MD_FLAG_HMAC
+Turn the algorithm into a HMAC message authentication algorithm.  This
+only works if just one algorithm is enabled for the handle.  Note that the function
+@code{gcry_md_setkey} must be used to set the MAC key.  If you want CBC
+message authentication codes based on a cipher, see @xref{Working with
+cipher handles}.
+
 @end table
 @end table
+@c begin table of hash flags
 
 
-@node Working with handles
-@section Working with handles
+You may use the function @code{gcry_md_is_enabled} to later check
+whether an algorithm has been enabled.
 
 
-In order to use an algorithm, an according handle must be created.
-This is done using the following function:
+@end deftypefun
+@c end function gcry_md_open
 
 
-@deftypefun gcry_error_t gcry_ac_open (gcry_ac_handle_t *@var{handle}, int @var{algorithm}, int @var{flags})
+If you want to calculate several hash algorithms at the same time, you
+have to use the following function right after the @code{gcry_md_open}:
 
 
-Creates a new handle for the algorithm @var{algorithm} and stores it
-in @var{handle}.  @var{flags} is not used currently.
+@deftypefun gcry_error_t gcry_md_enable (gcry_md_hd_t @var{h}, int @var{algo})
 
 
-@var{algorithm} must be a valid algorithm ID, see @xref{Available
-asymmetric algorithms}, for a list of supported algorithms and the
-according constants.  Besides using the listed constants directly, the
-functions @code{gcry_pk_name_to_id} may be used to convert the textual
-name of an algorithm into the according numeric ID.
+Add the message digest algorithm @var{algo} to the digest object
+described by handle @var{h}.  Duplicated enabling of algorithms is
+detected and ignored.
 @end deftypefun
 
 @end deftypefun
 
-@deftypefun void gcry_ac_close (gcry_ac_handle_t @var{handle})
-Destroys the handle @var{handle}.
+If the flag @code{GCRY_MD_FLAG_HMAC} was used, the key for the MAC must
+be set using the function:
+
+@deftypefun gcry_error_t gcry_md_setkey (gcry_md_hd_t @var{h}, const void *@var{key}, size_t @var{keylen})
+
+For use with the HMAC feature, set the MAC key to the value of @var{key}
+of length @var{keylen}.
 @end deftypefun
 
 @end deftypefun
 
-@node Working with keys
-@section Working with keys
 
 
-@deftp {Data type} gcry_ac_key_type_t
-Defined constants:
+After you are done with the hash calculation, you should release the
+resources by using</