File libdomainkeys-openssl-1.1.patch of Package domainkeys

Changelog inside domainkeys.c 
tx Manvendra Banghui www.indimail.org

diff -ruN libdomainkeys-0.69-original/Makefile libdomainkeys-0.69-mbanghui-ssl-1.1/Makefile
--- libdomainkeys-0.69-original/Makefile	2006-01-18 01:28:58.000000000 +0100
+++ libdomainkeys-0.69-mbanghui-ssl-1.1/Makefile	2017-08-29 14:41:39.000000000 +0200
@@ -1,5 +1,5 @@
 CC=gcc
-CFLAGS=-DBIND_8_COMPAT -O2
+CFLAGS=-DBIND_8_COMPAT -O2 -DDOMAIN_KEYS
 #CFLAGS += -DDK_DEBUG -DDK_HASH_BUFF -Wall
 #CFLAGS += -DUNIXWARE
 INCS=-I.
diff -ruN libdomainkeys-0.69-original/domainkeys.c libdomainkeys-0.69-mbanghui-ssl-1.1/domainkeys.c
--- libdomainkeys-0.69-original/domainkeys.c	2008-04-01 00:50:39.000000000 +0200
+++ libdomainkeys-0.69-mbanghui-ssl-1.1/domainkeys.c	2017-08-31 07:05:46.000000000 +0200
@@ -1,41 +1,111 @@
+/*
+ * $Log: domainkeys.c,v $
+ * Revision 1.19  2017-08-09 22:07:51+05:30  Cprogrammer
+ * initialize EVP_MD_CTX variable
+ *
+ * Revision 1.18  2017-08-08 23:56:03+05:30  Cprogrammer
+ * openssl 1.1.0 port
+ *
+ * Revision 1.17  2014-03-24 12:29:35+05:30  Cprogrammer
+ * fixed dkparse822()
+ *
+ * Revision 1.16  2013-08-17 16:00:19+05:30  Cprogrammer
+ * added case for duplicate DomainKey-Signature header
+ *
+ * Revision 1.15  2013-08-12 11:55:29+05:30  Cprogrammer
+ * moved dk_strdup() to dns_text.c
+ *
+ * Revision 1.14  2011-07-29 09:28:18+05:30  Cprogrammer
+ * fixed gcc 4.6 warnings
+ *
+ * Revision 1.13  2009-03-27 16:49:55+05:30  Cprogrammer
+ * moved out dns_text function
+ *
+ * Revision 1.12  2009-03-20 22:29:44+05:30  Cprogrammer
+ * sender address fix patch
+ * added dk_set_seleheaders() to select headers for signing
+ * fixed issue with verification of multi-line headers
+ *
+ * Revision 1.11  2009-03-14 16:30:46+05:30  Cprogrammer
+ * Added dk_remdupe() to turn on/off ignoring hashing in duplicate headers when signing
+ * Added dk_selector() to return the selector name used or NULL if there isn't one
+ * Added test to dk_message() to detect stray CRs
+ * Fixed parent domain handling
+ * Added dk_compare_trace(), dk_enable_trace() and dk_get_trace()
+ * Performance improvments (see source for DK_HASH_BUFF)
+ * Fixed dkt_generate to remove the last ':' char and report accurate length of string returned
+ * Fixed memory leak in dk_headers()
+ * Incompatible changes made: dk_free requires an additional parameter, used to specify the OpenSSL Err
+ * Added dk_setopts() and dk_getopts()
+ * Deprecated dk_enable_trace() and dk_remdupe() in favor of using dk_setopts()
+ * Added dk_shutdown() to be used at application shutdown (frees dklib and openssl memory when done)
+ * Added dk_settxt() to bypass dns lookups and set query responses manually
+ * Added dk_domain() to return the domain name used (dk->domain)
+ * Added dk_granularity() to retrieve the value of (g=) tag in DNS lookup (called after dk_end)
+ * Added DK_STAT_GRANULARITY status enumeration
+ * Fixed dktest.c to check for DK_STAT_GRANULARITY
+ * Fixed dk_headers() to always return the proper length of a null terminated header list, even with a
+ * Added dk->granularity pointer to DK struct
+ *
+ * Revision 1.10  2008-08-03 18:25:22+05:30  Cprogrammer
+ * use proper proto
+ *
+ * Revision 1.9  2008-05-21 16:03:57+05:30  Cprogrammer
+ * fixed BIO_flush()
+ *
+ * Revision 1.8  2005-08-23 17:30:40+05:30  Cprogrammer
+ * gcc 4 compliance
+ *
+ * Revision 1.7  2005-05-16 16:31:44+05:30  Cprogrammer
+ * corrected code indentation
+ *
+ * Revision 1.6  2005-04-01 19:54:02+05:30  Cprogrammer
+ * libdomainkeys-0.64
+ *
+ * Revision 1.5  2004-10-25 13:23:42+05:30  Cprogrammer
+ * libdomainkeys-0.63
+ *
+ * Revision 1.4  2004-10-22 20:24:36+05:30  Cprogrammer
+ * added RCS id
+ *
+ * Revision 1.3  2004-10-21 21:55:41+05:30  Cprogrammer
+ * code beautified
+ *
+ * Revision 1.2  2004-10-20 17:30:20+05:30  Cprogrammer
+ * domainkeys-0.62
+ *
+ * Revision 1.1  2004-08-13 00:16:33+05:30  Cprogrammer
+ * Initial revision
+ *
+ */
+#ifdef DOMAIN_KEYS
 #include <sys/types.h>
 #include <ctype.h>
-#include <stdio.h>
-// added by nhatier for compilation under MSVC
-#ifdef _MSC_VER
 #include <string.h>
-  #define strncasecmp strnicmp
-  #define strcasecmp stricmp
-  #define snprintf _snprintf
-#else
-  #ifndef _STRINGS_H
-    #include <strings.h>
-  #endif
-  #ifndef _STRING_H
-    #include <string.h>
-  #endif
-#endif
-// end added by nhatier
-extern char *dns_text(char *);
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include "dktrace.h"
+
+EVP_MD_CTX     *evptr = NULL; /*- the hash */
 
 /* STARTHEAD */
-/* This is libdomainkeys.  It's Copyright (c) 2004 Yahoo, Inc.
+/*
+ * This is libdomainkeys.  It's Copyright (c) 2004 Yahoo, Inc.
  * This code incorporates intellectual property owned by
  * Yahoo! and licensed pursuant to the Yahoo! DomainKeys Public License
  * Agreement: http://domainkeys.sourceforge.net/license/softwarelicense1-0.html
  */
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-#include <openssl/err.h>
 
+#include "dktrace.h"
 #ifdef SWIG
-%module domainkeys
-%{
+%module domainkeys %
+{
 #include "domainkeys.h"
 %}
 #endif
-
-#include "dktrace.h"
+char           *dns_text(char *);
+char           *dk_strdup(const char *);
 
 /* Performance/Debug options.
  * Uncomment below or use -D switch in gcc
@@ -45,140 +115,143 @@
  *  canocalized message, reducing calls to the crypto library (from dkhash()),
  *  but can use up slightly more memory
 */
-//#define DK_DEBUG 1
-#define DK_HASH_BUFF 1
-
-
 #define DKMARK ('D' | 'K'<<8 | 'E'<<16 | 'Y'<<24)
 #define DK_SIGNING_SIGN 0
 #define DK_SIGNING_VERIFY 1
 #define DK_SIGNING_NOSIGN 2
 #define DK_SIGNING_NOVERIFY 3
-#define DK_MALLOC(s)  OPENSSL_malloc(s)
-#define DK_MFREE(s)   OPENSSL_free(s); s = NULL;
+#define DK_MALLOC(s)     OPENSSL_malloc(s)
+#define DK_REALLOC(s, n) OPENSSL_realloc(s, n)
+#define DK_MFREE(s)      OPENSSL_free(s); s = NULL;
 #define DKERR(x) ((dk->errline=__LINE__),(dk->errfile=__FILE__),(x))
+#define DK_HASH_BUFF 1
 #define DK_BLOCK 1024 //default size of malloc'd block
-
+/*- #define DK_DEBUG 1 *//*- Dumps whatever dkhash() hashes in to stderr */
 /*
  * Option Flags for dk_setopts
  * OR together or run dk_setopts several times
  * All option flags are OFF by default
-*/
+ */
 #define DKOPT_TRACE_h 0x01 //enables tracking character count in pre-canon header
 #define DKOPT_TRACE_H 0x02 //enables tracking character count in post-canon header
 #define DKOPT_TRACE_b 0x04 //enables tracking character count in pre-canon body
 #define DKOPT_TRACE_B 0x08 //enables tracking character count in post-canon header
-#define DKOPT_RDUPE 0x10 //enables skipping duplicate headers when generateing a signature
+#define DKOPT_RDUPE   0x10 //enables skipping duplicate headers when generateing a signature
+#define DKOPT_SELHEAD 0x20 //enables select headers when generating a signature
 
 typedef enum
 {
-  DK_STAT_OK, /* Function completed successfully */
-  DK_STAT_BADSIG, /* Signature was available but failed to verify against domain specified key */
-  DK_STAT_NOSIG, /* No signature available in message */
-  DK_STAT_NOKEY, /* No public key available (permanent failure) */
-  DK_STAT_BADKEY, /* Unusable key, public if verifying, private if signing */
-  DK_STAT_CANTVRFY, /* Cannot get domain key to verify signature (temporary failure) */
-  DK_STAT_SYNTAX, /* Message is not valid syntax. Signature could not be created/checked */
-  DK_STAT_NORESOURCE, /* Could not get critical resource (temporary failure) */
-  DK_STAT_ARGS, /* Arguments are not usable. */
-  DK_STAT_REVOKED,    /* Key has been revoked. */
-  DK_STAT_INTERNAL, /* cannot call this routine in this context.  Internal error. */
-  DK_STAT_GRANULARITY, /* Granularity mismatch: sender doesn't match g= option. */
+	DK_STAT_OK,					/*- Function completed successfully */
+	DK_STAT_BADSIG,				/*- Signature was available but failed to verify against domain specified key */
+	DK_STAT_NOSIG,				/*- No signature available in message */
+	DK_STAT_NOKEY,				/*- No public key available (permanent failure) */
+	DK_STAT_BADKEY,				/*- Unusable key, public if verifying, private if signing */
+	DK_STAT_CANTVRFY,			/*- Cannot get domain key to verify signature (temporary failure) */
+	DK_STAT_SYNTAX,				/*- Message is not valid syntax. Signature could not be created/checked */
+	DK_STAT_NORESOURCE,			/*- Could not get critical resource (temporary failure) */
+	DK_STAT_ARGS,				/*- Arguments are not usable.  */
+	DK_STAT_REVOKED,			/*- Key has been revoked.  */
+	DK_STAT_INTERNAL,			/*- cannot call this routine in this context.  Internal error.  */
+	DK_STAT_GRANULARITY,		/*- Granularity mismatch: sender doesn't match g= option. */
+	DK_STAT_DUPLICATE,          /*- Duplicate DomainKey-Header */
 } DK_STAT;
 
 typedef enum
 {
-  DK_FLAG_TESTING = 1,    /* set when in testing mode. */
-  DK_FLAG_SIGNSALL = 2,   /* domain signs all outgoing email. */
-  DK_FLAG_SET = 4,    /* flags set from a successful DNS query */
-  DK_FLAG_G = 8,    /* g tag was present in the selector. */
+	DK_FLAG_TESTING = 1,		/*- set when in testing mode.  */
+	DK_FLAG_SIGNSALL = 2,		/*- domain signs all outgoing email.  */
+	DK_FLAG_SET = 4,			/*- flags set from a successful DNS query */
+	DK_FLAG_G = 8,				/*- g tag was present in the selector.  */
 } DK_FLAGS;
+
 typedef enum
 {
-  DK_TXT_KEY = 0,
-  DK_TXT_POLICY
+	DK_TXT_KEY = 0,
+	DK_TXT_POLICY
 } DK_TXT;
 
 typedef enum
 {
-  DK_CANON_SIMPLE = 0,
-  DK_CANON_NOFWS = 1,
+	DK_CANON_SIMPLE = 0,
+	DK_CANON_NOFWS = 1,
 } DK_CANON;
+
 /* STARTSTRUCT */
 typedef struct
 {
 /* STARTPRIV */
-  const EVP_MD *md;
+	const EVP_MD   *md;
 /* STOPPRIV */
-
 } DK_LIB;
 /* STOPSTRUCT */
 
-//UnixWare Fix -Tim
 /* STARTSTRUCT */
 typedef struct
 {
 /* STARTPRIV */
-  int dkmarker;     /* in case somebody casts in */
-  EVP_MD_CTX mdctx;   /* the hash */
-  int signing;      /* our current signing/verifying state */
-  int in_headers;   /* true if we're still processing headers */
-  char *header;     /* points to a malloc'ed block for header. */
-  int headerlen;    /* total length of the header. */
-  int headermax;    /* length of malloc'ed block */
-  int headerlinelen;    /* current column of the header */
-  int start_signed;   /* offset into header of the start of the headers. */
-  char *from;     /* saved copy of From: header */
-  char *sender;     /* saved copy of Sender: header */
-  char *dksign;     /* saved copy of DK-Sig: header */
-  char *dktrace;  /* saved copy of DK-Trace: header */
-  char *domain;     /* d= */
-  char *selector;   /* s= */
-  char *signature;    /* b= */
-  char *granularity;    /* g= */
-  char *keyrec; /* caller supplied TXT key record */
-  char *policyrec; /* caller supplied TXT policy record */
-  int canon;      /* c= canonicalization being applied. */
-  int state;      /* state variable for canonicalization */
-  char *headers;    /* h= */
-  int errline;      /* source line of most recent error */
-  char *errfile;    /* source file of most recent error */
-  char *sender_beforesign; /* saved copy of Sender: header */
-  int opts;  /* trace and rdupe flags */
-  char last_char; /* the last character processed by dk_message() */
+	int             dkmarker;			/*- in case somebody casts in */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+	EVP_MD_CTX      mdctx;				/*- the hash */
+#else
+	EVP_MD_CTX     *mdctx;				/*- the hash */
+#endif
+	int             signing;			/*- our current signing/verifying state */
+	int             in_headers;			/*- true if we're still processing headers */
+	char           *header;				/*- points to a malloc'ed block for header.  */
+	int             headerlen;			/*- total length of the header.  */
+	int             headermax;			/*- length of malloc'ed block */
+	int             headerlinelen;		/*- current column of the header */
+	int             start_signed;		/*- offset into header of the start of the headers.  */
+	char           *from;				/*- saved copy of From: header */
+	char           *sender;				/*- saved copy of Sender: header */
+	char           *dksign;				/*- saved copy of DK-Sig: header */
+	char           *dktrace;			/*- saved copy of DK-Trace: header */
+	char           *domain;				/*- d= */
+	char           *selector;			/*- s= */
+	char           *signature;			/*- b= */
+	char           *granularity;		/*- g= */
+	char           *keyrec;				/*- caller supplied TXT key record */
+	char           *policyrec;			/*- caller supplied TXT policy record */
+	int             canon;				/*- c= canonicalization being applied.  */
+	int             state;				/*- state variable for canonicalization */
+	char           *headers;			/*- h= */
+	int             errline;			/*- source line of most recent error */
+	char           *errfile;			/*- source file of most recent error */
+	char           *sender_beforesign;	/*- saved copy of Sender: header */
+	int             opts;				/*- trace and rdupe flags */
+	char            last_char;			/*- the last character processed by dk_message() */
 #ifdef DK_HASH_BUFF
-  char *hash_buff; /* buffer for hashing */
-  int hash_buff_len; /* length of hashing buffer */
+	char           *hash_buff;			/*- buffer for hashing */
+	int             hash_buff_len;		/*- length of hashing buffer */
 #endif
-  DK_TRACE *trace; /* pointer to trace count table */
-  DK_TRACE *traceheader; /* pointer to trace count table from DK-Trace:*/
+	DK_TRACE       *trace;				/*- pointer to trace count table */
+	DK_TRACE       *traceheader;		/*- pointer to trace count table from DK-Trace:*/
+	char           *sel_headers;		/*- selected headers */
 /* STOPPRIV */
 } DK;
 /* STOPSTRUCT */
-
-
 /* STARTPRIV */
-static char *errors[] =
-{
-  "DK_STAT_OK: Function completed successfully",
-  "DK_STAT_BADSIG: Signature was available but failed to verify against domain specified key",
-  "DK_STAT_NOSIG: No signature available in message",
-  "DK_STAT_NOKEY: No public key available (permanent failure)",
-  "DK_STAT_BADKEY: Unusable key, public if verifying, private if signing.",
-  "DK_STAT_CANTVRFY: Cannot get domain key to verify signature (temporary failure)",
-  "DK_STAT_SYNTAX: Message is not valid syntax. Signature could not be created/checked",
-  "DK_STAT_NORESOURCE: Could not get critical resource (temporary failure)",
-  "DK_STAT_ARGS: Arguments are not usable.",
-  "DK_STAT_REVOKED: Key has been revoked.",
-  "DK_STAT_INTERNAL: cannot call this routine in this context.  Internal error.",
-  "DK_STAT_GRANULARITY: Granularity mismatch: sender doesn't match g= option."
+static char    *errors[] = {
+	"DK_STAT_OK: Function completed successfully",
+	"DK_STAT_BADSIG: Signature was available but failed to verify against domain specified key",
+	"DK_STAT_NOSIG: No signature available in message",
+	"DK_STAT_NOKEY: No public key available (permanent failure)",
+	"DK_STAT_BADKEY: Unusable key, public if verifying, private if signing.",
+	"DK_STAT_CANTVRFY: Cannot get domain key to verify signature (temporary failure)",
+	"DK_STAT_SYNTAX: Message is not valid syntax. Signature could not be created/checked",
+	"DK_STAT_NORESOURCE: Could not get critical resource (temporary failure)",
+	"DK_STAT_ARGS: Arguments are not usable.",
+	"DK_STAT_REVOKED: Key has been revoked.",
+	"DK_STAT_INTERNAL: cannot call this routine in this context.  Internal error.",
+	"DK_STAT_GRANULARITY: Granularity mismatch: sender doesn't match g= option.",
+	"DK_STAT_DUPLICATE: duplicate Domainkey-Signature in message",
 };
 /* STOPPRIV */
 /* STOPHEAD */
-//prototype for dk_from
-char* dk_from(DK *);
-int dk_headers(DK *, char *);
 
+char           *dk_from(DK *);
+int             dk_headers(DK *, char *);
+static char    *strncasestr(const char *, const char *, size_t slen);
 char* dk_strdup(const char* s)
 {
   char* new = DK_MALLOC(strlen(s)+1);
@@ -190,21 +263,24 @@
 }
 
 /* HEADER */
-/* returns the source file from which an error was returned. */
-char * dk_errfile(DK *dk)
+/*- returns the source file from which an error was returned.  */
+char           *
+dk_errfile(DK *dk)
 {
-  return dk->errfile;
+	return dk->errfile;
 }
 
 /* HEADER */
-/* returns the source line number from which an error was returned. */
-int dk_errline(DK *dk)
+/*- returns the source line number from which an error was returned.  */
+int
+dk_errline(DK *dk)
 {
-  return dk->errline;
+	return dk->errline;
 }
 
 /* HEADER */
-/* Per-process, one-time initialization
+/*
+ * Per-process, one-time initialization
  * Returns library structure for subsequent dk_sign or dk_verify calls.
  * Consult statp before using.
  *
@@ -213,139 +289,134 @@
  * NOTE: DK_LIB pointers are safe to use over multiple threads
  *       DK pointers are NOT safe to use over multiple threads
  */
-DK_LIB *dk_init(DK_STAT *statp)
+DK_LIB         *
+dk_init(DK_STAT *statp)
 {
-  DK_LIB *dklib;
+	DK_LIB         *dklib;
 
-  dklib = DK_MALLOC(sizeof(DK_LIB));
-  if (!dklib)
-  {
-    if (statp)
-    {
-      *statp = DK_STAT_NORESOURCE;
-    }
-    return NULL;
-  }
-  dklib->md = EVP_sha1();
-  if (!dklib->md)
-  {
-    if (statp)
-    {
-      *statp = DK_STAT_INTERNAL;
-    }
-    DK_MFREE(dklib);
-    return NULL;
-  }
-  if (statp)
-  {
-    *statp = DK_STAT_OK;
-  }
-  return dklib;
+	if (!(dklib = DK_MALLOC(sizeof(DK_LIB))))
+	{
+		if (statp)
+			*statp = DK_STAT_NORESOURCE;
+		return NULL;
+	}
+	if (!(dklib->md = EVP_sha1()))
+	{
+		if (statp)
+			*statp = DK_STAT_INTERNAL;
+		DK_MFREE(dklib);
+		return NULL;
+	}
+	if (statp)
+		*statp = DK_STAT_OK;
+	return dklib;
 }
 
 /* HEADER */
-/* Per-process, one-time cleanup
+/* 
+ * Per-process, one-time cleanup
  * Should be called just before the application ends.
  * the dklib pointer is not valid anymore after this call
  * This function should be called even if dk_init failed.
  * It's safe to call dk_shutdown with a NULL pointer
  */
-void dk_shutdown(DK_LIB * dklib)
+void
+dk_shutdown(DK_LIB *dklib)
 {
-   if (dklib)
-   {
-      DK_MFREE(dklib);
-   }
-   CRYPTO_cleanup_all_ex_data();
+	if (dklib)
+		DK_MFREE(dklib);
+	CRYPTO_cleanup_all_ex_data();
 }
 
-/* start a new header */
-static DK_STAT dkinit_new_header(DK *dk)
+/*
+ * start a new header 
+ */
+static          DK_STAT
+dkinit_new_header(DK *dk)
 {
-  dk->headermax = DK_BLOCK;
-  dk->header = DK_MALLOC(DK_BLOCK);
-  if (!dk->header)
-  {
-    return DKERR(DK_STAT_NORESOURCE);
-  }
-  memset(dk->header,0,DK_BLOCK);
-  dk->headerlen = 0;
-  dk->headerlinelen = 1;  /* always store the first char. */
-  dk->in_headers = 1;
-  dk->start_signed = 0;
-  dk->from = NULL;
-  dk->sender = NULL;
-  dk->dksign = NULL;
-  dk->dktrace = NULL;
-  dk->domain = NULL;
-  dk->selector = NULL;
-  dk->signature = NULL;
-  dk->canon = DK_CANON_SIMPLE;
-  dk->state = 0;
-  dk->headers = 0;
-  dk->sender_beforesign = NULL;
-  dk->opts = 0;
-  dk->last_char = '\0';
-  dk->trace = NULL;
-  dk->traceheader = NULL;
-  dk->granularity = NULL;
-  dk->keyrec = NULL;
-  dk->policyrec = NULL;
+	dk->headermax = DK_BLOCK;
+	if (!(dk->header = DK_MALLOC(dk->headermax)))
+		return DKERR(DK_STAT_NORESOURCE);
+	memset(dk->header, 0, DK_BLOCK);
+	dk->headerlen = 0;
+	dk->headerlinelen = 1;		/*- always store the first char.  */
+	dk->in_headers = 1;
+	dk->start_signed = 0;
+	dk->from = NULL;
+	dk->sender = NULL;
+	dk->dksign = NULL;
+	dk->dktrace = NULL;
+	dk->domain = NULL;
+	dk->selector = NULL;
+	dk->signature = NULL;
+	dk->canon = DK_CANON_SIMPLE;
+	dk->state = 0;
+	dk->headers = 0;
+	dk->sender_beforesign = NULL;
+	dk->opts = 0;
+	dk->last_char = '\0';
+	dk->trace = NULL;
+	dk->traceheader = NULL;
+	dk->granularity = NULL;
+	dk->keyrec = NULL;
+	dk->policyrec = NULL;
+	dk->sel_headers = NULL;
 #ifdef DK_HASH_BUFF
-  dk->hash_buff = DK_MALLOC(DK_BLOCK);
-  if (!dk->hash_buff)
-  {
-    return DKERR(DK_STAT_NORESOURCE);
-  }
-  memset(dk->hash_buff,0,DK_BLOCK);
-  dk->hash_buff_len = 0;
+	dk->hash_buff = DK_MALLOC(DK_BLOCK);
+	if (!dk->hash_buff)
+		return DKERR(DK_STAT_NORESOURCE);
+	memset(dk->hash_buff, 0, DK_BLOCK);
+	dk->hash_buff_len = 0;
 #endif
-  return DKERR(DK_STAT_OK);
+	return DKERR(DK_STAT_OK);
 }
 
 /* HEADER */
-/* Set dk options, use instead of dk_remdupe and dk_enable_trace
+/*
+ * Set dk options, use instead of dk_remdupe and dk_enable_trace
  * Can be called multiple times.
  * use after dk_sign()/dk_verify()
- *
  * the bits field can be an OR of any of the following
- *DKOPT_TRACE_h Trace pre-canon header
- *DKOPT_TRACE_H Trace post-canon header
- *DKOPT_TRACE_b Trace pre-canon body
- *DKOPT_TRACE_B Trace post-canon body
- *DKOPT_RDUPE   Exclude duplicate headers from hash (Signing only)
- */
-DK_STAT dk_setopts(DK *dk, int bits)
-{
-  if (!dk)
-    return DK_STAT_ARGS;
-  if ((dk->headerlen == 0)&&((dk->signing == DK_SIGNING_NOVERIFY)||(dk->signing == DK_SIGNING_SIGN)))
-  {
-    dk->opts |= bits;
-    if ((bits & (DKOPT_TRACE_h|DKOPT_TRACE_H|DKOPT_TRACE_b|DKOPT_TRACE_B)) && !dk->trace)
-    {
-      dk->trace = DK_MALLOC(sizeof(DK_TRACE));
-      if (!dk->trace)
-        return DKERR(DK_STAT_NORESOURCE);
-      dkt_init(dk->trace);
-    }
-    if ((dk->signing != DK_SIGNING_SIGN) && (bits & DKOPT_RDUPE))
-    {
-      return DKERR(DK_STAT_INTERNAL); //cant do rdupe in verify mode
-    }
-    return DKERR(DK_STAT_OK);
-  }
-  return DKERR(DK_STAT_INTERNAL);
+ * DKOPT_TRACE_h Trace pre-canon header
+ * DKOPT_TRACE_H Trace post-canon header
+ * DKOPT_TRACE_b Trace pre-canon body
+ * DKOPT_TRACE_B Trace post-canon body
+ * DKOPT_RDUPE   Exclude duplicate headers from hash (Signing only)
+ *DKOPT_SELHEAD Include only selected headers into hash (Signing only)
+ */
+DK_STAT
+dk_setopts(DK *dk, int bits)
+{
+	if (!dk)
+		return DK_STAT_ARGS;
+	if ((dk->headerlen == 0) && ((dk->signing == DK_SIGNING_NOVERIFY) || (dk->signing == DK_SIGNING_SIGN)))
+	{
+		dk->opts |= bits;
+		if ((bits & (DKOPT_TRACE_h|DKOPT_TRACE_H|DKOPT_TRACE_b|DKOPT_TRACE_B)) && !dk->trace)
+		{
+			dk->trace = DK_MALLOC(sizeof(DK_TRACE));
+			if (!dk->trace)
+				return DKERR(DK_STAT_NORESOURCE);
+			dkt_init(dk->trace);
+		}
+		if ((dk->signing != DK_SIGNING_SIGN) && (bits & DKOPT_RDUPE))
+			return DKERR(DK_STAT_INTERNAL); /*- can't do rdupe in verify mode */
+		return DKERR(DK_STAT_OK);
+	}
+	return DKERR(DK_STAT_INTERNAL);
 }
+
 /* HEADER */
-/* returns the int holding the options set
+/* 
+ * returns the int holding the options set
  * See dk_setopts for bit flags
  */
-int dk_getopts(DK *dk)
+int
+dk_getopts(DK *dk)
 {
-  if (!dk)
-    return 0;
-  return (dk->opts);
+	if (!dk)
+		return 0;
+	return (dk->opts);
 }
 
 /* HEADER */
@@ -354,342 +425,335 @@
  *
  * use after dk_sign()/dk_verify()
  */
-DK_STAT dk_enable_trace(DK *dk)
+DK_STAT
+dk_enable_trace(DK *dk)
 {
-  return dk_setopts(dk,(DKOPT_TRACE_h|DKOPT_TRACE_H|DKOPT_TRACE_b|DKOPT_TRACE_B));
+	return dk_setopts(dk,(DKOPT_TRACE_h|DKOPT_TRACE_H|DKOPT_TRACE_b|DKOPT_TRACE_B));
 }
+
 /* HEADER */
-/* Prints trace table to *store variable (char string)
+/*
+ * Prints trace table to *store variable (char string)
  * *dk is the container for the table
  * *store is a pointer to a character array to output to
  * store_size is the size of the character array *store
- *
  */
-DK_STAT dk_get_trace(DK *dk, DK_TRACE_TYPE type, char *store, int store_size)
+DK_STAT
+dk_get_trace(DK *dk, DK_TRACE_TYPE type, char *store, int store_size)
 {
-  if (!dk)
-    return DK_STAT_ARGS;
-  if (dk->trace)
-  {
-    if (!dkt_generate(dk->trace, type, store, store_size))
-    {
-      return DK_STAT_NORESOURCE; //not enough buffer space
-    }
-    return DKERR(DK_STAT_OK);
-  }
-  return DKERR(DK_STAT_INTERNAL);
+	if (!dk)
+		return DK_STAT_ARGS;
+	if (dk->trace) {
+		if (!dkt_generate(dk->trace, type, store, store_size)) {
+			return DK_STAT_NORESOURCE;	//not enough buffer space
+		}
+		return DKERR(DK_STAT_OK);
+	}
+	return DKERR(DK_STAT_INTERNAL);
 }
 
 /* HEADER */
-/* Prints difference trace table to *store variable (char string)
+/*
+ * Prints difference trace table to *store variable (char string)
  * *dk is the container for the table
  * *store is a pointer to a character array to output to
  * store_size is the size of the character array *store
  * return DK_STAT_NOSIG if no DK-Trace header was found
  */
-DK_STAT dk_compare_trace(DK *dk, DK_TRACE_TYPE type, char *store, int store_size)
+DK_STAT
+dk_compare_trace(DK *dk, DK_TRACE_TYPE type, char *store, int store_size)
 {
-  DK_TRACE table;
-  if (!dk)
-    return DK_STAT_ARGS;
-  if (!dk->dktrace || !dk->trace)
-    return DK_STAT_NOSIG;
-  dkt_init(&table);
-  if (!dk->traceheader) //make DK_TRACE from header
-  {
-    dk->traceheader = DK_MALLOC(sizeof(DK_TRACE));
-    if (!dk->traceheader)
-      return DKERR(DK_STAT_NORESOURCE);
-    dkt_init(dk->traceheader);
-
-    if (!dkt_hdrtotrace(dk->dktrace,dk->traceheader))
-    {
-      return DK_STAT_NORESOURCE;
-    }
-  }
-  dkt_diff(dk->traceheader, dk->trace, type, &table);
-  if (!dkt_generate(&table, type, store, store_size))
-  {
-    return DK_STAT_NORESOURCE; //not enough buffer space
-  }
-  return DK_STAT_OK;
+	DK_TRACE        table;
+
+	if (!dk)
+		return DK_STAT_ARGS;
+	if (!dk->dktrace || !dk->trace)
+		return DK_STAT_NOSIG;
+	dkt_init(&table);
+	if (!dk->traceheader)		//make DK_TRACE from header
+	{
+		dk->traceheader = DK_MALLOC(sizeof (DK_TRACE));
+		if (!dk->traceheader)
+			return DKERR(DK_STAT_NORESOURCE);
+		dkt_init(dk->traceheader);
+
+		if (!dkt_hdrtotrace(dk->dktrace, dk->traceheader)) {
+			return DK_STAT_NORESOURCE;
+		}
+	}
+	dkt_diff(dk->traceheader, dk->trace, type, &table);
+	if (!dkt_generate(&table, type, store, store_size)) {
+		return DK_STAT_NORESOURCE;	//not enough buffer space
+	}
+	return DK_STAT_OK;
 }
 
 
 /* HEADER */
-/* Sets the DNS key/policy record manually (no DNS lookup)
+/* 
+ * Sets the DNS key/policy record manually (no DNS lookup)
  * txtrecord needs to be set to "e=perm;" to force a permanent DNS failure
  * txtrecord needs to be set to "e=temp;" to force a temporary DNS failure
  * Valid DK_TXT types are:
  * DK_TXT_KEY (normal selector record; for <selctor>._domainkey.<domain>)
  * DK_TXT_POLICY (domain policy record; for _domainkey.<domain>)
  */
-DK_STAT dk_settxt(DK *dk, DK_TXT recordtype, const char *txtrecord)
+DK_STAT
+dk_settxt(DK *dk, DK_TXT recordtype, const char *txtrecord)
 {
-  char **ptr; //pointer to keyrecord/policyrecord pointer
-  if (!dk|| !txtrecord)
-    return DK_STAT_ARGS;
-  switch (recordtype)
-  {
-    case DK_TXT_KEY:
-      ptr = &dk->keyrec;
-      break;
-    case DK_TXT_POLICY:
-      ptr = &dk->policyrec;
-      break;
-    default:
-      return DK_STAT_ARGS;
-  }
-  // Free the value iff it is currently set.
-  if (*ptr)
-  {
-    DK_MFREE(*ptr);
-  }
-  *ptr = dk_strdup(txtrecord);
-  return DKERR(DK_STAT_OK);
+	char          **ptr; //pointer to keyrecord/policyrecord pointer
+
+	if (!dk|| !txtrecord)
+		return DK_STAT_ARGS;
+	switch (recordtype)
+	{
+	case DK_TXT_KEY:
+		ptr = &dk->keyrec;
+		break;
+	case DK_TXT_POLICY:
+		ptr = &dk->policyrec;
+		break;
+	default:
+		return DK_STAT_ARGS;
+	}
+	/*- Free the value iff it is currently set. */
+	if (*ptr)
+		DK_MFREE(*ptr);
+	*ptr = dk_strdup(txtrecord);
+	return DKERR(DK_STAT_OK);
 }
 
-static DK_STAT dkstore_char(DK *dk, char ch)
+static          DK_STAT
+dkstore_char(DK *dk, char ch)
 {
-  if (dk->headerlen >= dk->headermax)
-  {
-    char *hp;
-    hp = DK_MALLOC(dk->headermax * 2 + 1024 + 1); /* leave room for null */
-    if (!hp)
-    {
-      return DKERR(DK_STAT_NORESOURCE);
-    }
-    if (dk->headermax)
-    {
-      memcpy(hp, dk->header, dk->headerlen);
-      DK_MFREE(dk->header);
-    }
-    dk->header = hp;
-    dk->headermax = dk->headermax * 2 + 1024;
-  }
-  dk->header[dk->headerlen++] = ch;
-  dk->headerlinelen++;
-  return DKERR(DK_STAT_OK);
+	if (dk->headerlen >= dk->headermax)
+	{
+		char           *hp;
+
+		if (!(hp = DK_MALLOC(dk->headermax * 2 + 1024 + 1)))	/*- leave room for null */
+			return DKERR(DK_STAT_NORESOURCE);
+		if (dk->headermax)
+		{
+			memcpy(hp, dk->header, dk->headerlen);
+			DK_MFREE(dk->header);
+		}
+		dk->header = hp;
+		dk->headermax = dk->headermax * 2 + 1024;
+	}
+	dk->header[dk->headerlen++] = ch;
+	dk->headerlinelen++;
+	return DKERR(DK_STAT_OK);
 }
 
 /* HEADER */
-/* Per-message, may be threaded.
+/*
+ * Per-message, may be threaded.
  * canon is one of DK_CANON_*.
  * Returns state structure for operation.  Consult statp before using.
  */
-DK *dk_sign(DK_LIB *dklib, DK_STAT *statp, int canon)
+DK             *
+dk_sign(DK_LIB *dklib, DK_STAT *statp, int canon)
 {
-  DK *dk;
-
-  dk = DK_MALLOC(sizeof(DK));
-  if (!dk)
-  {
-    if (statp)
-    {
-      *statp = DKERR(DK_STAT_NORESOURCE);
-    }
-    return NULL;
-  }
-  dk->dkmarker = DKMARK;
-  dk->signing = DK_SIGNING_SIGN;
-  if (dkinit_new_header(dk) != DK_STAT_OK)
-  {
-    /* couldn't malloc a header. */
-    DK_MFREE(dk);
-    if (statp)
-    {
-      *statp = DKERR(DK_STAT_NORESOURCE);
-    }
-    return NULL;
-  }
-  dk->canon = canon; /* TC13-simple, TC13-nofws */
-  EVP_SignInit(&dk->mdctx, dklib->md);
+	DK             *dk;
 
-  if (statp)
-  {
-    *statp = DKERR(DK_STAT_OK);
-  }
-  return dk;
+	if (!(dk = DK_MALLOC(sizeof(DK))))
+	{
+		if (statp)
+			*statp = DKERR(DK_STAT_NORESOURCE);
+		return NULL;
+	}
+	dk->dkmarker = DKMARK;
+	dk->signing = DK_SIGNING_SIGN;
+	if (dkinit_new_header(dk) != DK_STAT_OK)
+	{
+		/*- couldn't malloc a header.  */
+		DK_MFREE(dk);
+		if (statp)
+			*statp = DKERR(DK_STAT_NORESOURCE);
+		return NULL;
+	}
+	dk->canon = canon;			/*- TC13-simple, TC13-nofws */
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+	if (!(dk->mdctx = EVP_MD_CTX_new())) {
+		DK_MFREE(dk);
+		if (statp)
+			*statp = DKERR(DK_STAT_NORESOURCE);
+		return NULL;
+	}
+	evptr = dk->mdctx;
+#else
+	evptr = &dk->mdctx;
+#endif
+	EVP_SignInit(evptr, dklib->md);
+	if (statp)
+		*statp = DKERR(DK_STAT_OK);
+	return dk;
 }
 
 /* HEADER */
-/* Per-message, may be threaded.
+/*
+ * Per-message, may be threaded.
  * Returns state structure for operation.  Consult statp before using.
  */
-DK *dk_verify(DK_LIB *dklib, DK_STAT *statp)
+DK             *
+dk_verify(DK_LIB *dklib, DK_STAT *statp)
 {
-  DK *dk;
-
-  dk = DK_MALLOC(sizeof(DK));
-  if (!dk)
-  {
-    if (statp)
-    {
-      *statp = DKERR(DK_STAT_NORESOURCE);
-    }
-    return NULL;
-  }
-  dk->dkmarker = DKMARK;
-  dk->signing = DK_SIGNING_NOVERIFY; /* wait to verify until we see DK-Signature. */
-  if (dkinit_new_header(dk) != DK_STAT_OK)
-  {
-    /* couldn't malloc a header. */
-    DK_MFREE(dk);
-    if (statp)
-    {
-      *statp = DKERR(DK_STAT_NORESOURCE);
-    }
-    return NULL;
-  }
-  EVP_VerifyInit(&dk->mdctx, dklib->md);
+	DK             *dk;
 
-  if (statp)
-  {
-    *statp = DKERR(DK_STAT_OK);
-  }
-  return dk;
+	if (!(dk = DK_MALLOC(sizeof(DK))))
+	{
+		if (statp)
+			*statp = DKERR(DK_STAT_NORESOURCE);
+		return NULL;
+	}
+	dk->dkmarker = DKMARK;
+	dk->signing = DK_SIGNING_NOVERIFY;	/*- wait to verify until we see DK-Signature.  */
+	if (dkinit_new_header(dk) != DK_STAT_OK)
+	{
+		/*- couldn't malloc a header.  */
+		DK_MFREE(dk);
+		if (statp)
+			*statp = DKERR(DK_STAT_NORESOURCE);
+		return NULL;
+	}
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+	if (!(dk->mdctx = EVP_MD_CTX_new())) {
+		DK_MFREE(dk);
+		if (statp)
+			*statp = DKERR(DK_STAT_NORESOURCE);
+		return NULL;
+	}
+	evptr = dk->mdctx;
+#else
+	evptr = &dk->mdctx;
+#endif
+	EVP_VerifyInit(evptr, dklib->md);
+	if (statp)
+		*statp = DKERR(DK_STAT_OK);
+	return dk;
 }
 
-/* parse an rfc822 address */
-/* leave it in the dk_address() format; that is, with the existing
- * first letter, followed by the address */
-static DK_STAT dkparse822(char *address, unsigned int offset)
-{
-  int foundangle = 0;   /* true if it's in angle brackets */
-  int foundat = 0;
-  char *from, *to;
-  int level = 1;
-
-  to = address + 1;
-  from = address + offset;
-  while (*from)
-  {   /* nuke comments. */
-    if (*from == ')')
-    {
-      return DK_STAT_SYNTAX;
-    }
-    else if (*from == '\\' && from[1])
-    {
-      /* skip backslash-quoted characters */
-      *to++ = *from++;
-      *to++ = *from++;
-    }
-    else if (*from == '"')
-    {
-      /* we have to ignore parenthesis inside quotes. */
-      from++;
-      for (;;)
-      {
-        if (*from == '\0')
-        {
-          return DK_STAT_SYNTAX;
-        }
-        else if (*from == '"')
-        {
-          from++;
-          break;
-        }
-        else if (*from == '\\' && from[1])
-        {
-          *to++ = *from++;
-        }
-        *to++ = *from++;
-      }
-    }
-    else if (*from == '(')
-    {
-      level = 1;
-      from++;
-      while (level)
-      {
-        if (*from == '\0')
-        {
-          return DK_STAT_SYNTAX;
-        }
-        else if (*from == '(')
-        {
-          ++level;
-        }
-        else if (*from == ')')
-        {
-          --level;
-        }
-        else if (*from == '\\' && from[1])
-        {
-          ++from;
-        }
-        ++from;
-      }
-    }
-    else if (*from == ' ')
-    {
-      ++from;
-    }
-    else if (*from == '\t')
-    {
-      ++from;
-    }
-    else
-    {
-      *to++ = *from++;
-    }
-  } //end while(*from)
-  *to = '\0';
-  from = address + 1;
-  to = address + 1;
-  while (*from)
-  {
-    if (*from == '@')
-    {
-      foundat = 1;
-    }
-    if (*from == '\\' && from[1])
-    {
-      *to++ = *from++;
-      *to++ = *from++;
-    }
-    else if (*from == '<')
-    {
-      from++;
-      to = address + 1;
-      foundangle = 1;
-      foundat = 0;
-    }
-    else if (*from == ',' || *from == ':' )
-    {
-      from++;
-      to = address + 1;
-      foundat = 0;
-    }
-    else if (foundangle && *from == '>')
-    {
-      break;
-    }
-    else if (*from == ';')
-    {
-      break;
-    }
-    else
-    {
-      *to++ = *from++;
-    }
-  }
-  *to = '\0';
-  if (foundat)
-  {
-    return DK_STAT_OK;
-  }
-  else if (!address[1])
-  {
-    return DK_STAT_OK;
-  }
-  else
-  {
-    return DK_STAT_SYNTAX;  /* no @ in the address */
-  }
+/*
+ * parse an rfc822 address 
+ *
+ * leave it in the dk_address() format; that is, with the existing
+ * first letter, followed by the address 
+ */
+static          DK_STAT
+dkparse822(char *address, unsigned int offset)
+{
+	int             foundangle = 0;	/*- true if it's in angle brackets */
+	int             foundat = 0;
+	char           *from, *to;
+	int             level = 1;
+
+	to = address + 1;
+	from = address + offset;
+	while (*from)
+	{	/*- nuke comments.  */
+		if (*from == ')')
+			return DK_STAT_SYNTAX;
+		else
+		if (*from == '\\' && from[1])
+		{
+			/*- skip backslash-quoted characters */
+			*to++ = *from++;
+			*to++ = *from++;
+		} else
+		if (*from == '"')
+		{
+			/*- we have to ignore parenthesis inside quotes.  */
+			from++;
+			for (;;)
+			{
+				if (*from == '\0')
+					return DK_STAT_SYNTAX;
+				else
+				if (*from == '"')
+				{
+					from++;
+					break;
+				} else
+				if (*from == '\\' && from[1])
+					*to++ = *from++;
+				*to++ = *from++;
+			}
+		} else
+		if (*from == '(')
+		{
+			level = 1;
+			from++;
+			while (level)
+			{
+				if (*from == '\0')
+					return DK_STAT_SYNTAX;
+				else
+				if (*from == '(')
+					++level;
+				else
+				if (*from == ')')
+					--level;
+				else
+				if (*from == '\\' && from[1])
+					++from;
+				++from;
+			}
+		} else
+		if (*from == ' ')
+			++from;
+		else
+		if (*from == '\t')
+			++from;
+		else
+			*to++ = *from++;
+	}
+	*to = '\0';
+	from = address + 1;
+	to = address + 1;
+	while (*from)
+	{
+		if (*from == '@')
+			foundat = 1;
+		if (*from == '\\' && from[1])
+		{
+			*to++ = *from++;
+			*to++ = *from++;
+		} else
+		if (*from == '<')
+		{
+			from++;
+			to = address + 1;
+			foundangle = 1;
+			foundat = 0;
+		} else
+		if (*from == ',' || *from == ':')
+		{
+			from++;
+			to = address + 1;
+			foundat = 0;
+		} else
+		if (foundangle && *from == '>')
+		{
+			break;
+		} else
+		if (foundat && *from == ';')
+		{
+			break;
+		} else
+			*to++ = *from++;
+	}
+	*to = '\0';
+	if (foundat)
+		return DK_STAT_OK;
+	else
+	if (!address[1])
+		return DK_STAT_OK;
+	else
+		return DK_STAT_SYNTAX;	/*- no @ in the address */
 }
 
-/* Given a list of key=value; pairs, find all the keys found in letters.
+/*
+ * Given a list of key=value; pairs, find all the keys found in letters.
  * Store the value in the corresponding entry in values[].
  * Modifies list to insert nulls in the place of the semicolons which terminate
  * each of the values except possibly the last.
@@ -699,883 +763,785 @@
  * of the existing values need spaces, so we always remove them.
  */
 
-static DK_STAT dkparselist(char *list, char *letters, char *values[])
+static DK_STAT
+dkparselist(char *list, char *letters, char *values[])
 {
-  char key;
-  int i;
-  char *value;
+	char            key;
+	int             i;
+	char           *value;
+
+	/*- start with all args unset */
+	for (i = 0; letters[i]; i++)
+		values[i] = NULL;
+	key = 0;
+	while (*list)
+	{
+		if ((*list == ' ') || (*list == '\t') || (*list == '\r') || (*list == '\n'))
+			list++;
+		else
+		if (*list == '=')
+		{
+			char           *ws;
 
-  /* start with all args unset */
-  for (i = 0; letters[i]; i++)
-  {
-    values[i] = NULL;
-  }
-  key = 0;
-  while (*list)
-  {
-    if ((*list == ' ')||(*list == '\t')||(*list == '\r')||(*list == '\n'))
-    {
-      list++;
-    }
-    else if (*list == '=')
-    {
-      char *ws;
-
-      ++list;
-      value = list;
-      ws = list;
-      while (1)
-      {
-        /* copy up to null or semicolon, deleting whitespace as we go */
-        *ws = *list;
-        if ((*list == ' ')||(*list == '\t')||(*list == '\r')||(*list == '\n'))
-        {
-          /* ignore */
-        }
-        else if (!*list)
-        {
-          break;
-        }
-        else if (*list == ';')
-        {
-          *ws = '\0';
-          list++;
-          break;
-        }
-        else
-        {
-          ws++;
-        }
-        list++;
-      }
-      if (!key)
-      {
-        return DK_STAT_SYNTAX; /* we didn't get a key. TC22 */
-      }
-      /* if we find a matching letter, remember the value */
-      for (i = 0; letters[i]; i++)
-      {
-        if (key == letters[i])
-        {
-          if (values[i])
-          {
-            return DK_STAT_SYNTAX; /* no duplicate keys. TC23 */
-          }
-          values[i] = value;
-        }
-      }
-      key = 0;
-    }
-    else
-    {
-      if (key)
-      {
-        return DK_STAT_SYNTAX; /* they already gave us a key. TC24 */
-      }
-      key = *list++;
-      if (!islower((int)key))
-      {
-        return DK_STAT_SYNTAX; /* must be lowercase letter. TC25 */
-      }
-    }
-  }
-  if (key)
-  {
-    return DK_STAT_SYNTAX; /* we ended up with an extra key. TC25-1 */
-  }
-  return DK_STAT_OK;
+			++list;
+			value = list;
+			ws = list;
+			while (1)
+			{
+				/*- copy up to null or semicolon, deleting whitespace as we go */
+				*ws = *list;
+				if ((*list == ' ') || (*list == '\t') || (*list == '\r') || (*list == '\n'))
+				{
+					/*- NOOP */
+				} else
+				if (!*list)
+					break;
+				else
+				if (*list == ';')
+				{
+					*ws = '\0';
+					list++;
+					break;
+				} else
+					ws++;
+				list++;
+			}
+			if (!key)
+				return DK_STAT_SYNTAX;	/* we didn't get a key. TC22 */
+			/*-
+			 * if we find a matching letter, remember the value 
+			 */
+			for (i = 0; letters[i]; i++)
+			{
+				if (key == letters[i])
+				{
+					if (values[i])
+						return DK_STAT_SYNTAX;	/* no duplicate keys. TC23 */
+					values[i] = value;
+				}
+			}
+			key = 0;
+		} else
+		{
+			if (key)
+				return DK_STAT_SYNTAX;	/* they already gave us a key. TC24 */
+			key = *list++;
+			if (!islower((int) key))
+				return DK_STAT_SYNTAX;	/* must be lowercase letter. TC25 */
+		}
+	}
+	if (key)
+		return DK_STAT_SYNTAX;	/* we ended up with an extra key. TC25-1 */
+	return DK_STAT_OK;
 }
 
 /* HEADER */
-/* DEPRECATED in favor of calling dk_setopts()
+/* 
+ * DEPRECATED in favor of calling dk_setopts()
  * set option to remove dupe headers
  * should be called after dk_sign();
  * any int NOT 0 turns dupe removal on
  */
-DK_STAT dk_remdupe(DK *dk,int i)
+DK_STAT
+dk_remdupe(DK *dk, int i)
 {
-  if (i != 0)
-    return dk_setopts(dk,DKOPT_RDUPE);
-  return DK_STAT_OK;
+	if (i != 0)
+		return dk_setopts(dk,DKOPT_RDUPE);
+	return DK_STAT_OK;
 }
 
-
 /* HEADER */
-/* Returns the policy flags belonging to the signing domain.
+/*
+ * Returns the policy flags belonging to the signing domain.
  * Sender: overrides From:, and the d= entry in the DK-Sig overrides both.
  * If the policy flags were not successfully fetched, DK_FLAG_SET will not
  * be set.
  */
-DK_FLAGS dk_policy(DK *dk)
+DK_FLAGS
+dk_policy(DK *dk)
 {
-  char *query, *results, *flags[2];
-  char *domain;
-  int dkf = 0;
-
-  if (!dk)
-    return 0;
-  domain = NULL;
-  if (dk->dksign)
-  {
-    domain = dk->domain;
-  }
-  if (!domain)
-  {
-    domain = dk_from(dk);
-  }
-  if (!domain)
-  {
-    return 0;
-  }
-
-  query = DK_MALLOC(strlen("_domainkey.") + strlen(domain) + 1);
-  if (query)
-  {
-     /* allow user to supply the DNS TXT policy record */
-    if (!dk->policyrec)
-    {
-      sprintf(query, "_domainkey.%s", domain);
-      results = dns_text(query);
-      DK_MFREE(query);
-    }
-    else
-    {
-      results = dk_strdup(dk->policyrec);
-    }
-
-    if (!strcmp(results,"e=perm;"))
-    {
-    }
-    else if (!strcmp(results,"e=temp;"))
-    {
-    }
-    else
-    {
-      dkparselist(results, "ot", flags);
-
-      if (flags[0] && *flags[0] == '-')  /* TC36 */
-      {
-        dkf |= DK_FLAG_SIGNSALL;
-      }
-      if (flags[1] && *flags[1] == 'y')  /* TC36-1 */
-      {
-        dkf |= DK_FLAG_TESTING;
-      }
-      dkf |= DK_FLAG_SET;
-    }
-    DK_MFREE(results);
-  }
-  return dkf;
+	char           *query, *results, *flags[2];
+	char           *domain;
+	int             dkf = 0;
+
+	if (!dk)
+		return 0;
+	domain = NULL;
+	if (dk->dksign)
+		domain = dk->domain;
+	if (!domain)
+		domain = dk_from(dk);
+	if (!domain)
+		return 0;
+	if ((query = DK_MALLOC(strlen("_domainkey.") + strlen(domain) + 1)))
+	{
+		/* allow user to supply the DNS TXT policy record */
+		if (!dk->policyrec)
+		{
+			sprintf(query, "_domainkey.%s", domain);
+			results = dns_text(query);
+			DK_MFREE(query);
+		} else
+			results = dk_strdup(dk->policyrec);
+		if (!strcmp(results, "e=perm;"))
+			;
+		else
+		if (!strcmp(results, "e=temp;"))
+			;
+		else
+		{
+			dkparselist(results, "ot", flags);
+			if (flags[0] && *flags[0] == '-')	/*- TC36 */
+				dkf |= DK_FLAG_SIGNSALL;
+			if (flags[1] && *flags[1] == 'y')	/*- TC36-1 */
+				dkf |= DK_FLAG_TESTING;
+			dkf |= DK_FLAG_SET;
+		}
+		DK_MFREE(results);
+	}
+	return dkf;
 }
 
 /*
-dkhash
-Internal function. Hashes in a single character, Will NOT has in ' ' or '\t'
-if in NOFWS canon. Otherwise tracks \r and \r\n and hashes
-them accordingly with the rest of the message.
-Should ONLY be called when
-  dk->signing == DK_SIGNING_SIGN||DK_SIGNING_VERIFY
-otherwise its pointless
-*/
-static void dkhash(DK *dk, const unsigned char *ptr)
+ * Internal function. Hashes in a single character, Will NOT has in ' ' or '\t'
+ * if in NOFWS canon. Otherwise tracks \r and \r\n and hashes
+ * them accordingly with the rest of the message.  Should ONLY be called when
+ * dk->signing == DK_SIGNING_SIGN||DK_SIGNING_VERIFY
+ * otherwise its pointless
+ */
+static void
+dkhash(DK *dk, const unsigned char *ptr)
 {
 #ifdef DK_DEBUG
-  if ((dk->signing != DK_SIGNING_SIGN)&&(dk->signing != DK_SIGNING_VERIFY))
-  {
-    //called when we shouldnt of, this will break the sig
-    fprintf(stderr,"\nDKHASH() called for \'%c\' in mode: %i\n",*ptr,dk->signing);
-  }
+	if ((dk->signing != DK_SIGNING_SIGN) && (dk->signing != DK_SIGNING_VERIFY))
+	{
+		/* called when we shouldnt of, this will break the sig*/
+		fprintf(stderr, "\nDKHASH() called for \'%c\' in mode: %i\n", *ptr, dk->signing);
+	}
 #endif
-  if (dk->canon == DK_CANON_NOFWS && (*ptr == ' ' || *ptr == '\t'))
-  {
-    return;
-  }
-
-  if ((dk->in_headers && dk->trace) && (dk->opts & DKOPT_TRACE_H))
-  {
-    if (dk->canon == DK_CANON_NOFWS)
-    {
-      if (*ptr != '\r')
-      {
-        if (*ptr == '\n')
-        {
-          dk->trace->ccounts_H[10]++;
-          dk->trace->ccounts_H[13]++;
-        }
-        else
-        {
-          dk->trace->ccounts_H[(int) *ptr]++;
-        }
-      }
-    }
-    else
-    {
-      dk->trace->ccounts_H[(int) *ptr]++;
-    }
-  }
-
-  if (*ptr == '\r' && ((dk->state & 1) == 0))
-  {
-    dk->state++;
-  }
-  else if (*ptr == '\n' && ((dk->state & 1) == 1))
-  {
-    dk->state++;
-  }
-  else
-  {
-    while (dk->state >= 2)
-    {
-
+	if (dk->canon == DK_CANON_NOFWS && (*ptr == ' ' || *ptr == '\t'))
+		return;
+	if ((dk->in_headers && dk->trace) && (dk->opts & DKOPT_TRACE_H))
+	{
+		if (dk->canon == DK_CANON_NOFWS)
+		{
+			if (*ptr != '\r')
+			{
+				if (*ptr == '\n') /*- printf("!added \\r\\n\n"); */
+				{
+					dk->trace->ccounts_H[10]++;
+					dk->trace->ccounts_H[13]++;
+				} else /*- printf("!added %c\n",*ptr); */
+					dk->trace->ccounts_H[(int) *ptr]++;
+			}
+		}
+		else /*- printf("!added %c\n",*ptr); */
+			dk->trace->ccounts_H[(int) *ptr]++;
+	}
+	if (*ptr == '\r' && ((dk->state & 1) == 0))
+		dk->state++;
+	else
+	if (*ptr == '\n' && ((dk->state & 1) == 1))
+		dk->state++;
+	else
+	{
+		while (dk->state >= 2)
+		{
 #ifndef DK_HASH_BUFF
-      EVP_DigestUpdate(&dk->mdctx, "\r\n", 2);
+			EVP_DigestUpdate(evptr, "\r\n", 2);
 #else
-      /* buffer hack */
-      dk->hash_buff[dk->hash_buff_len++] = '\r';
-      dk->hash_buff[dk->hash_buff_len++] = '\n';
-      if (dk->hash_buff_len >= (DK_BLOCK - 1))
-      {
-        EVP_DigestUpdate(&dk->mdctx, dk->hash_buff, dk->hash_buff_len);
-        dk->hash_buff_len = 0;
-      }
-      /* buffer hack */
+			/* buffer hack */
+			dk->hash_buff[dk->hash_buff_len++] = '\r';
+			dk->hash_buff[dk->hash_buff_len++] = '\n';
+			if (dk->hash_buff_len >= (DK_BLOCK - 1))
+			{
+				EVP_DigestUpdate(evptr, dk->hash_buff, dk->hash_buff_len);
+				dk->hash_buff_len = 0;
+			}
+		/* buffer hack */
 #endif
-      if ((!dk->in_headers && dk->trace) && (dk->opts & DKOPT_TRACE_B))
-      {
-        dk->trace->ccounts_B[10]++;
-        dk->trace->ccounts_B[13]++;
-      }
+			if ((!dk->in_headers && dk->trace) && (dk->opts & DKOPT_TRACE_B))
+			{
+				dk->trace->ccounts_B[10]++;
+				dk->trace->ccounts_B[13]++;
+			}
 #ifdef DK_DEBUG
-      fprintf(stderr,"\r\n");
+			fprintf(stderr, "\r\n");
 #endif
-      dk->state -= 2;
-    }
-    if (dk->state)
-    {
-      if (dk->canon == DK_CANON_SIMPLE)//if nofws we ignore \r
-      {
+			dk->state -= 2;
+		}
+		if (dk->state)
+		{
+			if (dk->canon == DK_CANON_SIMPLE)	//if nofws we ignore \r
+			{
 #ifndef DK_HASH_BUFF
-        EVP_DigestUpdate(&dk->mdctx, "\r", 1);
+				EVP_DigestUpdate(evptr, "\r", 1);
 #else
-        /* buffer hack */
-        dk->hash_buff[dk->hash_buff_len++] = '\r';
-        if (dk->hash_buff_len >= (DK_BLOCK - 1))
-        {
-          EVP_DigestUpdate(&dk->mdctx, dk->hash_buff, dk->hash_buff_len);
-          dk->hash_buff_len = 0;
-        }
-        /* buffer hack */
+				/* buffer hack */
+				dk->hash_buff[dk->hash_buff_len++] = '\r';
+				if (dk->hash_buff_len >= (DK_BLOCK - 1))
+				{
+					EVP_DigestUpdate(evptr, dk->hash_buff, dk->hash_buff_len);
+					dk->hash_buff_len = 0;
+				}
+				/* buffer hack */
 #endif
-        if ((!dk->in_headers && dk->trace) && (dk->opts & DKOPT_TRACE_B))
-        {
-          dk->trace->ccounts_B[13]++;
-        }
+				if ((!dk->in_headers && dk->trace) && (dk->opts & DKOPT_TRACE_B))
+					dk->trace->ccounts_B[13]++;
 #ifdef DK_DEBUG
-        fprintf(stderr,"\r");
+				fprintf(stderr, "\r");
 #endif
-      }
-      dk->state --;
-    }
+			}
+			dk->state--;
+		}
 #ifndef DK_HASH_BUFF
-    EVP_DigestUpdate(&dk->mdctx, ptr, 1);
+		EVP_DigestUpdate(evptr, ptr, 1);
 #else
-    /* buffer hack */
-    dk->hash_buff[dk->hash_buff_len++] = *ptr;
-    if (dk->hash_buff_len >= (DK_BLOCK - 1))
-    {
-      EVP_DigestUpdate(&dk->mdctx, dk->hash_buff, dk->hash_buff_len);
-      dk->hash_buff_len = 0;
-    }
-    /* buffer hack */
+    	/* buffer hack */
+		dk->hash_buff[dk->hash_buff_len++] = *ptr;
+		if (dk->hash_buff_len >= (DK_BLOCK - 1))
+		{
+			EVP_DigestUpdate(evptr, dk->hash_buff, dk->hash_buff_len);
+			dk->hash_buff_len = 0;
+		}
+		/* buffer hack */
 #endif
-
-    if ((!dk->in_headers && dk->trace) && (dk->opts & DKOPT_TRACE_B))
-    {
-      dk->trace->ccounts_B[(int) *ptr]++;
-    }
-
+		if ((!dk->in_headers && dk->trace) && (dk->opts & DKOPT_TRACE_B))
+			dk->trace->ccounts_B[(int) *ptr]++;
 #ifdef DK_DEBUG
-    fprintf(stderr,"%c", *ptr);
+		fprintf(stderr, "%c", *ptr);
 #endif
-  }
+	}
 }
 
-/* process headers if there's a h=*/
-/* dk->start_signed + 1 is the offset into headers pointing at the first header after DK-Sig */
-/* Changed to fix h= handling, checks if header is listed in h=
- *  handles duplicate Header items properly. (see section 3.3 h= draft-02)
+/*
+ * process headers if there's a h=
+ * dk->start_signed + 1 is the offset into headers pointing at the first header after DK-Sig 
+ * Changed to fix h= handling, checks if header is listed in h=
+ * handles duplicate Header items properly. (see section 3.3 h= draft-02)
  * We don't "look" for missing headers, maybe later.... -Tim
  */
-static DK_STAT dkheaders_header(DK *dk)
+static DK_STAT
+dkheaders_header(DK *dk)
 {
-  char *header_line_start,*header_label_end;
-  char header_list[1024];
-  char header_label[1024];
-
-  char *p;
-  //search hack redo later? -tim
-  if (snprintf(header_list,sizeof(header_list),":%s:",dk->headers) >= sizeof(header_list))
-  {
-    //header list is too large for buffer
-    return DKERR(DK_STAT_SYNTAX);
-  }
+	char           *p, *header_line_start, *header_label_end;
+	char           *header_label;
+	static char    *header_list;
+	int             header_len;
 
-  /*convert to all lowercase*/
-  for (p = header_list; p[0] != '\0'; ++p)
-  {
-    p[0] = tolower(p[0]);
-  }
+	/*- search hack redo later? -tim */
+	if (!(header_list = DK_REALLOC(header_list, (header_len = strlen(dk->headers)) + 3)))
+	{
+		DK_MFREE(dk);
+		return(DKERR(DK_STAT_NORESOURCE));
+	}
+	if (!(header_label = DK_MALLOC(header_len + 3)))
+	{
+		DK_MFREE(dk);
+		return(DKERR(DK_STAT_NORESOURCE));
+	}
+	if (snprintf(header_list, header_len + 3, ":%s:", dk->headers) >= header_len + 3)
+	{
+		/*header list is too large for buffer */
+		DK_MFREE(header_label);
+		return DKERR(DK_STAT_SYNTAX);
+	}
+	/*- convert to all lowercase */
+	for (p = header_list; p[0] != '\0'; ++p)
+		p[0] = tolower(p[0]);
+	header_label[0] = ':';
+	/*- first char in header_line_start is '\0' unless signing */
+	header_line_start = dk->header + dk->start_signed;
+	if (dk->signing != DK_SIGNING_SIGN)
+		++header_line_start;
+	while (1) {
+		if (header_line_start >= (dk->header + dk->headerlen))
+		{
+			DK_MFREE(header_label);
+			return DKERR(DK_STAT_OK);	/*- done reading headers */
+		}
+		header_label_end = header_line_start;
+		p = &header_label[1];
+		/*- while (p < (header_label + sizeof (header_label) - 2)) { -*/
+		while (p < (header_label + header_len - 2)) {
+			if (header_label_end[0] != ':') {
+				p[0] = tolower(header_label_end[0]);
+				++p;
+				++header_label_end;
+			} else
+				break;
+		}
+		p[0] = ':';
+		p[1] = '\0';
+		/*- if the header is found in the h= list */
+		if (strstr(header_list, header_label) != NULL) {
+			/* Found listed header, hash it in */
+			while (header_line_start[0] != '\0') {
+				/*- we kept folded headers \r\n as markers -Tim */
+				if ((header_line_start[0] == '\n') || (header_line_start[0] == '\r')) {
+					/* if simple we keep the folded lines */
+					/* if nofws we ignore it to unwrap it */
+					if (dk->canon == DK_CANON_NOFWS) {
+						++header_line_start;
+						continue;
+					}
+				}
+				dkhash(dk, (unsigned char *) &header_line_start[0]);
+				++header_line_start;
+			}
+			dkhash(dk, (unsigned char *) "\r");
+			dkhash(dk, (unsigned char *) "\n");
+		} else	/*- skip hashing this header */
+		{
+			while (header_line_start[0] != '\0')
+				++header_line_start;
+		}
+		/*- goto next header */
+		++header_line_start;
+	} /*- while(1) */
+}
 
-  header_label[0] = ':';
-  //first char in header_line_start is '\0' unless signing
-  header_line_start = dk->header + dk->start_signed;
-  if (dk->signing != DK_SIGNING_SIGN)
-  {
-    ++header_line_start;
-  }
-  while (1)
-  {
-    if (header_line_start >= (dk->header + dk->headerlen))
-    {
-      return DKERR(DK_STAT_OK);  //done reading headers
-    }
-    header_label_end = header_line_start;
-    p = &header_label[1];
-    while (p < (header_label + sizeof(header_label) - 2))
-    {
-      if (header_label_end[0] != ':')
-      {
-        p[0] = tolower(header_label_end[0]);
-        ++p;
-        ++header_label_end;
-      }
-      else
-      {
-        break;
-      }
-    }
-    p[0] = ':';
-    p[1] = '\0';
-    //fprintf(stderr,"searching for: %s in %s\n",header_label, header_list);
-    //if the header is found in the h= list
-    if (strstr(header_list, header_label) != NULL)
-    {
-      //Found listed header, hash it in
-      while(header_line_start[0] != '\0')
-      {
-        //we kept folded headers \r\n as markers -Tim
-        if ((header_line_start[0] == '\n')||(header_line_start[0] == '\r'))
-        {
-          //if simple we keep the folded lines
-          //if nofws we ignore it to unwrap it
-          if (dk->canon == DK_CANON_NOFWS)
-          {
-            ++header_line_start;
-            continue;
-          }
-        }
-        dkhash(dk,&header_line_start[0]);
-        ++header_line_start;
-      }
-      dkhash(dk, "\r");
-      dkhash(dk, "\n");
-    }
-    else //skip hashing this header
-    {
-      while(header_line_start[0] != '\0')
-      {
-        ++header_line_start;
-      }
-    }
-    //goto next header
-    ++header_line_start;
-
-  }//end while
-}
-/* dkheaders
-  When Signing (DK_SIGNING_SIGN), Hashes in ALL headers and Greps out Sender:/From: headers
-
-  When Verifying, reads headers until DK-Sig is found
-  then
-  If an h= tag is found, Greps out Sender:/From: headers, then calls dkheaders_header
-    to hash in the listed headers
-  If NO h= tag is present, it Greps out Sender:/From: headers as well as hashes in the
-    headers that follow the DK-Sig header.
-*/
-static DK_STAT dkheaders(DK *dk)
+/*
+ * When Signing (DK_SIGNING_SIGN), Hashes in ALL headers and Greps out Sender:/From: headers
+ * When Verifying, reads headers until DK-Sig is found
+ * then
+ * If an h= tag is found, Greps out Sender:/From: headers, then calls dkheaders_header
+ * to hash in the listed headers
+ * If NO h= tag is present, it Greps out Sender:/From: headers as well as hashes in the
+ * headers that follow the DK-Sig header.
+ */
+static DK_STAT
+dkheaders(DK *dk)
 {
-  int i;
+	int             i;
 
-  for (i = 0; i < dk->headerlen; i++)
-  {
-    if (dk->headers && dk->signing == DK_SIGNING_VERIFY) //if h= wait till after parsing
-    {
-      //NOOP
-    }
-    else if (dk->canon == DK_CANON_NOFWS && (dk->header[i] == '\r' || dk->header[i] == '\n'))
-    {
-      //NOOP
-    }
-    /* Newcode */
-    else if ((dk->opts & DKOPT_RDUPE)&&(dk->signing == DK_SIGNING_SIGN))
-    {
-      //NOOP
-    }
-    else if ((dk->signing == DK_SIGNING_SIGN)||(dk->signing == DK_SIGNING_VERIFY))
-    {
-      //we wont bother calling dkhash unless we are signing or verifying -Tim
-      if (dk->header[i])
-      {
-        dkhash(dk, dk->header + i);
-      }
-      else //terminate end of header line
-      {
-        dkhash(dk, "\r");
-        dkhash(dk, "\n");
-      }
-    }
-    /* Newcode end */
-
-    if (i==0 || dk->header[i-1] == '\0')
-    {
-      if (!strncasecmp(dk->header + i, "From:", 5))
-      {
-        /* Remember the From: and forget the current. */
-        if (dk->from)
-        {
-          /* if we already got a From: header, fuhgeddabout it. */
-          return DKERR(DK_STAT_SYNTAX);
-        }
-        dk->from = dk_strdup(dk->header + i);
-        if (dkparse822(dk->from, 5) != DK_STAT_OK)
-        {
-          DK_MFREE(dk->from);
-          dk->from = 0;
-          return DKERR(DK_STAT_SYNTAX);
-        }
-      }
-      else if (!strncasecmp(dk->header + i, "Sender:", 7))
-      {
-        if (dk->sender)
-        {
-          /* if we already got a Sender: header, fuhgeddabout it. */
-          return DKERR(DK_STAT_SYNTAX);
-        }
-        if (dk->signing != DK_SIGNING_NOVERIFY)
-        {
-          /* only remember the Sender if we're verifying already. */
-          dk->sender = dk_strdup(dk->header + i);
-          if (dkparse822(dk->sender, 7) != DK_STAT_OK)
-          {
-            DK_MFREE(dk->sender);
-            dk->sender = 0;
-            return DKERR(DK_STAT_SYNTAX);
-          }
-        }
-        else if (!dk->sender_beforesign)
-        {
-          dk->sender_beforesign = dk_strdup(dk->header + i);
-          if (dkparse822(dk->sender_beforesign, 7) != DK_STAT_OK)
-          {
-            DK_MFREE(dk->sender_beforesign);
-            dk->sender_beforesign = 0;
-            return DKERR(DK_STAT_SYNTAX);
-          }
-        }
-      }
-      else if (!strncasecmp(dk->header + i, "DomainKey-Trace:", 16))
-      {
-        if (dk->trace && !dk->dktrace)//only set this once
-        {
-          dk->dktrace = dk->header + i;
-        }
-      }
-      else if (!strncasecmp(dk->header + i, "DomainKey-Signature:", 20))
-      {
-        int thisheaderlen = strlen(dk->header + i);
-
-        /* Do not sign email that already has a dksign unless the Sender was found first, 3.5.2 TC41, TC41-1*/
-        if (dk->signing == DK_SIGNING_SIGN && !dk->sender)
-        {
-          return DKERR(DK_STAT_SYNTAX);
-        }
-        /* check the outermost (first encountered) signature (need to fix when multiple sigs are present)
-        * ONLY if we are verifying, if we are signing then ignore it (sender before dk-sig) -Tim
-        */
-        if ((!dk->dksign)&&(dk->signing != DK_SIGNING_SIGN))
-        {
-          char *values[7];  /* dsbchqa */
-          dk->dksign = dk->header + i;
-          /* parse the dksign header .*/
-          if (dkparselist(dk->dksign + 20,"dsbchqa", values) != DK_STAT_OK)
-          {
-            return DKERR(DK_STAT_SYNTAX);
-          }
-
-          dk->domain = values[0];
-          dk->selector = values[1];
-          dk->signature = values[2];
-          if (!dk->selector || !dk->domain || !dk->signature)
-          {
-            /* we really do need to have a domain, selector and key. TC21 TC40 */
-            return DKERR(DK_STAT_NOSIG);
-          }
-
-          if (!values[3])
-          {
-            dk->canon = DK_CANON_SIMPLE;
-          }
-          else if (!strcasecmp(values[3], "simple"))
-          {
-            dk->canon = DK_CANON_SIMPLE;
-          }
-          else if (!strcasecmp(values[3], "nofws"))
-          {
-            dk->canon = DK_CANON_NOFWS;
-          }
-          else
-          {
-            return DKERR(DK_STAT_SYNTAX); /* TC42 */
-          }
-
-          dk->headers = values[4];
-
-          if (values[5] && strcasecmp(values[5], "dns")) /* TC42-2 */
-          {
-            return DKERR(DK_STAT_SYNTAX);
-          }
-          if (values[6] && strcasecmp(values[6], "rsa-sha1")) /* TC42-3 */
-          {
-            return DKERR(DK_STAT_SYNTAX);
-          }
-
-        }
-        /* if we're waiting to verify, start now. */
-        if (dk->signing == DK_SIGNING_NOVERIFY)
-        {
-          dk->signing = DK_SIGNING_VERIFY; /* the signature starts here */
-          i += thisheaderlen;
-          if (dk->start_signed == 0) //we should set it only once right?
-          {
-            dk->start_signed = i;
-          }
-        }
-      }
-      //end trace
-    }
-  }
-  if ((!dk->from)||(!dk_from(dk)))
-  {
-    /* No From:, 3.1 says that it's no good..  TC11/TC16 */
-    return DKERR(DK_STAT_SYNTAX);
-  }
-  if (dk->signing == DK_SIGNING_NOVERIFY)
-  {
-    /* No DK-Sig: should return No Signature. */
-    return DKERR(DK_STAT_NOSIG);
-  }
-  if (dk->headers && dk->signing == DK_SIGNING_VERIFY)
-  {
-    return dkheaders_header(dk);
-  }
-  if ((dk->signing == DK_SIGNING_SIGN)&&(dk->opts & DKOPT_RDUPE)) //remove dupe headers for sig
-  {
-    DK_STAT ret;
-    dk->headers = DK_MALLOC(dk->headermax);
-    (void *)dk_headers(dk, dk->headers);
-    ret = dkheaders_header(dk);
-    DK_MFREE(dk->headers);
-    return ret;
-  }
-  return DKERR(DK_STAT_OK);
+	for (i = 0; i < dk->headerlen; i++) {
+		if (dk->headers && dk->signing == DK_SIGNING_VERIFY)	//if h= wait till after parsing
+		{
+			/*- NOOP */
+		} else
+		if (dk->canon == DK_CANON_NOFWS && (dk->header[i] == '\r' || dk->header[i] == '\n'))
+		{
+			/*- NOOP */
+		} else /*- Newcode */
+		if ((dk->opts & DKOPT_RDUPE) && (dk->signing == DK_SIGNING_SIGN))
+		{
+			/*- NOOP */
+		} else
+		if ((dk->opts & DKOPT_SELHEAD) && (dk->signing == DK_SIGNING_SIGN))
+		{
+			/*- NOOP */
+		} else
+		if ((dk->signing == DK_SIGNING_SIGN) || (dk->signing == DK_SIGNING_VERIFY)) {
+			/*- we wont bother calling dkhash unless we are signing or verifying -Tim */
+			if (dk->header[i])
+				dkhash(dk, (const unsigned char *) dk->header + i);
+			else /*- terminate end of header line */
+			{
+				dkhash(dk, (const unsigned char *) "\r");
+				dkhash(dk, (const unsigned char *) "\n");
+			}
+		}
+		/*- Newcode end */
+		if (i == 0 || dk->header[i - 1] == '\0') {
+			if (!strncasecmp(dk->header + i, "From:", 5)) {
+				/*
+				 * Remember the From: and forget the current. 
+				 */
+				if (dk->from) {
+					/*
+					 * if we already got a From: header, fuhgeddabout it. 
+					 */
+					return DKERR(DK_STAT_SYNTAX);
+				}
+				dk->from = dk_strdup(dk->header + i);
+				if (dkparse822(dk->from, 5) != DK_STAT_OK) {
+					DK_MFREE(dk->from);
+					dk->from = 0;
+					return DKERR(DK_STAT_SYNTAX);
+				}
+			} else
+			if (!strncasecmp(dk->header + i, "Sender:", 7)) {
+				if (dk->sender) {
+					/*
+					 * if we already got a Sender: header, fuhgeddabout it. 
+					 */
+					return DKERR(DK_STAT_SYNTAX);
+				}
+				if (dk->signing != DK_SIGNING_NOVERIFY) {
+					/*
+					 * only remember the Sender if we're verifying already. 
+					 */
+					dk->sender = dk_strdup(dk->header + i);
+					if (dkparse822(dk->sender, 7) != DK_STAT_OK) {
+						DK_MFREE(dk->sender);
+						dk->sender = 0;
+						return DKERR(DK_STAT_SYNTAX);
+					}
+				} else
+				if (!dk->sender_beforesign) {
+					dk->sender_beforesign = dk_strdup(dk->header + i);
+					if (dkparse822(dk->sender_beforesign, 7) != DK_STAT_OK) {
+						DK_MFREE(dk->sender_beforesign);
+						dk->sender_beforesign = 0;
+						return DKERR(DK_STAT_SYNTAX);
+					}
+				}
+			} else
+			if (!strncasecmp(dk->header + i, "DomainKey-Trace:", 16)) {
+				if (dk->trace && !dk->dktrace)	//only set this once
+					dk->dktrace = dk->header + i;
+			} else
+			if (!strncasecmp(dk->header + i, "DomainKey-Signature:", 20)) {
+				int             thisheaderlen = strlen(dk->header + i);
+
+				/*
+				 * Do not sign email that already has a dksign unless the
+				 * Sender was found first, 3.5.2 TC41, TC41-1
+				 */
+				if (dk->signing == DK_SIGNING_SIGN && !dk->sender)
+					return DKERR(DK_STAT_DUPLICATE);
+				/*
+				 * check the outermost (first encountered) signature
+				 * (need to fix when multiple sigs are present)
+				 * ONLY if we are verifying, if we are signing then ignore it
+				 * (sender before dk-sig) -Tim
+				 */
+				if (!dk->dksign && dk->signing != DK_SIGNING_SIGN) {
+					char           *values[7];	/* dsbchqa */
+					dk->dksign = dk->header + i;
+					/*- parse the dksign header .  */
+					if (dkparselist(dk->dksign + 20, "dsbchqa", values) != DK_STAT_OK)
+						return DKERR(DK_STAT_SYNTAX);
+					dk->domain = values[0];
+					dk->selector = values[1];
+					dk->signature = values[2];
+					if (!dk->selector || !dk->domain || !dk->signature) 
+						/*
+						 * we really do need to have a domain, selector and key. TC21 TC40 
+						 */
+						return DKERR(DK_STAT_NOSIG);
+					if (!values[3])
+						dk->canon = DK_CANON_SIMPLE;
+					else
+					if (!strcasecmp(values[3], "simple"))
+						dk->canon = DK_CANON_SIMPLE;
+					else
+					if (!strcasecmp(values[3], "nofws"))
+						dk->canon = DK_CANON_NOFWS;
+					else
+						return DKERR(DK_STAT_SYNTAX);	/* TC42 */
+					dk->headers = values[4];
+					if (values[5] && strcasecmp(values[5], "dns"))	/* TC42-2 */
+						return DKERR(DK_STAT_SYNTAX);
+					if (values[6] && strcasecmp(values[6], "rsa-sha1"))	/* TC42-3 */
+						return DKERR(DK_STAT_SYNTAX);
+				}
+				/*
+				 * if we're waiting to verify, start now. 
+				 */
+				if (dk->signing == DK_SIGNING_NOVERIFY) {
+					dk->signing = DK_SIGNING_VERIFY;	/* the signature starts here */
+					i += thisheaderlen;
+					if (dk->start_signed == 0)	//we should set it only once right?
+						dk->start_signed = i;
+				}
+			} /* end trace */
+		}
+	}
+	if (!dk->from || !dk_from(dk)) /*- No From:, 3.1 says that it's no good..  TC11/TC16 */
+		return DKERR(DK_STAT_SYNTAX);
+	if (dk->signing == DK_SIGNING_NOVERIFY) /*- No DK-Sig: should return No Signature. */
+		return DKERR(DK_STAT_NOSIG);
+	if (dk->headers && dk->signing == DK_SIGNING_VERIFY)
+		return dkheaders_header(dk);
+	if (dk->signing == DK_SIGNING_SIGN && 
+		((dk->opts & DKOPT_RDUPE) || (dk->opts & DKOPT_SELHEAD)))
+	{ /*- remove dupe headers for sig */
+		DK_STAT         ret;
+		dk->headers = DK_MALLOC(dk->headermax);
+		dk_headers(dk, dk->headers);
+		ret = dkheaders_header(dk);
+		DK_MFREE(dk->headers);
+		return ret;
+	}
+	return DKERR(DK_STAT_OK);
 }
 
 /* HEADER */
-/* Copies the header names that were signed into the pointer.
+/*
+ * Copies the header names that were signed into the pointer.
  * Returns the number of bytes copied.
  * ptr may be NULL, in which case the bytes are just counted, not copied.
  * Feel free to call this twice; once to get the length, and again to
  * copy the data.
+ * If we preserve duplicate headers, actually return something (len)
+ * If we remove duplicate headers, len may be innacurate (greater than what's
+ * really needed when calling with ptr == NULL
  * NOTE: If the return value is 0 then an error occured.
- *	It's a good idea to check for this
+ *     It's a good idea to check for this
  */
-int dk_headers(DK *dk, char *ptr)
+int
+dk_headers(DK *dk, char *ptr)
 {
-  register int len = 0;
-  register int label_len = 0;
-  int list_size;
-  char *header_start = NULL;
-  char *header_end = NULL;
-  char *h_label = NULL;
-  char *h_list = NULL;
-
-  char *dupe_list = NULL;
-
-
-  if (ptr) //if you dont check if return is 0, ptr can be anything
-  	ptr[0] = 0;
-
-  if ((!dk)||(dk->dkmarker != DKMARK))
-  {
-    return 0;
-  }
-  list_size = dk->headermax;
-
-  h_list = (char *) DK_MALLOC(list_size);
-  if (!h_list)
-    return 0;
-  memset(h_list,0,list_size);
-  h_list[len++] = ':';
-
-  header_start = dk->header + dk->start_signed;
-
-  for (header_end = header_start; header_end < (dk->header + dk->headerlen); header_end++)
-  {
-    if (*header_end == '\0')
-    {
-      header_start = header_end+1;//point to start of next line
-    }
-    else if (*header_end == ':' && header_start)
-    {
-      label_len = (header_end - header_start) + 1;
-	  //grow list array
-	  if ((len+label_len) >= list_size)
-	  {
-	  	char *temp = NULL;
-		list_size += dk->headermax;
-		temp = DK_MALLOC(list_size);
-		if (!temp)
-		{
-			len = 1; //out of memory?
-			goto END;
-		}
-		memset(temp,0,list_size);
-		memcpy(temp,h_list,len);
-		DK_MFREE(h_list);
-		h_list = temp;
-	  }
-
-      memcpy(h_list + len, header_start, label_len);
-      len += label_len;
-      header_start = NULL;
-    }
-  }
+	int             len;
+	int             k, m;
 
-  if (dk->opts & DKOPT_RDUPE)
-  {
-
-    h_label = (char *) DK_MALLOC(list_size);
-	dupe_list = (char *) DK_MALLOC(list_size);
-
-    if (!h_label || !dupe_list)
-	{
-      len = 1;
-	  goto END;
+	if (!dk)
+		return 0;
+	if (dk->dkmarker != DKMARK)
+		return 0;
+	len = 0;
+	m = dk->start_signed;
+	for (k = dk->start_signed; k < dk->headerlen; k++) {
+		if (dk->header[k] == '\0')
+			m = k + 1;
+		else
+		if (dk->header[k] == ':' && m >= 0) {
+			if (ptr) {
+				memcpy(ptr + len, dk->header + m, k - m + 1);
+			}
+			len += k - m + 1;
+			m = -1;
+		}
 	}
-    memset(h_label,0,list_size);
-    memset(dupe_list,0,list_size);
-
-    len = 0;
-  	header_start = h_list;
-	for (header_end = header_start + 1; *header_end != '\0'; header_end++)
-	{
-		if (*header_end == ':')
-		{
-			label_len = (header_end - header_start)+1;
-	        memcpy(h_label, header_start, label_len);
-    	    h_label[label_len] = 0;
-			if ((strstr(h_list,h_label) == header_start)  && (strstr(header_start + 1,h_label) == NULL) )
-			{
-				memcpy(dupe_list + len ,h_label,label_len);
-				len += label_len -1;
+	if ((dk->opts & DKOPT_RDUPE) && (ptr)){
+		int             headpos = 0;
+		char           *copy = (char *) DK_MALLOC(len + 2);
+
+		copy[0] = ':';
+		memcpy(copy + 1, ptr, len - 1);
+		copy[len] = ':';
+		copy[len + 1] = 0;
+		ptr[0] = 0;
+		m = 0;
+
+		for (k = 1; k < len + 2; k++) {
+			if (copy[k] == ':') {
+				int             found = 0;
+				int             sub;
+				for (sub = 0; sub < len + 2; sub++) {
+					if ((copy[sub] == ':') && (sub != m)) {
+						if (!strncmp(copy + sub, copy + m, k - m)) {
+							found = 1;
+							break;
+						}
+					}
+				}
+				if (!found) {
+					memcpy(ptr + headpos, copy + m + 1, k - m);
+					headpos += k - m;
+					ptr[headpos] = 0;
+				}
+				m = k;
 			}
-			header_start = header_end;
 		}
+		DK_MFREE(copy);
+		len = headpos;
 	}
-	len++;
-	if (ptr)
-		memcpy(h_list, dupe_list, len);
-  }
-
-  if ((ptr != NULL)&&(len > 1))
-  {
-    memcpy(ptr,h_list+1,(len-2));//dont count the prefix and postfix'd ":"
-    ptr[len-2] = 0;
-  }
-  END:
-  if (h_label)
-    DK_MFREE(h_label);
-  if (h_list)
-    DK_MFREE(h_list);
-  if (dupe_list)
-    DK_MFREE(dupe_list);
-
-  return --len;
+	if ((dk->opts & DKOPT_SELHEAD) && (ptr)) {
+		int             headpos = 0;
+		char           *copy = (char *) DK_MALLOC(len + 2);
+
+		copy[0] = ':';
+		memcpy(copy + 1, ptr, len - 1);
+		copy[len] = ':';
+		copy[len + 1] = 0;
+		ptr[0] = 0;
+		m = 0;
+		for (k = 1; k < len + 2; k++) {
+			if (copy[k] == ':') {
+				int             found = 0;
+				int             n = 0, s;
+				int             len_s = strlen(dk->sel_headers);
+				for (s = 1; s < len_s; s++) {
+					if (dk->sel_headers[s] == ':') {
+						if (s - n == k - m) {
+							if (!strncasecmp(copy + m + 1, dk->sel_headers + n + 1, k - m)) {
+								found = 1;
+								break;
+							}
+						}
+						n = s;
+					}
+				}
+				if (found) {
+					memcpy(ptr + headpos, copy + m + 1, k - m);
+					headpos += k - m;
+					ptr[headpos] = 0;
+				}
+				m = k;
+			}
+		}
+		len = headpos;
+		DK_MFREE(copy);
+	}
+	if (len && ptr) {
+		ptr[len - 1] = '\0';	/* change the last colon into a null. */
+	}
+	return len;	/*- return size including '\0' */
+}
 
+/* HEADER */
+/*
+ * Returns a pointer to a null-terminated string containing the granularity
+ * value found in the selector DNS record, if any, but only after dk_end
+ * has been called. Otherwise returns NULL.
+ */
+char           *
+dk_granularity(DK *dk)
+{
+	if (!dk)
+		return NULL;
+	if (dk->dkmarker != DKMARK)
+		return NULL;
+	return dk->granularity;
 }
 
 /* HEADER */
-/* Must NOT include dots inserted for SMTP encapsulation.
+/*
+ * Must NOT include dots inserted for SMTP encapsulation.
  * Must NOT include CRLF.CRLF which terminates the message.
  * Otherwise must be exactly that which is sent or received over the SMTP session.
  * May be called multiple times (not necessary to read an entire message into memory).
  */
-DK_STAT dk_message(DK *dk, const unsigned char *ptr, size_t len)
+DK_STAT
+dk_message(DK *dk, const unsigned char *ptr, size_t len)
 {
-  DK_STAT st;
-  int tb=0,th=0;
-  if (!dk)
-  {
-    return DK_STAT_ARGS;
-  }
-  if (dk->dkmarker != DKMARK)
-  {
-    return DK_STAT_ARGS;
-  }
-  if (len && !ptr)
-  {
-    return DKERR(DK_STAT_ARGS);
-  }
-  if (dk->trace && (dk->opts & DKOPT_TRACE_b))
-    tb = 1;
-  if (dk->trace && (dk->opts & DKOPT_TRACE_h))
-    th = 1;
+	DK_STAT         st;
+	int             tb = 0, th = 0;
 
-  while (len--)
-  {
-    if ((*ptr == '\n') && (dk->last_char != '\r'))
-    {
-      //input not formatted correctly
-      //CR should preceed LF
-      return DKERR(DK_STAT_SYNTAX);
-    }
-    /* parse headers */
-    if (!dk->in_headers)
-    {
-      dkhash(dk, ptr); //hash body of message
-      //precanon probably wont be accurate as dk_message() only takes in SMTP format -Tim
-      if (tb)
-        dk->trace->ccounts_b[(int) *ptr]++;
-    }
-    else if (*ptr == '\n' && dk->headerlinelen != 0)
-    {
-      /* beginning a new line, but we can't do anything until we get a char. */
-      dk->headerlinelen = 0;
-    }
-    else if (*ptr == '\r')
-    {
-      /* ignore carriage-returns, even bare ones.  We'll add them back in later.*/
-      if (dk->last_char == '\r') //keep embedded CR
-      {
-        if (dkstore_char(dk, '\r') != DK_STAT_OK)
-        {
-          return DKERR(DK_STAT_NORESOURCE);
-        }
-        if (th)
-          dk->trace->ccounts_h[13]++;
-      }
-    }
-    else if (dk->headerlinelen)
-    {
-
-      if (dk->last_char == '\r') //keep embedded CR
-      {
-        if (dkstore_char(dk, '\r') != DK_STAT_OK)
-        {
-          return DKERR(DK_STAT_NORESOURCE);
-        }
-        if (th)
-          dk->trace->ccounts_h[13]++;
-      }
-
-      /* if we're not starting a new header, just store it */
-      if (dkstore_char(dk, *ptr) != DK_STAT_OK)
-      {
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      if (th)
-        dk->trace->ccounts_h[(int) *ptr]++;
-    }
-    else if (*ptr == ' ' || *ptr == '\t')
-    {
-      /* a new header ... starting with whitespace.  Must be continuation */
-      /* just remember the whitespace */
-      //preserv folded headers for simple canon -Tim
-      if (dkstore_char(dk, '\r') != DK_STAT_OK)
-      {
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      if (dkstore_char(dk, '\n') != DK_STAT_OK)
-      {
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      if (dkstore_char(dk, *ptr) != DK_STAT_OK)
-      {
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      if (th)
-      {
-        dk->trace->ccounts_h[10]++;
-        dk->trace->ccounts_h[13]++;
-        dk->trace->ccounts_h[(int) *ptr]++;
-      }
-
-    }
-    else if (*ptr == '\n')
-    {
-      /* an empty line terminates header processing */
-      /* terminate the previous header */
-      if (dkstore_char(dk, '\0') != DK_STAT_OK)
-      {
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      if (th)
-      {
-        dk->trace->ccounts_h[10]++;
-        dk->trace->ccounts_h[13]++;
-      }
-      if (tb)
-      {
-        dk->trace->ccounts_b[10]++;
-        dk->trace->ccounts_b[13]++;
-      }
-      st = dkheaders(dk);
-      dk->in_headers = 0;
-      dkhash(dk, "\r");
-      dkhash(dk, "\n");
-
-      if (st != DK_STAT_OK)
-      {
-        return st;
-      }
-    }
-    else
-    {
-      /* we're starting a new header.  Terminate the previous one. */
-      if (dkstore_char(dk, '\0') != DK_STAT_OK)
-      {
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      /* remember the first character of a new header. */
-      if (dkstore_char(dk, *ptr) != DK_STAT_OK)
-      {
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      if (th)
-      {
-        dk->trace->ccounts_h[10]++;
-        dk->trace->ccounts_h[13]++;
-        dk->trace->ccounts_h[(int) *ptr]++;
-      }
-    }
-    dk->last_char = *ptr; //remember last character processed
-    ptr++;
-  }
-  return DKERR(DK_STAT_OK);
+	if (!dk)
+		return DK_STAT_ARGS;
+	if (dk->dkmarker != DKMARK)
+		return DK_STAT_ARGS;
+	if (len && !ptr)
+		return DKERR(DK_STAT_ARGS);
+	if (dk->trace && (dk->opts & DKOPT_TRACE_b))
+		tb = 1;
+	if (dk->trace && (dk->opts & DKOPT_TRACE_h))
+		th = 1;
+	while (len--) {
+		if ((*ptr == '\n') && (dk->last_char != '\r'))
+		{
+			/* 
+			 * input not formatted correctly
+			 * CR should preceed LF
+			 */
+			return DKERR(DK_STAT_SYNTAX);
+		}
+		/*- parse headers */
+		if (!dk->in_headers) {
+			dkhash(dk, ptr);	//hash body of message
+			/*
+			 * precanon probably wont be accurate as dk_message()
+			 * only takes in SMTP format -Tim
+			 */
+			if (tb)
+				dk->trace->ccounts_b[(int) *ptr]++;
+		} else
+		if (*ptr == '\n' && dk->headerlinelen != 0) {
+			/*
+			 * beginning a new line, but we can't do anything until we get a char. 
+			 */
+			dk->headerlinelen = 0;
+		} else
+		if (*ptr == '\r') {
+			/*
+			 * ignore carriage-returns, even bare ones.  We'll add them back in later.
+			 */
+			if (dk->last_char == '\r') //keep embedded CR
+			{
+				if (dkstore_char(dk, '\r') != DK_STAT_OK)
+					return DKERR(DK_STAT_NORESOURCE);
+				if (th)
+					dk->trace->ccounts_h[13]++;
+			}
+		} else
+		if (dk->headerlinelen) {
+			if (dk->last_char == '\r') //keep embedded CR
+			{
+				if (dkstore_char(dk, '\r') != DK_STAT_OK)
+					return DKERR(DK_STAT_NORESOURCE);
+				if (th)
+					dk->trace->ccounts_h[13]++;
+			}
+			/*
+			 * if we're not starting a new header, just store it 
+			 */
+			if (dkstore_char(dk, *ptr) != DK_STAT_OK)
+				return DKERR(DK_STAT_NORESOURCE);
+			if (th)
+				dk->trace->ccounts_h[(int) *ptr]++;
+		} else
+		if (*ptr == ' ' || *ptr == '\t') {
+			/*
+			 * a new header ... starting with whitespace.  Must be continuation 
+			 * just remember the whitespace 
+			 * preserv folded headers for simple canon -Tim
+			 */
+			if (dkstore_char(dk, '\r') != DK_STAT_OK)
+				return DKERR(DK_STAT_NORESOURCE);
+			if (dkstore_char(dk, '\n') != DK_STAT_OK)
+				return DKERR(DK_STAT_NORESOURCE);
+			if (dkstore_char(dk, *ptr) != DK_STAT_OK)
+				return DKERR(DK_STAT_NORESOURCE);
+			if (th)
+			{
+				dk->trace->ccounts_h[10]++;
+				dk->trace->ccounts_h[13]++;
+				dk->trace->ccounts_h[(int) *ptr]++;
+			}
+		} else
+		if (*ptr == '\n') {
+			/*
+			 * an empty line terminates header processing 
+			 * terminate the previous header 
+			 */
+			if (dkstore_char(dk, '\0') != DK_STAT_OK)
+				return DKERR(DK_STAT_NORESOURCE);
+			if (th)
+			{
+				dk->trace->ccounts_h[10]++;
+				dk->trace->ccounts_h[13]++;
+			}
+			if (tb)
+			{
+				dk->trace->ccounts_b[10]++;
+				dk->trace->ccounts_b[13]++;
+			}
+			st = dkheaders(dk);
+			dk->in_headers = 0;
+			dkhash(dk, (const unsigned char *) "\r");
+			dkhash(dk, (const unsigned char *) "\n");
+			if (st != DK_STAT_OK)
+				return st;
+		} else {
+			/*
+			 * we're starting a new header.  Terminate the previous one. 
+			 */
+			if (dkstore_char(dk, '\0') != DK_STAT_OK)
+				return DKERR(DK_STAT_NORESOURCE);
+			/*
+			 * remember the first character of a new header. 
+			 */
+			if (dkstore_char(dk, *ptr) != DK_STAT_OK)
+				return DKERR(DK_STAT_NORESOURCE);
+			if (th)
+			{
+				dk->trace->ccounts_h[10]++;
+				dk->trace->ccounts_h[13]++;
+				dk->trace->ccounts_h[(int) *ptr]++;
+			}
+		}
+		dk->last_char = *ptr; //remember last character processed
+		ptr++;
+	}
+	return DKERR(DK_STAT_OK);
 }
-
 /* HEADER */
-/* DEPRECATED in favor of calling dk_address().
+/*
+ * DEPRECATED in favor of calling dk_address().
  * Returns a pointer to a null-terminated domain name portion of an RFC 2822 address.
  * If a Sender: was encountered, it returns that domain.  Otherwise,
  * if a From: was encountered, it returns that domain.  Otherwise,
@@ -1584,65 +1550,48 @@
  * return NULL if the dk is unusable for any reason.
  * return NULL if the address is unusable for any reason.
  */
-char *dk_from(DK *dk)
+char           *
+dk_from(DK *dk)
 {
-  char *s;
+	char           *s, *ptr;
+	int             i;
 
-  if (!dk)
-  {
-    return NULL;
-  }
-  if (dk->dkmarker != DKMARK)
-  {
-    return NULL;
-  }
-
-  s = NULL;
-  if (dk->sender)
-  {
-    s = dk->sender; /* TC14-1 */
-  }
-  else if (dk->sender_beforesign && (dk->signing == DK_SIGNING_NOVERIFY))
-  {
-    s = dk->sender_beforesign;
-  }
-  else if (dk->from)
-  {
-    s = dk->from; /* TC14-2 */
-  }
-  if (s && *s && s[1] && s[1] != '@')
-  {
-    s = strchr(s, '@') + 1;
-    if (*s == '\0')
-    {
-      //make sure we have an actual domain after @
-      s = NULL;
-    }
-  }
-  else
-  {
-    s = NULL;
-  }
-  return s;
+	if (!dk)
+		return NULL;
+	if (dk->dkmarker != DKMARK)
+		return NULL;
+	s = NULL;
+	if (dk->sender)
+		s = dk->sender;			/*- TC14-1 */
+	else
+	if (dk->sender_beforesign && (dk->signing == DK_SIGNING_NOVERIFY))
+		s = dk->sender_beforesign;
+	else
+	if (dk->from)
+		s = dk->from;			/*- TC14-2 */
+	if (s && *s && s[1] && s[1] != '@')
+	{
+		ptr = strchr(s, '@');
+		if (*ptr++)
+			s = ptr;
+		else
+			s = NULL;
+	} else
+		s = NULL;
+	return s;
 }
 
 /* HEADER */
-/* Returns a pointer to the selector name used or NULL if there isn't one
+/* 
+ * Returns a pointer to the selector name used or NULL if there isn't one
  * Added by rjp
  */
-const char *dk_selector(DK *dk)
+const char     *
+dk_selector(DK *dk)
 {
-  if (!dk) return NULL;
-  return (dk->selector);
-}
-
-/* HEADER */
-/* Returns a pointer to the domain name used or NULL if there isn't one
- */
-const char *dk_domain(DK *dk)
-{
-  if (!dk) return NULL;
-  return (dk->domain);
+	if (!dk)
+		return NULL;
+	return (dk->selector);
 }
 
 /* HEADER */
@@ -1654,40 +1603,18 @@
  * "S" if the address came from the Sender: field, and "F" if the
  * address came from the From: field.
  */
-char *dk_address(DK *dk)
-{
-  if ((!dk)||(dk->dkmarker != DKMARK))
-  {
-    return "N";
-  }
-  if (dk->sender)
-  {
-    return dk->sender; /* TC14-3 */
-  }
-  if (dk->from)
-  {
-    return dk->from; /* TC14-4 */
-  }
-  return "N";     /* TC14-5 */
-}
-
-/* HEADER */
-/*
- * Returns a pointer to a null-terminated string containing the granularity
- * value found in the selector DNS record, if any, but only after dk_end
- * has been called. Otherwise returns NULL.
- */
-char *dk_granularity(DK *dk)
+char           *
+dk_address(DK *dk)
 {
-  if (!dk)
-  {
-    return NULL;
-  }
-  if (dk->dkmarker != DKMARK)
-  {
-    return NULL;
-  }
-  return dk->granularity;
+	if (!dk || dk->dkmarker != DKMARK)
+		return "N";
+	if (dk->sender)
+		return dk->sender;		/*- TC14-3 */
+	if (dk->sender_beforesign && dk->signing == DK_SIGNING_NOVERIFY)
+		return dk->sender_beforesign;
+	if (dk->from)
+		return dk->from;		/*- TC14-4 */
+	return "N";					/*- TC14-5 */
 }
 
 /* HEADER */
@@ -1711,306 +1638,256 @@
  * DK_STAT_BADKEY
  * DK_STAT_CANTVERIFY
  */
-DK_STAT dk_end(DK *dk, DK_FLAGS *dkf)
+DK_STAT
+dk_end(DK *dk, DK_FLAGS *dkf)
 {
-  if ((!dk)||(dk->dkmarker != DKMARK))
-  {
-    return DK_STAT_ARGS;
-  }
-
-  /* yes, the only way we can still be in the headers at the end of
-     the message is if they supplied us with a message that not only
-     has no body, but also lacks the blank line terminating the
-     headers.  Still, we have to handle it correctly.  TC13-nobody */
-  if (dk->in_headers)
-  {
-    DK_STAT st;
-
-    if (dkstore_char(dk, '\0') != DK_STAT_OK)
-    {
-      return DKERR(DK_STAT_NORESOURCE);
-    }
-    st = dkheaders(dk);
-    if (st != DK_STAT_OK)
-    {
-      return st;
-    }
-  }
+	if ((!dk) || (dk->dkmarker != DKMARK))
+		return DK_STAT_ARGS;
 
-  switch (dk->signing)
-  {
-  case DK_SIGNING_SIGN:
-  case DK_SIGNING_VERIFY:
-    //force hash final CRLF to terminate email
+	/*
+	 * yes, the only way we can still be in the headers at the end of
+	 * the message is if they supplied us with a message that not only
+	 * has no body, but also lacks the blank line terminating the
+	 * headers.  Still, we have to handle it correctly.  TC13-nobody 
+	 */
+	if (dk->in_headers) {
+		DK_STAT         st;
+
+		if (dkstore_char(dk, '\0') != DK_STAT_OK)
+			return DKERR(DK_STAT_NORESOURCE);
+		st = dkheaders(dk);
+		if (st != DK_STAT_OK)
+			return st;
+	}
+	switch (dk->signing) {
+	case DK_SIGNING_SIGN:
+	case DK_SIGNING_VERIFY:
+		/*- force hash final CRLF to terminate email */
 #ifdef DK_HASH_BUFF
-    //clean out hash buffer
-    dk->hash_buff[dk->hash_buff_len++] = '\r';
-    dk->hash_buff[dk->hash_buff_len++] = '\n';
-    EVP_DigestUpdate(&dk->mdctx, dk->hash_buff, dk->hash_buff_len);
-    dk->hash_buff_len = 0;
+		//clean out hash buffer
+		dk->hash_buff[dk->hash_buff_len++] = '\r';
+		dk->hash_buff[dk->hash_buff_len++] = '\n';
+		EVP_DigestUpdate(evptr, dk->hash_buff, dk->hash_buff_len);
+		dk->hash_buff_len = 0;
 #else
-    EVP_DigestUpdate(&dk->mdctx, "\r\n", 2);
+		EVP_DigestUpdate(evptr, "\r\n", 2);
+		/*
+		if (dk->trace)
+			dkt_add(dk->trace, DKT_CANON_BODY, "\r\n", 2);
+		*/
 #endif
 #ifdef DK_DEBUG
-    fprintf(stderr,"\r\n");
+		fprintf(stderr, "\r\n");
 #endif
-
-  }
-
-  switch (dk->signing)
-  {
-  case DK_SIGNING_SIGN:
-  case DK_SIGNING_NOSIGN:
-    if (!dk->from)
-    {
-      return DKERR(DK_STAT_SYNTAX);
-    }
-    return DKERR(DK_STAT_OK);
-  case DK_SIGNING_VERIFY:
-  case DK_SIGNING_NOVERIFY:
-    {
-      unsigned char md_value[1024];
-      int md_len=0;
-      char *s = NULL; //pointer to domain portion of email addy
-      char *sndr = NULL;
-      char *domainkeys; /* malloc'ed */
-      char *txtrec; /* malloc'ed */
-      char *pubkeyvals[4];
-      int i;
-      DK_STAT st;
-
-      BIO *bio, *b64;
-      EVP_PKEY *publickey;
-
-      /* make sure that we got a header */
-      if (!dk->dksign)
-      {
-        return DKERR(DK_STAT_NOSIG); /* TC11 */
-      }
-
-      /* make sure that domain on the From: matches the d data. TC26 */
-      /* Or is a subdomain of the d data.  TC26-1, etc. */
-      if (dk->sender)
-      {
-        sndr = dk->sender;
-      }
-      else if (dk->sender_beforesign && (dk->signing == DK_SIGNING_NOVERIFY))
-      {
-        sndr = dk->sender_beforesign;
-      }
-      else
-      {
-        sndr = dk->from;
-      }
-
-      if (!sndr)
-      {
-        return DKERR(DK_STAT_SYNTAX);
-      }
-      /* we already know that sndr has an '@' in it; otherwise it would not
-      * have passed dkparse822. */
-      
-      /* sndr can also be a one-character string if the from/sender header
-      * was there but empty */
-      if (!(s = strchr(sndr, '@')))
-      {
-        return DKERR(DK_STAT_SYNTAX);
-      }
-      s++; // we skip the tag
-
-      i = (int)strlen(s);
-      if (strcasecmp(dk->domain, s))
-      {
-        for (; md_len < i; md_len++)
-        {
-          if (s[md_len] == '.')
-          {
-            if (!strcasecmp(dk->domain, s + md_len + 1))
-            {
-              break;
-            }
-          }
-        }
-      }
-      if (md_len == i)
-      {
-        return DKERR(DK_STAT_SYNTAX);
-      }
-
-      /* convert their signature from base64 into binary */
-      bio = BIO_new_mem_buf(dk->signature, -1);
-      b64 = BIO_new(BIO_f_base64());
-      BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
-      BIO_push(b64, bio);
-      md_len = BIO_read(b64, md_value, sizeof(md_value));
-      BIO_free_all(b64);
-      if (md_len >= sizeof(md_value))
-      {
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-
-      /* allow user to supply the DNS TXT key record */
-      if (!dk->keyrec )
-      {
-        /* get the s data and the d data and lookup s._domainkey.d */
-        domainkeys = DK_MALLOC(strlen(dk->selector) + strlen(dk->domain) + strlen("._domainkey.") + 1);
-        if (!domainkeys)
-        {
-          return DKERR(DK_STAT_NORESOURCE);
-        }
-        sprintf(domainkeys, "%s._domainkey.%s", dk->selector, dk->domain);
-        txtrec = dns_text(domainkeys);
-        DK_MFREE(domainkeys);
-      }
-      else
-      {
-        txtrec = dk_strdup(dk->keyrec);
-      }
-
-      if (!strcmp(txtrec,"e=perm;")) /* TC31 */
-      {
-        DK_MFREE(txtrec);
-        return DKERR(DK_STAT_NOKEY);
-      }
-
-      if (!strcmp(txtrec,"e=temp;")) /* TC30 */
-      {
-        DK_MFREE(txtrec);
-        return DKERR(DK_STAT_CANTVRFY);
-      }
-
-      if (dkparselist(txtrec, "ptog", pubkeyvals) != DK_STAT_OK)
-      {
-        DK_MFREE(txtrec);
-        return DKERR(DK_STAT_BADKEY);
-      }
-      if (dkf) //set this asap
-      {
-        /* TC35 and TC37 */
-        if (pubkeyvals[1] && *pubkeyvals[1] == 'y')
-        {
-          *dkf |= DK_FLAG_TESTING;
-        }
-        /* tell them that we got the g= flag.  This means that the entire
-         * address matches, not just the domain name */
-        if (pubkeyvals[3] && *pubkeyvals[3])
-        {
-          *dkf |= DK_FLAG_G;
-        }
-        *dkf |= DK_FLAG_SET;
-      }
-      /* Store the granularity, if any, and check it against the local part
-       * of the sending address */
- 
-      if (pubkeyvals[3] && *pubkeyvals[3])
-      {
-        dk->granularity = dk_strdup(pubkeyvals[3]);
-		// Note that sndr has a leading 'F' or 'S' 
-        if (strncasecmp(dk->granularity, sndr+1, strcspn(sndr+1,"@")))
-		{
-	        DK_MFREE(txtrec);
-	  		return DKERR(DK_STAT_GRANULARITY);
-		}
-      }
-      if (!pubkeyvals[0])
-      {
-        DK_MFREE(txtrec);
-        return DKERR(DK_STAT_NOKEY); /* TC27 */
-      }
-
-      if (!*pubkeyvals[0])
-      {
-        DK_MFREE(txtrec);
-        return DKERR(DK_STAT_REVOKED); /* TC27 */
-      }
-
-      /* convert their public key from base64 into binary */
-      bio = BIO_new_mem_buf(pubkeyvals[0], -1);
-      if (!bio)
-      {
-        DK_MFREE(txtrec);
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      b64 = BIO_new(BIO_f_base64());
-      if (!b64)
-      {
-        DK_MFREE(txtrec);
-        BIO_free(bio);
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
-      BIO_push(b64, bio);
-      publickey = d2i_PUBKEY_bio(b64, NULL);
-      BIO_free_all(b64);
-      DK_MFREE(txtrec);
-      if (!publickey)
-      {
-        return DKERR(DK_STAT_BADKEY);
-      }
-
-      /* using that key, verify that the digest is properly signed */
-      i = EVP_VerifyFinal(&dk->mdctx, md_value, md_len, publickey);
-
-      if (i > 0)
-      {
-        st = DK_STAT_OK;
-      }
-      else
-      {
-        st = DK_STAT_BADSIG;
-      }
-      EVP_PKEY_free(publickey);
-      return DKERR(st);
-    }
-  }//End switch
-  return DK_STAT_ARGS;
+	}
+	switch (dk->signing)
+	{
+	case DK_SIGNING_SIGN:
+	case DK_SIGNING_NOSIGN:
+		if (!dk->from)
+			return DKERR(DK_STAT_SYNTAX);
+		return DKERR(DK_STAT_OK);
+	case DK_SIGNING_VERIFY:
+	case DK_SIGNING_NOVERIFY:
+		{
+			unsigned char   md_value[1024];
+			int             md_len = 0;
+			char           *s = NULL; //pointer to domain portion of email addy
+			char           *ptr;
+			char           *sndr = NULL;
+			char           *domainkeys;	/* malloc'ed */
+			char           *txtrec;		/* malloc'ed */
+			char           *pubkeyvals[4];
+			int             i;
+			DK_STAT         st;
+			BIO            *bio, *b64;
+			EVP_PKEY       *publickey;
+
+			/*
+			 * make sure that we got a header 
+			 */
+			if (!dk->dksign)
+				return DKERR(DK_STAT_NOSIG);	/* TC11 */
+			/*
+			 * make sure that domain on the From: matches the d data. TC26 
+			 * Or is a subdomain of the d data.  TC26-1, etc. 
+			 */
+			if (dk->sender)
+				sndr = dk->sender;
+			else
+			if (dk->sender_beforesign && (dk->signing == DK_SIGNING_NOVERIFY))
+				sndr = dk->sender_beforesign;
+			else
+				sndr = dk->from;
+			if (!sndr)
+				return DKERR(DK_STAT_SYNTAX);
+			/* 
+			 * we already know that sndr has an '@' in it; otherwise it would not
+			 * have passed dkparse822. 
+			 */
+			ptr = strchr(sndr, '@');
+			if (*ptr++)
+				s = ptr; /*- we skip the tag */
+			else
+				return DKERR(DK_STAT_SYNTAX);
+			i = (int) strlen(s);
+			if (strcasecmp(dk->domain, s))
+			{
+				for (; md_len < i; md_len++)
+				{
+					if (s[md_len] == '.' && !strcasecmp(dk->domain, s + md_len + 1))
+						break;
+				}
+			}
+			if (md_len == i)
+				return DKERR(DK_STAT_SYNTAX);
+			/*
+			 * convert their signature from base64 into binary 
+			 */
+			bio = BIO_new_mem_buf(dk->signature, -1);
+			b64 = BIO_new(BIO_f_base64());
+			BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+			BIO_push(b64, bio);
+			md_len = BIO_read(b64, md_value, sizeof (md_value));
+			BIO_free_all(b64);
+			if (md_len >= sizeof (md_value))
+				return DKERR(DK_STAT_NORESOURCE);
+			/* allow user to supply the DNS TXT key record */
+			if (!dk->keyrec)
+			{
+				/*
+				 * get the s data and the d data and lookup s._domainkey.d 
+				 */
+				if (!(domainkeys = DK_MALLOC(strlen(dk->selector) + strlen(dk->domain)
+					+ strlen("._domainkey.") + 1)))
+					return DKERR(DK_STAT_NORESOURCE);
+				sprintf(domainkeys, "%s._domainkey.%s", dk->selector, dk->domain);
+				txtrec = dns_text(domainkeys);
+				DK_MFREE(domainkeys);
+			} else
+				txtrec = dk_strdup(dk->keyrec);
+			if (!strcmp(txtrec, "e=perm;")) {	/* TC31 */
+				DK_MFREE(txtrec);
+				return DKERR(DK_STAT_NOKEY);
+			}
+			if (!strcmp(txtrec, "e=temp;")) {	/* TC30 */
+				DK_MFREE(txtrec);
+				return DKERR(DK_STAT_CANTVRFY);
+			}
+			if (dkparselist(txtrec, "ptog", pubkeyvals) != DK_STAT_OK) {
+				DK_MFREE(txtrec);
+				return DKERR(DK_STAT_BADKEY);
+			}
+			if (dkf) {
+				/*
+				 * TC35 and TC37 
+				 */
+				if (pubkeyvals[1] && *pubkeyvals[1] == 'y')
+					*dkf |= DK_FLAG_TESTING;
+				/*
+				 * tell them that we got the g= flag.  This means that the entire
+				 * address matches, not just the domain name 
+				 */
+				if (pubkeyvals[3] && *pubkeyvals[3])
+					*dkf |= DK_FLAG_G;
+				*dkf |= DK_FLAG_SET;
+			}
+			/*
+			 * Store the granularity, if any, and check it against the local part
+			 * of the sending address
+			 */
+			if (pubkeyvals[3] && *pubkeyvals[3])
+			{
+				dk->granularity = dk_strdup(pubkeyvals[3]);
+				/* Note that sndr has a leading 'F' or 'S' */
+				if (strncasecmp(dk->granularity, sndr+1, strcspn(sndr+1,"@")))
+				{
+					DK_MFREE(txtrec);
+					return DKERR(DK_STAT_GRANULARITY);
+				}
+			}
+			if (!pubkeyvals[0])
+			{
+				DK_MFREE(txtrec);
+				return DKERR(DK_STAT_NOKEY); /* TC27 */
+			}
+			if (!*pubkeyvals[0])
+			{
+				DK_MFREE(txtrec);
+				return DKERR(DK_STAT_REVOKED); /* TC27 */
+			}
+			/*
+			 * convert their public key from base64 into binary 
+			 */
+			if (!(bio = BIO_new_mem_buf(pubkeyvals[0], -1))) {
+				DK_MFREE(txtrec);
+				return DKERR(DK_STAT_NORESOURCE);
+			}
+			b64 = BIO_new(BIO_f_base64());
+			if (!b64) {
+				DK_MFREE(txtrec);
+				BIO_free(bio);
+				return DKERR(DK_STAT_NORESOURCE);
+			}
+			BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+			BIO_push(b64, bio);
+			publickey = d2i_PUBKEY_bio(b64, NULL);
+			BIO_free_all(b64);
+			DK_MFREE(txtrec);
+			if (!publickey)
+				return DKERR(DK_STAT_BADKEY);
+			/*
+			 * using that key, verify that the digest is properly signed 
+			 */
+			if ((i = EVP_VerifyFinal(evptr, md_value, md_len, publickey)) > 0)
+				st = DK_STAT_OK;
+			else
+				st = DK_STAT_BADSIG;
+			EVP_PKEY_free(publickey);
+			return DKERR(st);
+		}
+	} /*- switch (dk->signing) */
+	return DK_STAT_ARGS;
 }
-
-
 /* HEADER */
 /*
  * DEPRECATED in favor of calling dk_end and dk_policy() directly.
  * If you pass in NULL for dkf, the policy flags will not be fetched.
  * If the message verified okay, the policy flags will not be fetched.
  */
-DK_STAT dk_eom(DK *dk, DK_FLAGS *dkf)
+DK_STAT
+dk_eom(DK *dk, DK_FLAGS *dkf)
 {
-  DK_STAT dkstat;
+		DK_STAT         dkstat;
 
-  dkstat = dk_end(dk, dkf);  /* TC36* */
-  if (dkf && dkstat != DK_STAT_OK)
-  {
-    *dkf |= dk_policy(dk);
-  }
-  return dkstat;
+		dkstat = dk_end(dk, dkf);	/*- TC36 */
+		if (dkf && dkstat != DK_STAT_OK)
+			*dkf |= dk_policy(dk);
+		return dkstat;
 }
 
-
 /* HEADER */
 /*
- *
+ * 
  * privatekey is the private key used to create the signature; It should contain
  * the entire contents of a PEM-format private key file, thusly it will begin with
  * -----BEGIN RSA PRIVATE KEY-----.  It should be null-terminated.
  */
-size_t dk_siglen(void *privatekey)
+size_t
+dk_siglen(void *privatekey)
 {
-  BIO *bio;
-  EVP_PKEY *pkey;
-  size_t len;
-
-  if (!privatekey)
-  {
-    return 0;
-  }
-
-  bio = BIO_new_mem_buf(privatekey, -1);
-  pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
-  BIO_free(bio);
-
-  len = (EVP_PKEY_size(pkey) + 2) / 3 * 4;
-  EVP_PKEY_free(pkey);
-  return len;
+		BIO            *bio;
+		EVP_PKEY       *pkey;
+		size_t          len;
+
+		if (!privatekey)
+			return 0;
+		bio = BIO_new_mem_buf(privatekey, -1);
+		pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+		BIO_free(bio);
+		len = (EVP_PKEY_size(pkey) + 2) / 3 * 4;
+		EVP_PKEY_free(pkey);
+		return len;
 }
 
 
@@ -2025,83 +1902,73 @@
  * If you pass in NULL for buf, you'll get back DK_STAT_NORESOURCE.
  * If len is not big enough, you'll get back DK_STAT_NORESOURCE.
  */
-DK_STAT dk_getsig(DK *dk, void *privatekey, unsigned char buf[], size_t len)
+DK_STAT
+dk_getsig(DK *dk, void *privatekey, unsigned char buf[], size_t len)
 {
-  if ((!dk)||(dk->dkmarker != DKMARK)||(!privatekey))
-  {
-    return DK_STAT_ARGS;
-  }
-  if (!buf)
-  {
-    return DKERR(DK_STAT_NORESOURCE);
-  }
-  switch (dk->signing)
-  {
-    case DK_SIGNING_SIGN:
-    case DK_SIGNING_NOSIGN:
-    {
-      unsigned int siglen;
-      unsigned char *sig;
-      int size;
-      BIO *bio, *b64;
-      EVP_PKEY *pkey;
-
-      bio = BIO_new_mem_buf(privatekey, -1);
-      pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
-      BIO_free(bio);
-
-      if (!pkey)
-      {
-        /* their private key is no good TC33 */
-        return DKERR(DK_STAT_BADKEY);
-      }
-
-      siglen = EVP_PKEY_size(pkey);
-      sig = (unsigned char*) OPENSSL_malloc(siglen);
-      EVP_SignFinal(&dk->mdctx, sig, &siglen, pkey);
-      EVP_PKEY_free(pkey);
-
-      bio = BIO_new(BIO_s_mem());
-      if (!bio)
-      {
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      b64 = BIO_new(BIO_f_base64());
-      if (!b64)
-      {
-        BIO_free(bio);
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
-      BIO_push(b64, bio);
-      if ((size_t)BIO_write(b64, sig, siglen) < siglen)
-      {
-        OPENSSL_free(sig);
-        BIO_free_all(b64);
-        return DKERR(DK_STAT_NORESOURCE);
-      }
-      BIO_flush(b64);
-      OPENSSL_free(sig);
-
-      size = BIO_read(bio, buf, len);
-      BIO_free_all(b64);
-
-      if ((size_t)size >= len)
-      {
-        return DKERR(DK_STAT_NORESOURCE); /* TC28 */
-      }
-
-      buf[size] = '\0';
-      return DKERR(DK_STAT_OK);
-    }
-    case DK_SIGNING_VERIFY:
-    case DK_SIGNING_NOVERIFY:
-      return DKERR(DK_STAT_INTERNAL);
-  }//end switch
-  return DK_STAT_ARGS;
+	if ((!dk) || (dk->dkmarker != DKMARK) || !privatekey)
+		return DK_STAT_ARGS;
+	if (!buf)
+		return DKERR(DK_STAT_NORESOURCE);
+	switch (dk->signing)
+	{
+		case DK_SIGNING_SIGN:
+		case DK_SIGNING_NOSIGN:
+			{
+				unsigned int    siglen;
+				unsigned char  *sig;
+				int             size;
+				BIO            *bio, *b64;
+				EVP_PKEY       *pkey;
+
+				bio = BIO_new_mem_buf(privatekey, -1);
+				pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+				BIO_free(bio);
+				if (!pkey) /*- their private key is no good TC33 */
+					return DKERR(DK_STAT_BADKEY);
+				siglen = EVP_PKEY_size(pkey);
+				sig = (unsigned char *) OPENSSL_malloc(siglen);
+				EVP_SignFinal(evptr, sig, &siglen, pkey);
+				EVP_PKEY_free(pkey);
+				if (!(bio = BIO_new(BIO_s_mem())))
+					return DKERR(DK_STAT_NORESOURCE);
+				if (!(b64 = BIO_new(BIO_f_base64())))
+				{
+					BIO_free(bio);
+					return DKERR(DK_STAT_NORESOURCE);
+				}
+				BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+				BIO_push(b64, bio);
+				if ((size_t) BIO_write(b64, sig, siglen) < siglen)
+				{
+					OPENSSL_free(sig);
+					BIO_free_all(b64);
+					return DKERR(DK_STAT_NORESOURCE);
+				}
+				for (;;)
+				{
+					if (BIO_flush(b64) == -1) /*- retry */
+					{
+						if (BIO_should_retry(b64))
+							continue;
+					} else
+						break;
+				}
+				OPENSSL_free(sig);
+				size = BIO_read(bio, buf, len);
+				BIO_free_all(b64);
+				if ((size_t) size >= len)
+					return DKERR(DK_STAT_NORESOURCE);	/*- TC28 */
+				buf[size] = '\0';
+				return DKERR(DK_STAT_OK);
+			}
+		case DK_SIGNING_VERIFY:
+		case DK_SIGNING_NOVERIFY:
+			return DKERR(DK_STAT_INTERNAL);
+	} /*- switch (dk->signing) */
+	/*- Not REACHED*/
+	return DK_STAT_ARGS;
 }
 
-
 /* HEADER */
 /*
  * Free all resources associated with this message.
@@ -2111,57 +1978,47 @@
  * want to call openssl's ERR_remove_state(0) by yourself
  * ERR_remove_state(0) is declared in <openssl/err.h>
  */
-DK_STAT dk_free(DK *dk, int doClearErrState)
+DK_STAT
+dk_free(DK *dk, int doClearErrState)
 {
-  if ((!dk)||(dk->dkmarker != DKMARK))
-  {
-    return DK_STAT_ARGS;
-  }
-  if (dk->from)
-  {
-    DK_MFREE(dk->from);
-  }
-  if (dk->sender)
-  {
-    DK_MFREE(dk->sender);
-  }
-  if (dk->sender_beforesign)
-  {
-    DK_MFREE(dk->sender_beforesign);
-  }
-  if (dk->trace)
-  {
-    DK_MFREE(dk->trace);
-  }
-  if (dk->traceheader)
-  {
-    DK_MFREE(dk->trace);
-  }
-  if (dk->keyrec)
-  {
-    DK_MFREE(dk->keyrec);
-  }
-  if (dk->policyrec)
-  {
-    DK_MFREE(dk->policyrec);
-  }
-  if (dk->granularity)
-  {
-    DK_MFREE(dk->granularity);
-  }
+	if (!dk)
+		return DK_STAT_ARGS;
+	if (dk->dkmarker != DKMARK)
+		return DK_STAT_ARGS;
+	if (dk->from)
+		DK_MFREE(dk->from);
+	if (dk->sender)
+		DK_MFREE(dk->sender);
+	if (dk->sender_beforesign)
+		DK_MFREE(dk->sender_beforesign);
+	if (dk->trace || dk->traceheader)
+		DK_MFREE(dk->trace);
+	if (dk->keyrec)
+		DK_MFREE(dk->keyrec);
+	if (dk->policyrec)
+		DK_MFREE(dk->policyrec);
+	if (dk->granularity)
+		DK_MFREE(dk->granularity);
+	if (dk->sel_headers)
+		DK_MFREE(dk->sel_headers);
 #ifdef DK_HASH_BUFF
-  DK_MFREE(dk->hash_buff);
+	DK_MFREE(dk->hash_buff);
 #endif
-  EVP_MD_CTX_cleanup(&dk->mdctx);
-  DK_MFREE(dk->header);   /* alloc'ing dk->header is not optional. */
-  dk->dkmarker = ~DKMARK;
-  DK_MFREE(dk);
-
-  if (doClearErrState)
-  {
-     ERR_remove_state(0);
-  }
-  return DK_STAT_OK;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+	if (evptr)
+		EVP_MD_CTX_free(evptr);
+#else
+	if (evptr)
+		EVP_MD_CTX_cleanup(evptr);
+#endif
+	DK_MFREE(dk->header);		/*- alloc'ing dk->header is not optional.  */
+	dk->dkmarker = ~DKMARK;
+	DK_MFREE(dk);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+	if (doClearErrState)
+		ERR_remove_state(0);
+#endif
+	return DK_STAT_OK;
 }
 
 /* HEADER */
@@ -2171,17 +2028,104 @@
  * contain the name of the DK_STAT constant.  From there to the end of
  * string is a human-readable description of the error.
  */
-const char *DK_STAT_to_string(DK_STAT st)
+const char     *
+DK_STAT_to_string(DK_STAT st)
 {
-  /* TC53 */
-  if (st >= (sizeof errors) / (sizeof errors[0]))
-  {
-    return "DK_STAT_UNKNOWN: unknown status";
-  }
-  else
-  {
-    return errors[st];
-  }
+	/*- TC53 */
+	if (st >= (sizeof errors) / (sizeof errors[0]))
+		return "DK_STAT_UNKNOWN: unknown status";
+	else
+		return errors[st];
 }
 
+/* HEADER */
+/*
+ * if DKOPT_SELHEAD is set and *ptr != NULL set dk->sel_headers.
+ */
+int
+dk_set_selheaders(DK *dk, char *ptr)
+{
+	int             found = 0;
+	char           *copy;
+	size_t          len, add;
+
+	if (!dk || !ptr || !(dk->opts & DKOPT_SELHEAD)) {
+		return 0;
+	}
+
+	len = strlen(ptr);
+	copy = (char *) DK_MALLOC(len + 2);
+	if (!copy) {
+		return 0;
+	}
+	copy[0] = ':';
+	memcpy(copy + 1, ptr, len - 1);
+	copy[len] = ':';
+	copy[len + 1] = 0;
+
+	if (strncasestr(copy, ":From:", len) != NULL) {
+		found++;
+	}
+	if (strncasestr(copy, ":Sender:", len) != NULL) {
+		found++;
+	}
+	DK_MFREE(copy);
+
+	if (dk->sel_headers) {		/* if previous value exists */
+		DK_MFREE(dk->sel_headers);
+	}
 
+	add = 0;
+	if (!found) {
+		add = 5 + 7;			/* add room for From: + Sender: */
+	}
+	dk->sel_headers = DK_MALLOC(len + add + 2);
+	if (!dk->sel_headers) {
+		return 0;
+	}
+	dk->sel_headers[0] = ':';
+	memcpy(dk->sel_headers + 1, ptr, len - 1);
+	dk->sel_headers[len] = ':';
+	dk->sel_headers[len + 1] = 0;
+	if (!found) {
+		memcpy(dk->sel_headers + len + 1, "Sender:From:", add);
+		dk->sel_headers[len + 1 + add] = 0;
+	}
+	return len + 1 + add;
+}
+
+/*
+ * Find the first occurrence of find in s, where the search is limited to the
+ * first slen characters of s, ignore case.
+ */
+static char    *
+strncasestr(const char *s, const char *find, size_t slen)
+{
+	char            c, sc;
+	size_t          len;
+
+	if ((c = *find++) != '\0') {
+		c = tolower((unsigned char) c);
+		len = strlen((char *) find);
+		do {
+			do {
+				if (slen-- < 1 || (sc = *s++) == '\0')
+					return (NULL);
+			} while ((char) tolower((unsigned char) sc) != c);
+			if (len > slen)
+				return (NULL);
+		} while (strncasecmp((char *) s, (char *) find, len) != 0);
+		s--;
+	}
+	return ((char *) s);
+}
+#endif
+
+void
+getversion_domainkeys_c()
+{
+	static char    *x = "$Id: domainkeys.c,v 1.19 2017-08-09 22:07:51+05:30 Cprogrammer Exp mbhangui $";
+
+	x++;
+}
+// vim: shiftwidth=2:tabstop=4:softtabstop=4
diff -ruN libdomainkeys-0.69-original/socket.lib libdomainkeys-0.69-mbanghui-ssl-1.1/socket.lib
--- libdomainkeys-0.69-original/socket.lib	1970-01-01 01:00:00.000000000 +0100
+++ libdomainkeys-0.69-mbanghui-ssl-1.1/socket.lib	2015-12-15 09:56:37.000000000 +0100
@@ -0,0 +1 @@
+-lresolv
openSUSE Build Service is sponsored by