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.
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
-EXTRA_DIST = BUGS autogen.sh README.SVN
+EXTRA_DIST = autogen.sh README.SVN
 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
 ------------------------------------------------
 
+ * 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)
 ------------------------------------------------
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
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 \
+hmac-tests.c \
 bithelp.h  \
 primegen.c  \
 rmd.h
@@ -65,6 +66,7 @@ twofish.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' `
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;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   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;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   /* 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;
 
+  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);
@@ -370,6 +379,9 @@ _gcry_ac_data_get_name (gcry_ac_data_t data, unsigned int flags,
   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);
@@ -421,6 +433,9 @@ _gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int flags,
   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);
@@ -496,6 +511,9 @@ _gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp,
   arg_list = NULL;
   err = 0;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   /* 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;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   /* 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 (fips_mode ())
+    return;
+
   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));
 
+  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));
 
@@ -1362,6 +1389,9 @@ _gcry_ac_open (gcry_ac_handle_t *handle,
   *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)
@@ -1431,6 +1461,9 @@ _gcry_ac_key_init (gcry_ac_key_t *key, gcry_ac_handle_t handle,
 
   (void)handle;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   /* 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;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   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;
 
+  if (fips_mode ())
+    return NULL;
+
   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)
 {
+  if (fips_mode ())
+    return NULL;
   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;
 
+  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);
@@ -1744,6 +1788,9 @@ _gcry_ac_key_get_nbits (gcry_ac_handle_t handle,
   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],
@@ -1777,6 +1824,9 @@ _gcry_ac_key_get_grip (gcry_ac_handle_t handle,
   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);
@@ -1823,6 +1873,9 @@ _gcry_ac_data_encrypt (gcry_ac_handle_t handle,
   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;
@@ -1897,6 +1950,9 @@ _gcry_ac_data_decrypt (gcry_ac_handle_t handle,
   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;
@@ -1969,6 +2025,9 @@ _gcry_ac_data_sign (gcry_ac_handle_t handle,
   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;
@@ -2039,6 +2098,9 @@ _gcry_ac_data_verify (gcry_ac_handle_t handle,
   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;
@@ -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)
 {
+  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);
 }
@@ -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)
 {
+  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);
 }
@@ -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;
 
+  if (fips_mode ())
+    return;
+
   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;
 
+  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);
@@ -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;
   
+  if (fips_mode ())
+    return;
+
   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;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   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;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   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;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   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;
 
+  if (fips_mode ())
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
   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)
 {
+  if (fips_mode ())
+    return GPG_ERR_NOT_SUPPORTED;
+
   return 0;
 }
index 66470ee..e328435 100644 (file)
@@ -1,6 +1,6 @@
 /* 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.
  *
 #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;
+  cipher_extra_spec_t *extraspec;
   unsigned int algorithm;
+  int fips_allowed;
 } 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
-    { &_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
-    { &_gcry_cipher_spec_arcfour,    GCRY_CIPHER_ARCFOUR },
+    { &_gcry_cipher_spec_arcfour,    
+      &dummy_extra_spec,                  GCRY_CIPHER_ARCFOUR },
 #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
-    { &_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
-    { &_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
-    { &_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
-    { &_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
-    { &_gcry_cipher_spec_seed,       GCRY_CIPHER_SEED },
+    { &_gcry_cipher_spec_seed, 
+      &dummy_extra_spec,                  GCRY_CIPHER_SEED },
 #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                    }
   };
@@ -104,7 +129,7 @@ static int 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); \
@@ -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
-gcry_cipher_register_default (void)
+cipher_register_default (void)
 {
   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 ( fips_mode () && !cipher_table[i].fips_allowed )
+        continue;
+
       err = _gcry_module_add (&ciphers_registered,
                              cipher_table[i].algorithm,
                              (void *) cipher_table[i].cipher,
+                             (void *) cipher_table[i].extraspec,
                              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
-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;
 
+  /* 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,
-                         (void *) cipher, &mod);
+                         (void *)cipher, 
+                         (void *)(extraspec? extraspec : &dummy_extra_spec), 
+                          &mod);
   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)
 {
@@ -572,7 +609,7 @@ cipher_get_keylen (int algorithm)
   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);
     }
@@ -793,7 +830,7 @@ gcry_cipher_close (gcry_cipher_hd_t h)
 {
   size_t off;
 
-  if (! h)
+  if (!h)
     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
-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);
-  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);
 }
@@ -848,8 +887,11 @@ cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen )
   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);
@@ -876,12 +918,13 @@ static void
 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 )
 {
-    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
-           * 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 );
@@ -1400,10 +1444,12 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
   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;
@@ -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)
-    /* 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)
@@ -1510,7 +1558,7 @@ gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
  * 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)
     {
@@ -1524,24 +1572,58 @@ cipher_sync( gcry_cipher_hd_t c )
 
 
 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)
     {
-    case GCRYCTL_SET_KEY:
+    case GCRYCTL_SET_KEY:  /* Deprecated; use gcry_cipher_setkey.  */
       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;
+
     case GCRYCTL_RESET:
       cipher_reset (h);
       break;
+
     case GCRYCTL_CFB_SYNC:
       cipher_sync( h );
       break;
+
     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;
+
     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;
+
     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;
-    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)
@@ -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_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;
 
@@ -1606,27 +1695,29 @@ gcry_cipher_info( gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
   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)
@@ -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;
 
-  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;
 }
 
+/* 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) 
 {
@@ -1702,7 +1806,7 @@ gcry_cipher_get_algo_blklen (int algo)
   return n;
 }
 
-
+/* Explicitly initialize this module.  */
 gcry_err_code_t
 _gcry_cipher_init (void)
 {
@@ -1730,3 +1834,41 @@ gcry_cipher_list (int *list, int *list_length)
 
   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
- *      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()) )
@@ -310,7 +310,7 @@ static byte encrypt_rotate_tab[16] =
 
 /*
  * 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.
@@ -584,7 +584,7 @@ des_setkey (struct _des_ctx *ctx, const byte * key)
   static const char *selftest_failed;
   int i;
 
-  if (! initialized)
+  if (!fips_mode () && !initialized)
     {
       initialized = 1;
       selftest_failed = selftest ();
@@ -691,7 +691,7 @@ tripledes_set3keys (struct _tripledes_ctx *ctx,
   static const char *selftest_failed;
   int i;
 
-  if (! initialized)
+  if (!fips_mode () && !initialized)
     {
       initialized = 1;
       selftest_failed = selftest ();
@@ -956,7 +956,6 @@ selftest (void)
 
     byte               result[8];
     int                i;
-    static char        error[80];
     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))
-          {
-            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))
-          {
-            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;
 
-    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)
-      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);
-    gcry_md_close (h);
+    _gcry_md_close (h);
     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);
 }
 
+
+
+\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),
@@ -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
   };
+
+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,
- *               2006  Free Software Foundation, Inc.
+ *               2006, 2008  Free Software Foundation, Inc.
  *
  * 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 < 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]);
@@ -531,6 +534,57 @@ _gcry_dsa_get_nbits (int algo, gcry_mpi_t *pkey)
   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",
@@ -551,4 +605,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_dsa =
     _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
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
 
    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.  */
+  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.  */
@@ -135,7 +136,7 @@ static const struct
 } domain_parms[] =
   {
     {
-      "NIST P-192", 192,
+      "NIST P-192", 192, 1,
       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
@@ -145,7 +146,7 @@ static const struct
       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
     },
     {
-      "NIST P-224", 224,
+      "NIST P-224", 224, 1,
       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
@@ -155,7 +156,7 @@ static const struct
       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"
     },
     {
-      "NIST P-256", 256,
+      "NIST P-256", 256, 1,
       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
@@ -165,7 +166,7 @@ static const struct
       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
     },
     {
-      "NIST P-384", 384,
+      "NIST P-384", 384, 1,
       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
       "ffffffff0000000000000000ffffffff",
       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
@@ -181,7 +182,7 @@ static const struct
       "0a60b1ce1d7e819d7a431d7c90ea0e5f"
     },
     {
-      "NIST P-521", 521,
+      "NIST P-521", 521, 1,
       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
@@ -197,7 +198,7 @@ static const struct
       "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
     },
 
-    { "brainpoolP160r1", 160,
+    { "brainpoolP160r1", 160, 0, 
       "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
       "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
@@ -206,7 +207,7 @@ static const struct
       "0x1667cb477a1a8ec338f94741669c976316da6321"
     },
 
-    { "brainpoolP192r1", 192,
+    { "brainpoolP192r1", 192, 0, 
       "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
       "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
@@ -215,7 +216,7 @@ static const struct
       "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f"
     },
 
-    { "brainpoolP224r1", 224,
+    { "brainpoolP224r1", 224, 0,
       "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
       "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
@@ -224,7 +225,7 @@ static const struct
       "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd"
     },
 
-    { "brainpoolP256r1", 256, 
+    { "brainpoolP256r1", 256, 0,
       "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
       "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
@@ -233,7 +234,7 @@ static const struct
       "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997"
     },
 
-    { "brainpoolP320r1", 320, 
+    { "brainpoolP320r1", 320, 0,
       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
       "fcd412b1f1b32e27",
       "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
@@ -248,7 +249,7 @@ static const struct
       "d35245d1692e8ee1"
     },
 
-    { "brainpoolP384r1", 384, 
+    { "brainpoolP384r1", 384, 0,
       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
       "acd3a729901d1a71874700133107ec53",
       "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
@@ -263,7 +264,7 @@ static const struct
       "0e4646217791811142820341263c5315"
     },
 
-    { "brainpoolP512r1", 512,
+    { "brainpoolP512r1", 512, 0,
       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
       "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
       "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
@@ -278,7 +279,7 @@ static const struct
       "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;
 
+  /* 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);
@@ -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",
@@ -1195,4 +1253,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
     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
- * 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.
  *
@@ -14,8 +15,7 @@
  * 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 "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;
+  md_extra_spec_t *extraspec;
   unsigned int algorithm;
+  int fips_allowed;
 } 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
-    { &_gcry_digest_spec_md4, GCRY_MD_MD4 },
+    { &_gcry_digest_spec_md4,
+      &dummy_extra_spec,                 GCRY_MD_MD4 },
 #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
-    { &_gcry_digest_spec_rmd160, GCRY_MD_RMD160 },
+    { &_gcry_digest_spec_rmd160,
+      &dummy_extra_spec,                 GCRY_MD_RMD160 },
 #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
-    { &_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
-    { &_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
-    { &_gcry_digest_spec_tiger, GCRY_MD_TIGER },
+    { &_gcry_digest_spec_tiger,
+      &dummy_extra_spec,                 GCRY_MD_TIGER },
 #endif
 #if USE_WHIRLPOOL
-    { &_gcry_digest_spec_whirlpool, GCRY_MD_WHIRLPOOL },
+    { &_gcry_digest_spec_whirlpool,
+      &dummy_extra_spec,                 GCRY_MD_WHIRLPOOL },
 #endif
     { NULL },
   };
@@ -115,7 +140,7 @@ struct gcry_md_context
       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); \
@@ -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
-gcry_md_register_default (void)
+md_register_default (void)
 {
   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 ();
@@ -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
-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;
 
+  /* 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,
-                         (void *) digest, &mod);
+                         (void *) digest, 
+                         (void *)(extraspec? extraspec : &dummy_extra_spec), 
+                          &mod);
   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)
     {
-      /* FIXME: should we really do that? - yes [-wk] */
+      /* Hmmm, should we really do that? - yes [-wk] */
       _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_err_code_t err = md_enable (hd, algorithm);
-  return gcry_error (err);
+  return gcry_error (md_enable (hd, algorithm));
 }
 
 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_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);
@@ -669,7 +708,9 @@ void
 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)
@@ -713,6 +754,7 @@ md_close (gcry_md_hd_t a)
 void
 gcry_md_close (gcry_md_hd_t hd)
 {
+  /* Note: We allow this even in fips non operational mode.  */
   md_close (hd);
 }
 
@@ -771,7 +813,9 @@ md_final (gcry_md_hd_t a)
 
       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). */
@@ -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;
 
-  if (! hd->ctx->macpads)
+  if (!hd->ctx->macpads)
     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)
 {
+  /* 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);
 }
 
-/****************
- * 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)
@@ -973,6 +969,7 @@ gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen)
   (void)buflen;
 
   /*md_digest ... */
+  fips_signal_error ("unimplemented function called");
   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);
-  else if (algo == GCRY_MD_RMD160)
+  else if (algo == GCRY_MD_RMD160 && !fips_mode () )
     _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)
-    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;
 }
 
@@ -1158,6 +1158,9 @@ md_start_debug ( gcry_md_hd_t md, const char *suffix )
 {
   static int idx=0;
   char buf[50];
+
+  if (fips_mode ())
+    return;
   
   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);
 }
 
+
+/* Explicitly initialize this module.  */
 gcry_err_code_t
 _gcry_md_init (void)
 {
@@ -1296,3 +1301,41 @@ gcry_md_list (int *list, int *list_length)
 
   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
- * 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.
  *
@@ -15,8 +15,7 @@
  * 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>
@@ -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);
 
+
+/* 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
-   libgcrypt.  */
+   libgcrypt.  FIPS_ALLOWED indicated whether the algorithm is used in
+   FIPS mode. */
 static struct pubkey_table_entry
 {
   gcry_pk_spec_t *pubkey;
+  pk_extra_spec_t *extraspec;
   unsigned int algorithm;
+  int fips_allowed; 
 } 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
-    { &_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
-    { &_gcry_pubkey_spec_dsa, GCRY_PK_DSA   },
+    { &_gcry_pubkey_spec_dsa,
+      &_gcry_pubkey_extraspec_dsa,   GCRY_PK_DSA, 1   },
 #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 },
   };
@@ -82,7 +96,7 @@ static int 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); \
@@ -101,6 +115,7 @@ dummy_generate (int algorithm, unsigned int nbits, unsigned long dummy,
   (void)dummy;
   (void)skey;
   (void)retfactors;
+  fips_signal_error ("using dummy public key function");
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -109,6 +124,7 @@ dummy_check_secret_key (int algorithm, gcry_mpi_t *skey)
 {
   (void)algorithm;
   (void)skey;
+  fips_signal_error ("using dummy public key function");
   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;
+  fips_signal_error ("using dummy public key function");
   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;
+  fips_signal_error ("using dummy public key function");
   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;
+  fips_signal_error ("using dummy public key function");
   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;
+  fips_signal_error ("using dummy public key function");
   return GPG_ERR_NOT_IMPLEMENTED;
 }
 
@@ -166,13 +186,14 @@ dummy_get_nbits (int algorithm, gcry_mpi_t *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
-gcry_pk_register_default (void)
+pk_register_default (void)
 {
   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
+
       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)
@@ -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
-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;
 
+  /* 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,
-                         (void *) pubkey, &mod);
+                         (void *) pubkey, 
+                         (void *)(extraspec? extraspec : &dummy_extra_spec), 
+                          &mod);
   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,
@@ -582,7 +620,10 @@ pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
   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++)
@@ -604,7 +645,7 @@ pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
  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] );
@@ -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 */
-  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++)
@@ -654,7 +695,7 @@ pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
  ready:
   ath_mutex_unlock (&pubkeys_registered_lock);
 
-  if (! rc && DBG_CIPHER)
+  if (!rc && DBG_CIPHER && !fips_mode ())
     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;
 
-  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++)
@@ -699,7 +740,7 @@ pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
  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]);
 
@@ -720,7 +761,7 @@ pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
   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++)
@@ -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)
     {
+#if USE_ECC
       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 /* !USE_ECC */
+      err = GPG_ERR_INV_OBJ; /* "curve" given but ECC not supported. */
+      goto leave;
+#endif /* !USE_ECC */
     }
 
   /* 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)
-    { /* 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;
@@ -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)
-    { /* 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 )
@@ -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);
       
-              /* 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);
             }
           
@@ -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;
 
+  *r_ciph = NULL;
+
   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;
@@ -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 :-(.  */
-    /* 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)
@@ -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;
 
+  *r_plain = NULL;
+
   REGISTER_DEFAULT_PUBKEYS;
 
-  *r_plain = NULL;
   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;
 
+  *r_sig = NULL;
+
   REGISTER_DEFAULT_PUBKEYS;
 
-  *r_sig = NULL;
   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;
 
-  REGISTER_DEFAULT_PUBKEYS;
-
   skey[0] = NULL;
   *r_key = NULL;
 
+  REGISTER_DEFAULT_PUBKEYS;
+
   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 USE_ECC
+# ifdef __GNUC__
+#  warning needs to be fixed for ECC.
+# endif
+#endif
+
   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 -
-         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);
@@ -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_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)
 {
@@ -2627,6 +2687,46 @@ gcry_pk_list (int *list, int *list_length)
   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)
 {
index 7f3fc7b..b54e069 100644 (file)
  *
  * 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 <assert.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;
   
-  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 ();
-      if( selftest_failed )
+      if (selftest_failed)
         log_error ("%s\n", selftest_failed );
     }
-  if( selftest_failed )
+  if (selftest_failed)
     return GPG_ERR_SELFTEST_FAILED;
 
   ctx->decryption_prepared = 0;
@@ -774,85 +786,368 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv,
 
 
 \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*
-selftest (void)
+selftest_basic_128 (void)
 {
   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);
-  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)))
-    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)))
-    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)))
-    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)))
-    return "Rijndael-256 test decryption failed.";
+    return "AES-256 test decryption failed.";
     
   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[] =
@@ -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
   };
+cipher_extra_spec_t _gcry_cipher_extraspec_aes = 
+  {
+    run_selftests
+  };
 
 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
   };
+cipher_extra_spec_t _gcry_cipher_extraspec_aes192 = 
+  {
+    run_selftests
+  };
 
 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
   };
+
+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)
- * 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.
  *
@@ -53,8 +53,8 @@ typedef struct
 
 
 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);
@@ -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
  */
-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 */
@@ -124,7 +124,10 @@ generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e)
   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++; 
 
@@ -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 );
+
+  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;
-  gpg_err_code_t rc;
+  gpg_err_code_t ec;
   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));
 
+  /* 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.  */
@@ -650,6 +661,58 @@ _gcry_rsa_get_nbits (int algo, gcry_mpi_t *pkey)
   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",
@@ -671,3 +734,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_rsa =
     _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 };
@@ -398,3 +448,8 @@ gcry_md_spec_t _gcry_digest_spec_sha1 =
     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
- *     Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ *     Copyright (C) 2003, 2006, 2008 Free Software Foundation, Inc.
  *
  * 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
- * 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;
 }
 
+
+\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,
@@ -347,6 +421,10 @@ gcry_md_spec_t _gcry_digest_spec_sha224 =
     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 =
   {
@@ -354,3 +432,7 @@ gcry_md_spec_t _gcry_digest_spec_sha256 =
     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
- *     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.
  *
@@ -15,9 +13,8 @@
  * 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;
 }
 
-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[] =
   {
@@ -379,18 +451,23 @@ static gcry_md_oid_spec_t oid_spec_sha512[] =
     { 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 */
-{
-  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[] =
   {
@@ -402,8 +479,13 @@ static gcry_md_oid_spec_t oid_spec_sha384[] =
     { 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_
 
+/* 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*/
 ])
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
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
 
-EXTRA_DIST = README.apichanges HACKING 
+EXTRA_DIST = README.apichanges HACKING \
+            libgcrypt-modules.eps \
+            libgcrypt-modules.png \
+             libgcrypt-modules.pdf
 
 DISTCLEANFILES = gcrypt.cps
 
+BUILT_SOURCES = libgcrypt-modules.eps \
+                libgcrypt-modules.png \
+                libgcrypt-modules.pdf
+
 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
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.
 
-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
@@ -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.
+* Public Key cryptography::      How to use public key cryptography.
 * 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.
+* Architecture::                 How Libgcrypt works internally.
 
 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
@@ -87,86 +88,6 @@ Indices
 * 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
@@ -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
-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
@@ -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.
+* FIPS mode::                   How to enable the FIPS mode.
 @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 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
 
-
 @node Building sources
 @section Building sources
 
@@ -394,10 +315,10 @@ after program startup.
 
 @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.
@@ -406,6 +327,94 @@ required version number @var{req_version}, if this value is not a null
 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
@@ -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.
 
+
+
+@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 **********************************************************
@@ -541,49 +589,72 @@ your application.
 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.
 
-@item GCRYCTL_DUMP_SECMEM_STATS
+@item GCRYCTL_DUMP_SECMEM_STATS; Arguments: none
 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
-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
-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
-
 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
-
 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
-
 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.
 
-@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
+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.
 
-
 @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.
 
-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
@@ -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
-@acronym{Libgctypt} is:
+@acronym{Libgcrypt} is:
 
 @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.
 
+@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 ...
@@ -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:
 
-@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}
@@ -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.
 
-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
@@ -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:
 
-@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
-requirement of the selected algorithm and mode.  Note that this is
-implemented as a macro.
+requirement of the selected algorithm and mode. 
 @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
-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})
@@ -1674,1878 +1800,1883 @@ with it.
 
 
 @c **********************************************************
-@c *******************  Hash Functions  *********************
+@c *******************  Public Key  *************************
 @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
-* 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
 
-@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 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
 
-@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
 
-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
 
-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
+@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
+@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
+@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
 
-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
-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
-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
-(private-key
-  (ecc
-    (curve "NIST P-192")
-    (q @var{q-point})
-    (d @var{d-mpi})))
+(genkey
+  (rsa
+    (nbits 4:1024)))
 @end example
 
-The @code{curve} parameter may be given in any case and is used to replace
-missing parameters.
-
 @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
-@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
-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
-@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
-@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
-@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
 
 
-@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
 
-@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
 
-@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
 
+@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
-@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
 
-@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
-@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
-@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
-@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
 
-@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
-@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
-* 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
 
-@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
 
-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
 
-@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
 
-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
-@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
+@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
 
-@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
 
-@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:
 
-@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 void gcry_md_close (gcry_md_hd_t @var{h})
 
-@deftp {Data type} gcry_ac_key_t
-This type represents a single `key', either a secret one or a public
-one.
-@end deftp
+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.
 
-@deftp {Data type} gcry_ac_key_pair_t
-This type represents a `key pair' containing a secret and a public key.
-@end deftp
+@end deftypefun
 
-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.
+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:
 
-@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}.
+@deftypefun void gcry_md_reset (gcry_md_hd_t @var{h})
+
+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
 
-@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})
 
-Generates a new key pair via the handle @var{handle} of @var{NBITS}
-bits and stores it in @var{key_pair}.
+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:
 
-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.
+@deftypefun gcry_error_t gcry_md_copy (gcry_md_hd_t *@var{handle_dst}, gcry_md_hd_t @var{handle_src})
 
-@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
+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
 
-Example code:
-@example
-@{
-  gcry_ac_key_pair_t key_pair;
-  gcry_ac_key_spec_rsa_t rsa_spec;
 
-  rsa_spec.e = gcry_mpi_new (0);
-  gcry_mpi_set_ui (rsa_spec.e, 1);
+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.
 
-  err = gcry_ac_open  (&handle, GCRY_AC_RSA, 0);
-  assert (! err);
+@deftypefun void gcry_md_write (gcry_md_hd_t @var{h}, const void *@var{buffer}, size_t @var{length})
 
-  err = gcry_ac_key_pair_generate (handle, 1024, &rsa_spec, &key_pair, NULL);
-  assert (! err);
-@}
-@end example
+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.
 @end deftypefun
 
+@deftypefun void gcry_md_putc (gcry_md_hd_t @var{h}, int @var{c})
 
-@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}.
+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. 
 @end deftypefun
 
-@deftypefun void gcry_ac_key_destroy (gcry_ac_key_t @var{key})
-Destroys the key @var{key}.
-@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_ac_key_pair_destroy (gcry_ac_key_pair_t @var{key_pair})
-Destroys the key pair @var{key_pair}.
-@end deftypefun
+@deftypefun void gcry_md_final (gcry_md_hd_t @var{h})
 
-@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}.
+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.
 @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}.
+The way to read out the calculated message digest is by using the
+function:
+
+@deftypefun unsigned char *gcry_md_read (gcry_md_hd_t @var{h}, int @var{algo})
+
+@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
 
-@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}.
+Because it is often necessary to get the message digest of one block of
+memory, a fast convenience function is available for this task: 
+
+@deftypefun void gcry_md_hash_buffer (int @var{algo}, void *@var{digest}, const void *@var{buffer}, size_t @var{length});
+
+@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}.
+
+Note that this function will abort the process if an unavailable
+algorithm is used.
 @end deftypefun
 
-@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}.
+@c ***********************************
+@c ***** MD info functions ***********
+@c ***********************************
+
+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.
+
+@deftypefun const char *gcry_md_algo_name (int @var{algo})
+
+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
 
-@node Using cryptographic functions
-@section Using cryptographic functions
+@deftypefun int gcry_md_map_name (const char *@var{name})
 
-The following flags might be relevant:
+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
 
-@table @code
-@item GCRY_AC_FLAG_NO_BLINDING
-Disable any blinding, which might be supported by the chosen
-algorithm; blinding is the default.
-@end table
+@deftypefun gcry_error_t gcry_md_get_asnoid (int @var{algo}, void *@var{buffer}, size_t *@var{length})
 
-There exist two kinds of cryptographic functions available through the
-ac interface: primitives, and high-level functions.
+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.
 
-Primitives deal with MPIs (data sets) directly; what they provide is
-direct access to the cryptographic operations provided by an algorithm
-implementation.
+@end deftypefun
 
-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.
 
-What follows is a description of the cryptographic primitives.
+To test whether an algorithm is actually available for use, the
+following macro should be used:
 
-@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
+@deftypefun gcry_error_t gcry_md_test_algo (int @var{algo}) 
 
-@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}.
+The macro returns 0 if the algorithm @var{algo} is available for use.
 @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
+If the length of a message digest is not known, it can be retrieved
+using the following function:
 
-@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 unsigned int gcry_md_get_algo_dlen (int @var{algo})
 
-What follows is a description of the high-level functions.
+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
 
-The type ``gcry_ac_em_t'' is used for specifying encoding methods; the
-following methods are supported:
 
-@table @code
-@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.
+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:
 
-@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
+@deftypefun int gcry_md_get_algo (gcry_md_hd_t @var{h})
 
-Option structure types:
+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}.
+@end deftypefun
 
-@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
+The following macro might also be useful:
 
-Encoding methods can be used directly through the following functions:
+@deftypefun int gcry_md_is_secure (gcry_md_hd_t @var{h})
 
-@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}.
+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_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
+@deftypefun int gcry_md_is_enabled (gcry_md_hd_t @var{h}, int @var{algo})
 
-The type ``gcry_ac_scheme_t'' is used for specifying schemes; the
-following schemes are supported:
+This function returns true when the algorithm @var{algo} has been
+enabled for the digest object @var{h}.
+@end deftypefun
 
-@table @code
-@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
 
-Option structure types:
 
-@table @code
-@item gcry_ac_ssa_pkcs_v1_5_t
-@table @code
-@item gcry_md_algo_t md
-@end table
-@end table
+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.
 
-The functions implementing schemes:
+@deftypefun void gcry_md_debug (gcry_md_hd_t @var{h}, const char *@var{suffix})
 
-@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}.
+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
 
-@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
 
-@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
+The following two deprecated macros are used for debugging by old code.
+They shopuld be replaced by @code{gcry_md_debug}.
 
-@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.
+@deftypefun void gcry_md_start_debug (gcry_md_hd_t @var{h}, const char *@var{suffix})
+
+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}.
 @end deftypefun
 
-@node Handle-independent functions
-@section Handle-independent functions
 
-These two functions are deprecated; do not use them for new code.
+@deftypefun void gcry_md_stop_debug (gcry_md_hd_t @var{h}, int @var{reserved})
 
-@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}.
+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
 
-@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
 
 @c **********************************************************
 @c *******************  Random  *****************************
@@ -3588,16 +3719,18 @@ as defined by @var{level}.
 
 @deftypefun void * gcry_random_bytes (size_t @var{nbytes}, enum gcry_random_level @var{level})
 
-Allocate a memory block consisting of @var{nbytes} fresh random bytes
-using a random quality as defined by @var{level}.
+Convenience function to allocate a memory block consisting of
+@var{nbytes} fresh random bytes using a random quality as defined by
+@var{level}.
 @end deftypefun
 
 @deftypefun void * gcry_random_bytes_secure (size_t @var{nbytes}, enum gcry_random_level @var{level})
 
-Allocate a memory block consisting of @var{nbytes} fresh random bytes
-using a random quality as defined by @var{level}.  This function
-differs from @code{gcry_random_bytes} in that the returned buffer is
-allocated in a ``secure'' area of the memory.
+Convenience function to allocate a memory block consisting of
+@var{nbytes} fresh random bytes using a random quality as defined by
+@var{level}.  This function differs from @code{gcry_random_bytes} in
+that the returned buffer is allocated in a ``secure'' area of the
+memory.
 @end deftypefun
 
 @deftypefun void gcry_create_nonce (unsigned char *@var{buffer}, size_t @var{length})
@@ -4132,16 +4265,16 @@ The next 2 functions are used to compare MPIs:
 
 @deftypefun int gcry_mpi_cmp (@w{const gcry_mpi_t @var{u}}, @w{const gcry_mpi_t @var{v}})
 
-Compare the big integer number @var{u} and @var{v} returning 0 for
-equality, a positive value for @var{u} > @var{v} and a negative for
-@var{u} < @var{v}.
+Compare the multi-precision-integers number @var{u} and @var{v}
+returning 0 for equality, a positive value for @var{u} > @var{v} and a
+negative for @var{u} < @var{v}.
 @end deftypefun
 
 @deftypefun int gcry_mpi_cmp_ui (@w{const gcry_mpi_t @var{u}}, @w{unsigned long @var{v}})
 
-Compare the big integer number @var{u} with the unsigned integer @var{v}
-returning 0 for equality, a positive value for @var{u} > @var{v} and a
-negative for @var{u} < @var{v}.
+Compare the multi-precision-integers number @var{u} with the unsigned
+integer @var{v} returning 0 for equality, a positive value for @var{u} >
+@var{v} and a negative for @var{u} < @var{v}.
 @end deftypefun
 
 
@@ -4221,8 +4354,8 @@ stored in "secure memory".
 
 @deftypefun void gcry_mpi_clear_flag (@w{gcry_mpi_t @var{a}}, @w{enum gcry_mpi_flag @var{flag}})
 
-Clear @var{flag} for the big integer @var{a}.  Note that this function is
-currently useless as no flags are allowed.
+Clear @var{flag} for the multi-precision-integers @var{a}.  Note that
+this function is currently useless as no flags are allowed.
 @end deftypefun
 
 @deftypefun int gcry_mpi_get_flag (@w{gcry_mpi_t @var{a}}, @w{enum gcry_mpi_flag @var{flag}})
@@ -4232,10 +4365,10 @@ Return true when the @var{flag} is set for @var{a}.
 
 @deftypefun void gcry_mpi_randomize (@w{gcry_mpi_t @var{w}}, @w{unsigned int @var{nbits}}, @w{enum gcry_random_level @var{level}})
 
-Set the big integer @var{w} to a random value of @var{nbits}, using
-random data quality of level @var{level}.  In case @var{nbits} is not
-a multiple of a byte, @var{nbits} is rounded up to the next byte
-boundary.
+Set the multi-precision-integers @var{w} to a random value of
+@var{nbits}, using random data quality of level @var{level}.  In case
+@var{nbits} is not a multiple of a byte, @var{nbits} is rounded up to
+the next byte boundary.
 @end deftypefun
 
 @c **********************************************************
@@ -4337,74 +4470,167 @@ Release the memory area pointed to by @var{p}.
 @end deftypefun
 
 @c **********************************************************
-@c *******************  Appendices  *************************
+@c *****************  Architecure Overview  *****************
 @c **********************************************************
+@node Architecture
+@chapter Architecture
+
+This chapter describes the internal architecture of Libgcrypt.
+
+Libgcrypt is a function library written in ISO C-90.  Any compliant
+compiler should be able to build Libgcrypt as long as the target is
+either a POSIX platform or compatible to the API used by Windows NT.
+Provisions have been take so that the library can be directly used from
+C++ applications; however building with a C++ compiler is not supported.
+
+Building libgcrypt is done by using the common @code{./configure && make}
+approach.  The configure command is included in the source distribution
+and as a portable shell script it works on any Unix-alike system.  The
+result of running the configure script are a C header file
+(@file{config.h}), customized Makefiles, the setup of symbolic links and
+a few other things.  After that the make tool builds and optionally
+installs the library and the documentation.  See the files
+@file{INSTALL} and @file{README} in the source distribution on how to do
+this.
+
+Libgcrypt is developed using a Subversion@footnote{A version control
+system available for many platforms} repository.  Although all released
+versions are tagged in this repository, they should not be used to build
+production versions of Libgcrypt.  Instead released tarballs should be
+used.  These tarballs are available from several places with the master
+copy at @indicateurl{ftp://ftp.gnupg.org/gcrypt/libgcrypt/}.
+Announcements of new releases are posted to the
+@indicateurl{gnupg-announce@@gnupg.org} mailing list@footnote{See
+@url{http://www.gnupg.org/documentation/mailing-lists.en.html} for
+details.}.
 
-@include lgpl.texi
+@noindent
+Libgcrypt consists of several subsystems as shown by this diagram:
 
-@include gpl.texi
+@center @image{libgcrypt-modules, 10cm,,Module Overview}
 
-@node Concept Index
-@unnumbered Concept Index
+All of these subsystems provide a public API including the helper
+systesm like S-expression.  The API style depends on the subsystem; in
+general an open, use, close approach is implemented.  The open returns a
+handle to a context used for all futher operations on this handle,
+several functions may then be used on this handle and a final close
+function releases all resources associated with the handle.
 
-@printindex cp
+@menu
+* Public-Key Subsystem Architecture::              All about public keys.
+* Symmetric Encryption Subsystem Architecture::    All about standard ciphers.
+* Hashing and MACing Subsystem Architecture::      All about hashing.
+* Multi-Precision-Integer Subsystem Architecture:: All about big integers.
+* Prime-Number-Generator Subsystem Architecture::  All about prime numbers.
+* Random-Number Subsystem Architecture::           All about random stuff.
+* Helper Subsystems Architecture::                 All about other stuff.
+@end menu
 
-@node Function and Data Index
-@unnumbered Function and Data Index
 
-@printindex fn
 
-@bye
+@node Public-Key Subsystem Architecture
+@section Public-Key Architecture
 
-  /* Version check should be the very first gcry call because it
-     makes sure that constructor functions are run. */
-  if (!gcry_check_version (GCRYPT_VERSION))
-    die ("version mismatch\n");
-  /* Many applications don't require secure memory, so they should
-     disable it right away.  There won't be a problem unless one makes
-     use of a feature which requires secure memory - in that case the
-     process would abort because the secmem is not initialized. */
-  gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+TBD.
 
-  /* .. add whatever initialization you want, but better don't make calls
-        to libgcrypt from more than one thread ... */
+@node Symmetric Encryption Subsystem Architecture
+@section Symmetric Encryption Subsystem Architecturen
 
-  /* Tell Libgcrypt that initialization has completed. */
-  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+TBD.
 
+@node Hashing and MACing Subsystem Architecture
+@section Hashing and MACing Subsystem Architecture
 
-If you require secure memory, this code should be used: 
+TBD.
 
-  if (!gcry_check_version (GCRYPT_VERSION))
-    die ("version mismatch\n");
-  /* We don't want to see any warnings, e.g. because we have not yet
-    parsed options which might be used to suppress such warnings */
-  gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
 
-  /* ... */
+@node Multi-Precision-Integer Subsystem Architecture
+@section Multi-Precision-Integer Subsystem Architecture
 
-  /* Allocate a pool of 16k secure memory.  This also drops privileges
-     on some systems. */
-  gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
+TBD.
 
-  /* It is now okay to let Libgcrypt complain when there was/is a problem
-     with the secure memory. */
-  gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
+@node Prime-Number-Generator Subsystem Architecture
+@section Prime-Number-Generator Subsystem Architecture
 
-  /* Tell Libgcrypt that initialization has completed. */
-  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+TBD.
 
+@node Random-Number Subsystem Architecture
+@section Random-Number Subsystem Architecture
 
-This sounds a bit complicated but has the advantage that the caller
-must decide whether he wants secure memory or not - there is no
-default.
+TBD.
 
-It is important that this initialization is not done by a library but
-in the application.  The library might want to check for finished
-initialization using:
 
-  if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P))
-    return MYLIB_ERROR_LIBGCRYPT_NOT_INITIALIZED;
+@node Helper Subsystems Architecture
+@section Helper Subsystems Architecture
+
+There are a few smaller subsystems which are mainly used internally by
+Libgcrypt but also available to applications.
+
+@menu
+* S-expression Subsystem Architecture::   Details about the S-expression architecture.
+* Memory Subsystem Architecture::         Details about the memory allocation architecture.
+* Miscellaneous Subsystems Architecture:: Details about other subsystems.
+@end menu
+
+@node S-expression Subsystem Architecture
+@subsection S-expression Subsystem Architecture
+
+TBD.
+
+
+@node Memory Subsystem Architecture 
+@subsection Memory Subsystem Architecture 
+
+TBD.
+
+
+@node Miscellaneous Subsystems Architecture
+@subsection Miscellaneous Subsystems Architecture
+
+TBD.
+
+
+
+
+
+@c **********************************************************
+@c *******************  Appendices  *************************
+@c **********************************************************
+
+@node FIPS Restrictions
+@appendix Restrictions in FIPS mode
+
+If Libgcrypt is used FIPS mode these restrictions are effective:
+
+@itemize
+
+@item  TBD
+
+
+
+@end itemize
+
+
+
+
+@c **********************************************************
+@c *************  Appendices (license etc.)  ****************
+@c **********************************************************
+@include lgpl.texi
+
+@include gpl.texi
+
+@node Concept Index
+@unnumbered Concept Index
+
+@printindex cp
+
+@node Function and Data Index
+@unnumbered Function and Data Index
+
+@printindex fn
+
+@bye
 
 
 @c  LocalWords:  int HD
index f3e685d..c99eb2d 100644 (file)
@@ -1,3 +1,34 @@
+2008-08-15  Werner Koch  <wk@g10code.com>
+
+       * random-fips.c: New.
+
+       * random-csprng.c (process-cb, progress_cb_data): Move to
+       random.c.
+       (_gcry_register_random_progress, _gcry_random_progress): Ditto.
+       (_gcry_random_initialize): Rename to _gcry_rngcsprng_initialize.
+       (_gcry_random_dump_stats): Rename to _gcry_rngcsprng_dump_stats.
+       (_gcry_secure_random_alloc): Rename to
+       _gcry_rngcsprng_secure_alloc.
+       (_gcry_enable_quick_random_gen): Rename to
+       _gcry_rngcsprng_enable_quick_gen.
+       (_gcry_set_random_daemon_socket): Rename to
+       _gcry_rngcsprng_set_daemon_socket.
+       (_gcry_use_random_daemon): Rename to _gcry_rngcsprng_use_daemon.
+       (_gcry_random_is_faked): Rename to _gcry_rngcsprng_is_faked.
+       (gcry_random_add_bytes): Rename to _gcry_rngcsprng_add_bytes.
+       (gcry_random_bytes): Remove
+       (gcry_random_bytes_secure): Remove.
+       (gcry_randomize): Rename to _gcry_rngcsprng_randomize.
+       (_gcry_set_random_seed_file): Rename to
+       _gcry_rngcsprng_set_seed_file.
+       (_gcry_update_random_seed_file): Rename to
+       _gcry_rngcsprng_update_seed_file.
+       (_gcry_fast_random_poll): Rename to _gcry_rngcsprng_fast_poll.
+       (gcry_create_nonce): Rename to _gcry_rngcsprng_create_nonce.
+
+       * random.c: Factor all code out to random-csprng.c and implement
+       wrapper functions.
+
 2008-07-05  Werner Koch  <wk@g10code.com>
 
        * random-daemon.c, random.h, rndhw.c, rndunix.c, rand-internal.h *
index b5a7c45..336109a 100644 (file)
@@ -32,8 +32,10 @@ librandom_la_LIBADD = $(GCRYPT_MODULES)
 
 librandom_la_SOURCES = \
 random.c random.h \
-rndhw.c \
-rand-internal.h
+rand-internal.h \
+random-csprng.c \
+random-fips.c \
+rndhw.c
 
 if USE_RANDOM_DAEMON
 librandom_la_SOURCES += random-daemon.c 
index 9ba4022..7a2edf5 100644 (file)
@@ -14,9 +14,9 @@
  * 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/>.
  */
+
 #ifndef G10_RAND_INTERNAL_H
 #define G10_RAND_INTERNAL_H
 
@@ -36,24 +36,71 @@ enum random_origins
 
 
 
-
+/*-- random.c --*/
 void _gcry_random_progress (const char *what, int printchar,
                             int current, int total);
 
 
+/*-- random-csprng.c --*/
+void _gcry_rngcsprng_initialize (int full);
+void _gcry_rngcsprng_dump_stats (void);
+void _gcry_rngcsprng_secure_alloc (void);
+void _gcry_rngcsprng_enable_quick_gen (void);
+void _gcry_rngcsprng_set_daemon_socket (const char *socketname);
+int  _gcry_rngcsprng_use_daemon (int onoff);
+int  _gcry_rngcsprng_is_faked (void);
+gcry_error_t _gcry_rngcsprng_add_bytes (const void *buf, size_t buflen,
+                                        int quality);
+void *_gcry_rngcsprng_get_bytes (size_t nbytes,
+                                 enum gcry_random_level level);
+void *_gcry_rngcsprng_get_bytes_secure (size_t nbytes, 
+                                        enum gcry_random_level level);
+void _gcry_rngcsprng_randomize (void *buffer, size_t length,
+                                enum gcry_random_level level);
+void _gcry_rngcsprng_set_seed_file (const char *name);
+void _gcry_rngcsprng_update_seed_file (void);
+void _gcry_rngcsprng_fast_poll (void);
+void _gcry_rngcsprng_create_nonce (void *buffer, size_t length);
+
+/*-- random-rngcsprng.c --*/
+void _gcry_rngfips_initialize (int full);
+void _gcry_rngfips_dump_stats (void);
+int  _gcry_rngfips_is_faked (void);
+gcry_error_t _gcry_rngfips_add_bytes (const void *buf, size_t buflen,
+                                        int quality);
+void *_gcry_rngfips_get_bytes (size_t nbytes,
+                               enum gcry_random_level level);
+void *_gcry_rngfips_get_bytes_secure (size_t nbytes, 
+                                      enum gcry_random_level level);
+void _gcry_rngfips_randomize (void *buffer, size_t length,
+                                enum gcry_random_level level);
+void _gcry_rngfips_create_nonce (void *buffer, size_t length);
+
+
+
+
+
+
+/*-- rndlinux.c --*/
 int _gcry_rndlinux_gather_random (void (*add) (const void *, size_t,
                                                enum random_origins),
                                    enum random_origins origin,
                                   size_t length, int level);
+
+/*-- rndunix.c --*/
 int _gcry_rndunix_gather_random (void (*add) (const void *, size_t,
                                               enum random_origins),
                                  enum random_origins origin,
                                  size_t length, int level);
+
+/*-- rndelg.c --*/
 int _gcry_rndegd_gather_random (void (*add) (const void *, size_t,
                                              enum random_origins),
                                 enum random_origins origin,
                                 size_t length, int level);
 int _gcry_rndegd_connect_socket (int nofail);
+
+/*-- rndw32.c --*/
 int _gcry_rndw32_gather_random (void (*add) (const void *, size_t,
                                              enum random_origins),
                                 enum random_origins origin,
@@ -62,6 +109,7 @@ void _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
                                                   enum random_origins),
                                       enum random_origins origin );
 
+/*-- rndhw.c --*/
 int _gcry_rndhw_failed_p (void);
 void _gcry_rndhw_poll_fast (void (*add)(const void*, size_t,
                                         enum random_origins),
diff --git a/random/random-csprng.c b/random/random-csprng.c
new file mode 100644 (file)
index 0000000..ef16805
--- /dev/null
@@ -0,0 +1,1388 @@
+/* random-csprng.c - CSPRNG style random number generator (libgcrypt clssic)
+ * Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ *               2007, 2008  Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+   This random number generator is modelled after the one described in
+   Peter Gutmann's paper: "Software Generation of Practically Strong
+   Random Numbers". See also chapter 6 in his book "Cryptographic
+   Security Architecture", New York, 2004, ISBN 0-387-95387-6.
+ */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#ifdef HAVE_GETHRTIME
+#include <sys/times.h>
+#endif
+#ifdef HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+#endif
+#ifdef HAVE_GETRUSAGE
+#include <sys/resource.h>
+#endif
+#ifdef __MINGW32__
+#include <process.h>
+#endif
+#include "g10lib.h"
+#include "../cipher/rmd.h"
+#include "random.h"
+#include "rand-internal.h"
+#include "cipher.h" /* Required for the rmd160_hash_buffer() prototype.  */
+#include "ath.h"
+
+#ifndef RAND_MAX   /* For SunOS. */
+#define RAND_MAX 32767
+#endif
+
+/* Check whether we can lock the seed file read write. */
+#if defined(HAVE_FCNTL) && defined(HAVE_FTRUNCATE) && !defined(HAVE_W32_SYSTEM)
+#define LOCK_SEED_FILE 1
+#else
+#define LOCK_SEED_FILE 0
+#endif
+
+/* Define the constant we use for transforming the pool at read-out. */
+#if SIZEOF_UNSIGNED_LONG == 8
+#define ADD_VALUE 0xa5a5a5a5a5a5a5a5
+#elif SIZEOF_UNSIGNED_LONG == 4
+#define ADD_VALUE 0xa5a5a5a5
+#else
+#error weird size for an unsigned long
+#endif
+
+/* Contstants pertaining to the hash pool. */
+#define BLOCKLEN  64   /* Hash this amount of bytes... */
+#define DIGESTLEN 20   /* ... into a digest of this length (rmd160). */
+/* POOLBLOCKS is the number of digests which make up the pool.  */
+#define POOLBLOCKS 30
+/* POOLSIZE must be a multiple of the digest length to make the AND
+   operations faster, the size should also be a multiple of unsigned
+   long.  */
+#define POOLSIZE (POOLBLOCKS*DIGESTLEN)
+#if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
+#error Please make sure that poolsize is a multiple of unsigned long
+#endif
+#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
+
+
+/* RNDPOOL is the pool we use to collect the entropy and to stir it
+   up.  Its allocated size is POOLSIZE+BLOCKLEN.  Note that this is
+   also an indication on whether the module has been fully
+   initialized. */
+static unsigned char *rndpool; 
+
+/* KEYPOOL is used as a scratch copy to read out random from RNDPOOL.
+   Its allocated size is also POOLSIZE+BLOCKLEN.  */
+static unsigned char *keypool; 
+
+/* This is the offset into RNDPOOL where the next random bytes are to
+   be mixed in.  */
+static size_t pool_writepos;
+
+/* When reading data out of KEYPOOL, we start the read at different
+   positions.  This variable keeps track on where to read next.  */
+static size_t pool_readpos;
+
+/* This flag is set to true as soon as the pool has been completely
+   filled the first time.  This may happen either by rereading a seed
+   file or by adding enough entropy.  */
+static int pool_filled;
+
+/* This counter is used to track whether the initial seeding has been
+   done with enough bytes from a reliable entropy source.  */
+static size_t pool_filled_counter;
+
+/* If random of level GCRY_VERY_STRONG_RANDOM has been requested we
+   have stricter requirements on what kind of entropy is in the pool.
+   In particular POOL_FILLED is not sufficient.  Thus we add some
+   extra seeding and set this flag to true if the extra seeding has
+   been done.  */
+static int did_initial_extra_seeding;
+
+/* This variable is used to estimated the amount of fresh entropy
+   available in RNDPOOL.  */
+static int pool_balance;
+
+/* After a mixing operation this variable will be set to true and
+   cleared if new entropy has been added or a remix is required for
+   otehr reasons.  */
+static int just_mixed;
+
+/* The name of the seed file or NULL if no seed file has been defined.
+   The seed file needs to be regsitered at initialiation time.  We
+   keep a malloced copy here.  */
+static char *seed_file_name;
+
+/* If a seed file has been registered and maybe updated on exit this
+   flag set. */
+static int allow_seed_file_update;
+
+/* Option flag set at initialiation time to force allocation of the
+   pool in secure memory.  */
+static int secure_alloc;
+
+/* This function pointer is set to the actual entropy gathering
+   function during initailization.  After initialization it is
+   guaranteed to point to function.  (On systems without a random
+   gatherer module a dummy function is used).*/
+static int (*slow_gather_fnc)(void (*)(const void*, size_t,
+                                       enum random_origins),
+                              enum random_origins, size_t, int);
+
+/* This function is set to the actual fast entropy gathering fucntion
+   during initialization.  If it is NULL, no such function is
+   available. */
+static void (*fast_gather_fnc)(void (*)(const void*, size_t,
+                                        enum random_origins),
+                               enum random_origins);
+
+
+/* Option flag useful for debugging and the test suite.  If set
+   requests for very strong random are degraded to strong random.  Not
+   used by regular applications.  */
+static int quick_test;
+
+/* On systems without entropy gathering modules, this flag is set to
+   indicate that the random generator is not working properly.  A
+   warning message is issued as well.  This is useful only for
+   debugging and during development.  */
+static int faked_rng;
+
+/* This is the lock we use to protect all pool operations.  */
+static ath_mutex_t pool_lock = ATH_MUTEX_INITIALIZER;
+
+/* This is a helper for assert calls.  These calls are used to assert
+   that functions are called in a locked state.  It is not meant to be
+   thread-safe but as a method to get aware of missing locks in the
+   test suite.  */
+static int pool_is_locked;
+
+/* This is the lock we use to protect the buffer used by the nonce
+   generation.  */
+static ath_mutex_t nonce_buffer_lock = ATH_MUTEX_INITIALIZER;
+
+
+/* We keep some counters in this structure for the sake of the
+   _gcry_random_dump_stats () function.  */
+static struct
+{
+  unsigned long mixrnd;
+  unsigned long mixkey;
+  unsigned long slowpolls;
+  unsigned long fastpolls;
+  unsigned long getbytes1;
+  unsigned long ngetbytes1;
+  unsigned long getbytes2;
+  unsigned long ngetbytes2;
+  unsigned long addbytes;
+  unsigned long naddbytes;
+} rndstats;
+
+
+
+/* --- Stuff pertaining to the random daemon support. --- */
+#ifdef USE_RANDOM_DAEMON
+
+/* If ALLOW_DAEMON is true, the module will try to use the random
+   daemon first.  If the daemon has failed, this variable is set to
+   back to false and the code continues as normal.  Note, we don't
+   test this flag in a locked state because a wrong value does not
+   harm and the trhead will find out itself that the daemon does not
+   work and set it (again) to false.  */
+static int allow_daemon;       
+
+/* During initialization, the user may set a non-default socket name
+   for accessing the random daemon.  If this value is NULL, the
+   default name will be used. */
+static char *daemon_socket_name;
+
+#endif /*USE_RANDOM_DAEMON*/
+
+
+
+/* ---  Prototypes  --- */
+static void read_pool (byte *buffer, size_t length, int level );
+static void add_randomness (const void *buffer, size_t length, 
+                            enum random_origins origin);
+static void random_poll (void);
+static void do_fast_random_poll (void);
+static int (*getfnc_gather_random (void))(void (*)(const void*, size_t, 
+                                                   enum random_origins), 
+                                          enum random_origins, size_t, int);
+static void (*getfnc_fast_random_poll (void))(void (*)(const void*, size_t,
+                                                       enum random_origins),
+                                              enum random_origins);
+static void read_random_source (enum random_origins origin,
+                                size_t length, int level);
+static int gather_faked (void (*add)(const void*, size_t, enum random_origins),
+                         enum random_origins, size_t length, int level );
+
+
+\f
+/* ---  Functions  --- */
+
+
+/* Basic initialization which is required to initialize mutexes and
+   such.  It does not run a full initialization so that the filling of
+   the random pool can be delayed until it is actually needed.  We
+   assume that this function is used before any concurrent access
+   happens. */
+static void
+initialize_basics(void)
+{
+  static int initialized;
+  int err;
+
+  if (!initialized)
+    {
+      initialized = 1;
+      err = ath_mutex_init (&pool_lock);
+      if (err)
+        log_fatal ("failed to create the pool lock: %s\n", strerror (err) );
+      
+      err = ath_mutex_init (&nonce_buffer_lock);
+      if (err)
+        log_fatal ("failed to create the nonce buffer lock: %s\n",
+                   strerror (err) );
+
+#ifdef USE_RANDOM_DAEMON
+      _gcry_daemon_initialize_basics ();
+#endif /*USE_RANDOM_DAEMON*/
+
+      /* Make sure that we are still using the values we have
+         traditionally used for the random levels.  */
+      assert ( GCRY_WEAK_RANDOM == 0 
+               && GCRY_STRONG_RANDOM == 1
+               && GCRY_VERY_STRONG_RANDOM == 2);
+    }
+}
+
+/* Take the pool lock. */
+static void
+lock_pool (void)
+{
+  int err; 
+
+  err = ath_mutex_lock (&pool_lock);
+  if (err)
+    log_fatal ("failed to acquire the pool lock: %s\n", strerror (err));
+  pool_is_locked = 1;
+}
+
+/* Release the pool lock. */
+static void
+unlock_pool (void)
+{
+  int err; 
+
+  pool_is_locked = 0;
+  err = ath_mutex_unlock (&pool_lock);
+  if (err)
+    log_fatal ("failed to release the pool lock: %s\n", strerror (err));
+}
+
+
+/* Full initialization of this module. */
+static void
+initialize(void)
+{
+  /* Although the basic initialization should have happened already,
+     we call it here to make sure that all prerequisites are met.  */
+  initialize_basics ();
+
+  /* Now we can look the pool and complete the initialization if
+     necessary.  */
+  lock_pool ();
+  if (!rndpool)
+    {
+      /* The data buffer is allocated somewhat larger, so that we can
+         use this extra space (which is allocated in secure memory) as
+         a temporary hash buffer */
+      rndpool = (secure_alloc
+                 ? gcry_xcalloc_secure (1, POOLSIZE + BLOCKLEN)
+                 : gcry_xcalloc (1, POOLSIZE + BLOCKLEN));
+      keypool = (secure_alloc
+                 ? gcry_xcalloc_secure (1, POOLSIZE + BLOCKLEN)
+                 : gcry_xcalloc (1, POOLSIZE + BLOCKLEN));
+
+      /* Setup the slow entropy gathering function.  The code requires
+         that this function exists. */
+      slow_gather_fnc = getfnc_gather_random ();
+      if (!slow_gather_fnc)
+        {
+          faked_rng = 1;
+          slow_gather_fnc = gather_faked;
+       }
+      
+      /* Setup the fast entropy gathering function.  */
+      fast_gather_fnc = getfnc_fast_random_poll ();
+
+    }
+  unlock_pool ();
+}
+
+
+
+
+/* Initialize this random subsystem.  If FULL is false, this function
+   merely calls the initialize and does not do anything more.  Doing
+   this is not really required but when running in a threaded
+   environment we might get a race condition otherwise. */
+void
+_gcry_rngcsprng_initialize (int full)
+{
+  if (!full)
+    initialize_basics ();
+  else
+    initialize ();
+}
+
+
+void
+_gcry_rngcsprng_dump_stats (void)
+{
+  /* FIXME: don't we need proper locking here? -mo.  
+     Yes. However this is usually called during cleanup and thenwe _
+     might_ run into problems.  Needs to be checked.  -wk */
+
+  log_info ("random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n"
+           "              outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu%s\n",
+            POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls,
+            rndstats.naddbytes, rndstats.addbytes,
+            rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1,
+            rndstats.ngetbytes2, rndstats.getbytes2,
+            _gcry_rndhw_failed_p()? " (hwrng failed)":"");
+}
+
+
+/* This function should be called during initialization and before
+   intialization of this module to place the random pools into secure
+   memory.  */
+void
+_gcry_rngcsprng_secure_alloc (void)
+{
+  secure_alloc = 1;
+}
+
+
+/* This may be called before full initialization to degrade the
+   quality of the RNG for the sake of a faster running test suite.  */
+void
+_gcry_rngcsprng_enable_quick_gen (void)
+{
+  quick_test = 1;
+}
+
+
+void
+_gcry_rngcsprng_set_daemon_socket (const char *socketname)
+{
+#ifdef USE_RANDOM_DAEMON
+  if (daemon_socket_name)
+    BUG ();
+
+  daemon_socket_name = gcry_xstrdup (socketname);
+#else /*!USE_RANDOM_DAEMON*/
+  (void)socketname;
+#endif /*!USE_RANDOM_DAEMON*/
+}
+
+/* With ONOFF set to 1, enable the use of the daemon.  With ONOFF set
+   to 0, disable the use of the daemon.  With ONOF set to -1, return
+   whether the daemon has been enabled. */
+int
+_gcry_rngcsprng_use_daemon (int onoff)
+{
+#ifdef USE_RANDOM_DAEMON
+  int last;
+  
+  /* FIXME: This is not really thread safe. */
+  last = allow_daemon;
+  if (onoff != -1)
+    allow_daemon = onoff;
+
+  return last;
+#else /*!USE_RANDOM_DAEMON*/
+  (void)onoff;
+  return 0;
+#endif /*!USE_RANDOM_DAEMON*/
+}
+
+
+/* This function returns true if no real RNG is available or the
+   quality of the RNG has been degraded for test purposes.  */
+int
+_gcry_rngcsprng_is_faked (void)
+{
+  /* We need to initialize due to the runtime determination of
+     available entropy gather modules.  */
+  initialize();
+  return (faked_rng || quick_test);
+}
+
+
+/* Add BUFLEN bytes from BUF to the internal random pool.  QUALITY
+   should be in the range of 0..100 to indicate the goodness of the
+   entropy added, or -1 for goodness not known.  */
+gcry_error_t
+_gcry_rngcsprng_add_bytes (const void *buf, size_t buflen, int quality)
+{
+  size_t nbytes;
+  const char *bufptr;
+
+  if (quality == -1)
+    quality = 35;
+  else if (quality > 100)
+    quality = 100;
+  else if (quality < 0)
+    quality = 0;
+      
+  if (!buf)
+    return gpg_error (GPG_ERR_INV_ARG);
+
+  if (!buflen || quality < 10)
+    return 0; /* Take a shortcut. */
+
+  /* Because we don't increment the entropy estimation with FASTPOLL,
+     we don't need to take lock that estimation while adding from an
+     external source.  This limited entropy estimation also means that
+     we can't take QUALITY into account.  */
+  initialize_basics ();
+  bufptr = buf;
+  while (buflen)
+    {
+      nbytes = buflen > POOLSIZE? POOLSIZE : buflen;
+      lock_pool ();
+      if (rndpool)
+        add_randomness (bufptr, nbytes, RANDOM_ORIGIN_EXTERNAL);
+      unlock_pool ();
+      bufptr += nbytes;
+      buflen -= nbytes;
+    }
+  return 0;
+}   
+
+    
+/* Public function to fill the buffer with LENGTH bytes of
+   cryptographically strong random bytes.  Level GCRY_WEAK_RANDOM is
+   not very strong, GCRY_STRONG_RANDOM is strong enough for most
+   usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but
+   may be very slow.  */
+void
+_gcry_rngcsprng_randomize (void *buffer, size_t length,
+                           enum gcry_random_level level)
+{
+  unsigned char *p;
+
+  /* Make sure we are initialized. */
+  initialize ();
+
+  /* Handle our hack used for regression tests of Libgcrypt. */
+  if ( quick_test && level > GCRY_STRONG_RANDOM )
+    level = GCRY_STRONG_RANDOM;
+
+  /* Make sure the level is okay. */
+  level &= 3;
+
+#ifdef USE_RANDOM_DAEMON
+  if (allow_daemon
+      && !_gcry_daemon_randomize (daemon_socket_name, buffer, length, level))
+    return; /* The daemon succeeded. */
+  allow_daemon = 0; /* Daemon failed - switch off. */
+#endif /*USE_RANDOM_DAEMON*/
+
+  /* Acquire the pool lock. */
+  lock_pool ();
+
+  /* Update the statistics. */
+  if (level >= GCRY_VERY_STRONG_RANDOM)
+    {
+      rndstats.getbytes2 += length;
+      rndstats.ngetbytes2++;
+    }
+  else
+    {
+      rndstats.getbytes1 += length;
+      rndstats.ngetbytes1++;
+    }
+
+  /* Read the random into the provided buffer. */
+  for (p = buffer; length > 0;)
+    {
+      size_t n;
+
+      n = length > POOLSIZE? POOLSIZE : length;
+      read_pool (p, n, level);
+      length -= n;
+      p += n;
+    }
+
+  /* Release the pool lock. */
+  unlock_pool ();
+}
+
+
+
+
+/*
+   Mix the pool:
+
+   |........blocks*20byte........|20byte|..44byte..|
+   <..44byte..>           <20byte> 
+        |                    |
+        |                    +------+
+        +---------------------------|----------+
+                                    v          v
+   |........blocks*20byte........|20byte|..44byte..|
+                                 <.....64bytes.....>   
+                                         |
+      +----------------------------------+
+     Hash
+      v
+   |.............................|20byte|..44byte..|
+   <20byte><20byte><..44byte..>
+      |                |
+      |                +---------------------+
+      +-----------------------------+        |
+                                    v        v
+   |.............................|20byte|..44byte..|
+                                 <.....64byte......>
+                                        |
+              +-------------------------+
+             Hash
+              v
+   |.............................|20byte|..44byte..|
+   <20byte><20byte><..44byte..>
+
+   and so on until we did this for all blocks. 
+
+   To better protect against implementation errors in this code, we
+   xor a digest of the entire pool into the pool before mixing.
+
+   Note: this function must only be called with a locked pool.
+ */
+static void
+mix_pool(unsigned char *pool)
+{
+  static unsigned char failsafe_digest[DIGESTLEN];
+  static int failsafe_digest_valid;
+
+  unsigned char *hashbuf = pool + POOLSIZE;
+  unsigned char *p, *pend;
+  int i, n;
+  RMD160_CONTEXT md;
+
+#if DIGESTLEN != 20
+#error must have a digest length of 20 for ripe-md-160
+#endif
+
+  assert (pool_is_locked);
+  _gcry_rmd160_init( &md );
+
+  /* Loop over the pool.  */
+  pend = pool + POOLSIZE;
+  memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN );
+  memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
+  _gcry_rmd160_mixblock( &md, hashbuf);
+  memcpy(pool, hashbuf, 20 );
+
+  if (failsafe_digest_valid && pool == rndpool)
+    {
+      for (i=0; i < 20; i++)
+        pool[i] ^= failsafe_digest[i];
+    }
+  
+  p = pool;
+  for (n=1; n < POOLBLOCKS; n++)
+    {
+      memcpy (hashbuf, p, DIGESTLEN);
+
+      p += DIGESTLEN;
+      if (p+DIGESTLEN+BLOCKLEN < pend)
+        memcpy (hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN);
+      else 
+        {
+          unsigned char *pp = p + DIGESTLEN;
+          
+          for (i=DIGESTLEN; i < BLOCKLEN; i++ )
+            {
+              if ( pp >= pend )
+                pp = pool;
+              hashbuf[i] = *pp++;
+           }
+       }
+      
+      _gcry_rmd160_mixblock ( &md, hashbuf);
+      memcpy(p, hashbuf, 20 );
+    }
+
+    /* Our hash implementation does only leave small parts (64 bytes)
+       of the pool on the stack, so it is okay not to require secure
+       memory here.  Before we use this pool, it will be copied to the
+       help buffer anyway. */
+    if ( pool == rndpool)
+      {
+        _gcry_rmd160_hash_buffer (failsafe_digest, pool, POOLSIZE);
+        failsafe_digest_valid = 1;
+      }
+
+    _gcry_burn_stack (384); /* for the rmd160_mixblock(), rmd160_hash_buffer */
+}
+
+
+void
+_gcry_rngcsprng_set_seed_file (const char *name)
+{
+  if (seed_file_name)
+    BUG ();
+  seed_file_name = gcry_xstrdup (name);
+}
+
+
+/* Lock an open file identified by file descriptor FD and wait a
+   reasonable time to succeed.  With FOR_WRITE set to true a write
+   lock will be taken.  FNAME is used only for diagnostics. Returns 0
+   on success or -1 on error. */
+static int
+lock_seed_file (int fd, const char *fname, int for_write)
+{
+#if LOCK_SEED_FILE
+  struct flock lck;
+  struct timeval tv;
+  int backoff=0;
+
+  /* We take a lock on the entire file. */
+  memset (&lck, 0, sizeof lck);
+  lck.l_type = for_write? F_WRLCK : F_RDLCK;
+  lck.l_whence = SEEK_SET;
+
+  while (fcntl (fd, F_SETLK, &lck) == -1)
+    {
+      if (errno != EAGAIN && errno != EACCES)
+        {
+          log_info (_("can't lock `%s': %s\n"), fname, strerror (errno));
+          return -1;
+        }
+
+      if (backoff > 2) /* Show the first message after ~2.25 seconds. */
+        log_info( _("waiting for lock on `%s'...\n"), fname);
+      
+      tv.tv_sec = backoff;
+      tv.tv_usec = 250000;
+      select (0, NULL, NULL, NULL, &tv);
+      if (backoff < 10)
+        backoff++ ;
+    }
+#endif /*LOCK_SEED_FILE*/
+  return 0;
+}
+
+
+/* Read in a seed from the random_seed file and return true if this
+   was successful.
+
+   Note: Multiple instances of applications sharing the same random
+   seed file can be started in parallel, in which case they will read
+   out the same pool and then race for updating it (the last update
+   overwrites earlier updates).  They will differentiate only by the
+   weak entropy that is added in read_seed_file based on the PID and
+   clock, and up to 16 bytes of weak random non-blockingly.  The
+   consequence is that the output of these different instances is
+   correlated to some extent.  In the perfect scenario, the attacker
+   can control (or at least guess) the PID and clock of the
+   application, and drain the system's entropy pool to reduce the "up
+   to 16 bytes" above to 0.  Then the dependencies of the inital
+   states of the pools are completely known.  */
+static int
+read_seed_file (void)
+{
+  int fd;
+  struct stat sb;
+  unsigned char buffer[POOLSIZE];
+  int n;
+
+  assert (pool_is_locked);
+
+  if (!seed_file_name)
+    return 0;
+  
+#ifdef HAVE_DOSISH_SYSTEM
+  fd = open( seed_file_name, O_RDONLY | O_BINARY );
+#else
+  fd = open( seed_file_name, O_RDONLY );
+#endif
+  if( fd == -1 && errno == ENOENT)
+    {
+      allow_seed_file_update = 1;
+      return 0;
+    }
+
+  if (fd == -1 )
+    {
+      log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
+      return 0;
+    }
+  if (lock_seed_file (fd, seed_file_name, 0))
+    {
+      close (fd);
+      return 0;
+    }
+  if (fstat( fd, &sb ) )
+    {
+      log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
+      close(fd);
+      return 0;
+    }
+  if (!S_ISREG(sb.st_mode) )
+    {
+      log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
+      close(fd);
+      return 0;
+    }
+  if (!sb.st_size )
+    {
+      log_info(_("note: random_seed file is empty\n") );
+      close(fd);
+      allow_seed_file_update = 1;
+      return 0;
+    }
+  if (sb.st_size != POOLSIZE ) 
+    {
+      log_info(_("warning: invalid size of random_seed file - not used\n") );
+      close(fd);
+      return 0;
+    }
+
+  do
+    {
+      n = read( fd, buffer, POOLSIZE );
+    } 
+  while (n == -1 && errno == EINTR );
+
+  if (n != POOLSIZE)
+    {
+      log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
+      close(fd);/*NOTREACHED*/
+      return 0;
+    }
+  
+  close(fd);
+
+  add_randomness( buffer, POOLSIZE, RANDOM_ORIGIN_INIT );
+  /* add some minor entropy to the pool now (this will also force a mixing) */
+  {    
+    pid_t x = getpid();
+    add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
+  }
+  {
+    time_t x = time(NULL);
+    add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
+  }
+  {    
+    clock_t x = clock();
+    add_randomness( &x, sizeof(x), RANDOM_ORIGIN_INIT );
+  }
+
+  /* And read a few bytes from our entropy source.  By using a level
+   * of 0 this will not block and might not return anything with some
+   * entropy drivers, however the rndlinux driver will use
+   * /dev/urandom and return some stuff - Do not read too much as we
+   * want to be friendly to the scare system entropy resource. */
+  read_random_source ( RANDOM_ORIGIN_INIT, 16, GCRY_WEAK_RANDOM );
+
+  allow_seed_file_update = 1;
+  return 1;
+}
+
+
+void
+_gcry_rngcsprng_update_seed_file (void)
+{
+  unsigned long *sp, *dp;
+  int fd, i;
+
+  /* We do only a basic initialization so that we can lock the pool.
+     This is required to cope with the case that this function is
+     called by some cleanup code at a point where the RNG has never
+     been initialized.  */
+  initialize_basics ();
+  lock_pool ();
+
+  if ( !seed_file_name || !rndpool || !pool_filled )
+    {
+      unlock_pool ();
+      return;
+    }
+  if ( !allow_seed_file_update )
+    {
+      unlock_pool ();
+      log_info(_("note: random_seed file not updated\n"));
+      return;
+    }
+
+  /* At this point we know that there is something in the pool and
+     thus we can conclude that the pool has been fully initialized.  */
+
+
+  /* Copy the entropy pool to a scratch pool and mix both of them. */
+  for (i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool;
+       i < POOLWORDS; i++, dp++, sp++ ) 
+    {
+      *dp = *sp + ADD_VALUE;
+    }
+  mix_pool(rndpool); rndstats.mixrnd++;
+  mix_pool(keypool); rndstats.mixkey++;
+
+#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
+  fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
+             S_IRUSR|S_IWUSR );
+#else
+# if LOCK_SEED_FILE
+    fd = open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
+# else
+    fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
+# endif
+#endif
+
+  if (fd == -1 )
+    log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
+  else if (lock_seed_file (fd, seed_file_name, 1))
+    {
+      close (fd);
+    }
+#if LOCK_SEED_FILE
+  else if (ftruncate (fd, 0))
+    {
+      log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno));
+      close (fd);
+    }
+#endif /*LOCK_SEED_FILE*/
+  else 
+    {
+      do
+        {
+          i = write (fd, keypool, POOLSIZE );
+        } 
+      while (i == -1 && errno == EINTR);
+      if (i != POOLSIZE) 
+        log_info (_("can't write `%s': %s\n"),seed_file_name, strerror(errno));
+      if (close(fd))
+        log_info (_("can't close `%s': %s\n"),seed_file_name, strerror(errno));
+    }
+  
+  unlock_pool ();
+}
+
+
+/* Read random out of the pool.  This function is the core of the
+   public random functions.  Note that Level GCRY_WEAK_RANDOM is not
+   anymore handled special and in fact is an alias in the API for
+   level GCRY_STRONG_RANDOM.  Must be called with the pool already
+   locked.  */
+static void
+read_pool (byte *buffer, size_t length, int level)
+{
+  int i;
+  unsigned long *sp, *dp;
+  /* The volatile is there to make sure the compiler does not optimize
+     the code away in case the getpid function is badly attributed.
+     Note that we keep a pid in a static variable as well as in a
+     stack based one; the latter is to detect ill behaving thread
+     libraries, ignoring the pool mutexes. */
+  static volatile pid_t my_pid = (pid_t)(-1); 
+  volatile pid_t my_pid2;
+
+  assert (pool_is_locked);
+
+ retry:
+  /* Get our own pid, so that we can detect a fork. */
+  my_pid2 = getpid ();
+  if (my_pid == (pid_t)(-1))                                
+    my_pid = my_pid2;
+  if ( my_pid != my_pid2 )
+    {
+      /* We detected a plain fork; i.e. we are now the child.  Update
+         the static pid and add some randomness. */
+      pid_t x;
+
+      my_pid = my_pid2;
+      x = my_pid;
+      add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT);
+      just_mixed = 0; /* Make sure it will get mixed. */
+    }
+
+  assert (pool_is_locked);
+
+  /* Our code does not allow to extract more than POOLSIZE.  Better
+     check it here. */
+  if (length > POOLSIZE)
+    {
+      log_bug("too many random bits requested\n");
+    }
+
+  if (!pool_filled)
+    {
+      if (read_seed_file() )
+        pool_filled = 1;
+    }
+
+  /* For level 2 quality (key generation) we always make sure that the
+     pool has been seeded enough initially. */
+  if (level == GCRY_VERY_STRONG_RANDOM && !did_initial_extra_seeding)
+    {
+      size_t needed;
+
+      pool_balance = 0;
+      needed = length - pool_balance;
+      if (needed < POOLSIZE/2)
+        needed = POOLSIZE/2;
+      else if( needed > POOLSIZE )
+        BUG ();
+      read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed,
+                          GCRY_VERY_STRONG_RANDOM);
+      pool_balance += needed;
+      did_initial_extra_seeding = 1;
+    }
+
+  /* For level 2 make sure that there is enough random in the pool. */
+  if (level == GCRY_VERY_STRONG_RANDOM && pool_balance < length)
+    {
+      size_t needed;
+      
+      if (pool_balance < 0)
+        pool_balance = 0;
+      needed = length - pool_balance;
+      if (needed > POOLSIZE)
+        BUG ();
+      read_random_source (RANDOM_ORIGIN_EXTRAPOLL, needed,
+                          GCRY_VERY_STRONG_RANDOM);
+      pool_balance += needed;
+    }
+
+  /* Make sure the pool is filled. */
+  while (!pool_filled)
+    random_poll();
+
+  /* Always do a fast random poll (we have to use the unlocked version). */
+  do_fast_random_poll();
+  
+  /* Mix the pid in so that we for sure won't deliver the same random
+     after a fork. */
+  {
+    pid_t apid = my_pid;
+    add_randomness (&apid, sizeof (apid), RANDOM_ORIGIN_INIT);
+  }
+
+  /* Mix the pool (if add_randomness() didn't it). */
+  if (!just_mixed)
+    {
+      mix_pool(rndpool);
+      rndstats.mixrnd++;
+    }
+
+  /* Create a new pool. */
+  for(i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool;
+      i < POOLWORDS; i++, dp++, sp++ )
+    *dp = *sp + ADD_VALUE;
+
+  /* Mix both pools. */
+  mix_pool(rndpool); rndstats.mixrnd++;
+  mix_pool(keypool); rndstats.mixkey++;
+
+  /* Read the requested data.  We use a read pointer to read from a
+     different position each time.  */
+  while (length--)
+    {
+      *buffer++ = keypool[pool_readpos++];
+      if (pool_readpos >= POOLSIZE)
+        pool_readpos = 0;
+      pool_balance--;
+    }
+  if (pool_balance < 0)
+    pool_balance = 0;
+
+  /* Clear the keypool. */
+  memset (keypool, 0, POOLSIZE);
+
+  /* We need to detect whether a fork has happened.  A fork might have
+     an identical pool and thus the child and the parent could emit
+     the very same random number.  This test here is to detect forks
+     in a multi-threaded process.  It does not work with all thread
+     implementations in particular not with pthreads.  However it is
+     good enough for GNU Pth. */
+  if ( getpid () != my_pid2 )
+    {
+      pid_t x = getpid();
+      add_randomness (&x, sizeof(x), RANDOM_ORIGIN_INIT);
+      just_mixed = 0; /* Make sure it will get mixed. */
+      my_pid = x;     /* Also update the static pid. */
+      goto retry;
+    }
+}
+
+
+
+/* Add LENGTH bytes of randomness from buffer to the pool.  ORIGIN is
+   used to specify the randomness origin.  This is one of the
+   RANDOM_ORIGIN_* values. */
+static void
+add_randomness (const void *buffer, size_t length, enum random_origins origin)
+{
+  const unsigned char *p = buffer;
+  size_t count = 0;
+
+  assert (pool_is_locked);
+
+  rndstats.addbytes += length;
+  rndstats.naddbytes++;
+  while (length-- )
+    {
+      rndpool[pool_writepos++] ^= *p++;
+      count++;
+      if (pool_writepos >= POOLSIZE )
+        {
+          /* It is possible that we are invoked before the pool is
+             filled using an unreliable origin of entropy, for example
+             the fast random poll.  To avoid flagging the pool as
+             filled in this case, we track the initial filling state
+             separately.  See also the remarks about the seed file. */
+          if (origin >= RANDOM_ORIGIN_SLOWPOLL && !pool_filled)
+            {
+              pool_filled_counter += count;
+              count = 0;
+              if (pool_filled_counter >= POOLSIZE)
+                pool_filled = 1;
+            }
+          pool_writepos = 0;
+          mix_pool(rndpool); rndstats.mixrnd++;
+          just_mixed = !length;
+       }
+    }
+}
+
+
+
+static void
+random_poll()
+{
+  rndstats.slowpolls++;
+  read_random_source (RANDOM_ORIGIN_SLOWPOLL, POOLSIZE/5, GCRY_STRONG_RANDOM);
+}
+
+
+/* Runtime determination of the slow entropy gathering module.  */
+static int (*
+getfnc_gather_random (void))(void (*)(const void*, size_t, 
+                                      enum random_origins), 
+                             enum random_origins, size_t, int)
+{
+  int (*fnc)(void (*)(const void*, size_t, enum random_origins), 
+             enum random_origins, size_t, int);
+  
+#if USE_RNDLINUX
+  if ( !access (NAME_OF_DEV_RANDOM, R_OK)
+       && !access (NAME_OF_DEV_URANDOM, R_OK))
+    {
+      fnc = _gcry_rndlinux_gather_random;
+      return fnc;
+    }
+#endif
+
+#if USE_RNDEGD
+  if ( _gcry_rndegd_connect_socket (1) != -1 )
+    {
+      fnc = _gcry_rndegd_gather_random;
+      return fnc;
+    }
+#endif
+
+#if USE_RNDUNIX
+  fnc = _gcry_rndunix_gather_random;
+  return fnc;
+#endif
+
+#if USE_RNDW32
+  fnc = _gcry_rndw32_gather_random;
+  return fnc;
+#endif
+
+  log_fatal (_("no entropy gathering module detected\n"));
+
+  return NULL; /*NOTREACHED*/
+}
+
+/* Runtime determination of the fast entropy gathering function.
+   (Currently a compile time method is used.)  */
+static void (*
+getfnc_fast_random_poll (void))( void (*)(const void*, size_t,
+                                          enum random_origins),
+                                 enum random_origins)
+{
+#if USE_RNDW32
+  return _gcry_rndw32_gather_random_fast;
+#endif
+  return NULL;
+}
+
+
+
+static void
+do_fast_random_poll (void)
+{
+  assert (pool_is_locked);
+
+  rndstats.fastpolls++;
+
+  if (fast_gather_fnc)
+    fast_gather_fnc (add_randomness, RANDOM_ORIGIN_FASTPOLL);
+
+  /* Continue with the generic functions. */
+#if HAVE_GETHRTIME
+  {    
+    hrtime_t tv;
+    tv = gethrtime();
+    add_randomness( &tv, sizeof(tv), RANDOM_ORIGIN_FASTPOLL );
+  }
+#elif HAVE_GETTIMEOFDAY
+  {    
+    struct timeval tv;
+    if( gettimeofday( &tv, NULL ) )
+      BUG();
+    add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL );
+    add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), RANDOM_ORIGIN_FASTPOLL );
+  }
+#elif HAVE_CLOCK_GETTIME
+  {    struct timespec tv;
+  if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
+    BUG();
+  add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), RANDOM_ORIGIN_FASTPOLL );
+  add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), RANDOM_ORIGIN_FASTPOLL );
+  }
+#else /* use times */
+# ifndef HAVE_DOSISH_SYSTEM
+  {    struct tms buf;
+  times( &buf );
+  add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL );
+  }
+# endif
+#endif
+
+#ifdef HAVE_GETRUSAGE
+# ifdef RUSAGE_SELF
+  {    
+    struct rusage buf;
+    /* QNX/Neutrino does return ENOSYS - so we just ignore it and add
+       whatever is in buf.  In a chroot environment it might not work
+       at all (i.e. because /proc/ is not accessible), so we better
+       ignore all error codes and hope for the best. */
+    getrusage (RUSAGE_SELF, &buf );
+    add_randomness( &buf, sizeof buf, RANDOM_ORIGIN_FASTPOLL );
+    memset( &buf, 0, sizeof buf );
+  }
+# else /*!RUSAGE_SELF*/
+#  ifdef __GCC__
+#   warning There is no RUSAGE_SELF on this system
+#  endif
+# endif /*!RUSAGE_SELF*/
+#endif /*HAVE_GETRUSAGE*/
+
+  /* Time and clock are availabe on all systems - so we better do it
+     just in case one of the above functions didn't work.  */
+  {
+    time_t x = time(NULL);
+    add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL );
+  }
+  {    
+    clock_t x = clock();
+    add_randomness( &x, sizeof(x), RANDOM_ORIGIN_FASTPOLL );
+  }
+
+  /* If the system features a fast hardware RNG, read some bytes from
+     there.  */
+  _gcry_rndhw_poll_fast (add_randomness, RANDOM_ORIGIN_FASTPOLL);
+}
+
+
+/* The fast random pool function as called at some places in
+   libgcrypt.  This is merely a wrapper to make sure that this module
+   is initalized and to look the pool.  Note, that this function is a
+   NOP unless a random function has been used or _gcry_initialize (1)
+   has been used.  We use this hack so that the internal use of this
+   function in cipher_open and md_open won't start filling up the
+   random pool, even if no random will be required by the process. */
+void
+_gcry_rngcsprng_fast_poll (void)
+{
+  initialize_basics ();
+
+  lock_pool ();
+  if (rndpool)
+    {
+      /* Yes, we are fully initialized. */
+      do_fast_random_poll ();
+    }
+  unlock_pool ();
+}
+
+
+
+static void
+read_random_source (enum random_origins orgin, size_t length, int level )
+{
+  if ( !slow_gather_fnc )
+    log_fatal ("Slow entropy gathering module not yet initialized\n");
+
+  if ( slow_gather_fnc (add_randomness, orgin, length, level) < 0)
+    log_fatal ("No way to gather entropy for the RNG\n");
+}
+
+
+static int
+gather_faked (void (*add)(const void*, size_t, enum random_origins),
+              enum random_origins origin, size_t length, int level )
+{
+  static int initialized=0;
+  size_t n;
+  char *buffer, *p;
+  
+  (void)add;
+  (void)level;
+  
+  if ( !initialized )
+    {
+      log_info(_("WARNING: using insecure random number generator!!\n"));
+      initialized=1;
+#ifdef HAVE_RAND
+      srand( time(NULL)*getpid());
+#else
+      srandom( time(NULL)*getpid());
+#endif
+    }
+
+  p = buffer = gcry_xmalloc( length );
+  n = length;
+#ifdef HAVE_RAND
+  while ( n-- )
+    *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
+#else
+  while ( n-- )
+    *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
+#endif
+  add_randomness ( buffer, length, origin );
+  gcry_free (buffer);
+  return 0; /* okay */
+}
+
+
+/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
+void
+_gcry_rngcsprng_create_nonce (void *buffer, size_t length)
+{
+  static unsigned char nonce_buffer[20+8];
+  static int nonce_buffer_initialized = 0;
+  static volatile pid_t my_pid; /* The volatile is there to make sure the
+                                   compiler does not optimize the code away
+                                   in case the getpid function is badly
+                                   attributed. */
+  volatile pid_t apid;
+  unsigned char *p;
+  size_t n;
+  int err;
+
+  /* Make sure we are initialized. */
+  initialize ();
+
+#ifdef USE_RANDOM_DAEMON
+  if (allow_daemon
+      && !_gcry_daemon_create_nonce (daemon_socket_name, buffer, length))
+    return; /* The daemon succeeded. */
+  allow_daemon = 0; /* Daemon failed - switch off. */
+#endif /*USE_RANDOM_DAEMON*/
+
+  /* Acquire the nonce buffer lock. */
+  err = ath_mutex_lock (&nonce_buffer_lock);
+  if (err)
+    log_fatal ("failed to acquire the nonce buffer lock: %s\n",
+               strerror (err));
+
+  apid = getpid ();
+  /* The first time intialize our buffer. */
+  if (!nonce_buffer_initialized)
+    {
+      time_t atime = time (NULL);
+      pid_t xpid = apid;
+
+      my_pid = apid;
+
+      if ((sizeof apid + sizeof atime) > sizeof nonce_buffer)
+        BUG ();
+
+      /* Initialize the first 20 bytes with a reasonable value so that
+         a failure of gcry_randomize won't affect us too much.  Don't
+         care about the uninitialized remaining bytes. */
+      p = nonce_buffer;
+      memcpy (p, &xpid, sizeof xpid);
+      p += sizeof xpid;
+      memcpy (p, &atime, sizeof atime); 
+
+      /* Initialize the never changing private part of 64 bits. */
+      gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
+
+      nonce_buffer_initialized = 1;
+    }
+  else if ( my_pid != apid )
+    {
+      /* We forked. Need to reseed the buffer - doing this for the
+         private part should be sufficient. */
+      gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM);
+      /* Update the pid so that we won't run into here again and
+         again. */
+      my_pid = apid;
+    }
+
+  /* Create the nonce by hashing the entire buffer, returning the hash
+     and updating the first 20 bytes of the buffer with this hash. */
+  for (p = buffer; length > 0; length -= n, p += n)
+    {
+      _gcry_sha1_hash_buffer (nonce_buffer,
+                              nonce_buffer, sizeof nonce_buffer);
+      n = length > 20? 20 : length;
+      memcpy (p, nonce_buffer, n);
+    }
+
+
+  /* Release the nonce buffer lock. */
+  err = ath_mutex_unlock (&nonce_buffer_lock);
+  if (err)
+    log_fatal ("failed to release the nonce buffer lock: %s\n",
+               strerror (err));
+
+}
diff --git a/random/random-fips.c b/random/random-fips.c
new file mode 100644 (file)
index 0000000..d29f21c
--- /dev/null
@@ -0,0 +1,102 @@
+/* random-fips.c - FIPS style random number generator
+ * Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+  FIXME:  Explain
+
+
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "random.h"
+#include "rand-internal.h"
+#include "ath.h"
+
+
+
+
+\f
+/* ---  Functions  --- */
+
+
+/* Initialize this random subsystem.  If FULL is false, this function
+   merely calls the basic initialization of the module and does not do
+   anything more.  Doing this is not really required but when running
+   in a threaded environment we might get a race condition
+   otherwise. */
+void
+_gcry_rngfips_initialize (int full)
+{
+}
+
+
+void
+_gcry_rngfips_dump_stats (void)
+{
+}
+
+
+/* This function returns true if no real RNG is available or the
+   quality of the RNG has been degraded for test purposes.  */
+int
+_gcry_rngfips_is_faked (void)
+{
+  return 0;  /* Faked random is not allowed.  */
+}
+
+
+/* Add BUFLEN bytes from BUF to the internal random pool.  QUALITY
+   should be in the range of 0..100 to indicate the goodness of the
+   entropy added, or -1 for goodness not known.  */
+gcry_error_t
+_gcry_rngfips_add_bytes (const void *buf, size_t buflen, int quality)
+{
+  return 0;
+}   
+
+    
+/* Public function to fill the buffer with LENGTH bytes of
+   cryptographically strong random bytes.  Level GCRY_WEAK_RANDOM is
+   here mapped to GCRY_STRING_RANDOM, GCRY_STRONG_RANDOM is strong
+   enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key
+   generation stuff but may be very slow.  */
+void
+_gcry_rngfips_randomize (void *buffer, size_t length,
+                         enum gcry_random_level level)
+{
+  BUG ();
+}
+
+
+/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */
+void
+_gcry_rngfips_create_nonce (void *buffer, size_t length)
+{
+  /* No special nonce support here; divert to the standard random
+     function.  */
+  _gcry_rngfips_randomize (buffer, length, GCRY_WEAK_RANDOM);
+}
+
+
index 3db7296..020c651 100644 (file)
@@ -1,6 +1,5 @@
-/* random.c  - random number generator
- * Copyright (C) 1998, 2000, 2001, 2002, 2003,
- *               2004, 2005, 2006, 2007  Free Software Foundation, Inc.
+/* random.c - Random number switch
+ * Copyright (C) 2008  Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  */
 
 /*
-   This random number generator is modelled after the one described in
-   Peter Gutmann's paper: "Software Generation of Practically Strong
-   Random Numbers". See also chapter 6 in his book "Cryptographic
-   Security Architecture", New York, 2004, ISBN 0-387-95387-6.
+  This module switches between different implementations of random
+  number generators and provides a few help functions.
  */
 
-
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
 #include <errno.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-#ifdef HAVE_GETHRTIME
-#include <sys/times.h>
-#endif
-#ifdef HAVE_GETTIMEOFDAY
-#include <sys/time.h>
-#endif
-#ifdef HAVE_GETRUSAGE
-#include <sys/resource.h>
-#endif
-#ifdef __MINGW32__
-#include <process.h>
-#endif
+
 #include "g10lib.h"
-#include "../cipher/rmd.h"
 #include "random.h"
 #include "rand-internal.h"
-#include "cipher.h" /* Required for the rmd160_hash_buffer() prototype.  */
 #include "ath.h"
 
-#ifndef RAND_MAX   /* For SunOS. */
-#define RAND_MAX 32767
-#endif
-
-/* Check whether we can lock the seed file read write. */
-#if defined(HAVE_FCNTL) && defined(HAVE_FTRUNCATE) && !defined(HAVE_W32_SYSTEM)
-#define LOCK_SEED_FILE 1
-#else
-#define LOCK_SEED_FILE 0
-#endif
-
-/* Define the constant we use for transforming the pool at read-out. */
-#if SIZEOF_UNSIGNED_LONG == 8
-#define ADD_VALUE 0xa5a5a5a5a5a5a5a5
-#elif SIZEOF_UNSIGNED_LONG == 4
-#define ADD_VALUE 0xa5a5a5a5
-#else
-#error weird size for an unsigned long
-#endif
-
-/* Contstants pertaining to the hash pool. */
-#define BLOCKLEN  64   /* Hash this amount of bytes... */
-#define DIGESTLEN 20   /* ... into a digest of this length (rmd160). */
-/* POOLBLOCKS is the number of digests which make up the pool.  */
-#define POOLBLOCKS 30
-/* POOLSIZE must be a multiple of the digest length to make the AND
-   operations faster, the size should also be a multiple of unsigned
-   long.  */
-#define POOLSIZE (POOLBLOCKS*DIGESTLEN)
-#if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
-#error Please make sure that poolsize is a multiple of unsigned long
-#endif
-#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
-
-
-/* RNDPOOL is the pool we use to collect the entropy and to stir it
-   up.  Its allocated size is POOLSIZE+BLOCKLEN.  Note that this is
-   also an indication on whether the module has been fully
-   initialized. */
-static unsigned char *rndpool; 
-
-/* KEYPOOL is used as a scratch copy to read out random from RNDPOOL.
-   Its allocated size is also POOLSIZE+BLOCKLEN.  */
-static unsigned char *keypool; 
-
-/* This is the offset into RNDPOOL where the next random bytes are to
-   be mixed in.  */
-static size_t pool_writepos;
-
-/* When reading data out of KEYPOOL, we start the read at different
-   positions.  This variable keeps track on where to read next.  */
-static size_t pool_readpos;
-
-/* This flag is set to true as soon as the pool has been completely
-   filled the first time.  This may happen either by rereading a seed
-   file or by adding enough entropy.  */
-static int pool_filled;
-
-/* This counter is used to track whether the initial seeding has been
-   done with enough bytes from a reliable entropy source.  */
-static size_t pool_filled_counter;
-
-/* If random of level GCRY_VERY_STRONG_RANDOM has been requested we
-   have stricter requirements on what kind of entropy is in the pool.
-   In particular POOL_FILLED is not sufficient.  Thus we add some
-   extra seeding and set this flag to true if the extra seeding has
-   been done.  */
-static int did_initial_extra_seeding;
-
-/* This variable is used to estimated the amount of fresh entropy
-   available in RNDPOOL.  */
-static int pool_balance;
-
-/* After a mixing operation this variable will be set to true and
-   cleared if new entropy has been added or a remix is required for
-   otehr reasons.  */
-static int just_mixed;
-
-/* The name of the seed file or NULL if no seed file has been defined.
-   The seed file needs to be regsitered at initialiation time.  We
-   keep a malloced copy here.  */
-static char *seed_file_name;
-
-/* If a seed file has been registered and maybe updated on exit this
-   flag set. */
-static int allow_seed_file_update;
-
-/* Option flag set at initialiation time to force allocation of the
-   pool in secure memory.  */
-static int secure_alloc;
-
-/* This function pointer is set to the actual entropy gathering
-   function during initailization.  After initialization it is
-   guaranteed to point to function.  (On systems without a random
-   gatherer module a dummy function is used).*/
-static int (*slow_gather_fnc)(void (*)(const void*, size_t,
-                                       enum random_origins),
-                              enum random_origins, size_t, int);
-
-/* This function is set to the actual fast entropy gathering fucntion
-   during initialization.  If it is NULL, no such function is
-   available. */
-static void (*fast_gather_fnc)(void (*)(const void*, size_t,
-                                        enum random_origins),
-              &