Merge branch 'master' into 4.next
authorJeremy Harris <jgh146exb@wizmail.org>
Tue, 2 Feb 2016 11:46:50 +0000 (11:46 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Tue, 2 Feb 2016 12:26:15 +0000 (12:26 +0000)
113 files changed:
Readme.pod
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/OS/os.c-Linux
src/OS/os.h-OpenBSD
src/OS/os.h-SunOS5
src/exim_monitor/em_main.c
src/scripts/MakeLinks
src/src/EDITME
src/src/acl.c
src/src/auths/call_radius.c
src/src/auths/cram_md5.c
src/src/auths/get_data.c
src/src/auths/heimdal_gssapi.c
src/src/base64.c
src/src/buildconfig.c
src/src/configure.default
src/src/dane-openssl.c
src/src/deliver.c
src/src/dkim.c
src/src/dkim.h
src/src/dns.c
src/src/enq.c
src/src/exicyclog.src
src/src/exim.c
src/src/exim.h
src/src/expand.c
src/src/functions.h
src/src/globals.c
src/src/globals.h
src/src/lookups/ibase.c
src/src/lookups/nis.c
src/src/lookups/nisplus.c
src/src/lookups/oracle.c
src/src/lookups/redis.c
src/src/lookups/whoson.c
src/src/mime.c
src/src/mime.h
src/src/moan.c
src/src/os.c
src/src/pdkim/Makefile
src/src/pdkim/README
src/src/pdkim/bignum.c [deleted file]
src/src/pdkim/blob.h [new file with mode: 0644]
src/src/pdkim/crypt_ver.h [new file with mode: 0644]
src/src/pdkim/hash.c [new file with mode: 0644]
src/src/pdkim/hash.h [new file with mode: 0644]
src/src/pdkim/part-x509parse.c [deleted file]
src/src/pdkim/pdkim-rsa.c [deleted file]
src/src/pdkim/pdkim-rsa.h [deleted file]
src/src/pdkim/pdkim.c
src/src/pdkim/pdkim.h
src/src/pdkim/polarssl/bignum.h [deleted file]
src/src/pdkim/polarssl/bn_mul.h [deleted file]
src/src/pdkim/polarssl/config.h [deleted file]
src/src/pdkim/polarssl/part-x509.h [deleted file]
src/src/pdkim/polarssl/private-x509parse_c.h [deleted file]
src/src/pdkim/polarssl/rsa.h [deleted file]
src/src/pdkim/polarssl/sha1.h [deleted file]
src/src/pdkim/polarssl/sha2.h [deleted file]
src/src/pdkim/rsa.c
src/src/pdkim/rsa.h [new file with mode: 0644]
src/src/pdkim/sha1.c [deleted file]
src/src/pdkim/sha2.c [deleted file]
src/src/readconf.c
src/src/receive.c
src/src/rfc2047.c
src/src/smtp_in.c
src/src/spool_mbox.c
src/src/store.c
src/src/string.c
src/src/tls-openssl.c
src/src/tlscert-gnu.c
src/src/tlscert-openssl.c
src/src/tod.c
src/src/transports/tf_maildir.c
test/README
test/aux-fixed/dkim/sign.pl
test/confs/0001
test/confs/0041
test/confs/0572 [changed from symlink to file mode: 0644]
test/confs/0573 [new file with mode: 0644]
test/confs/2002
test/confs/2102
test/confs/4503 [new file with mode: 0644]
test/dnszones-src/db.test.ex
test/log/0562
test/log/0573 [new file with mode: 0644]
test/log/2002
test/log/2102
test/log/4500
test/log/4503 [new file with mode: 0644]
test/log/5400
test/mail/0573.limited [new file with mode: 0644]
test/mail/0573.not_limited [new file with mode: 0644]
test/rejectlog/0562
test/runtest
test/scripts/0000-Basic/0002
test/scripts/0000-Basic/0041
test/scripts/0000-Basic/0562
test/scripts/0000-Basic/0572
test/scripts/0000-Basic/0573 [new file with mode: 0644]
test/scripts/4500-Domain-Keys-Identified-Mail/4500
test/scripts/4500-Domain-Keys-Identified-Mail/4503 [new file with mode: 0644]
test/scripts/5400-cutthrough/5400
test/scripts/5600-OCSP-OpenSSL/5601
test/stderr/0041
test/stdout/0002
test/stdout/0041
test/stdout/0562
test/stdout/0572
test/stdout/5400

index d49fc96512273e89fe428898deba51668e73cf41..b82161e9373e55493554e682a406f029abb1d736 100644 (file)
@@ -37,12 +37,12 @@ Currently this is all done using Bugzilla at L<http://bugs.exim.org/>
 
 =head2 Mailing List
 
-Development issues are normally discussed on the exim-dev Mailing list
+Development issues are normally discussed on the exim-dev mailing list
 - see L<http://www.exim.org/maillist.html>
 
 =head2 Exim Release Process
 
-Some documentation on the realse process can be found at
+Some documentation on the release process can be found at
 L<http://wiki.exim.org/EximRelease>.
 
 =head2 General Exim Information
@@ -63,4 +63,4 @@ In any case you can always ask on the
 Exim Users mailing list L<https://lists.exim.org/mailman/listinfo/exim-users> 
 for further information.
 
-[End]
\ No newline at end of file
+[End]
index 7e59c304de5c39a854e020e915bfe4a6f712aef1..904f831e8abe9893fedc89025bb95e25895a3de1 100644 (file)
@@ -9677,7 +9677,8 @@ ${readsocket{inet:[::1]:1234}{request string}}
 Only a single host name may be given, but if looking it up yields more than
 one IP address, they are each tried in turn until a connection is made. For
 both kinds of socket, Exim makes a connection, writes the request string
-(unless it is an empty string) and reads from the socket until an end-of-file
+unless it is an empty string; and no terminating NUL is ever sent)
+and reads from the socket until an end-of-file
 is read. A timeout of 5 seconds is applied. Additional, optional arguments
 extend what can be done. Firstly, you can vary the timeout. For example:
 .code
@@ -10033,6 +10034,25 @@ environments where Exim uses base 36 instead of base 62 for its message
 identifiers, base-36 digits. The number is converted to decimal and output as a
 string.
 
+.new
+.vitem &*${base64:*&<&'string'&>&*}*&
+.cindex "expansion" "base64 encoding"
+.cindex "base64 encoding" "in string expansion"
+.cindex "&%base64%& expansion item"
+.cindex certificate "base64 of DER"
+This operator converts a string into one that is base64 encoded.
+
+If the string is a single variable of type certificate,
+returns the base64 encoding of the DER form of the certificate.
+
+
+.vitem &*${base64d:*&<&'string'&>&*}*&
+.cindex "expansion" "base64 decoding"
+.cindex "base64 decoding" "in string expansion"
+.cindex "&%base64d%& expansion item"
+This operator converts a base64-encoded string into the un-coded form.
+.wen
+
 
 .vitem &*${domain:*&<&'string'&>&*}*&
 .cindex "domain" "extraction"
@@ -10463,10 +10483,10 @@ the system administrator. &*Warning*&: The file size may be incorrect on 32-bit
 systems for files larger than 2GB.
 
 .vitem &*${str2b64:*&<&'string'&>&*}*&
-.cindex "expansion" "base64 encoding"
-.cindex "base64 encoding" "in string expansion"
 .cindex "&%str2b64%& expansion item"
-This operator converts a string into one that is base64 encoded.
+.new
+Now deprecated, a synonym for the &%base64%& expansion operator.
+.wen
 
 
 
@@ -13767,6 +13787,7 @@ See also the &'Policy controls'& section above.
 .row &%bounce_message_file%&         "content of bounce"
 .row &%bounce_message_text%&         "content of bounce"
 .row &%bounce_return_body%&          "include body if returning message"
+.row &%bounce_return_linesize_limit%& "limit on returned message line length"
 .row &%bounce_return_message%&       "include original message in bounce"
 .row &%bounce_return_size_limit%&    "limit on returned message"
 .row &%bounce_sender_authentication%& "send authenticated sender with bounce"
@@ -14075,6 +14096,24 @@ error that is detected during reception, only those header lines preceding the
 point at which the error was detected are returned.
 .cindex "bounce message" "including original"
 
+.option bounce_return_linesize_limit main integer 998
+.cindex "size" "of bounce lines, limit"
+.cindex "bounce message" "line length limit"
+.cindex "limit" "bounce message line length"
+This option sets a limit in bytes on the line length of messages
+that are returned to senders due to delivery problems,
+when &%bounce_return_message%& is true.
+The default value corresponds to RFC limits.
+If the message being returned has lines longer than this value it is
+treated as if the &%bounce_return_size_limit%& (below) restriction was exceeded.
+
+The option also applies to bounces returned when an error is detected
+during reception of a messsage.
+In this case lines from the original are truncated.
+
+The option does not apply to messages generated by an &(autoreply)& transport.
+
+
 .option bounce_return_message main boolean true
 If this option is set false, none of the original message is included in
 bounce messages generated by Exim. See also &%bounce_return_size_limit%& and
@@ -15412,7 +15451,7 @@ harm. This option overrides the &%pipe_as_creator%& option of the &(pipe)&
 transport driver.
 
 
-.option openssl_options main "string list" "+no_sslv2"
+.option openssl_options main "string list" "+no_sslv2 +single_dh_use"
 .cindex "OpenSSL "compatibility options"
 This option allows an administrator to adjust the SSL options applied
 by OpenSSL to connections.  It is given as a space-separated list of items,
@@ -27529,6 +27568,12 @@ Note that a client may issue more than one EHLO or HELO command in an SMTP
 session, and indeed is required to issue a new EHLO or HELO after successfully
 setting up encryption following a STARTTLS command.
 
+.new
+Note also that a deny neither forces the client to go away nor means that
+mail will be refused on the connection.  Consider checking for
+&$sender_helo_name$& being defined in a MAIL or RCPT ACL to do that.
+.wen
+
 If the command is accepted by an &%accept%& verb that has a &%message%&
 modifier, the message may not contain more than one line (it will be truncated
 at the first newline and a panic logged if it does). Such a message cannot
@@ -34021,13 +34066,20 @@ specific badly-behaved hosts that you have to live with.
 When Exim receives a VRFY or EXPN command on a TCP/IP connection, it
 runs the ACL specified by &%acl_smtp_vrfy%& or &%acl_smtp_expn%& (as
 appropriate) in order to decide whether the command should be accepted or not.
-If no ACL is defined, the command is rejected.
 
+.new
 .cindex "VRFY" "processing"
+When no ACL is defined for VRFY, or if it rejects without
+setting an explicit response code, the command is accepted
+(with a 252 SMTP response code)
+in order to support awkward clients that do a VRFY before every RCPT.
+.wen
 When VRFY is accepted, it runs exactly the same code as when Exim is
-called with the &%-bv%& option.
+called with the &%-bv%& option, and returns 250/451/550
+SMTP response codes.
 
 .cindex "EXPN" "processing"
+If no ACL for EXPN is defined, the command is rejected.
 When EXPN is accepted, a single-level expansion of the address is done.
 EXPN is treated as an &"address test"& (similar to the &%-bt%& option) rather
 than a verification (the &%-bv%& option). If an unqualified local part is given
@@ -37916,8 +37968,10 @@ linked to a domain which that entity controls.  It permits reputation to
 be tracked on a per-domain basis, rather than merely upon source IP address.
 DKIM is documented in RFC 4871.
 
-Since version 4.70, DKIM support is compiled into Exim by default. It can be
-disabled by setting DISABLE_DKIM=yes in &_Local/Makefile_&.
+.new
+DKIM support is compiled into Exim by default if TLS support is present.
+.wen
+It can be disabled by setting DISABLE_DKIM=yes in &_Local/Makefile_&.
 
 Exim's DKIM implementation allows to
 .olist
@@ -37967,7 +38021,7 @@ option is put into the &%$dkim_domain%& expansion variable.
 MANDATORY:
 This sets the key selector string. You can use the &%$dkim_domain%& expansion
 variable to look up a matching selector. The result is put in the expansion
-variable &%$dkim_selector%& which should be used in the &%dkim_private_key%&
+variable &%$dkim_selector%& which may be used in the &%dkim_private_key%&
 option along with &%$dkim_domain%&.
 
 .option dkim_private_key smtp string&!! unset
index 03a4cedf56d82bef51543135732130086a870968..b48b7b9888aa844ae56ffa7411741dca6fb3f63f 100644 (file)
@@ -140,6 +140,33 @@ JH/32 Move Redis support from Experimental to mainline, enabled for a build
 JH/33 Bug 1748: Permit ACL dnslists= condition in non-smtp ACLs if explicit
       keys are given for lookup.
 
+JH/34 Bug 1192: replace the embedded copy of PolarSSL RSA routines in the DKIM
+      support, by using OpenSSL or GnuTLS library ones.  This means DKIM is
+      only supported when built with TLS support.  The PolarSSL SHA routines
+      are still used when the TLS library is too old for convenient support.
+
+JH/35 Require SINGLE_DH_USE by default in OpenSSL (main config option
+      openssl_options), for security.  OpenSSL forces this from version 1.1.0
+      server-side so match that on older versions.
+
+JH/36 Bug 1778: longstanding bug in memory use by the ${run } expansion: A fresh
+      allocation for $value could be released as the expansion processing
+      concluded, but leaving the global pointer active for it.
+
+JH/37 Bug 1769: Permit a VRFY ACL to override the default 252 response,
+      and to use the domains and local_parts ACL conditions.
+
+JH/38 Fix cutthrough bug with body lines having a single dot. The dot was
+      incorrectly not doubled on cutthrough transmission, hence seen as a
+      body-termination at the receiving system - resulting in truncated mails.
+      Commonly the sender saw a TCP-level error, and retransmitted the message
+      via the normal store-and-forward channel. This could result in duplicates
+      received - but deduplicating mailstores were liable to retain only the
+      initial truncated version.
+
+JH/39 Bug 1781: Fix use of private-keys having trailing '=' in the base-64.
+
+
 
 Exim version 4.86
 -----------------
index 7385212cc7c4c713ba3ffe7b7e99b6a946f7f973..01bd0111e0b54daac3ed2e756afc0a202069ab03 100644 (file)
@@ -28,6 +28,13 @@ Version 4.87
 
  6. New $dkim_key_length variable.
 
+ 7. New base64d and base64 expansion items (the existing str2b64 being a
+    synonym of the latter).  Add support in base64 for certificates.
+
+ 8. New main configuration option "bounce_return_linesize_limit" to
+    avoid oversize bodies in bounces. The dafault value matches RFC
+    limits.
+
 
 Version 4.86
 ------------
index df0dff9db123344deffb0a50b2683b966f4e24b3..0043e86276d757628d31daea6ba86b5df595a687 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1997 - 2001 */
+/* Copyright (c) University of Cambridge 1997 - 2014 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Linux-specific code. This is concatenated onto the generic
index 35eddd5a52fac7eeccfdd17f052bdf245d2cf074..5d55a967ea5d6dda5f736e69df493f2913cd29ff 100644 (file)
@@ -23,4 +23,8 @@ typedef struct __res_state *res_state;
 /* default is non-const */
 #define ICONV_ARG2_TYPE const char **
 
+#ifndef EPROTO
+# define EPROTO 71
+#endif
+
 /* End */
index bb1d77fe9cff2c3025c5718e08d33b4722d35886..45a1171c8c1f632975daff4ebb3a7a99eb1017f2 100644 (file)
@@ -34,7 +34,7 @@ it seems. */
 
 #if _POSIX_C_SOURCE < 200112L
 # define MISSING_UNSETENV_3
-#endof
+#endif
 
 
 /* End */
index e8e763184360fde3de3144e809ede76d19378bad..69354c0862e0b88469ed546c84d5d4ef247b0490 100644 (file)
@@ -2,7 +2,7 @@
 *                  Exim Monitor                  *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
index 0e5497943df3da9f72d7cf886c98927d761f7cef..88621403039a5d11443799ad00f9ddb4a77474ba 100755 (executable)
@@ -82,17 +82,12 @@ cd ..
 # Likewise for the code for the PDKIM library
 mkdir pdkim
 cd pdkim
-for f in README Makefile bignum.c part-x509parse.c pdkim.c \
-  pdkim.h pdkim-rsa.c pdkim-rsa.h rsa.c sha1.c sha2.c
+for f in README Makefile crypt_ver.h pdkim.c \
+  pdkim.h hash.c hash.h rsa.c rsa.h blob.h
 do
   ln -s ../../src/pdkim/$f $f
 done
-mkdir polarssl
-cd polarssl
-for i in `ls ../../../src/pdkim/polarssl/` ; do
-  ln -s ../../../src/pdkim/polarssl/$i $i
-done
-cd ../..
+cd ..
 
 # The basic source files for Exim and utilities. NB local_scan.h gets linked,
 # but local_scan.c does not, because its location is taken from the build-time
index a3b021218e75eab7287268b95f7b99aa8e43d01e..30a296e89254d67ea83c9c748f429078fcf17c32 100644 (file)
@@ -411,7 +411,7 @@ EXIM_MONITOR=eximon.bin
 
 
 #------------------------------------------------------------------------------
-# By default Exim includes code to support DKIM (DomainKeys Identified
+# If built with TLS, Exim includes code to support DKIM (DomainKeys Identified
 # Mail, RFC4871) signing and verification.  Verification of signatures is
 # turned on by default.  See the spec for information on conditionally
 # disabling it.  To disable the inclusion of the entire feature, set
index 1456cc72425fd65a0c1b077eda22d2d07c7adf4b..684b93bbb31641bb4e59784b1f3d9589e91f4e09 100644 (file)
@@ -482,6 +482,7 @@ static unsigned int cond_forbids[] = {
 
   (unsigned int)
   ~((1<<ACL_WHERE_RCPT)                            /* domains */
+    |(1<<ACL_WHERE_VRFY)
   #ifndef DISABLE_PRDR
     |(1<<ACL_WHERE_PRDR)
   #endif
@@ -499,6 +500,7 @@ static unsigned int cond_forbids[] = {
 
   (unsigned int)
   ~((1<<ACL_WHERE_RCPT)                             /* local_parts */
+    |(1<<ACL_WHERE_VRFY)
   #ifndef DISABLE_PRDR
     |(1<<ACL_WHERE_PRDR)
   #endif
@@ -4454,9 +4456,9 @@ ratelimiters_cmd = NULL;
 log_reject_target = LOG_MAIN|LOG_REJECT;
 
 #ifndef DISABLE_PRDR
-if (where == ACL_WHERE_RCPT || where == ACL_WHERE_PRDR)
+if (where==ACL_WHERE_RCPT || where==ACL_WHERE_VRFY || where==ACL_WHERE_PRDR)
 #else
-if (where == ACL_WHERE_RCPT)
+if (where==ACL_WHERE_RCPT || where==ACL_WHERE_VRFY)
 #endif
   {
   adb = address_defaults;
index 78ee466d876a36b6df0950264115855f5561e3cc..455000ea70f9e977e769d47406a386826aa49695 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* This file was originally supplied by Ian Kirk. The libradius support came
index 83d47c1818725a6d9dec96e352c20e9ef643024c..2d5c0d1e2b0c1ce639f029ce7531a6fdc8265ba3 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
index 6e344ce3933d8956b917f93b57fd268aa90f37f8..4d6c6d4a647bf69a00d5a4a45452a52f05cdfbf6 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 #include "../exim.h"
index 42b6450b2bb860340fedf164753349973bb1bb5d..94e689d58a7416cb298d0da312ecff17bc86a138 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Copyright (c) Twitter Inc 2012
index f4c4f233b0105fd03547b44edd1cab07cae391a6..031beb923e5a61d741d76d5a6ab1a0e4397d5393 100644 (file)
@@ -100,21 +100,21 @@ return size;
 #endif /*WITH_CONTENT_SCAN*/
 
 /*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************
+ *************************************************/
 
 
 /*************************************************
@@ -129,11 +129,12 @@ compact loop is messy and would probably run more slowly.
 Arguments:
   code        points to the coded string, zero-terminated
   ptr         where to put the pointer to the result, which is in
-              dynamic store, and zero-terminated
+              allocated store, and zero-terminated
 
 Returns:      the number of bytes in the result,
               or -1 if the input was malformed
 
+Whitespace in the input is ignored.
 A zero is added on to the end to make it easy in cases where the result is to
 be interpreted as text. This is not included in the count. */
 
@@ -161,28 +162,51 @@ quantum this may decode to 1, 2, or 3 output bytes. */
 
 while ((x = *code++) != 0)
   {
+  if (isspace(x)) continue;
+  /* debug_printf("b64d: '%c'\n", x); */
+
   if (x > 127 || (x = dec64table[x]) == 255) return -1;
-  if ((y = *code++) == 0 || (y = dec64table[y]) == 255)
+
+  while (isspace(y = *code++)) ;
+  /* debug_printf("b64d: '%c'\n", y); */
+  if (y == 0 || (y = dec64table[y]) == 255)
     return -1;
 
   *result++ = (x << 2) | (y >> 4);
+  /* debug_printf("b64d:      -> %02x\n", result[-1]); */
 
-  if ((x = *code++) == '=')
+  while (isspace(x = *code++)) ;
+  /* debug_printf("b64d: '%c'\n", x); */
+  if (x == '=')                /* endmarker, but there should be another */
     {
-    if (*code++ != '=' || *code != 0) return -1;
+    while (isspace(x = *code++)) ;
+    /* debug_printf("b64d: '%c'\n", x); */
+    if (x != '=') return -1;
+    while (isspace(y = *code++)) ;
+    if (y != 0) return -1;
+    /* debug_printf("b64d: DONE\n"); */
+    break;
     }
   else
     {
     if (x > 127 || (x = dec64table[x]) == 255) return -1;
     *result++ = (y << 4) | (x >> 2);
-    if ((y = (*code++)) == '=')
+    /* debug_printf("b64d:      -> %02x\n", result[-1]); */
+
+    while (isspace(y = *code++)) ;
+    /* debug_printf("b64d: '%c'\n", y); */
+    if (y == '=')
       {
-      if (*code != 0) return -1;
+      while (isspace(y = *code++)) ;
+      if (y != 0) return -1;
+      /* debug_printf("b64d: DONE\n"); */
+      break;
       }
     else
       {
       if (y > 127 || (y = dec64table[y]) == 255) return -1;
       *result++ = (x << 6) | y;
+      /* debug_printf("b64d:      -> %02x\n", result[-1]); */
       }
     }
   }
@@ -192,23 +216,6 @@ return result - *ptr;
 }
 
 
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-/*************************************************
-
 /*************************************************
 *          Encode byte-string in base 64         *
 *************************************************/
index f3390cb7513bfb91f9f3861811bbc28196ab4819..45e820c81b850d313fc4f1bfbc3000f8fa929851 100644 (file)
@@ -734,6 +734,21 @@ else if (isgroup)
     continue;
     }
 
+  /* DISABLE_DKIM is special; must be forced if no SUPPORT_TLS */
+  if (strcmp(name, "DISABLE_DKIM") == 0)
+    {
+    char *d_dkim = getenv("DISABLE_DKIM");
+    char *tls = getenv("SUPPORT_TLS");
+
+    if (d_dkim)
+      fprintf(new, "#define DISABLE_DKIM          yes\n");
+    else if (!tls)
+      fprintf(new, "#define DISABLE_DKIM          yes /* forced by lack of TLS */\n");
+    else
+      fprintf(new, "/* DISABLE_DKIM not set */\n");
+    continue;
+    }
+
   /* Otherwise, check whether a value exists in the environment. Remember if
   it is an AUTH setting or SUPPORT_CRYPTEQ. */
 
index ec60700dfefbef91b2d97dd8d285e26f006e5cbb..ee94d2f910b72636f2217f25e401f752943d6f74 100644 (file)
@@ -436,6 +436,11 @@ acl_check_rcpt:
           control       = submission
           control       = dkim_disable_verify
 
+  # Insist that a HELO/EHLO was accepted.
+
+  require message      = nice hosts say HELO first
+          condition    = ${if def:sender_helo_name}
+
   # Insist that any other recipient address that we accept is either in one of
   # our local domains, or is in a domain for which we explicitly allow
   # relaying. Any other domain is rejected as being unacceptable for relaying.
index e5f9f978490ad9b1f84db0cff771cd4c12f7d10a..803fb0652859e4968edfa95aeaed1ba3a3bb861c 100644 (file)
@@ -20,8 +20,8 @@
 # error "OpenSSL 1.0.0 or higher required"
 #else   /* remainder of file */
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-#define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+# define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509)
 #endif
 
 #include "danessl.h"
index 6eb9a65d588319a38028ab2fec275a279e9c48a8..e588ee4a446976e158bfa225b44b5717b314192e 100644 (file)
@@ -7401,6 +7401,9 @@ wording. */
       if (dsn_ret == dsn_ret_hdrs)
         topt |= topt_no_body;
       else
+       {
+       struct stat statbuf;
+
         /* no full body return at all? */
         if (!bounce_return_body)
           {
@@ -7409,16 +7412,18 @@ wording. */
           if (dsn_ret == dsn_ret_full)
             dsnnotifyhdr = dsnlimitmsg;
           }
+       /* line length limited... return headers only if oversize */
         /* size limited ... return headers only if limit reached */
-        else if (bounce_return_size_limit > 0)
-          {
-          struct stat statbuf;
-          if (fstat(deliver_datafile, &statbuf) == 0 && statbuf.st_size > max)
-            {
-              topt |= topt_no_body;
-              dsnnotifyhdr = dsnlimitmsg;
-            }
+       else if (  max_received_linelength > bounce_return_linesize_limit
+               || (  bounce_return_size_limit > 0
+                  && fstat(deliver_datafile, &statbuf) == 0
+                  && statbuf.st_size > max
+               )  )
+         {
+         topt |= topt_no_body;
+         dsnnotifyhdr = dsnlimitmsg;
           }
+       }
 
 #ifdef SUPPORT_I18N
       if (message_smtputf8)
@@ -7748,6 +7753,7 @@ else if (addr_defer != (address_item *)(+1))
         FILE *wmf = NULL;
         FILE *f = fdopen(fd, "wb");
        uschar * bound;
+        int topt;
 
         if (warn_message_file)
           if (!(wmf = Ufopen(warn_message_file, "rb")))
@@ -7894,7 +7900,7 @@ else if (addr_defer != (address_item *)(+1))
 
         fflush(f);
         /* header only as required by RFC. only failure DSN needs to honor RET=FULL */
-        int topt = topt_add_return_path | topt_no_body;
+        topt = topt_add_return_path | topt_no_body;
         transport_filter_argv = NULL;   /* Just in case */
         return_path = sender_address;   /* In case not previously set */
         /* Write the original email out */
index 3fa43fc3d8ccef0c3a026a06ef53cb538cf0a110..349947ab1644c12a1abdc3aef2971ec8d56ce0f4 100644 (file)
@@ -59,6 +59,13 @@ return PDKIM_FAIL;
 }
 
 
+void
+dkim_exim_init(void)
+{
+pdkim_init();
+}
+
+
 void
 dkim_exim_verify_init(void)
 {
@@ -129,7 +136,7 @@ for (sig = dkim_signatures; sig; sig = sig->next)
              sig->canon_headers == PDKIM_CANON_SIMPLE ?  "simple" : "relaxed",
              sig->canon_body == PDKIM_CANON_SIMPLE ?  "simple" : "relaxed",
              sig->algo == PDKIM_ALGO_RSA_SHA256 ?  "rsa-sha256" : "rsa-sha1",
-             sig->sigdata_len * 8
+             sig->sigdata.len * 8
              ),
 
        sig->identity ? string_sprintf("i=%s ", sig->identity) : US"",
@@ -158,7 +165,8 @@ for (sig = dkim_signatures; sig; sig = sig->next)
                        "overlong public key record]");
          break;
 
-       case PDKIM_VERIFY_INVALID_PUBKEY_PARSING:
+       case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:
+       case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT:
          logmsg = string_append(logmsg, &size, &ptr, 1,
                       "syntax error in public key record]");
          break;
@@ -254,7 +262,7 @@ for (sig = dkim_signatures; sig; sig = sig->next)
 
     dkim_signing_domain = US sig->domain;
     dkim_signing_selector = US sig->selector;
-    dkim_key_length = sig->sigdata_len * 8;
+    dkim_key_length = sig->sigdata.len * 8;
     return;
     }
 }
@@ -339,7 +347,7 @@ switch (what)
 
   case DKIM_HEADERNAMES:
     return dkim_cur_sig->headernames
-      ?  US dkim_cur_sig->headernames : dkim_exim_expand_defaults(what);
+      ? dkim_cur_sig->headernames : dkim_exim_expand_defaults(what);
 
   case DKIM_IDENTITY:
     return dkim_cur_sig->identity
@@ -395,7 +403,8 @@ switch (what)
       {
       case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE:
                                                return US"pubkey_unavailable";
-      case PDKIM_VERIFY_INVALID_PUBKEY_PARSING:        return US"pubkey_syntax";
+      case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD:return US"pubkey_dns_syntax";
+      case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return US"pubkey_der_syntax";
       case PDKIM_VERIFY_FAIL_BODY:             return US"bodyhash_mismatch";
       case PDKIM_VERIFY_FAIL_MESSAGE:          return US"signature_incorrect";
       }
@@ -563,12 +572,13 @@ while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep,
 
   ctx = pdkim_init_sign( (char *) dkim_signing_domain,
                         (char *) dkim_signing_selector,
-                        (char *) dkim_private_key_expanded);
+                        (char *) dkim_private_key_expanded,
+                        PDKIM_ALGO_RSA_SHA256);
   pdkim_set_optional(ctx,
                      (char *) dkim_sign_headers_expanded,
                      NULL,
                      pdkim_canon,
-                     pdkim_canon, -1, PDKIM_ALGO_RSA_SHA256, 0, 0);
+                     pdkim_canon, -1, 0, 0);
 
   lseek(dkim_fd, 0, SEEK_SET);
 
index 39a0408a1ffbd32374fbcbe0c31ad80f6d6533fa..1655f8e450a5e90a188b16fbb97ad324d5bc9fcc 100644 (file)
@@ -5,6 +5,7 @@
 /* Copyright (c) University of Cambridge, 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
+void    dkim_exim_init(void);
 uschar *dkim_exim_sign(int, uschar *, const uschar *, uschar *, uschar *, uschar *);
 void    dkim_exim_verify_init(void);
 void    dkim_exim_verify_feed(uschar *, int);
index e6e4fb6b3e7708b4bc4b1f3fe39293e28e644923..bb6693254cacf4343dec99fcd6470ef5e9890f48 100644 (file)
@@ -305,6 +305,15 @@ else
 
 
 
+/* Increment the aptr in dnss, checking against dnsa length.
+Return: TRUE for a bad result
+*/
+static BOOL
+dnss_inc(dns_answer * dnsa, dns_scan * dnss, unsigned delta)
+{
+return (dnss->aptr += delta) >= dnsa->answer + dnsa->answerlen;
+}
+
 /*************************************************
 *       Get next DNS record from answer block    *
 *************************************************/
@@ -328,10 +337,19 @@ dns_next_rr(dns_answer *dnsa, dns_scan *dnss, int reset)
 HEADER *h = (HEADER *)dnsa->answer;
 int namelen;
 
+char * trace = NULL;
+#ifdef rr_trace
+# define TRACE DEBUG(D_dns)
+#else
+trace = trace;
+# define TRACE if (FALSE)
+#endif
+
 /* Reset the saved data when requested to, and skip to the first required RR */
 
 if (reset != RESET_NEXT)
   {
+  TRACE debug_printf("%s: reset\n", __FUNCTION__);
   dnss->rrcount = ntohs(h->qdcount);
   dnss->aptr = dnsa->answer + sizeof(HEADER);
 
@@ -339,10 +357,13 @@ if (reset != RESET_NEXT)
 
   while (dnss->rrcount-- > 0)
     {
+    TRACE trace = "Q-namelen";
     namelen = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
-      dnss->aptr, (DN_EXPAND_ARG4_TYPE) &(dnss->srr.name), DNS_MAXNAME);
-    if (namelen < 0) { dnss->rrcount = 0; return NULL; }
-    dnss->aptr += namelen + 4;    /* skip name & type & class */
+      dnss->aptr, (DN_EXPAND_ARG4_TYPE) &dnss->srr.name, DNS_MAXNAME);
+    if (namelen < 0) goto null_return;
+    /* skip name & type & class */
+    TRACE trace = "Q-skip";
+    if (dnss_inc(dnsa, dnss, namelen+4)) goto null_return;
     }
 
   /* Get the number of answer records. */
@@ -353,23 +374,37 @@ if (reset != RESET_NEXT)
   the NS records (i.e. authority section) if wanting to look at the additional
   records. */
 
-  if (reset == RESET_ADDITIONAL) dnss->rrcount += ntohs(h->nscount);
+  if (reset == RESET_ADDITIONAL)
+    {
+    TRACE debug_printf("%s: additional\n", __FUNCTION__);
+    dnss->rrcount += ntohs(h->nscount);
+    }
 
   if (reset == RESET_AUTHORITY || reset == RESET_ADDITIONAL)
     {
+    TRACE if (reset == RESET_AUTHORITY)
+      debug_printf("%s: authority\n", __FUNCTION__);
     while (dnss->rrcount-- > 0)
       {
+      TRACE trace = "A-namelen";
       namelen = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
-        dnss->aptr, (DN_EXPAND_ARG4_TYPE) &(dnss->srr.name), DNS_MAXNAME);
-      if (namelen < 0) { dnss->rrcount = 0; return NULL; }
-      dnss->aptr += namelen + 8;            /* skip name, type, class & TTL */
+        dnss->aptr, (DN_EXPAND_ARG4_TYPE) &dnss->srr.name, DNS_MAXNAME);
+      if (namelen < 0) goto null_return;
+      /* skip name, type, class & TTL */
+      TRACE trace = "A-hdr";
+      if (dnss_inc(dnsa, dnss, namelen+8)) goto null_return;
       GETSHORT(dnss->srr.size, dnss->aptr); /* size of data portion */
-      dnss->aptr += dnss->srr.size;         /* skip over it */
+      /* skip over it */
+      TRACE trace = "A-skip";
+      if (dnss_inc(dnsa, dnss, dnss->srr.size)) goto null_return;
       }
-    dnss->rrcount = (reset == RESET_AUTHORITY)
+    dnss->rrcount = reset == RESET_AUTHORITY
       ? ntohs(h->nscount) : ntohs(h->arcount);
     }
+  TRACE debug_printf("%s: %d RRs to read\n", __FUNCTION__, dnss->rrcount);
   }
+else
+  TRACE debug_printf("%s: next (%d left)\n", __FUNCTION__, dnss->rrcount);
 
 /* The variable dnss->aptr is now pointing at the next RR, and dnss->rrcount
 contains the number of RR records left. */
@@ -379,25 +414,39 @@ if (dnss->rrcount-- <= 0) return NULL;
 /* If expanding the RR domain name fails, behave as if no more records
 (something safe). */
 
+TRACE trace = "R-namelen";
 namelen = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen, dnss->aptr,
-  (DN_EXPAND_ARG4_TYPE) &(dnss->srr.name), DNS_MAXNAME);
-if (namelen < 0) { dnss->rrcount = 0; return NULL; }
+  (DN_EXPAND_ARG4_TYPE) &dnss->srr.name, DNS_MAXNAME);
+if (namelen < 0) goto null_return;
 
 /* Move the pointer past the name and fill in the rest of the data structure
 from the following bytes. */
 
-dnss->aptr += namelen;
-GETSHORT(dnss->srr.type, dnss->aptr); /* Record type */
-dnss->aptr += 2;                      /* Don't want class */
-GETLONG(dnss->srr.ttl, dnss->aptr);   /* TTL */
-GETSHORT(dnss->srr.size, dnss->aptr); /* Size of data portion */
-dnss->srr.data = dnss->aptr;          /* The record's data follows */
-dnss->aptr += dnss->srr.size;         /* Advance to next RR */
+TRACE trace = "R-name";
+if (dnss_inc(dnsa, dnss, namelen)) goto null_return;
+
+GETSHORT(dnss->srr.type, dnss->aptr);          /* Record type */
+TRACE trace = "R-class";
+if (dnss_inc(dnsa, dnss, 2)) goto null_return; /* Don't want class */
+GETLONG(dnss->srr.ttl, dnss->aptr);            /* TTL */
+GETSHORT(dnss->srr.size, dnss->aptr);          /* Size of data portion */
+dnss->srr.data = dnss->aptr;                   /* The record's data follows */
+
+/* Unchecked increment ok here since no further access on this iteration;
+will be checked on next at "R-name". */
+
+dnss->aptr += dnss->srr.size;                  /* Advance to next RR */
 
 /* Return a pointer to the dns_record structure within the dns_answer. This is
 for convenience so that the scans can use nice-looking for loops. */
 
-return &(dnss->srr);
+return &dnss->srr;
+
+null_return:
+  TRACE debug_printf("%s: terminate (%d RRs left). Last op: %s\n",
+    __FUNCTION__, dnss->rrcount, trace);
+  dnss->rrcount = 0;
+  return NULL;
 }
 
 
index 7f7bebc68978ac0ac4ef1cee5ffbbaccba457c10..573fc00ca4833cca78c0d20d44d6f6a0a1d54b07 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions concerned with serialization. */
index 1559a4794512b3f44e9a11613bbe530233ae95d5..c491b205b6f7cadaa86fabaf93b32966ad5cbf9b 100644 (file)
@@ -1,6 +1,6 @@
 #! /bin/sh
 
-# Copyright (c) University of Cambridge, 1995 - 2007
+# Copyright (c) University of Cambridge, 1995 - 2015
 # See the file NOTICE for conditions of use and distribution.
 
 # This script takes the following command line arguments:
index 28617a510e84a0bcdb53551c7c517360d28c28d9..ebc71dd371929028edd35f69d11745f1a5dd83dd 100644 (file)
@@ -1760,7 +1760,6 @@ regex_whitelisted_macro =
 
 for (i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;
 
-
 /* If the program is called as "mailq" treat it as equivalent to "exim -bp";
 this seems to be a generally accepted convention, since one finds symbolic
 links called "mailq" in standard OS configurations. */
@@ -4556,6 +4555,12 @@ if (list_config)
   }
 
 
+/* Initialise subsystems as required */
+#ifndef DISABLE_DKIM
+dkim_exim_init();
+#endif
+
+
 /* Handle a request to deliver one or more messages that are already on the
 queue. Values of msg_action other than MSG_DELIVER and MSG_LOAD are dealt with
 above. MSG_LOAD is handled with -be (which is the only time it applies) below.
index f94f00b978f8d8a9fe1f7bc9e571a5f8a902ae8b..385c3624e620b65c674bc381c3278d5f5535b81a 100644 (file)
@@ -11,6 +11,9 @@ that is needed. They don't all need everything, of course, but it's far too
 messy to have each one importing its own list, and anyway, most of them need
 most of these includes. */
 
+#ifndef EXIM_H
+#define EXIM_H
+
 /* Assume most systems have statfs() unless os.h undefines this macro */
 
 #define HAVE_STATFS
@@ -596,4 +599,5 @@ default to EDQUOT if it exists, otherwise ENOSPC. */
   #undef DISABLE_DNSSEC
 #endif
 
+#endif
 /* End of exim.h */
index d707c2cdb8607b2e83320a4446d72203f99b71f4..66172f378c76d49431d4abe36cce708faa75065f 100644 (file)
@@ -201,6 +201,8 @@ static uschar *op_table_main[] = {
   US"addresses",
   US"base62",
   US"base62d",
+  US"base64",
+  US"base64d",
   US"domain",
   US"escape",
   US"eval",
@@ -241,6 +243,8 @@ enum {
   EOP_ADDRESSES,
   EOP_BASE62,
   EOP_BASE62D,
+  EOP_BASE64,
+  EOP_BASE64D,
   EOP_DOMAIN,
   EOP_ESCAPE,
   EOP_EVAL,
@@ -1725,7 +1729,7 @@ if ((Ustrncmp(name, "acl_c", 5) == 0 || Ustrncmp(name, "acl_m", 5) == 0) &&
   {
   tree_node *node =
     tree_search((name[4] == 'c')? acl_var_c : acl_var_m, name + 4);
-  return (node == NULL)? (strict_acl_vars? NULL : US"") : node->data.ptr;
+  return node ? node->data.ptr : strict_acl_vars ? NULL : US"";
   }
 
 /* Handle $auth<n> variables. */
@@ -1760,153 +1764,148 @@ val = vp->value;
 switch (vp->type)
   {
   case vtype_filter_int:
-  if (!filter_running) return NULL;
-  /* Fall through */
-  /* VVVVVVVVVVVV */
+    if (!filter_running) return NULL;
+    /* Fall through */
+    /* VVVVVVVVVVVV */
   case vtype_int:
-  sprintf(CS var_buffer, "%d", *(int *)(val)); /* Integer */
-  return var_buffer;
+    sprintf(CS var_buffer, "%d", *(int *)(val)); /* Integer */
+    return var_buffer;
 
   case vtype_ino:
-  sprintf(CS var_buffer, "%ld", (long int)(*(ino_t *)(val))); /* Inode */
-  return var_buffer;
+    sprintf(CS var_buffer, "%ld", (long int)(*(ino_t *)(val))); /* Inode */
+    return var_buffer;
 
   case vtype_gid:
-  sprintf(CS var_buffer, "%ld", (long int)(*(gid_t *)(val))); /* gid */
-  return var_buffer;
+    sprintf(CS var_buffer, "%ld", (long int)(*(gid_t *)(val))); /* gid */
+    return var_buffer;
 
   case vtype_uid:
-  sprintf(CS var_buffer, "%ld", (long int)(*(uid_t *)(val))); /* uid */
-  return var_buffer;
+    sprintf(CS var_buffer, "%ld", (long int)(*(uid_t *)(val))); /* uid */
+    return var_buffer;
 
   case vtype_bool:
-  sprintf(CS var_buffer, "%s", *(BOOL *)(val) ? "yes" : "no"); /* bool */
-  return var_buffer;
+    sprintf(CS var_buffer, "%s", *(BOOL *)(val) ? "yes" : "no"); /* bool */
+    return var_buffer;
 
   case vtype_stringptr:                      /* Pointer to string */
-  s = *((uschar **)(val));
-  return (s == NULL)? US"" : s;
+    return (s = *((uschar **)(val))) ? s : US"";
 
   case vtype_pid:
-  sprintf(CS var_buffer, "%d", (int)getpid()); /* pid */
-  return var_buffer;
+    sprintf(CS var_buffer, "%d", (int)getpid()); /* pid */
+    return var_buffer;
 
   case vtype_load_avg:
-  sprintf(CS var_buffer, "%d", OS_GETLOADAVG()); /* load_average */
-  return var_buffer;
+    sprintf(CS var_buffer, "%d", OS_GETLOADAVG()); /* load_average */
+    return var_buffer;
 
   case vtype_host_lookup:                    /* Lookup if not done so */
-  if (sender_host_name == NULL && sender_host_address != NULL &&
-      !host_lookup_failed && host_name_lookup() == OK)
-    host_build_sender_fullhost();
-  return (sender_host_name == NULL)? US"" : sender_host_name;
+    if (sender_host_name == NULL && sender_host_address != NULL &&
+       !host_lookup_failed && host_name_lookup() == OK)
+      host_build_sender_fullhost();
+    return (sender_host_name == NULL)? US"" : sender_host_name;
 
   case vtype_localpart:                      /* Get local part from address */
-  s = *((uschar **)(val));
-  if (s == NULL) return US"";
-  domain = Ustrrchr(s, '@');
-  if (domain == NULL) return s;
-  if (domain - s > sizeof(var_buffer) - 1)
-    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "local part longer than " SIZE_T_FMT
-       " in string expansion", sizeof(var_buffer));
-  Ustrncpy(var_buffer, s, domain - s);
-  var_buffer[domain - s] = 0;
-  return var_buffer;
+    s = *((uschar **)(val));
+    if (s == NULL) return US"";
+    domain = Ustrrchr(s, '@');
+    if (domain == NULL) return s;
+    if (domain - s > sizeof(var_buffer) - 1)
+      log_write(0, LOG_MAIN|LOG_PANIC_DIE, "local part longer than " SIZE_T_FMT
+         " in string expansion", sizeof(var_buffer));
+    Ustrncpy(var_buffer, s, domain - s);
+    var_buffer[domain - s] = 0;
+    return var_buffer;
 
   case vtype_domain:                         /* Get domain from address */
-  s = *((uschar **)(val));
-  if (s == NULL) return US"";
-  domain = Ustrrchr(s, '@');
-  return (domain == NULL)? US"" : domain + 1;
+    s = *((uschar **)(val));
+    if (s == NULL) return US"";
+    domain = Ustrrchr(s, '@');
+    return (domain == NULL)? US"" : domain + 1;
 
   case vtype_msgheaders:
-  return find_header(NULL, exists_only, newsize, FALSE, NULL);
+    return find_header(NULL, exists_only, newsize, FALSE, NULL);
 
   case vtype_msgheaders_raw:
-  return find_header(NULL, exists_only, newsize, TRUE, NULL);
+    return find_header(NULL, exists_only, newsize, TRUE, NULL);
 
   case vtype_msgbody:                        /* Pointer to msgbody string */
   case vtype_msgbody_end:                    /* Ditto, the end of the msg */
-  ss = (uschar **)(val);
-  if (*ss == NULL && deliver_datafile >= 0)  /* Read body when needed */
-    {
-    uschar *body;
-    off_t start_offset = SPOOL_DATA_START_OFFSET;
-    int len = message_body_visible;
-    if (len > message_size) len = message_size;
-    *ss = body = store_malloc(len+1);
-    body[0] = 0;
-    if (vp->type == vtype_msgbody_end)
-      {
-      struct stat statbuf;
-      if (fstat(deliver_datafile, &statbuf) == 0)
-       {
-       start_offset = statbuf.st_size - len;
-       if (start_offset < SPOOL_DATA_START_OFFSET)
-         start_offset = SPOOL_DATA_START_OFFSET;
-       }
-      }
-    lseek(deliver_datafile, start_offset, SEEK_SET);
-    len = read(deliver_datafile, body, len);
-    if (len > 0)
+    ss = (uschar **)(val);
+    if (*ss == NULL && deliver_datafile >= 0)  /* Read body when needed */
       {
-      body[len] = 0;
-      if (message_body_newlines)   /* Separate loops for efficiency */
+      uschar *body;
+      off_t start_offset = SPOOL_DATA_START_OFFSET;
+      int len = message_body_visible;
+      if (len > message_size) len = message_size;
+      *ss = body = store_malloc(len+1);
+      body[0] = 0;
+      if (vp->type == vtype_msgbody_end)
        {
-       while (len > 0)
-         { if (body[--len] == 0) body[len] = ' '; }
+       struct stat statbuf;
+       if (fstat(deliver_datafile, &statbuf) == 0)
+         {
+         start_offset = statbuf.st_size - len;
+         if (start_offset < SPOOL_DATA_START_OFFSET)
+           start_offset = SPOOL_DATA_START_OFFSET;
+         }
        }
-      else
+      lseek(deliver_datafile, start_offset, SEEK_SET);
+      len = read(deliver_datafile, body, len);
+      if (len > 0)
        {
-       while (len > 0)
-         { if (body[--len] == '\n' || body[len] == 0) body[len] = ' '; }
+       body[len] = 0;
+       if (message_body_newlines)   /* Separate loops for efficiency */
+         while (len > 0)
+           { if (body[--len] == 0) body[len] = ' '; }
+       else
+         while (len > 0)
+           { if (body[--len] == '\n' || body[len] == 0) body[len] = ' '; }
        }
       }
-    }
-  return (*ss == NULL)? US"" : *ss;
+    return (*ss == NULL)? US"" : *ss;
 
   case vtype_todbsdin:                       /* BSD inbox time of day */
-  return tod_stamp(tod_bsdin);
+    return tod_stamp(tod_bsdin);
 
   case vtype_tode:                           /* Unix epoch time of day */
-  return tod_stamp(tod_epoch);
+    return tod_stamp(tod_epoch);
 
   case vtype_todel:                          /* Unix epoch/usec time of day */
-  return tod_stamp(tod_epoch_l);
+    return tod_stamp(tod_epoch_l);
 
   case vtype_todf:                           /* Full time of day */
-  return tod_stamp(tod_full);
+    return tod_stamp(tod_full);
 
   case vtype_todl:                           /* Log format time of day */
-  return tod_stamp(tod_log_bare);            /* (without timezone) */
+    return tod_stamp(tod_log_bare);            /* (without timezone) */
 
   case vtype_todzone:                        /* Time zone offset only */
-  return tod_stamp(tod_zone);
+    return tod_stamp(tod_zone);
 
   case vtype_todzulu:                        /* Zulu time */
-  return tod_stamp(tod_zulu);
+    return tod_stamp(tod_zulu);
 
   case vtype_todlf:                          /* Log file datestamp tod */
-  return tod_stamp(tod_log_datestamp_daily);
+    return tod_stamp(tod_log_datestamp_daily);
 
   case vtype_reply:                          /* Get reply address */
-  s = find_header(US"reply-to:", exists_only, newsize, TRUE,
-    headers_charset);
-  if (s != NULL) while (isspace(*s)) s++;
-  if (s == NULL || *s == 0)
-    {
-    *newsize = 0;                            /* For the *s==0 case */
-    s = find_header(US"from:", exists_only, newsize, TRUE, headers_charset);
-    }
-  if (s != NULL)
-    {
-    uschar *t;
-    while (isspace(*s)) s++;
-    for (t = s; *t != 0; t++) if (*t == '\n') *t = ' ';
-    while (t > s && isspace(t[-1])) t--;
-    *t = 0;
-    }
-  return (s == NULL)? US"" : s;
+    s = find_header(US"reply-to:", exists_only, newsize, TRUE,
+      headers_charset);
+    if (s != NULL) while (isspace(*s)) s++;
+    if (s == NULL || *s == 0)
+      {
+      *newsize = 0;                            /* For the *s==0 case */
+      s = find_header(US"from:", exists_only, newsize, TRUE, headers_charset);
+      }
+    if (s != NULL)
+      {
+      uschar *t;
+      while (isspace(*s)) s++;
+      for (t = s; *t != 0; t++) if (*t == '\n') *t = ' ';
+      while (t > s && isspace(t[-1])) t--;
+      *t = 0;
+      }
+    return (s == NULL)? US"" : s;
 
   case vtype_string_func:
     {
@@ -1931,12 +1930,12 @@ switch (vp->type)
   return var_buffer;
 
   case vtype_cert:
-  return *(void **)val ? US"<cert>" : US"";
+    return *(void **)val ? US"<cert>" : US"";
 
-  #ifndef DISABLE_DKIM
+#ifndef DISABLE_DKIM
   case vtype_dkim:
-  return dkim_exim_expand_query((int)(long)val);
-  #endif
+    return dkim_exim_expand_query((int)(long)val);
+#endif
 
   }
 
@@ -2787,7 +2786,7 @@ switch(cond_type)
       #define XSTR(s) STR(s)
       DEBUG(D_auth) debug_printf("crypteq: using %s()\n"
         "  subject=%s\n  crypted=%s\n",
-        (which == 0)? XSTR(DEFAULT_CRYPT) : (which == 1)? "crypt" : "crypt16",
+        which == 0 ? XSTR(DEFAULT_CRYPT) : which == 1 ? "crypt" : "crypt16",
         coded, sub[1]);
       #undef STR
       #undef XSTR
@@ -2796,8 +2795,16 @@ switch(cond_type)
       salt), force failure. Otherwise we get false positives: with an empty
       string the yield of crypt() is an empty string! */
 
-      tempcond = (Ustrlen(sub[1]) < 2)? FALSE :
-        (Ustrcmp(coded, sub[1]) == 0);
+      if (coded)
+       tempcond = Ustrlen(sub[1]) < 2 ? FALSE : Ustrcmp(coded, sub[1]) == 0;
+      else if (errno == EINVAL)
+       tempcond = FALSE;
+      else
+       {
+       expand_string_message = string_sprintf("crypt error: %s\n",
+         US strerror(errno));
+       return NULL;
+       }
       }
     break;
     #endif  /* SUPPORT_CRYPTEQ */
@@ -3143,7 +3150,8 @@ Arguments:
   yieldptr       points to the output string pointer
   sizeptr        points to the output string size
   ptrptr         points to the output string pointer
-  type           "lookup" or "if" or "extract" or "run", for error message
+  type           "lookup", "if", "extract", "run", "env", "listextract" or
+                 "certextract" for error message
   resetok       if not NULL, pointer to flag - write FALSE if unsafe to reset
                the store.
 
@@ -3174,7 +3182,7 @@ if (*s == '}')
     }
   else
     {
-    if (yes && lookup_value != NULL)
+    if (yes && lookup_value)
       *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, lookup_value,
         Ustrlen(lookup_value));
     lookup_value = save_lookup;
@@ -3201,10 +3209,11 @@ if (*s++ != '}') goto FAILED_CURLY;
 if (yes)
   *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, sub1, Ustrlen(sub1));
 
-/* If this is called from a lookup or an extract, we want to restore $value to
-what it was at the start of the item, so that it has this value during the
-second string expansion. For the call from "if" or "run" to this function,
-save_lookup is set to lookup_value, so that this statement does nothing. */
+/* If this is called from a lookup/env or a (cert)extract, we want to restore
+$value to what it was at the start of the item, so that it has this value
+during the second string expansion. For the call from "if" or "run" to this
+function, save_lookup is set to lookup_value, so that this statement does
+nothing. */
 
 lookup_value = save_lookup;
 
@@ -3435,9 +3444,9 @@ return finalhash_hex;
 *        Join a file onto the output string      *
 *************************************************/
 
-/* This is used for readfile and after a run expansion. It joins the contents
-of a file onto the output string, globally replacing newlines with a given
-string (optionally). The file is closed at the end.
+/* This is used for readfile/readsock and after a run expansion.
+It joins the contents of a file onto the output string, globally replacing
+newlines with a given string (optionally).
 
 Arguments:
   f            the FILE
@@ -3452,21 +3461,19 @@ Returns:       new value of string pointer
 static uschar *
 cat_file(FILE *f, uschar *yield, int *sizep, int *ptrp, uschar *eol)
 {
-int eollen;
+int eollen = eol ? Ustrlen(eol) : 0;
 uschar buffer[1024];
 
-eollen = (eol == NULL)? 0 : Ustrlen(eol);
-
-while (Ufgets(buffer, sizeof(buffer), f) != NULL)
+while (Ufgets(buffer, sizeof(buffer), f))
   {
   int len = Ustrlen(buffer);
-  if (eol != NULL && buffer[len-1] == '\n') len--;
+  if (eol && buffer[len-1] == '\n') len--;
   yield = string_cat(yield, sizep, ptrp, buffer, len);
   if (buffer[len] != 0)
     yield = string_cat(yield, sizep, ptrp, eol, eollen);
   }
 
-if (yield != NULL) yield[*ptrp] = 0;
+if (yield) yield[*ptrp] = 0;
 
 return yield;
 }
@@ -3923,16 +3930,12 @@ while (*s != 0)
 
     /* Variable */
 
-    else
+    else if (!(value = find_variable(name, FALSE, skipping, &newsize)))
       {
-      value = find_variable(name, FALSE, skipping, &newsize);
-      if (value == NULL)
-        {
-        expand_string_message =
-          string_sprintf("unknown variable name \"%s\"", name);
-          check_variable_error_message(name);
-        goto EXPAND_FAILED;
-        }
+      expand_string_message =
+       string_sprintf("unknown variable name \"%s\"", name);
+       check_variable_error_message(name);
+      goto EXPAND_FAILED;
       }
 
     /* If the data is known to be in a new buffer, newsize will be set to the
@@ -4866,8 +4869,7 @@ while (*s != 0)
       const uschar **argv;
       pid_t pid;
       int fd_in, fd_out;
-      int lsize = 0;
-      int lptr = 0;
+      int lsize = 0, lptr = 0;
 
       if ((expand_forbid & RDO_RUN) != 0)
         {
@@ -4895,15 +4897,11 @@ while (*s != 0)
             NULL,                               /* no transporting address */
             US"${run} expansion",               /* for error messages */
             &expand_string_message))            /* where to put error message */
-          {
           goto EXPAND_FAILED;
-          }
 
         /* Create the child process, making it a group leader. */
 
-        pid = child_open(USS argv, NULL, 0077, &fd_in, &fd_out, TRUE);
-
-        if (pid < 0)
+        if ((pid = child_open(USS argv, NULL, 0077, &fd_in, &fd_out, TRUE)) < 0)
           {
           expand_string_message =
             string_sprintf("couldn't create child process: %s", strerror(errno));
@@ -4916,12 +4914,14 @@ while (*s != 0)
 
         /* Read the pipe to get the command's output into $value (which is kept
         in lookup_value). Read during execution, so that if the output exceeds
-        the OS pipe buffer limit, we don't block forever. */
+        the OS pipe buffer limit, we don't block forever. Remember to not release
+       memory just allocated for $value. */
 
+       resetok = FALSE;
         f = fdopen(fd_out, "rb");
         sigalrm_seen = FALSE;
         alarm(60);
-        lookup_value = cat_file(f, lookup_value, &lsize, &lptr, NULL);
+        lookup_value = cat_file(f, NULL, &lsize, &lptr, NULL);
         alarm(0);
         (void)fclose(f);
 
@@ -5469,7 +5469,7 @@ while (*s != 0)
                &yield,                       /* output pointer */
                &size,                        /* output size */
                &ptr,                         /* output current point */
-               US"extract",                  /* condition type */
+               US"listextract",              /* condition type */
               &resetok))
         {
         case 1: goto EXPAND_FAILED;          /* when all is well, the */
@@ -5541,7 +5541,7 @@ while (*s != 0)
                &yield,                       /* output pointer */
                &size,                        /* output size */
                &ptr,                         /* output current point */
-               US"extract",                  /* condition type */
+               US"certextract",              /* condition type */
               &resetok))
         {
         case 1: goto EXPAND_FAILED;          /* when all is well, the */
@@ -6039,6 +6039,7 @@ while (*s != 0)
       case EOP_MD5:
       case EOP_SHA1:
       case EOP_SHA256:
+      case EOP_BASE64:
        if (s[1] == '$')
          {
          const uschar * s1 = s;
@@ -6883,9 +6884,30 @@ while (*s != 0)
       /* Convert string to base64 encoding */
 
       case EOP_STR2B64:
+      case EOP_BASE64:
+       {
+#ifdef SUPPORT_TLS
+       uschar * s = vp && *(void **)vp->value
+         ? tls_cert_der_b64(*(void **)vp->value)
+         : b64encode(sub, Ustrlen(sub));
+#else
+       uschar * s = b64encode(sub, Ustrlen(sub));
+#endif
+       yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
+       continue;
+       }
+
+      case EOP_BASE64D:
         {
-        uschar *encstr = b64encode(sub, Ustrlen(sub));
-        yield = string_cat(yield, &size, &ptr, encstr, Ustrlen(encstr));
+        uschar * s;
+        int len = b64decode(sub, &s);
+       if (len < 0)
+          {
+          expand_string_message = string_sprintf("string \"%s\" is not "
+            "well-formed for \"%s\" operator", sub, name);
+          goto EXPAND_FAILED;
+          }
+        yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
         continue;
         }
 
index d37b7489b73317b5b8eb7e415896c815a552223d..97d95dd3d49b697aff07346db801acf357393eda 100644 (file)
@@ -39,6 +39,7 @@ extern uschar * tls_cert_subject(void *, uschar * mod);
 extern uschar * tls_cert_subject_altname(void *, uschar * mod);
 extern uschar * tls_cert_version(void *, uschar * mod);
 
+extern uschar * tls_cert_der_b64(void * cert);
 extern uschar * tls_cert_fprt_md5(void *);
 extern uschar * tls_cert_fprt_sha1(void *);
 extern uschar * tls_cert_fprt_sha256(void *);
@@ -389,7 +390,7 @@ extern BOOL    smtp_get_port(uschar *, address_item *, int *, uschar *);
 extern int     smtp_getc(void);
 extern int     smtp_handle_acl_fail(int, int, uschar *, uschar *);
 extern void    smtp_log_no_mail(void);
-extern void    smtp_message_code(uschar **, int *, uschar **, uschar **);
+extern void    smtp_message_code(uschar **, int *, uschar **, uschar **, BOOL);
 extern BOOL    smtp_read_response(smtp_inblock *, uschar *, int, int, int);
 extern void    smtp_respond(uschar *, int, BOOL, uschar *);
 extern void    smtp_notquit_exit(uschar *, uschar *, uschar *, ...);
index 14a821a19eb1a0909f3ce49f49c246034f7bdabc..69f217642aa113371caf56aff7b6ee88fed679e5 100644 (file)
@@ -320,7 +320,6 @@ uschar *acl_wherecodes[]       = { US"550",     /* RCPT */
 
 BOOL    active_local_from_check = FALSE;
 BOOL    active_local_sender_retain = FALSE;
-int     body_8bitmime = 0;
 BOOL    accept_8bitmime        = TRUE; /* deliberately not RFC compliant */
 address_item  *addr_duplicate  = NULL;
 
@@ -469,12 +468,14 @@ int     bmi_deliver            = 1;
 int     bmi_run                = 0;
 uschar *bmi_verdicts           = NULL;
 #endif
+int     body_8bitmime          = 0;
 int     body_linecount         = 0;
 int     body_zerocount         = 0;
 uschar *bounce_message_file    = NULL;
 uschar *bounce_message_text    = NULL;
 uschar *bounce_recipient       = NULL;
 BOOL    bounce_return_body     = TRUE;
+int     bounce_return_linesize_limit = 998;
 BOOL    bounce_return_message  = TRUE;
 int     bounce_return_size_limit = 100*1024;
 uschar *bounce_sender_authentication = NULL;
index 9ae78a920773b95dfb7366370ad511fa4794b552..787de41f0b699efce8b907dbdfbac4944711a67f 100644 (file)
@@ -156,7 +156,6 @@ extern const uschar **address_expansions[ADDRESS_EXPANSIONS_COUNT];
 /* General global variables */
 
 extern BOOL    accept_8bitmime;        /* Allow *BITMIME incoming */
-extern int     body_8bitmime;          /* sender declared BODY= ; 7=7BIT, 8=8BITMIME */
 extern header_line *acl_added_headers; /* Headers added by an ACL */
 extern tree_node *acl_anchor;          /* Tree of named ACLs */
 extern uschar *acl_arg[9];             /* Argument to ACL call */
@@ -246,10 +245,12 @@ extern int     bmi_deliver;            /* Flag that determines if the message sh
 extern int     bmi_run;                /* Flag that determines if message should be run through Brightmail server */
 extern uschar *bmi_verdicts;           /* BASE64-encoded verdicts with recipient lists */
 #endif
+extern int     body_8bitmime;          /* sender declared BODY= ; 7=7BIT, 8=8BITMIME */
 extern uschar *bounce_message_file;    /* Template file */
 extern uschar *bounce_message_text;    /* One-liner */
 extern uschar *bounce_recipient;       /* When writing an errmsg */
 extern BOOL    bounce_return_body;     /* Include body in returned message */
+extern int     bounce_return_linesize_limit; /* Max line length in return */
 extern BOOL    bounce_return_message;  /* Include message in bounce */
 extern int     bounce_return_size_limit; /* Max amount to return */
 extern uschar *bounce_sender_authentication; /* AUTH address for bounces */
index 3c679c6cfcb58e9983d981ec187c3816c1f28d90..10c96201920ad558802031635f130c5c191e61c3 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* The code in this module was contributed by Ard Biesheuvel. */
index 1faa884a166667309e1ebcd14327ab2039bc76e7..278ee09c9c6ce3d042d4d049663882b9950d677e 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 #include "../exim.h"
index a4a7a2d5b7fc4966297e810d5e977c344d4e2d18..00f30193ce63f2880ca8b901f28e39cfb35cb671 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 #include "../exim.h"
index adb17b4da410cd8599c774b6e3b530a13dd72631..33d2234363670ceeca92b73e8e0f66acd2d692e8 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Interface to an Oracle database. This code was originally supplied by
index 7bab349714946f090983e57ea68d6b3aa5fc78c4..854d4162a7b4bdc2d5476f0ee8189d02c8643326 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 #include "../exim.h"
index 9ac5a3a4341625e84d23b70e25bf0e4f14bfea73..8f065e60e038d9b34bc6cc01a1e167b4bbf9c7ff 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* This code originally came from Robert Wal. */
index 373774b352502f739a237db7b035a718b25f6c5f..7b1fa387d7cde8be790e8c2c7d5b498fcdfb0142 100644 (file)
 
 FILE *mime_stream = NULL;
 uschar *mime_current_boundary = NULL;
+static int mime_header_list_size = sizeof(mime_header_list)/sizeof(mime_header);
+
+static mime_parameter mime_parameter_list[] = {
+  { US"name=",     5, &mime_filename },
+  { US"filename=", 9, &mime_filename },
+  { US"charset=",  8, &mime_charset  },
+  { US"boundary=", 9, &mime_boundary }
+};
+
 
 /*************************************************
 * set MIME anomaly level + text                  *
index 3022b18704ac8ced0a7eb4e1336221239a3c71c8..5c030ebcaf70a7c9a6e77e1126137c8a243391ba 100644 (file)
@@ -35,7 +35,6 @@ static mime_header mime_header_list[] = {
   { US"content-description:",       20, &mime_content_description }
 };
 
-static int mime_header_list_size = sizeof(mime_header_list)/sizeof(mime_header);
 
 
 
@@ -45,14 +44,6 @@ typedef struct mime_parameter {
   uschar ** value;
 } mime_parameter;
 
-static mime_parameter mime_parameter_list[] = {
-  { US"name=",     5, &mime_filename },
-  { US"filename=", 9, &mime_filename },
-  { US"charset=",  8, &mime_charset  },
-  { US"boundary=", 9, &mime_boundary }
-};
-
-
 /* MIME Anomaly list */
 #define MIME_ANOMALY_BROKEN_BASE64    1
 #define MIME_ANOMALY_BROKEN_QP        0
index e54117c345d18b1f705ce84c8e39a9724451393c..7d1a2c681d2b557c62177f362fc3038216ebca37 100644 (file)
@@ -86,7 +86,7 @@ else DEBUG(D_any) debug_printf("Child process %d for sending message\n", pid);
 /* Creation of child succeeded */
 
 f = fdopen(fd, "wb");
-if (errors_reply_to != NULL) fprintf(f, "Reply-To: %s\n", errors_reply_to);
+if (errors_reply_to) fprintf(f, "Reply-To: %s\n", errors_reply_to);
 fprintf(f, "Auto-Submitted: auto-replied\n");
 moan_write_from(f);
 fprintf(f, "To: %s\n", recipient);
@@ -94,140 +94,137 @@ fprintf(f, "To: %s\n", recipient);
 switch(ident)
   {
   case ERRMESS_BADARGADDRESS:
-  fprintf(f,
-  "Subject: Mail failure - malformed recipient address\n\n");
-  fprintf(f,
-  "A message that you sent contained a recipient address that was incorrectly\n"
-  "constructed:\n\n");
-  fprintf(f, "  %s  %s\n", eblock->text1, eblock->text2);
-  count = Ustrlen(eblock->text1);
-  if (count > 0 && eblock->text1[count-1] == '.')
     fprintf(f,
-    "\nRecipient addresses must not end with a '.' character.\n");
-  fprintf(f,
-  "\nThe message has not been delivered to any recipients.\n");
-  break;
+      "Subject: Mail failure - malformed recipient address\n\n");
+    fprintf(f,
+      "A message that you sent contained a recipient address that was incorrectly\n"
+      "constructed:\n\n");
+    fprintf(f, "  %s  %s\n", eblock->text1, eblock->text2);
+    count = Ustrlen(eblock->text1);
+    if (count > 0 && eblock->text1[count-1] == '.')
+      fprintf(f,
+       "\nRecipient addresses must not end with a '.' character.\n");
+    fprintf(f,
+      "\nThe message has not been delivered to any recipients.\n");
+    break;
 
   case ERRMESS_BADNOADDRESS:
   case ERRMESS_BADADDRESS:
-  fprintf(f,
-  "Subject: Mail failure - malformed recipient address\n\n");
-  fprintf(f,
-  "A message that you sent contained one or more recipient addresses that were\n"
-  "incorrectly constructed:\n\n");
+    fprintf(f,
+      "Subject: Mail failure - malformed recipient address\n\n");
+    fprintf(f,
+      "A message that you sent contained one or more recipient addresses that were\n"
+      "incorrectly constructed:\n\n");
 
-  while (eblock != NULL)
-    {
-    fprintf(f, "  %s: %s\n", eblock->text1, eblock->text2);
-    count++;
-    eblock = eblock->next;
-    }
+    while (eblock != NULL)
+      {
+      fprintf(f, "  %s: %s\n", eblock->text1, eblock->text2);
+      count++;
+      eblock = eblock->next;
+      }
 
-  fprintf(f, (count == 1)? "\nThis address has been ignored. " :
-    "\nThese addresses have been ignored. ");
+    fprintf(f, (count == 1)? "\nThis address has been ignored. " :
+      "\nThese addresses have been ignored. ");
 
-  fprintf(f, (ident == ERRMESS_BADADDRESS)?
-  "The other addresses in the message were\n"
-  "syntactically valid and have been passed on for an attempt at delivery.\n" :
+    fprintf(f, (ident == ERRMESS_BADADDRESS)?
+      "The other addresses in the message were\n"
+      "syntactically valid and have been passed on for an attempt at delivery.\n" :
 
-  "There were no other addresses in your\n"
-  "message, and so no attempt at delivery was possible.\n");
-  break;
+      "There were no other addresses in your\n"
+      "message, and so no attempt at delivery was possible.\n");
+    break;
 
   case ERRMESS_IGADDRESS:
-  fprintf(f, "Subject: Mail failure - no recipient addresses\n\n");
-  fprintf(f,
-  "A message that you sent using the -t command line option contained no\n"
-  "addresses that were not also on the command line, and were therefore\n"
-  "suppressed. This left no recipient addresses, and so no delivery could\n"
-  "be attempted.\n");
-  break;
+    fprintf(f, "Subject: Mail failure - no recipient addresses\n\n");
+    fprintf(f,
+      "A message that you sent using the -t command line option contained no\n"
+      "addresses that were not also on the command line, and were therefore\n"
+      "suppressed. This left no recipient addresses, and so no delivery could\n"
+      "be attempted.\n");
+    break;
 
   case ERRMESS_NOADDRESS:
-  fprintf(f, "Subject: Mail failure - no recipient addresses\n\n");
-  fprintf(f,
-  "A message that you sent contained no recipient addresses, and therefore no\n"
-  "delivery could be attempted.\n");
-  break;
+    fprintf(f, "Subject: Mail failure - no recipient addresses\n\n");
+    fprintf(f,
+      "A message that you sent contained no recipient addresses, and therefore no\n"
+      "delivery could be attempted.\n");
+    break;
 
   case ERRMESS_IOERR:
-  fprintf(f, "Subject: Mail failure - system failure\n\n");
-  fprintf(f,
-  "A system failure was encountered while processing a message that you sent,\n"
-  "so it has not been possible to deliver it. The error was:\n\n%s\n",
-    eblock->text1);
-  break;
+    fprintf(f, "Subject: Mail failure - system failure\n\n");
+    fprintf(f,
+      "A system failure was encountered while processing a message that you sent,\n"
+      "so it has not been possible to deliver it. The error was:\n\n%s\n",
+      eblock->text1);
+    break;
 
   case ERRMESS_VLONGHEADER:
-  fprintf(f, "Subject: Mail failure - overlong header section\n\n");
-  fprintf(f,
-  "A message that you sent contained a header section that was excessively\n"
-  "long and could not be handled by the mail transmission software. The\n"
-  "message has not been delivered to any recipients.\n");
-  break;
+    fprintf(f, "Subject: Mail failure - overlong header section\n\n");
+    fprintf(f,
+      "A message that you sent contained a header section that was excessively\n"
+      "long and could not be handled by the mail transmission software. The\n"
+      "message has not been delivered to any recipients.\n");
+    break;
 
   case ERRMESS_VLONGHDRLINE:
-  fprintf(f, "Subject: Mail failure - overlong header line\n\n");
-  fprintf(f,
-  "A message that you sent contained a header line that was excessively\n"
-  "long and could not be handled by the mail transmission software. The\n"
-  "message has not been delivered to any recipients.\n");
-  break;
+    fprintf(f, "Subject: Mail failure - overlong header line\n\n");
+    fprintf(f,
+      "A message that you sent contained a header line that was excessively\n"
+      "long and could not be handled by the mail transmission software. The\n"
+      "message has not been delivered to any recipients.\n");
+    break;
 
   case ERRMESS_TOOBIG:
-  fprintf(f, "Subject: Mail failure - message too big\n\n");
-  fprintf(f,
-  "A message that you sent was longer than the maximum size allowed on this\n"
-  "system. It was not delivered to any recipients.\n");
-  break;
+    fprintf(f, "Subject: Mail failure - message too big\n\n");
+    fprintf(f,
+      "A message that you sent was longer than the maximum size allowed on this\n"
+      "system. It was not delivered to any recipients.\n");
+    break;
 
   case ERRMESS_TOOMANYRECIP:
-  fprintf(f, "Subject: Mail failure - too many recipients\n\n");
-  fprintf(f,
-  "A message that you sent contained more recipients than allowed on this\n"
-  "system. It was not delivered to any recipients.\n");
-  break;
+    fprintf(f, "Subject: Mail failure - too many recipients\n\n");
+    fprintf(f,
+      "A message that you sent contained more recipients than allowed on this\n"
+      "system. It was not delivered to any recipients.\n");
+    break;
 
   case ERRMESS_LOCAL_SCAN:
   case ERRMESS_LOCAL_ACL:
-  fprintf(f, "Subject: Mail failure - rejected by local scanning code\n\n");
-  fprintf(f,
-  "A message that you sent was rejected by the local scanning code that\n"
-  "checks incoming messages on this system.");
-  if (eblock->text1 != NULL)
-    {
+    fprintf(f, "Subject: Mail failure - rejected by local scanning code\n\n");
     fprintf(f,
-    " The following error was given:\n\n  %s", eblock->text1);
-    }
+      "A message that you sent was rejected by the local scanning code that\n"
+      "checks incoming messages on this system.");
+      if (eblock->text1)
+       fprintf(f, " The following error was given:\n\n  %s", eblock->text1);
   fprintf(f, "\n");
   break;
 
 #ifdef EXPERIMENTAL_DMARC
   case ERRMESS_DMARC_FORENSIC:
-  bounce_return_message = TRUE;
-  bounce_return_body    = FALSE;
-  fprintf(f,
+    bounce_return_message = TRUE;
+    bounce_return_body    = FALSE;
+    fprintf(f,
           "Subject: DMARC Forensic Report for %s from IP %s\n\n",
          ((eblock == NULL) ? US"Unknown" : eblock->text2),
           sender_host_address);
-  fprintf(f,
-  "A message claiming to be from you has failed the published DMARC\n"
-  "policy for your domain.\n\n");
-  while (eblock != NULL)
-    {
-    fprintf(f, "  %s: %s\n", eblock->text1, eblock->text2);
-    count++;
-    eblock = eblock->next;
-    }
+    fprintf(f,
+      "A message claiming to be from you has failed the published DMARC\n"
+      "policy for your domain.\n\n");
+    while (eblock != NULL)
+      {
+      fprintf(f, "  %s: %s\n", eblock->text1, eblock->text2);
+      count++;
+      eblock = eblock->next;
+      }
   break;
 #endif
 
   default:
-  fprintf(f, "Subject: Mail failure\n\n");
-  fprintf(f,
-  "A message that you sent has caused the error routine to be entered with\n"
-  "an unknown error number (%d).\n", ident);
-  break;
+    fprintf(f, "Subject: Mail failure\n\n");
+    fprintf(f,
+      "A message that you sent has caused the error routine to be entered with\n"
+      "an unknown error number (%d).\n", ident);
+    break;
   }
 
 /* Now, if configured, copy the message; first the headers and then the rest of
@@ -267,7 +264,7 @@ if (bounce_return_message)
   /* If the error occurred before the Received: header was created, its text
   field will still be NULL; just omit such a header line. */
 
-  while (headers != NULL)
+  while (headers)
     {
     if (headers->text != NULL) fprintf(f, "%s", CS headers->text);
     headers = headers->next;
@@ -280,30 +277,47 @@ if (bounce_return_message)
   in which case we might have to terminate on a line containing just "."
   as well as on EOF. We may already have the first line in memory. */
 
-  if (bounce_return_body && message_file != NULL)
+  if (bounce_return_body && message_file)
     {
     int ch;
-    int state = 1;
+    enum {midline, beginline, haddot} state = beginline;
     BOOL enddot = dot_ends && message_file == stdin;
-    if (firstline != NULL) fprintf(f, "%s", CS firstline);
-    while ((ch = fgetc(message_file)) != EOF)
+    uschar * buf = store_get(bounce_return_linesize_limit+2);
+
+    if (firstline) fprintf(f, "%s", CS firstline);
+
+    while (fgets(buf, bounce_return_linesize_limit+2, message_file))
       {
-      fputc(ch, f);
-      if (size_limit > 0 && ++written > size_limit) break;
-      if (enddot)
-        {
-        if (state == 0) { if (ch == '\n') state = 1; }
-        else if (state == 1)
-          { if (ch == '.') state = 2; else if (ch != '\n') state = 0; }
-        else
-          { if (ch == '\n') break; else state = 0; }
-        }
+      int len;
+
+      if (enddot && *buf == '.' && buf[1] == '\n')
+       {
+       fputc('.', f);
+       break;
+       }
+
+      len = Ustrlen(buf);
+      if (buf[len-1] != '\n')
+       {       /* eat rest of partial line */
+       int ch;
+       while ((ch = fgetc(message_file)) != EOF && ch != '\n') ;
+       }
+
+      if (size_limit > 0 && len > size_limit - written)
+       {
+       buf[size_limit - written] = '\0';
+       fputs(buf, f);
+       break;
+       }
+
+      fputs(buf, f);
       }
     }
 #ifdef EXPERIMENTAL_DMARC
   /* Overkill, but use exact test in case future code gets inserted */
   else if (bounce_return_body && message_file == NULL)
     {
+    /*XXX limit line length here? */
     /* This doesn't print newlines, disable until can parse and fix
      * output to be legible.  */
     fprintf(f, "%s", expand_string(US"$message_body"));
@@ -365,24 +379,24 @@ moan_to_sender(int ident, error_block *eblock, header_line *headers,
 uschar *firstline = NULL;
 uschar *msg = US"Error while reading message with no usable sender address";
 
-if (message_reference != NULL)
+if (message_reference)
   msg = string_sprintf("%s (R=%s)", msg, message_reference);
 
 /* Find the sender from a From line if permitted and possible */
 
-if (check_sender && message_file != NULL && trusted_caller &&
+if (check_sender && message_file && trusted_caller &&
     Ufgets(big_buffer, BIG_BUFFER_SIZE, message_file) != NULL)
   {
   uschar *new_sender = NULL;
   if (regex_match_and_setup(regex_From, big_buffer, 0, -1))
     new_sender = expand_string(uucp_from_sender);
-  if (new_sender != NULL) sender_address = new_sender;
+  if (new_sender) sender_address = new_sender;
     else firstline = big_buffer;
   }
 
 /* If viable sender address, send a message */
 
-if (sender_address != NULL && sender_address[0] != 0 && !local_error_message)
+if (sender_address && sender_address[0] && !local_error_message)
   return moan_send_message(sender_address, ident, eblock, headers,
     message_file, firstline);
 
index 6e02b8fe298099e96323d39d435ab63107f3c189..ee754f9f2689c44461aa56dad2f16cf72c05595f 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 #ifdef STAND_ALONE
index 62df49cca0035851cb1fa55f4c554966eb54be82..c72a9426b975d8a275f1525443ab2dbf68139ea5 100644 (file)
@@ -1,6 +1,6 @@
 # Make file for building the pdkim library.
 
-OBJ = bignum.o pdkim.o rsa.o sha1.o sha2.o part-x509parse.o pdkim-rsa.o
+OBJ = pdkim.o hash.o rsa.o
 
 pdkim.a:         $(OBJ)
                 @$(RM_COMMAND) -f pdkim.a
@@ -12,13 +12,8 @@ pdkim.a:         $(OBJ)
 .c.o:;           @echo "$(CC) $*.c"
                 $(FE)$(CC) -c $(CFLAGS) $(INCLUDE) -I. $*.c
 
-bignum.o:           $(HDRS) bignum.c
-part-x509parse.o:   $(HDRS) part-x509parse.c
-pdkim.o:            $(HDRS) pdkim.h pdkim-rsa.h pdkim.c
-pdkim-rsa.o:        $(HDRS) polarssl/private-x509parse_c.h \
-                       pdkim-rsa.h pdkim-rsa.c
-rsa.o:              $(HDRS) rsa.c
-sha1.o:             $(HDRS) sha1.c
-sha2.o:             $(HDRS) sha2.c
+pdkim.o:            $(HDRS) crypt_ver.h hash.h blob.h pdkim.h pdkim.c
+hash.o:             $(HDRS) crypt_ver.h hash.h blob.h pdkim.h hash.c
+rsa.o:              $(HDRS) crypt_ver.h rsa.h blob.h rsa.c
 
 # End
index de04cff2d89c6e207cceacf52fa42a416616ce44..953e86eae2e831b0bc722aca30c5d3b5c5e954d0 100644 (file)
@@ -2,10 +2,8 @@ PDKIM - a RFC4871 (DKIM) implementation
 http://duncanthrax.net/pdkim/
 Copyright (C) 2009      Tom Kistner <tom@duncanthrax.net>
 
-Includes code from the PolarSSL project.
-http://polarssl.org
-Copyright (C) 2009      Paul Bakker <polarssl_maintainer@polarssl.org>
-Copyright (C) 2006-2008 Christophe Devine
+No longer includes code from the PolarSSL project.
+Copyright (C) 2016 Jeremy Harris <jgh@exim.org>
 
 This copy of PDKIM is included with Exim. For a standalone distribution,
 visit http://duncanthrax.net/pdkim/.
diff --git a/src/src/pdkim/bignum.c b/src/src/pdkim/bignum.c
deleted file mode 100644 (file)
index b55c2b8..0000000
+++ /dev/null
@@ -1,2038 +0,0 @@
-/*
- *  Multi-precision integer library
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- *  This MPI implementation is based on:
- *
- *  http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
- *  http://www.stillhq.com/extracted/gnupg-api/mpi/
- *  http://math.libtomcrypt.com/files/tommath.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_BIGNUM_C)
-
-#include "polarssl/bignum.h"
-#include "polarssl/bn_mul.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#define ciL    ((int) sizeof(t_int))    /* chars in limb  */
-#define biL    (ciL << 3)               /* bits  in limb  */
-#define biH    (ciL << 2)               /* half limb size */
-
-/*
- * Convert between bits/chars and number of limbs
- */
-#define BITS_TO_LIMBS(i)  (((i) + biL - 1) / biL)
-#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
-
-/*
- * Initialize one or more mpi
- */
-void mpi_init( mpi *X, ... )
-{
-    va_list args;
-
-    va_start( args, X );
-
-    while( X != NULL )
-    {
-        X->s = 1;
-        X->n = 0;
-        X->p = NULL;
-
-        X = va_arg( args, mpi* );
-    }
-
-    va_end( args );
-}
-
-/*
- * Unallocate one or more mpi
- */
-void mpi_free( mpi *X, ... )
-{
-    va_list args;
-
-    va_start( args, X );
-
-    while( X != NULL )
-    {
-        if( X->p != NULL )
-        {
-            memset( X->p, 0, X->n * ciL );
-            free( X->p );
-        }
-
-        X->s = 1;
-        X->n = 0;
-        X->p = NULL;
-
-        X = va_arg( args, mpi* );
-    }
-
-    va_end( args );
-}
-
-/*
- * Enlarge to the specified number of limbs
- */
-int mpi_grow( mpi *X, int nblimbs )
-{
-    t_int *p;
-
-    if( X->n < nblimbs )
-    {
-        if( ( p = (t_int *) malloc( nblimbs * ciL ) ) == NULL )
-            return( 1 );
-
-        memset( p, 0, nblimbs * ciL );
-
-        if( X->p != NULL )
-        {
-            memcpy( p, X->p, X->n * ciL );
-            memset( X->p, 0, X->n * ciL );
-            free( X->p );
-        }
-
-        X->n = nblimbs;
-        X->p = p;
-    }
-
-    return( 0 );
-}
-
-/*
- * Copy the contents of Y into X
- */
-int mpi_copy( mpi *X, const mpi *Y )
-{
-    int ret, i;
-
-    if( X == Y )
-        return( 0 );
-
-    for( i = Y->n - 1; i > 0; i-- )
-        if( Y->p[i] != 0 )
-            break;
-    i++;
-
-    X->s = Y->s;
-
-    MPI_CHK( mpi_grow( X, i ) );
-
-    memset( X->p, 0, X->n * ciL );
-    memcpy( X->p, Y->p, i * ciL );
-
-cleanup:
-
-    return( ret );
-}
-
-/*
- * Swap the contents of X and Y
- */
-void mpi_swap( mpi *X, mpi *Y )
-{
-    mpi T;
-
-    memcpy( &T,  X, sizeof( mpi ) );
-    memcpy(  X,  Y, sizeof( mpi ) );
-    memcpy(  Y, &T, sizeof( mpi ) );
-}
-
-/*
- * Set value from integer
- */
-int mpi_lset( mpi *X, int z )
-{
-    int ret;
-
-    MPI_CHK( mpi_grow( X, 1 ) );
-    memset( X->p, 0, X->n * ciL );
-
-    X->p[0] = ( z < 0 ) ? -z : z;
-    X->s    = ( z < 0 ) ? -1 : 1;
-
-cleanup:
-
-    return( ret );
-}
-
-/*
- * Return the number of least significant bits
- */
-int mpi_lsb( const mpi *X )
-{
-    int i, j, count = 0;
-
-    for( i = 0; i < X->n; i++ )
-        for( j = 0; j < (int) biL; j++, count++ )
-            if( ( ( X->p[i] >> j ) & 1 ) != 0 )
-                return( count );
-
-    return( 0 );
-}
-
-/*
- * Return the number of most significant bits
- */
-int mpi_msb( const mpi *X )
-{
-    int i, j;
-
-    for( i = X->n - 1; i > 0; i-- )
-        if( X->p[i] != 0 )
-            break;
-
-    for( j = biL - 1; j >= 0; j-- )
-        if( ( ( X->p[i] >> j ) & 1 ) != 0 )
-            break;
-
-    return( ( i * biL ) + j + 1 );
-}
-
-/*
- * Return the total size in bytes
- */
-int mpi_size( const mpi *X )
-{
-    return( ( mpi_msb( X ) + 7 ) >> 3 );
-}
-
-/*
- * Convert an ASCII character to digit value
- */
-static int mpi_get_digit( t_int *d, int radix, char c )
-{
-    *d = 255;
-
-    if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
-    if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
-    if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
-
-    if( *d >= (t_int) radix )
-        return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
-
-    return( 0 );
-}
-
-/*
- * Import from an ASCII string
- */
-int mpi_read_string( mpi *X, int radix, const char *s )
-{
-    int ret, i, j, n, slen;
-    t_int d;
-    mpi T;
-
-    if( radix < 2 || radix > 16 )
-        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
-    mpi_init( &T, NULL );
-
-    slen = strlen( s );
-
-    if( radix == 16 )
-    {
-        n = BITS_TO_LIMBS( slen << 2 );
-
-        MPI_CHK( mpi_grow( X, n ) );
-        MPI_CHK( mpi_lset( X, 0 ) );
-
-        for( i = slen - 1, j = 0; i >= 0; i--, j++ )
-        {
-            if( i == 0 && s[i] == '-' )
-            {
-                X->s = -1;
-                break;
-            }
-
-            MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
-            X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
-        }
-    }
-    else
-    {
-        MPI_CHK( mpi_lset( X, 0 ) );
-
-        for( i = 0; i < slen; i++ )
-        {
-            if( i == 0 && s[i] == '-' )
-            {
-                X->s = -1;
-                continue;
-            }
-
-            MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
-            MPI_CHK( mpi_mul_int( &T, X, radix ) );
-
-            if( X->s == 1 )
-            {
-                MPI_CHK( mpi_add_int( X, &T, d ) );
-            }
-            else
-            {
-                MPI_CHK( mpi_sub_int( X, &T, d ) );
-            }
-        }
-    }
-
-cleanup:
-
-    mpi_free( &T, NULL );
-
-    return( ret );
-}
-
-/*
- * Helper to write the digits high-order first
- */
-static int mpi_write_hlp( mpi *X, int radix, char **p )
-{
-    int ret;
-    t_int r;
-
-    if( radix < 2 || radix > 16 )
-        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
-    MPI_CHK( mpi_mod_int( &r, X, radix ) );
-    MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
-
-    if( mpi_cmp_int( X, 0 ) != 0 )
-        MPI_CHK( mpi_write_hlp( X, radix, p ) );
-
-    if( r < 10 )
-        *(*p)++ = (char)( r + 0x30 );
-    else
-        *(*p)++ = (char)( r + 0x37 );
-
-cleanup:
-
-    return( ret );
-}
-
-/*
- * Export into an ASCII string
- */
-int mpi_write_string( const mpi *X, int radix, char *s, int *slen )
-{
-    int ret = 0, n;
-    char *p;
-    mpi T;
-
-    if( radix < 2 || radix > 16 )
-        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
-    n = mpi_msb( X );
-    if( radix >=  4 ) n >>= 1;
-    if( radix >= 16 ) n >>= 1;
-    n += 3;
-
-    if( *slen < n )
-    {
-        *slen = n;
-        return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
-    }
-
-    p = s;
-    mpi_init( &T, NULL );
-
-    if( X->s == -1 )
-        *p++ = '-';
-
-    if( radix == 16 )
-    {
-        int c, i, j, k;
-
-        for( i = X->n - 1, k = 0; i >= 0; i-- )
-        {
-            for( j = ciL - 1; j >= 0; j-- )
-            {
-                c = ( X->p[i] >> (j << 3) ) & 0xFF;
-
-                if( c == 0 && k == 0 && (i + j) != 0 )
-                    continue;
-
-                p += sprintf( p, "%02X", c );
-                k = 1;
-            }
-        }
-    }
-    else
-    {
-        MPI_CHK( mpi_copy( &T, X ) );
-
-        if( T.s == -1 )
-            T.s = 1;
-
-        MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
-    }
-
-    *p++ = '\0';
-    *slen = p - s;
-
-cleanup:
-
-    mpi_free( &T, NULL );
-
-    return( ret );
-}
-
-/*
- * Read X from an opened file
- */
-int mpi_read_file( mpi *X, int radix, FILE *fin )
-{
-    t_int d;
-    int slen;
-    char *p;
-    char s[1024];
-
-    memset( s, 0, sizeof( s ) );
-    if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
-        return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
-
-    slen = strlen( s );
-    if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
-    if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
-
-    p = s + slen;
-    while( --p >= s )
-        if( mpi_get_digit( &d, radix, *p ) != 0 )
-            break;
-
-    return( mpi_read_string( X, radix, p + 1 ) );
-}
-
-/*
- * Write X into an opened file (or stdout if fout == NULL)
- */
-int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
-{
-    int n, ret;
-    size_t slen;
-    size_t plen;
-    char s[2048];
-
-    n = sizeof( s );
-    memset( s, 0, n );
-    n -= 2;
-
-    MPI_CHK( mpi_write_string( X, radix, s, (int *) &n ) );
-
-    if( p == NULL ) p = "";
-
-    plen = strlen( p );
-    slen = strlen( s );
-    s[slen++] = '\r';
-    s[slen++] = '\n';
-
-    if( fout != NULL )
-    {
-        if( fwrite( p, 1, plen, fout ) != plen ||
-            fwrite( s, 1, slen, fout ) != slen )
-            return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
-    }
-    else
-        printf( "%s%s", p, s );
-
-cleanup:
-
-    return( ret );
-}
-
-/*
- * Import X from unsigned binary data, big endian
- */
-int mpi_read_binary( mpi *X, const unsigned char *buf, int buflen )
-{
-    int ret, i, j, n;
-
-    for( n = 0; n < buflen; n++ )
-        if( buf[n] != 0 )
-            break;
-
-    MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
-    MPI_CHK( mpi_lset( X, 0 ) );
-
-    for( i = buflen - 1, j = 0; i >= n; i--, j++ )
-        X->p[j / ciL] |= ((t_int) buf[i]) << ((j % ciL) << 3);
-
-cleanup:
-
-    return( ret );
-}
-
-/*
- * Export X into unsigned binary data, big endian
- */
-int mpi_write_binary( const mpi *X, unsigned char *buf, int buflen )
-{
-    int i, j, n;
-
-    n = mpi_size( X );
-
-    if( buflen < n )
-        return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
-
-    memset( buf, 0, buflen );
-
-    for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
-        buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
-
-    return( 0 );
-}
-
-/*
- * Left-shift: X <<= count
- */
-int mpi_shift_l( mpi *X, int count )
-{
-    int ret, i, v0, t1;
-    t_int r0 = 0, r1;
-
-    v0 = count / (biL    );
-    t1 = count & (biL - 1);
-
-    i = mpi_msb( X ) + count;
-
-    if( X->n * (int) biL < i )
-        MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
-
-    ret = 0;
-
-    /*
-     * shift by count / limb_size
-     */
-    if( v0 > 0 )
-    {
-        for( i = X->n - 1; i >= v0; i-- )
-            X->p[i] = X->p[i - v0];
-
-        for( ; i >= 0; i-- )
-            X->p[i] = 0;
-    }
-
-    /*
-     * shift by count % limb_size
-     */
-    if( t1 > 0 )
-    {
-        for( i = v0; i < X->n; i++ )
-        {
-            r1 = X->p[i] >> (biL - t1);
-            X->p[i] <<= t1;
-            X->p[i] |= r0;
-            r0 = r1;
-        }
-    }
-
-cleanup:
-
-    return( ret );
-}
-
-/*
- * Right-shift: X >>= count
- */
-int mpi_shift_r( mpi *X, int count )
-{
-    int i, v0, v1;
-    t_int r0 = 0, r1;
-
-    v0 = count /  biL;
-    v1 = count & (biL - 1);
-
-    /*
-     * shift by count / limb_size
-     */
-    if( v0 > 0 )
-    {
-        for( i = 0; i < X->n - v0; i++ )
-            X->p[i] = X->p[i + v0];
-
-        for( ; i < X->n; i++ )
-            X->p[i] = 0;
-    }
-
-    /*
-     * shift by count % limb_size
-     */
-    if( v1 > 0 )
-    {
-        for( i = X->n - 1; i >= 0; i-- )
-        {
-            r1 = X->p[i] << (biL - v1);
-            X->p[i] >>= v1;
-            X->p[i] |= r0;
-            r0 = r1;
-        }
-    }
-
-    return( 0 );
-}
-
-/*
- * Compare unsigned values
- */
-int mpi_cmp_abs( const mpi *X, const mpi *Y )
-{
-    int i, j;
-
-    for( i = X->n - 1; i >= 0; i-- )
-        if( X->p[i] != 0 )
-            break;
-
-    for( j = Y->n - 1; j >= 0; j-- )
-        if( Y->p[j] != 0 )
-            break;
-
-    if( i < 0 && j < 0 )
-        return( 0 );
-
-    if( i > j ) return(  1 );
-    if( j > i ) return( -1 );
-
-    for( ; i >= 0; i-- )
-    {
-        if( X->p[i] > Y->p[i] ) return(  1 );
-        if( X->p[i] < Y->p[i] ) return( -1 );
-    }
-
-    return( 0 );
-}
-
-/*
- * Compare signed values
- */
-int mpi_cmp_mpi( const mpi *X, const mpi *Y )
-{
-    int i, j;
-
-    for( i = X->n - 1; i >= 0; i-- )
-        if( X->p[i] != 0 )
-            break;
-
-    for( j = Y->n - 1; j >= 0; j-- )
-        if( Y->p[j] != 0 )
-            break;
-
-    if( i < 0 && j < 0 )
-        return( 0 );
-
-    if( i > j ) return(  X->s );
-    if( j > i ) return( -X->s );
-
-    if( X->s > 0 && Y->s < 0 ) return(  1 );
-    if( Y->s > 0 && X->s < 0 ) return( -1 );
-
-    for( ; i >= 0; i-- )
-    {
-        if( X->p[i] > Y->p[i] ) return(  X->s );
-        if( X->p[i] < Y->p[i] ) return( -X->s );
-    }
-
-    return( 0 );
-}
-
-/*
- * Compare signed values
- */
-int mpi_cmp_int( const mpi *X, int z )
-{
-    mpi Y;
-    t_int p[1];
-
-    *p  = ( z < 0 ) ? -z : z;
-    Y.s = ( z < 0 ) ? -1 : 1;
-    Y.n = 1;
-    Y.p = p;
-
-    return( mpi_cmp_mpi( X, &Y ) );
-}
-
-/*
- * Unsigned addition: X = |A| + |B|  (HAC 14.7)
- */
-int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
-{
-    int ret, i, j;
-    t_int *o, *p, c;
-
-    if( X == B )
-    {
-        const mpi *T = A; A = X; B = T;
-    }
-
-    if( X != A )
-        MPI_CHK( mpi_copy( X, A ) );
-
-    /*
-     * X should always be positive as a result of unsigned additions.
-     */
-    X->s = 1;
-
-    for( j = B->n - 1; j >= 0; j-- )
-        if( B->p[j] != 0 )
-            break;
-
-    MPI_CHK( mpi_grow( X, j + 1 ) );
-
-    o = B->p; p = X->p; c = 0;
-
-    for( i = 0; i <= j; i++, o++, p++ )
-    {
-        *p +=  c; c  = ( *p <  c );
-        *p += *o; c += ( *p < *o );
-    }
-
-    while( c != 0 )
-    {
-        if( i >= X->n )
-        {
-            MPI_CHK( mpi_grow( X, i + 1 ) );
-            p = X->p + i;
-        }
-
-        *p += c; c = ( *p < c ); i++;
-    }
-
-cleanup:
-
-    return( ret );
-}
-
-/*
- * Helper for mpi substraction
- */
-static void mpi_sub_hlp( int n, t_int *s, t_int *d )
-{
-    int i;
-    t_int c, z;
-
-    for( i = c = 0; i < n; i++, s++, d++ )
-    {
-        z = ( *d <  c );     *d -=  c;
-        c = ( *d < *s ) + z; *d -= *s;
-    }
-
-    while( c != 0 )
-    {
-        z = ( *d < c ); *d -= c;
-        c = z; i++; d++;
-    }
-}
-
-/*
- * Unsigned substraction: X = |A| - |B|  (HAC 14.9)
- */
-int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
-{
-    mpi TB;
-    int ret, n;
-
-    if( mpi_cmp_abs( A, B ) < 0 )
-        return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
-
-    mpi_init( &TB, NULL );
-
-    if( X == B )
-    {
-        MPI_CHK( mpi_copy( &TB, B ) );
-        B = &TB;
-    }
-
-    if( X != A )
-        MPI_CHK( mpi_copy( X, A ) );
-
-    /*
-     * X should always be positive as a result of unsigned substractions.
-     */
-    X->s = 1;
-
-    ret = 0;
-
-    for( n = B->n - 1; n >= 0; n-- )
-        if( B->p[n] != 0 )
-            break;
-
-    mpi_sub_hlp( n + 1, B->p, X->p );
-
-cleanup:
-
-    mpi_free( &TB, NULL );
-
-    return( ret );
-}
-
-/*
- * Signed addition: X = A + B
- */
-int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
-{
-    int ret, s = A->s;
-
-    if( A->s * B->s < 0 )
-    {
-        if( mpi_cmp_abs( A, B ) >= 0 )
-        {
-            MPI_CHK( mpi_sub_abs( X, A, B ) );
-            X->s =  s;
-        }
-        else
-        {
-            MPI_CHK( mpi_sub_abs( X, B, A ) );
-            X->s = -s;
-        }
-    }
-    else
-    {
-        MPI_CHK( mpi_add_abs( X, A, B ) );
-        X->s = s;
-    }
-
-cleanup:
-
-    return( ret );
-}
-
-/*
- * Signed substraction: X = A - B
- */
-int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
-{
-    int ret, s = A->s;
-
-    if( A->s * B->s > 0 )
-    {
-        if( mpi_cmp_abs( A, B ) >= 0 )
-        {
-            MPI_CHK( mpi_sub_abs( X, A, B ) );
-            X->s =  s;
-        }
-        else
-        {
-            MPI_CHK( mpi_sub_abs( X, B, A ) );
-            X->s = -s;
-        }
-    }
-    else
-    {
-        MPI_CHK( mpi_add_abs( X, A, B ) );
-        X->s = s;
-    }
-
-cleanup:
-
-    return( ret );
-}
-
-/*
- * Signed addition: X = A + b
- */
-int mpi_add_int( mpi *X, const mpi *A, int b )
-{
-    mpi _B;
-    t_int p[1];
-
-    p[0] = ( b < 0 ) ? -b : b;
-    _B.s = ( b < 0 ) ? -1 : 1;
-    _B.n = 1;
-    _B.p = p;
-
-    return( mpi_add_mpi( X, A, &_B ) );
-}
-
-/*
- * Signed substraction: X = A - b
- */
-int mpi_sub_int( mpi *X, const mpi *A, int b )
-{
-    mpi _B;
-    t_int p[1];
-
-    p[0] = ( b < 0 ) ? -b : b;
-    _B.s = ( b < 0 ) ? -1 : 1;
-    _B.n = 1;
-    _B.p = p;
-
-    return( mpi_sub_mpi( X, A, &_B ) );
-}
-
-/*
- * Helper for mpi multiplication
- */
-static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b )
-{
-    t_int c = 0, t = 0;
-
-#if defined(MULADDC_HUIT)
-    for( ; i >= 8; i -= 8 )
-    {
-        MULADDC_INIT
-        MULADDC_HUIT
-        MULADDC_STOP
-    }
-
-    for( ; i > 0; i-- )
-    {
-        MULADDC_INIT
-        MULADDC_CORE
-        MULADDC_STOP
-    }
-#else
-    for( ; i >= 16; i -= 16 )
-    {
-        MULADDC_INIT
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_STOP
-    }
-
-    for( ; i >= 8; i -= 8 )
-    {
-        MULADDC_INIT
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_STOP
-    }
-
-    for( ; i > 0; i-- )
-    {
-        MULADDC_INIT
-        MULADDC_CORE
-        MULADDC_STOP
-    }
-#endif
-
-    t++;
-
-    do {
-        *d += c; c = ( *d < c ); d++;
-    }
-    while( c != 0 );
-}
-
-/*
- * Baseline multiplication: X = A * B  (HAC 14.12)
- */
-int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
-{
-    int ret, i, j;
-    mpi TA, TB;
-
-    mpi_init( &TA, &TB, NULL );
-
-    if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
-    if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
-
-    for( i = A->n - 1; i >= 0; i-- )
-        if( A->p[i] != 0 )
-            break;
-
-    for( j = B->n - 1; j >= 0; j-- )
-        if( B->p[j] != 0 )
-            break;
-
-    MPI_CHK( mpi_grow( X, i + j + 2 ) );
-    MPI_CHK( mpi_lset( X, 0 ) );
-
-    for( i++; j >= 0; j-- )
-        mpi_mul_hlp( i, A->p, X->p + j, B->p[j] );
-
-    X->s = A->s * B->s;
-
-cleanup:
-
-    mpi_free( &TB, &TA, NULL );
-
-    return( ret );
-}
-
-/*
- * Baseline multiplication: X = A * b
- */
-int mpi_mul_int( mpi *X, const mpi *A, t_int b )
-{
-    mpi _B;
-    t_int p[1];
-
-    _B.s = 1;
-    _B.n = 1;
-    _B.p = p;
-    p[0] = b;
-
-    return( mpi_mul_mpi( X, A, &_B ) );
-}
-
-/*
- * Division by mpi: A = Q * B + R  (HAC 14.20)
- */
-int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
-{
-    int ret, i, n, t, k;
-    mpi X, Y, Z, T1, T2;
-
-    if( mpi_cmp_int( B, 0 ) == 0 )
-        return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
-
-    mpi_init( &X, &Y, &Z, &T1, &T2, NULL );
-
-    if( mpi_cmp_abs( A, B ) < 0 )
-    {
-        if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
-        if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
-        return( 0 );
-    }
-
-    MPI_CHK( mpi_copy( &X, A ) );
-    MPI_CHK( mpi_copy( &Y, B ) );
-    X.s = Y.s = 1;
-
-    MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
-    MPI_CHK( mpi_lset( &Z,  0 ) );
-    MPI_CHK( mpi_grow( &T1, 2 ) );
-    MPI_CHK( mpi_grow( &T2, 3 ) );
-
-    k = mpi_msb( &Y ) % biL;
-    if( k < (int) biL - 1 )
-    {
-        k = biL - 1 - k;
-        MPI_CHK( mpi_shift_l( &X, k ) );
-        MPI_CHK( mpi_shift_l( &Y, k ) );
-    }
-    else k = 0;
-
-    n = X.n - 1;
-    t = Y.n - 1;
-    mpi_shift_l( &Y, biL * (n - t) );
-
-    while( mpi_cmp_mpi( &X, &Y ) >= 0 )
-    {
-        Z.p[n - t]++;
-        mpi_sub_mpi( &X, &X, &Y );
-    }
-    mpi_shift_r( &Y, biL * (n - t) );
-
-    for( i = n; i > t ; i-- )
-    {
-        if( X.p[i] >= Y.p[t] )
-            Z.p[i - t - 1] = ~0;
-        else
-        {
-#if defined(POLARSSL_HAVE_LONGLONG)
-            t_dbl r;
-
-            r  = (t_dbl) X.p[i] << biL;
-            r |= (t_dbl) X.p[i - 1];
-            r /= Y.p[t];
-            if( r > ((t_dbl) 1 << biL) - 1)
-                r = ((t_dbl) 1 << biL) - 1;
-
-            Z.p[i - t - 1] = (t_int) r;
-#else
-            /*
-             * __udiv_qrnnd_c, from gmp/longlong.h
-             */
-            t_int q0, q1, r0, r1;
-            t_int d0, d1, d, m;
-
-            d  = Y.p[t];
-            d0 = ( d << biH ) >> biH;
-            d1 = ( d >> biH );
-
-            q1 = X.p[i] / d1;
-            r1 = X.p[i] - d1 * q1;
-            r1 <<= biH;
-            r1 |= ( X.p[i - 1] >> biH );
-
-            m = q1 * d0;
-            if( r1 < m )
-            {
-                q1--, r1 += d;
-                while( r1 >= d && r1 < m )
-                    q1--, r1 += d;
-            }
-            r1 -= m;
-
-            q0 = r1 / d1;
-            r0 = r1 - d1 * q0;
-            r0 <<= biH;
-            r0 |= ( X.p[i - 1] << biH ) >> biH;
-
-            m = q0 * d0;
-            if( r0 < m )
-            {
-                q0--, r0 += d;
-                while( r0 >= d && r0 < m )
-                    q0--, r0 += d;
-            }
-            r0 -= m;
-
-            Z.p[i - t - 1] = ( q1 << biH ) | q0;
-#endif
-        }
-
-        Z.p[i - t - 1]++;
-        do
-        {
-            Z.p[i - t - 1]--;
-
-            MPI_CHK( mpi_lset( &T1, 0 ) );
-            T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
-            T1.p[1] = Y.p[t];
-            MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
-
-            MPI_CHK( mpi_lset( &T2, 0 ) );
-            T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
-            T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
-            T2.p[2] = X.p[i];
-        }
-        while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
-
-        MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
-        MPI_CHK( mpi_shift_l( &T1,  biL * (i - t - 1) ) );
-        MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
-
-        if( mpi_cmp_int( &X, 0 ) < 0 )
-        {
-            MPI_CHK( mpi_copy( &T1, &Y ) );
-            MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
-            MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
-            Z.p[i - t - 1]--;
-        }
-    }
-
-    if( Q != NULL )
-    {
-        mpi_copy( Q, &Z );
-        Q->s = A->s * B->s;
-    }
-
-    if( R != NULL )
-    {
-        mpi_shift_r( &X, k );
-        mpi_copy( R, &X );
-
-        R->s = A->s;
-        if( mpi_cmp_int( R, 0 ) == 0 )
-            R->s = 1;
-    }
-
-cleanup:
-
-    mpi_free( &X, &Y, &Z, &T1, &T2, NULL );
-
-    return( ret );
-}
-
-/*
- * Division by int: A = Q * b + R
- *
- * Returns 0 if successful
- *         1 if memory allocation failed
- *         POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
- */
-int mpi_div_int( mpi *Q, mpi *R, const mpi *A, int b )
-{
-    mpi _B;
-    t_int p[1];
-
-    p[0] = ( b < 0 ) ? -b : b;
-    _B.s = ( b < 0 ) ? -1 : 1;
-    _B.n = 1;
-    _B.p = p;
-
-    return( mpi_div_mpi( Q, R, A, &_B ) );
-}
-
-/*
- * Modulo: R = A mod B
- */
-int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
-{
-    int ret;
-
-    if( mpi_cmp_int( B, 0 ) < 0 )
-        return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
-
-    MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
-
-    while( mpi_cmp_int( R, 0 ) < 0 )
-      MPI_CHK( mpi_add_mpi( R, R, B ) );
-
-    while( mpi_cmp_mpi( R, B ) >= 0 )
-      MPI_CHK( mpi_sub_mpi( R, R, B ) );
-
-cleanup:
-
-    return( ret );
-}
-
-/*
- * Modulo: r = A mod b
- */
-int mpi_mod_int( t_int *r, const mpi *A, int b )
-{
-    int i;
-    t_int x, y, z;
-
-    if( b == 0 )
-        return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
-
-    if( b < 0 )
-        return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
-
-    /*
-     * handle trivial cases
-     */
-    if( b == 1 )
-    {
-        *r = 0;
-        return( 0 );
-    }
-
-    if( b == 2 )
-    {
-        *r = A->p[0] & 1;
-        return( 0 );
-    }
-
-    /*
-     * general case
-     */
-    for( i = A->n - 1, y = 0; i >= 0; i-- )
-    {
-        x  = A->p[i];
-        y  = ( y << biH ) | ( x >> biH );
-        z  = y / b;
-        y -= z * b;
-
-        x <<= biH;
-        y  = ( y << biH ) | ( x >> biH );
-        z  = y / b;
-        y -= z * b;
-    }
-
-    /*
-     * If A is negative, then the current y represents a negative value.
-     * Flipping it to the positive side.
-     */
-    if( A->s < 0 && y != 0 )
-        y = b - y;
-
-    *r = y;
-
-    return( 0 );
-}
-
-/*
- * Fast Montgomery initialization (thanks to Tom St Denis)
- */
-static void mpi_montg_init( t_int *mm, const mpi *N )
-{
-    t_int x, m0 = N->p[0];
-
-    x  = m0;
-    x += ( ( m0 + 2 ) & 4 ) << 1;
-    x *= ( 2 - ( m0 * x ) );
-
-    if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
-    if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
-    if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
-
-    *mm = ~x + 1;
-}
-
-/*
- * Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
- */
-static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_int mm, const mpi *T )
-{
-    int i, n, m;
-    t_int u0, u1, *d;
-
-    memset( T->p, 0, T->n * ciL );
-
-    d = T->p;
-    n = N->n;
-    m = ( B->n < n ) ? B->n : n;
-
-    for( i = 0; i < n; i++ )
-    {
-        /*
-         * T = (T + u0*B + u1*N) / 2^biL
-         */
-        u0 = A->p[i];
-        u1 = ( d[0] + u0 * B->p[0] ) * mm;
-
-        mpi_mul_hlp( m, B->p, d, u0 );
-        mpi_mul_hlp( n, N->p, d, u1 );
-
-        *d++ = u0; d[n + 1] = 0;
-    }
-
-    memcpy( A->p, d, (n + 1) * ciL );
-
-    if( mpi_cmp_abs( A, N ) >= 0 )
-        mpi_sub_hlp( n, N->p, A->p );
-    else
-        /* prevent timing attacks */
-        mpi_sub_hlp( n, A->p, T->p );
-}
-
-/*
- * Montgomery reduction: A = A * R^-1 mod N
- */
-static void mpi_montred( mpi *A, const mpi *N, t_int mm, const mpi *T )
-{
-    t_int z = 1;
-    mpi U;
-
-    U.n = U.s = z;
-    U.p = &z;
-
-    mpi_montmul( A, &U, N, mm, T );
-}
-
-/*
- * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
- */
-int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
-{
-    int ret, i, j, wsize, wbits;
-    int bufsize, nblimbs, nbits;
-    t_int ei, mm, state;
-    mpi RR, T, W[64];
-
-    if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
-        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
-    /*
-     * Init temps and window size
-     */
-    mpi_montg_init( &mm, N );
-    mpi_init( &RR, &T, NULL );
-    memset( W, 0, sizeof( W ) );
-
-    i = mpi_msb( E );
-
-    wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
-            ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
-
-    j = N->n + 1;
-    MPI_CHK( mpi_grow( X, j ) );
-    MPI_CHK( mpi_grow( &W[1],  j ) );
-    MPI_CHK( mpi_grow( &T, j * 2 ) );
-
-    /*
-     * If 1st call, pre-compute R^2 mod N
-     */
-    if( _RR == NULL || _RR->p == NULL )
-    {
-        MPI_CHK( mpi_lset( &RR, 1 ) );
-        MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
-        MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
-
-        if( _RR != NULL )
-            memcpy( _RR, &RR, sizeof( mpi ) );
-    }
-    else
-        memcpy( &RR, _RR, sizeof( mpi ) );
-
-    /*
-     * W[1] = A * R^2 * R^-1 mod N = A * R mod N
-     */
-    if( mpi_cmp_mpi( A, N ) >= 0 )
-        mpi_mod_mpi( &W[1], A, N );
-    else   mpi_copy( &W[1], A );
-
-    mpi_montmul( &W[1], &RR, N, mm, &T );
-
-    /*
-     * X = R^2 * R^-1 mod N = R mod N
-     */
-    MPI_CHK( mpi_copy( X, &RR ) );
-    mpi_montred( X, N, mm, &T );
-
-    if( wsize > 1 )
-    {
-        /*
-         * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
-         */
-        j =  1 << (wsize - 1);
-
-        MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
-        MPI_CHK( mpi_copy( &W[j], &W[1]    ) );
-
-        for( i = 0; i < wsize - 1; i++ )
-            mpi_montmul( &W[j], &W[j], N, mm, &T );
-
-        /*
-         * W[i] = W[i - 1] * W[1]
-         */
-        for( i = j + 1; i < (1 << wsize); i++ )
-        {
-            MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
-            MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
-
-            mpi_montmul( &W[i], &W[1], N, mm, &T );
-        }
-    }
-
-    nblimbs = E->n;
-    bufsize = 0;
-    nbits   = 0;
-    wbits   = 0;
-    state   = 0;
-
-    while( 1 )
-    {
-        if( bufsize == 0 )
-        {
-            if( nblimbs-- == 0 )
-                break;
-
-            bufsize = sizeof( t_int ) << 3;
-        }
-
-        bufsize--;
-
-        ei = (E->p[nblimbs] >> bufsize) & 1;
-
-        /*
-         * skip leading 0s
-         */
-        if( ei == 0 && state == 0 )
-            continue;
-
-        if( ei == 0 && state == 1 )
-        {
-            /*
-             * out of window, square X
-             */
-            mpi_montmul( X, X, N, mm, &T );
-            continue;
-        }
-
-        /*
-         * add ei to current window
-         */
-        state = 2;
-
-        nbits++;
-        wbits |= (ei << (wsize - nbits));
-
-        if( nbits == wsize )
-        {
-            /*
-             * X = X^wsize R^-1 mod N
-             */
-            for( i = 0; i < wsize; i++ )
-                mpi_montmul( X, X, N, mm, &T );
-
-            /*
-             * X = X * W[wbits] R^-1 mod N
-             */
-            mpi_montmul( X, &W[wbits], N, mm, &T );
-
-            state--;
-            nbits = 0;
-            wbits = 0;
-        }
-    }
-
-    /*
-     * process the remaining bits
-     */
-    for( i = 0; i < nbits; i++ )
-    {
-        mpi_montmul( X, X, N, mm, &T );
-
-        wbits <<= 1;
-
-        if( (wbits & (1 << wsize)) != 0 )
-            mpi_montmul( X, &W[1], N, mm, &T );
-    }
-
-    /*
-     * X = A^E * R * R^-1 mod N = A^E mod N
-     */
-    mpi_montred( X, N, mm, &T );
-
-cleanup:
-
-    for( i = (1 << (wsize - 1)); i < (1 << wsize); i++ )
-        mpi_free( &W[i], NULL );
-
-    if( _RR != NULL )
-         mpi_free( &W[1], &T, NULL );
-    else mpi_free( &W[1], &T, &RR, NULL );
-
-    return( ret );
-}
-
-/*
- * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
- */
-int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
-{
-    int ret, lz, lzt;
-    mpi TG, TA, TB;
-
-    mpi_init( &TG, &TA, &TB, NULL );
-
-    MPI_CHK( mpi_copy( &TA, A ) );
-    MPI_CHK( mpi_copy( &TB, B ) );
-
-    lz = mpi_lsb( &TA );
-    lzt = mpi_lsb( &TB );
-
-    if ( lzt < lz )
-        lz = lzt;
-
-    MPI_CHK( mpi_shift_r( &TA, lz ) );
-    MPI_CHK( mpi_shift_r( &TB, lz ) );
-
-    TA.s = TB.s = 1;
-
-    while( mpi_cmp_int( &TA, 0 ) != 0 )
-    {
-        MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
-        MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
-
-        if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
-        {
-            MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
-            MPI_CHK( mpi_shift_r( &TA, 1 ) );
-        }
-        else
-        {
-            MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
-            MPI_CHK( mpi_shift_r( &TB, 1 ) );
-        }
-    }
-
-    MPI_CHK( mpi_shift_l( &TB, lz ) );
-    MPI_CHK( mpi_copy( G, &TB ) );
-
-cleanup:
-
-    mpi_free( &TB, &TA, &TG, NULL );
-
-    return( ret );
-}
-
-#if defined(POLARSSL_GENPRIME)
-
-/*
- * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
- */
-int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
-{
-    int ret;
-    mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
-
-    if( mpi_cmp_int( N, 0 ) <= 0 )
-        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
-    mpi_init( &TA, &TU, &U1, &U2, &G,
-              &TB, &TV, &V1, &V2, NULL );
-
-    MPI_CHK( mpi_gcd( &G, A, N ) );
-
-    if( mpi_cmp_int( &G, 1 ) != 0 )
-    {
-        ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
-        goto cleanup;
-    }
-
-    MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
-    MPI_CHK( mpi_copy( &TU, &TA ) );
-    MPI_CHK( mpi_copy( &TB, N ) );
-    MPI_CHK( mpi_copy( &TV, N ) );
-
-    MPI_CHK( mpi_lset( &U1, 1 ) );
-    MPI_CHK( mpi_lset( &U2, 0 ) );
-    MPI_CHK( mpi_lset( &V1, 0 ) );
-    MPI_CHK( mpi_lset( &V2, 1 ) );
-
-    do
-    {
-        while( ( TU.p[0] & 1 ) == 0 )
-        {
-            MPI_CHK( mpi_shift_r( &TU, 1 ) );
-
-            if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
-            {
-                MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
-                MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
-            }
-
-            MPI_CHK( mpi_shift_r( &U1, 1 ) );
-            MPI_CHK( mpi_shift_r( &U2, 1 ) );
-        }
-
-        while( ( TV.p[0] & 1 ) == 0 )
-        {
-            MPI_CHK( mpi_shift_r( &TV, 1 ) );
-
-            if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
-            {
-                MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
-                MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
-            }
-
-            MPI_CHK( mpi_shift_r( &V1, 1 ) );
-            MPI_CHK( mpi_shift_r( &V2, 1 ) );
-        }
-
-        if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
-        {
-            MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
-            MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
-            MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
-        }
-        else
-        {
-            MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
-            MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
-            MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
-        }
-    }
-    while( mpi_cmp_int( &TU, 0 ) != 0 );
-
-    while( mpi_cmp_int( &V1, 0 ) < 0 )
-        MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
-
-    while( mpi_cmp_mpi( &V1, N ) >= 0 )
-        MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
-
-    MPI_CHK( mpi_copy( X, &V1 ) );
-
-cleanup:
-
-    mpi_free( &V2, &V1, &TV, &TB, &G,
-              &U2, &U1, &TU, &TA, NULL );
-
-    return( ret );
-}
-
-static const int small_prime[] =
-{
-        3,    5,    7,   11,   13,   17,   19,   23,
-       29,   31,   37,   41,   43,   47,   53,   59,
-       61,   67,   71,   73,   79,   83,   89,   97,
-      101,  103,  107,  109,  113,  127,  131,  137,
-      139,  149,  151,  157,  163,  167,  173,  179,
-      181,  191,  193,  197,  199,  211,  223,  227,
-      229,  233,  239,  241,  251,  257,  263,  269,
-      271,  277,  281,  283,  293,  307,  311,  313,
-      317,  331,  337,  347,  349,  353,  359,  367,
-      373,  379,  383,  389,  397,  401,  409,  419,
-      421,  431,  433,  439,  443,  449,  457,  461,
-      463,  467,  479,  487,  491,  499,  503,  509,
-      521,  523,  541,  547,  557,  563,  569,  571,
-      577,  587,  593,  599,  601,  607,  613,  617,
-      619,  631,  641,  643,  647,  653,  659,  661,
-      673,  677,  683,  691,  701,  709,  719,  727,
-      733,  739,  743,  751,  757,  761,  769,  773,
-      787,  797,  809,  811,  821,  823,  827,  829,
-      839,  853,  857,  859,  863,  877,  881,  883,
-      887,  907,  911,  919,  929,  937,  941,  947,
-      953,  967,  971,  977,  983,  991,  997, -103
-};
-
-/*
- * Miller-Rabin primality test  (HAC 4.24)
- */
-int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng )
-{
-    int ret, i, j, n, s, xs;
-    mpi W, R, T, A, RR;
-    unsigned char *p;
-
-    if( mpi_cmp_int( X, 0 ) == 0 ||
-        mpi_cmp_int( X, 1 ) == 0 )
-        return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
-
-    if( mpi_cmp_int( X, 2 ) == 0 )
-        return( 0 );
-
-    mpi_init( &W, &R, &T, &A, &RR, NULL );
-
-    xs = X->s; X->s = 1;
-
-    /*
-     * test trivial factors first
-     */
-    if( ( X->p[0] & 1 ) == 0 )
-        return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
-
-    for( i = 0; small_prime[i] > 0; i++ )
-    {
-        t_int r;
-
-        if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
-            return( 0 );
-
-        MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
-
-        if( r == 0 )
-            return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
-    }
-
-    /*
-     * W = |X| - 1
-     * R = W >> lsb( W )
-     */
-    MPI_CHK( mpi_sub_int( &W, X, 1 ) );
-    s = mpi_lsb( &W );
-    MPI_CHK( mpi_copy( &R, &W ) );
-    MPI_CHK( mpi_shift_r( &R, s ) );
-
-    i = mpi_msb( X );
-    /*
-     * HAC, table 4.4
-     */
-    n = ( ( i >= 1300 ) ?  2 : ( i >=  850 ) ?  3 :
-          ( i >=  650 ) ?  4 : ( i >=  350 ) ?  8 :
-          ( i >=  250 ) ? 12 : ( i >=  150 ) ? 18 : 27 );
-
-    for( i = 0; i < n; i++ )
-    {
-        /*
-         * pick a random A, 1 < A < |X| - 1
-         */
-        MPI_CHK( mpi_grow( &A, X->n ) );
-
-        p = (unsigned char *) A.p;
-        for( j = 0; j < A.n * ciL; j++ )
-            *p++ = (unsigned char) f_rng( p_rng );
-
-        j = mpi_msb( &A ) - mpi_msb( &W );
-        MPI_CHK( mpi_shift_r( &A, j + 1 ) );
-        A.p[0] |= 3;
-
-        /*
-         * A = A^R mod |X|
-         */
-        MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
-
-        if( mpi_cmp_mpi( &A, &W ) == 0 ||
-            mpi_cmp_int( &A,  1 ) == 0 )
-            continue;
-
-        j = 1;
-        while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
-        {
-            /*
-             * A = A * A mod |X|
-             */
-            MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
-            MPI_CHK( mpi_mod_mpi( &A, &T, X  ) );
-
-            if( mpi_cmp_int( &A, 1 ) == 0 )
-                break;
-
-            j++;
-        }
-
-        /*
-         * not prime if A != |X| - 1 or A == 1
-         */
-        if( mpi_cmp_mpi( &A, &W ) != 0 ||
-            mpi_cmp_int( &A,  1 ) == 0 )
-        {
-            ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
-            break;
-        }
-    }
-
-cleanup:
-
-    X->s = xs;
-
-    mpi_free( &RR, &A, &T, &R, &W, NULL );
-
-    return( ret );
-}
-
-/*
- * Prime number generation
- */
-int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
-                   int (*f_rng)(void *), void *p_rng )
-{
-    int ret, k, n;
-    unsigned char *p;
-    mpi Y;
-
-    if( nbits < 3 )
-        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
-
-    mpi_init( &Y, NULL );
-
-    n = BITS_TO_LIMBS( nbits );
-
-    MPI_CHK( mpi_grow( X, n ) );
-    MPI_CHK( mpi_lset( X, 0 ) );
-
-    p = (unsigned char *) X->p;
-    for( k = 0; k < X->n * ciL; k++ )
-        *p++ = (unsigned char) f_rng( p_rng );
-
-    k = mpi_msb( X );
-    if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
-    if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
-
-    X->p[0] |= 3;
-
-    if( dh_flag == 0 )
-    {
-        while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
-        {
-            if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
-                goto cleanup;
-
-            MPI_CHK( mpi_add_int( X, X, 2 ) );
-        }
-    }
-    else
-    {
-        MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
-        MPI_CHK( mpi_shift_r( &Y, 1 ) );
-
-        while( 1 )
-        {
-            if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
-            {
-                if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
-                    break;
-
-                if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
-                    goto cleanup;
-            }
-
-            if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
-                goto cleanup;
-
-            MPI_CHK( mpi_add_int( &Y, X, 1 ) );
-            MPI_CHK( mpi_add_int(  X, X, 2 ) );
-            MPI_CHK( mpi_shift_r( &Y, 1 ) );
-        }
-    }
-
-cleanup:
-
-    mpi_free( &Y, NULL );
-
-    return( ret );
-}
-
-#endif
-
-#if defined(POLARSSL_SELF_TEST)
-
-#define GCD_PAIR_COUNT 3
-
-static const int gcd_pairs[GCD_PAIR_COUNT][3] =
-{
-    { 693, 609, 21 },
-    { 1764, 868, 28 },
-    { 768454923, 542167814, 1 }
-};
-
-/*
- * Checkup routine
- */
-int mpi_self_test( int verbose )
-{
-    int ret, i;
-    mpi A, E, N, X, Y, U, V;
-
-    mpi_init( &A, &E, &N, &X, &Y, &U, &V, NULL );
-
-    MPI_CHK( mpi_read_string( &A, 16,
-        "EFE021C2645FD1DC586E69184AF4A31E" \
-        "D5F53E93B5F123FA41680867BA110131" \
-        "944FE7952E2517337780CB0DB80E61AA" \
-        "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
-
-    MPI_CHK( mpi_read_string( &E, 16,
-        "B2E7EFD37075B9F03FF989C7C5051C20" \
-        "34D2A323810251127E7BF8625A4F49A5" \
-        "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
-        "5B5C25763222FEFCCFC38B832366C29E" ) );
-
-    MPI_CHK( mpi_read_string( &N, 16,
-        "0066A198186C18C10B2F5ED9B522752A" \
-        "9830B69916E535C8F047518A889A43A5" \
-        "94B6BED27A168D31D4A52F88925AA8F5" ) );
-
-    MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
-
-    MPI_CHK( mpi_read_string( &U, 16,
-        "602AB7ECA597A3D6B56FF9829A5E8B85" \
-        "9E857EA95A03512E2BAE7391688D264A" \
-        "A5663B0341DB9CCFD2C4C5F421FEC814" \
-        "8001B72E848A38CAE1C65F78E56ABDEF" \
-        "E12D3C039B8A02D6BE593F0BBBDA56F1" \
-        "ECF677152EF804370C1A305CAF3B5BF1" \
-        "30879B56C61DE584A0F53A2447A51E" ) );
-
-    if( verbose != 0 )
-        printf( "  MPI test #1 (mul_mpi): " );
-
-    if( mpi_cmp_mpi( &X, &U ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-
-    if( verbose != 0 )
-        printf( "passed\n" );
-
-    MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
-
-    MPI_CHK( mpi_read_string( &U, 16,
-        "256567336059E52CAE22925474705F39A94" ) );
-
-    MPI_CHK( mpi_read_string( &V, 16,
-        "6613F26162223DF488E9CD48CC132C7A" \
-        "0AC93C701B001B092E4E5B9F73BCD27B" \
-        "9EE50D0657C77F374E903CDFA4C642" ) );
-
-    if( verbose != 0 )
-        printf( "  MPI test #2 (div_mpi): " );
-
-    if( mpi_cmp_mpi( &X, &U ) != 0 ||
-        mpi_cmp_mpi( &Y, &V ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-
-    if( verbose != 0 )
-        printf( "passed\n" );
-
-    MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
-
-    MPI_CHK( mpi_read_string( &U, 16,
-        "36E139AEA55215609D2816998ED020BB" \
-        "BD96C37890F65171D948E9BC7CBAA4D9" \
-        "325D24D6A3C12710F10A09FA08AB87" ) );
-
-    if( verbose != 0 )
-        printf( "  MPI test #3 (exp_mod): " );
-
-    if( mpi_cmp_mpi( &X, &U ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-
-    if( verbose != 0 )
-        printf( "passed\n" );
-
-    MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
-
-    MPI_CHK( mpi_read_string( &U, 16,
-        "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
-        "C3DBA76456363A10869622EAC2DD84EC" \
-        "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
-
-    if( verbose != 0 )
-        printf( "  MPI test #4 (inv_mod): " );
-
-    if( mpi_cmp_mpi( &X, &U ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( 1 );
-    }
-
-    if( verbose != 0 )
-        printf( "passed\n" );
-
-    if( verbose != 0 )
-        printf( "  MPI test #5 (simple gcd): " );
-
-    for ( i = 0; i < GCD_PAIR_COUNT; i++)
-    {
-        MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
-       MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
-
-       MPI_CHK( mpi_gcd( &A, &X, &Y ) );
-
-       if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
-       {
-               if( verbose != 0 )
-                       printf( "failed at %d\n", i );
-
-               return( 1 );
-       }
-    }
-
-    if( verbose != 0 )
-        printf( "passed\n" );
-
-cleanup:
-
-    if( ret != 0 && verbose != 0 )
-        printf( "Unexpected error, return code = %08X\n", ret );
-
-    mpi_free( &V, &U, &Y, &X, &N, &E, &A, NULL );
-
-    if( verbose != 0 )
-        printf( "\n" );
-
-    return( ret );
-}
-
-#endif
-
-#endif
diff --git a/src/src/pdkim/blob.h b/src/src/pdkim/blob.h
new file mode 100644 (file)
index 0000000..e1481c9
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ *  PDKIM - a RFC4871 (DKIM) implementation
+ *
+ *  Copyright (C) 2016  Exim maintainers
+ *
+ *  RSA signing/verification interface
+ */
+
+#ifndef BLOB_H /* entire file */
+#define BLOB_H
+
+typedef struct {
+  uschar * data;
+  size_t   len;
+} blob;
+
+#endif
diff --git a/src/src/pdkim/crypt_ver.h b/src/src/pdkim/crypt_ver.h
new file mode 100644 (file)
index 0000000..2a9dde9
--- /dev/null
@@ -0,0 +1,32 @@
+/*************************************************
+*     Exim - an Internet mail transport agent    *
+*************************************************/
+
+/* Copyright (c) Jeremy Harris 2016 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+/* RSA and SHA routine selection for PDKIM */
+
+#include "../exim.h"
+
+
+#ifdef USE_GNUTLS
+# include <gnutls/gnutls.h>
+
+# if GNUTLS_VERSION_NUMBER > 0x020c00
+#  define RSA_GNUTLS
+# else
+#  define RSA_GCRYPT
+# endif
+
+# if GNUTLS_VERSION_NUMBER >= 0x020a00
+#  define SHA_GNUTLS
+# else
+#  define SHA_GCRYPT
+# endif
+
+#else
+# define RSA_OPENSSL
+# define SHA_OPENSSL
+#endif
+
diff --git a/src/src/pdkim/hash.c b/src/src/pdkim/hash.c
new file mode 100644 (file)
index 0000000..0751683
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ *  PDKIM - a RFC4871 (DKIM) implementation
+ *
+ *  Copyright (C) 2016  Exim maintainers
+ *
+ *  Hash interface functions
+ */
+
+#include "../exim.h"
+
+#ifndef DISABLE_DKIM   /* entire file */
+
+#ifndef SUPPORT_TLS
+# error Need SUPPORT_TLS for DKIM
+#endif
+
+#include "crypt_ver.h"
+
+#ifdef RSA_OPENSSL
+# include <openssl/rsa.h>
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#elif defined(RSA_GNUTLS)
+# include <gnutls/gnutls.h>
+# include <gnutls/x509.h>
+# ifdef RSA_VERIFY_GNUTLS
+#  include <gnutls/abstract.h>
+# endif
+#endif
+
+#ifdef SHA_GNUTLS
+# include <gnutls/crypto.h>
+#endif
+
+#include "hash.h"
+
+
+/******************************************************************************/
+#ifdef SHA_OPENSSL
+
+void
+exim_sha_init(hctx * h, BOOL sha1)
+{
+h->sha1 = sha1;
+h->hashlen = sha1 ? 20 : 32;
+if (h->sha1)
+  SHA1_Init  (&h->u.sha1);
+else
+  SHA256_Init(&h->u.sha2);
+}
+
+
+void
+exim_sha_update(hctx * h, const char * data, int len)
+{
+if (h->sha1)
+  SHA1_Update  (&h->u.sha1, data, len);
+else
+  SHA256_Update(&h->u.sha2, data, len);
+}
+
+
+void
+exim_sha_finish(hctx * h, blob * b)
+{
+b->data = store_get(b->len = h->hashlen);
+
+if (h->sha1)
+  SHA1_Final  (b->data, &h->u.sha1);
+else
+  SHA256_Final(b->data, &h->u.sha2);
+}
+
+
+
+#elif defined(SHA_GNUTLS)
+/******************************************************************************/
+
+void
+exim_sha_init(hctx * h, BOOL sha1)
+{
+h->sha1 = sha1;
+h->hashlen = sha1 ? 20 : 32;
+gnutls_hash_init(&h->sha, sha1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256);
+}
+
+
+void
+exim_sha_update(hctx * h, const char * data, int len)
+{
+gnutls_hash(h->sha, data, len);
+}
+
+
+void
+exim_sha_finish(hctx * h, blob * b)
+{
+b->data = store_get(b->len = h->hashlen);
+gnutls_hash_output(h->sha, b->data);
+}
+
+
+
+#elif defined(SHA_GCRYPT)
+/******************************************************************************/
+
+void
+exim_sha_init(hctx * h, BOOL sha1)
+{
+h->sha1 = sha1;
+h->hashlen = sha1 ? 20 : 32;
+gcry_md_open(&h->sha, sha1 ? GCRY_MD_SHA1 : GCRY_MD_SHA256, 0);
+}
+
+
+void
+exim_sha_update(hctx * h, const char * data, int len)
+{
+gcry_md_write(h->sha, data, len);
+}
+
+
+void
+exim_sha_finish(hctx * h, blob * b)
+{
+b->data = store_get(b->len = h->hashlen);
+memcpy(b->data, gcry_md_read(h->sha, 0), h->hashlen);
+}
+
+
+
+
+#elif defined(SHA_POLARSSL)
+/******************************************************************************/
+
+void
+exim_sha_init(hctx * h, BOOL sha1)
+{
+h->sha1 = sha1;
+h->hashlen = sha1 ? 20 : 32;
+if (h->sha1)
+  sha1_starts(&h->u.sha1);
+else
+  sha2_starts(&h->u.sha2, 0);
+}
+
+
+void
+exim_sha_update(hctx * h, const char * data, int len)
+{
+if (h->sha1)
+  sha1_update(h->u.sha1, US data, len);
+else
+  sha2_update(h->u.sha2, US data, len);
+}
+
+
+void
+exim_sha_finish(hctx * h, blob * b)
+{
+b->data = store_get(b->len = h->hashlen);
+
+if (h->sha1)
+  sha1_finish(h->u.sha1, b->data);
+else
+  sha2_finish(h->u.sha2, b->data);
+}
+
+#endif
+/******************************************************************************/
+
+/* Common to all library versions */
+int
+exim_sha_hashlen(hctx * h)
+{
+return h->sha1 ? 20 : 32;
+}
+
+
+#endif /*DISABLE_DKIM*/
+/* End of File */
diff --git a/src/src/pdkim/hash.h b/src/src/pdkim/hash.h
new file mode 100644 (file)
index 0000000..afd7ea6
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  PDKIM - a RFC4871 (DKIM) implementation
+ *
+ *  Copyright (C) 2016  Exim maintainers
+ *
+ *  Hash interface functions
+ */
+
+#include "../exim.h"
+
+#if !defined(DISABLE_DKIM) && !defined(PDKIM_HASH_H)   /* entire file */
+#define PDKIM_HASH_H
+
+#ifndef SUPPORT_TLS
+# error Need SUPPORT_TLS for DKIM
+#endif
+
+#include "crypt_ver.h"
+#include "blob.h"
+
+#ifdef RSA_OPENSSL
+# include <openssl/rsa.h>
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#elif defined(RSA_GNUTLS)
+# include <gnutls/gnutls.h>
+# include <gnutls/x509.h>
+#endif
+
+#ifdef SHA_GNUTLS
+# include <gnutls/crypto.h>
+#elif defined(SHA_GCRYPT)
+# include <gcrypt.h>
+#elif defined(SHA_POLARSSL)
+# include "pdkim.h"
+# include "polarssl/sha1.h"
+# include "polarssl/sha2.h"
+#endif
+
+/* Hash context */
+typedef struct {
+  int sha1;
+  int hashlen;
+
+#ifdef SHA_OPENSSL
+  union {
+    SHA_CTX      sha1;       /* SHA1 block                                */
+    SHA256_CTX   sha2;       /* SHA256 block                              */
+  } u;
+
+#elif defined(SHA_GNUTLS)
+  gnutls_hash_hd_t sha;      /* Either SHA1 or SHA256 block               */
+
+#elif defined(SHA_GCRYPT)
+  gcry_md_hd_t sha;          /* Either SHA1 or SHA256 block               */
+
+#elif defined(SHA_POLARSSL)
+  union {
+    sha1_context sha1;       /* SHA1 block                                */
+    sha2_context sha2;       /* SHA256 block                              */
+  } u;
+#endif
+
+} hctx;
+
+#if defined(SHA_OPENSSL)
+# include "pdkim.h"
+#elif defined(SHA_GCRYPT)
+# include "pdkim.h"
+#endif
+
+
+extern void     exim_sha_init(hctx *, BOOL);
+extern void     exim_sha_update(hctx *, const char *a, int);
+extern void     exim_sha_finish(hctx *, blob *);
+extern int      exim_sha_hashlen(hctx *);
+
+#endif /*DISABLE_DKIM*/
+/* End of File */
diff --git a/src/src/pdkim/part-x509parse.c b/src/src/pdkim/part-x509parse.c
deleted file mode 100644 (file)
index 935d25a..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-#include "polarssl/bignum.h"
-#include "polarssl/part-x509.h"
-#include "polarssl/private-x509parse_c.h"
-
-#ifndef POLARSSL_PRIVATE_X509_PARSE_C_H
-#define POLARSSL_PRIVATE_X509_PARSE_C_H
-/* *************** begin copy from x509parse.c ********************/
-/*
- *  X.509 certificate and private key decoding
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- *  The ITU-T X.509 standard defines a certificat format for PKI.
- *
- *  http://www.ietf.org/rfc/rfc2459.txt
- *  http://www.ietf.org/rfc/rfc3279.txt
- *
- *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
- *
- *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
- *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
- */
-
-
-/*
- * ASN.1 DER decoding routines
- */
-static int asn1_get_len( unsigned char **p,
-                         const unsigned char *end,
-                         int *len )
-{
-    if( ( end - *p ) < 1 )
-        return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-    if( ( **p & 0x80 ) == 0 )
-        *len = *(*p)++;
-    else
-    {
-        switch( **p & 0x7F )
-        {
-        case 1:
-            if( ( end - *p ) < 2 )
-                return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-            *len = (*p)[1];
-            (*p) += 2;
-            break;
-
-        case 2:
-            if( ( end - *p ) < 3 )
-                return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-            *len = ( (*p)[1] << 8 ) | (*p)[2];
-            (*p) += 3;
-            break;
-
-        default:
-            return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
-            break;
-        }
-    }
-
-    if( *len > (int) ( end - *p ) )
-        return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-    return( 0 );
-}
-
-/* This function is not exported by PolarSSL 0.14.2
- * static */
-int asn1_get_tag( unsigned char **p,
-                         const unsigned char *end,
-                         int *len, int tag )
-{
-    if( ( end - *p ) < 1 )
-        return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
-
-    if( **p != tag )
-        return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
-
-    (*p)++;
-
-    return( asn1_get_len( p, end, len ) );
-}
-
-/* This function is not exported by PolarSSL 0.14.2
- * static */
-int asn1_get_int( unsigned char **p,
-                         const unsigned char *end,
-                         int *val )
-{
-    int ret, len;
-
-    if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
-        return( ret );
-
-    if( len > (int) sizeof( int ) || ( **p & 0x80 ) != 0 )
-        return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
-
-    *val = 0;
-
-    while( len-- > 0 )
-    {
-        *val = ( *val << 8 ) | **p;
-        (*p)++;
-    }
-
-    return( 0 );
-}
-
-/* This function is not exported by PolarSSL 0.14.2
- * static */
-int asn1_get_mpi( unsigned char **p,
-                         const unsigned char *end,
-                         mpi *X )
-{
-    int ret, len;
-
-    if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
-        return( ret );
-
-    ret = mpi_read_binary( X, *p, len );
-
-    *p += len;
-
-    return( ret );
-}
-/* ***************   end copy from x509parse.c ********************/
-#endif /* private-x509parse_c.h */
diff --git a/src/src/pdkim/pdkim-rsa.c b/src/src/pdkim/pdkim-rsa.c
deleted file mode 100644 (file)
index 87cbac1..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-#include "pdkim-rsa.h"
-#include <stdlib.h>
-#include <string.h>
-#include "polarssl/private-x509parse_c.h"
-
-/* PDKIM code (not copied from polarssl) */
-/*
- * Parse a public RSA key
-
-OpenSSL RSA public key ASN1 container
-  0:d=0  hl=3 l= 159 cons: SEQUENCE
-  3:d=1  hl=2 l=  13 cons: SEQUENCE
-  5:d=2  hl=2 l=   9 prim: OBJECT:rsaEncryption
- 16:d=2  hl=2 l=   0 prim: NULL
- 18:d=1  hl=3 l= 141 prim: BIT STRING:RSAPublicKey (below)
-
-RSAPublicKey ASN1 container
-  0:d=0  hl=3 l= 137 cons: SEQUENCE
-  3:d=1  hl=3 l= 129 prim: INTEGER:Public modulus
-135:d=1  hl=2 l=   3 prim: INTEGER:Public exponent
-*/
-
-int rsa_parse_public_key( rsa_context *rsa, unsigned char *buf, int buflen )
-{
-    unsigned char *p, *end;
-    int ret, len;
-
-    p = buf;
-    end = buf+buflen;
-
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) {
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
-    }
-
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) == 0 ) {
-        /* Skip over embedded rsaEncryption Object */
-        p+=len;
-
-        /* The RSAPublicKey ASN1 container is wrapped in a BIT STRING */
-        if( ( ret = asn1_get_tag( &p, end, &len,
-                ASN1_BIT_STRING ) ) != 0 ) {
-            return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
-        }
-
-        /* Limit range to that BIT STRING */
-        end = p + len;
-        p++;
-
-        if( ( ret = asn1_get_tag( &p, end, &len,
-                ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) {
-            return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
-        }
-    }
-
-    if ( ( ( ret = asn1_get_mpi( &p, end, &(rsa->N)  ) ) == 0 ) &&
-         ( ( ret = asn1_get_mpi( &p, end, &(rsa->E)  ) ) == 0 ) ) {
-        rsa->len = mpi_size( &rsa->N );
-        return 0;
-    }
-
-    return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
-}
-
-/*
- * Parse a private RSA key
- */
-int rsa_parse_key( rsa_context *rsa, unsigned char *buf, int buflen,
-                                     unsigned char *pwd, int pwdlen )
-{
-    int ret, len, enc;
-    unsigned char *s1, *s2;
-    unsigned char *p, *end;
-
-    s1 = (unsigned char *) strstr( (char *) buf,
-        "-----BEGIN RSA PRIVATE KEY-----" );
-
-    if( s1 != NULL )
-    {
-        s2 = (unsigned char *) strstr( (char *) buf,
-            "-----END RSA PRIVATE KEY-----" );
-
-        if( s2 == NULL || s2 <= s1 )
-            return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
-
-        s1 += 31;
-        if( *s1 == '\r' ) s1++;
-        if( *s1 == '\n' ) s1++;
-            else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
-
-        enc = 0;
-
-        if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
-        {
-            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-        }
-
-        len = 0;
-       {
-       extern unsigned char * string_copyn(const unsigned char *, int);
-       extern int b64decode(unsigned char *, unsigned char **);
-#define POLARSSL_ERR_BASE64_INVALID_CHARACTER              0x0012
-
-       s1 = string_copyn(s1, s2-s1); /* need nul-terminated string */
-       if ((len = b64decode(s1, &buf)) < 0)
-            return POLARSSL_ERR_BASE64_INVALID_CHARACTER
-               | POLARSSL_ERR_X509_KEY_INVALID_PEM;
-       }
-
-        buflen = len;
-
-        if( enc != 0 )
-        {
-            return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
-        }
-    }
-
-    memset( rsa, 0, sizeof( rsa_context ) );
-
-    p = buf;
-    end = buf + buflen;
-
-    /*
-     *  RSAPrivateKey ::= SEQUENCE {
-     *      version           Version,
-     *      modulus           INTEGER,  -- n
-     *      publicExponent    INTEGER,  -- e
-     *      privateExponent   INTEGER,  -- d
-     *      prime1            INTEGER,  -- p
-     *      prime2            INTEGER,  -- q
-     *      exponent1         INTEGER,  -- d mod (p-1)
-     *      exponent2         INTEGER,  -- d mod (q-1)
-     *      coefficient       INTEGER,  -- (inverse of q) mod p
-     *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
-     *  }
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-        rsa_free( rsa );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
-    }
-
-    end = p + len;
-
-    if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
-    {
-        rsa_free( rsa );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
-    }
-
-    if( rsa->ver != 0 )
-    {
-        rsa_free( rsa );
-        return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
-    }
-
-    if( ( ret = asn1_get_mpi( &p, end, &rsa->N  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->E  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->D  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->P  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->Q  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
-    {
-        rsa_free( rsa );
-        return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
-    }
-
-    rsa->len = mpi_size( &rsa->N );
-
-    if( p != end )
-    {
-        rsa_free( rsa );
-        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-    }
-
-    if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
-    {
-        rsa_free( rsa );
-        return( ret );
-    }
-
-    return( 0 );
-}
diff --git a/src/src/pdkim/pdkim-rsa.h b/src/src/pdkim/pdkim-rsa.h
deleted file mode 100644 (file)
index 1ef8787..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "polarssl/part-x509.h"
-#include "polarssl/rsa.h"
-
-/* PDKIM declarations (not part of polarssl) */
-int rsa_parse_public_key( rsa_context *rsa, unsigned char *buf, int buflen );
-int rsa_parse_key( rsa_context *rsa, unsigned char *buf, int buflen,
-                                     unsigned char *pwd, int pwdlen );
-
index a099f94b00d61c66e989f2e0a859367e8c2666f2..2d5f621b4da6c9ba16dc97d01741bc68eb6ef604 100644 (file)
@@ -1,7 +1,8 @@
 /*
  *  PDKIM - a RFC4871 (DKIM) implementation
  *
- *  Copyright (C) 2009 - 2015  Tom Kistner <tom@duncanthrax.net>
+ *  Copyright (C) 2009 - 2016  Tom Kistner <tom@duncanthrax.net>
+ *  Copyright (C) 2016  Jeremy Harris <jgh@exim.org>
  *
  *  http://duncanthrax.net/pdkim/
  *
  */
 
 #include "../exim.h"
-#include "pdkim.h"
-#include "pdkim-rsa.h"
 
-#include "polarssl/sha1.h"
-#include "polarssl/sha2.h"
-#include "polarssl/rsa.h"
+
+#ifndef DISABLE_DKIM   /* entire file */
+
+#ifndef SUPPORT_TLS
+# error Need SUPPORT_TLS for DKIM
+#endif
+
+#include "crypt_ver.h"
+
+#ifdef RSA_OPENSSL
+# include <openssl/rsa.h>
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#elif defined(RSA_GNUTLS)
+# include <gnutls/gnutls.h>
+# include <gnutls/x509.h>
+#endif
+
+#include "pdkim.h"
+#include "rsa.h"
 
 #define PDKIM_SIGNATURE_VERSION     "1"
 #define PDKIM_PUB_RECORD_VERSION    "DKIM1"
@@ -89,6 +105,7 @@ typedef struct pdkim_combined_canon_entry {
   int canon_headers;
   int canon_body;
 } pdkim_combined_canon_entry;
+
 pdkim_combined_canon_entry pdkim_combined_canons[] = {
   { "simple/simple",    PDKIM_CANON_SIMPLE,   PDKIM_CANON_SIMPLE },
   { "simple/relaxed",   PDKIM_CANON_SIMPLE,   PDKIM_CANON_RELAXED },
@@ -100,7 +117,11 @@ pdkim_combined_canon_entry pdkim_combined_canons[] = {
 };
 
 
-const char *pdkim_verify_status_str(int status) {
+/* -------------------------------------------------------------------------- */
+
+const char *
+pdkim_verify_status_str(int status)
+{
   switch(status) {
     case PDKIM_VERIFY_NONE:    return "PDKIM_VERIFY_NONE";
     case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
@@ -109,13 +130,17 @@ const char *pdkim_verify_status_str(int status) {
     default:                   return "PDKIM_VERIFY_UNKNOWN";
   }
 }
-const char *pdkim_verify_ext_status_str(int ext_status) {
+
+const char *
+pdkim_verify_ext_status_str(int ext_status)
+{
   switch(ext_status) {
     case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
     case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
     case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
     case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
-    case PDKIM_VERIFY_INVALID_PUBKEY_PARSING: return "PDKIM_VERIFY_INVALID_PUBKEY_PARSING";
+    case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
+    case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
     default: return "PDKIM_VERIFY_UNKNOWN";
   }
 }
@@ -123,8 +148,8 @@ const char *pdkim_verify_ext_status_str(int ext_status) {
 
 /* -------------------------------------------------------------------------- */
 /* Print debugging functions */
-void
-pdkim_quoteprint(const char *data, int len, int lf)
+static void
+pdkim_quoteprint(const char *data, int len)
 {
 int i;
 const unsigned char *p = (const unsigned char *)data;
@@ -148,27 +173,26 @@ for (i = 0; i < len; i++)
       break;
     }
   }
-if (lf)
-  debug_printf("\n");
+debug_printf("\n");
 }
 
-void
-pdkim_hexprint(const char *data, int len, int lf)
+static void
+pdkim_hexprint(const char *data, int len)
 {
 int i;
 const unsigned char *p = (const unsigned char *)data;
 
 for (i = 0 ; i < len; i++)
   debug_printf("%02x", p[i]);
-if (lf)
-  debug_printf("\n");
+debug_printf("\n");
 }
 
 
-/* -------------------------------------------------------------------------- */
-/* Simple string list implementation for convinience */
-pdkim_stringlist *
-pdkim_append_stringlist(pdkim_stringlist *base, char *str)
+
+/* String package: should be replaced by Exim standard ones */
+
+static pdkim_stringlist *
+pdkim_prepend_stringlist(pdkim_stringlist *base, char *str)
 {
 pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
 
@@ -186,24 +210,11 @@ else
   return new_entry;
 }
 
-pdkim_stringlist *
-pdkim_prepend_stringlist(pdkim_stringlist *base, char *str)
-{
-pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
-
-if (!new_entry) return NULL;
-memset(new_entry, 0, sizeof(pdkim_stringlist));
-if (!(new_entry->value = strdup(str))) return NULL;
-if (base)
-  new_entry->next = base;
-return new_entry;
-}
-
 
 /* -------------------------------------------------------------------------- */
 /* A small "growing string" implementation to escape malloc/realloc hell */
 
-pdkim_str *
+static pdkim_str *
 pdkim_strnew (const char *cstr)
 {
 unsigned int len = cstr ? strlen(cstr) : 0;
@@ -225,7 +236,7 @@ else
 return p;
 }
 
-char *
+static char *
 pdkim_strncat(pdkim_str *str, const char *data, int len)
 {
 if ((str->allocated - str->len) < (len+1))
@@ -244,21 +255,13 @@ str->str[str->len] = '\0';
 return str->str;
 }
 
-char *
+static char *
 pdkim_strcat(pdkim_str *str, const char *cstr)
 {
 return pdkim_strncat(str, cstr, strlen(cstr));
 }
 
-char *
-pdkim_numcat(pdkim_str *str, unsigned long num)
-{
-char minibuf[20];
-snprintf(minibuf, 20, "%lu", num);
-return pdkim_strcat(str, minibuf);
-}
-
-char *
+static char *
 pdkim_strtrim(pdkim_str *str)
 {
 char *p = str->str;
@@ -275,7 +278,7 @@ str->len = strlen(str->str);
 return str->str;
 }
 
-char *
+static char *
 pdkim_strclear(pdkim_str *str)
 {
 str->str[0] = '\0';
@@ -283,7 +286,7 @@ str->len = 0;
 return str->str;
 }
 
-void
+static void
 pdkim_strfree(pdkim_str *str)
 {
 if (!str) return;
@@ -295,7 +298,7 @@ free(str);
 
 /* -------------------------------------------------------------------------- */
 
-void
+static void
 pdkim_free_pubkey(pdkim_pubkey *pub)
 {
 if (pub)
@@ -306,7 +309,6 @@ if (pub)
   if (pub->keytype    ) free(pub->keytype);
   if (pub->srvtype    ) free(pub->srvtype);
   if (pub->notes      ) free(pub->notes);
-/*  if (pub->key        ) free(pub->key); */
   free(pub);
   }
 }
@@ -314,7 +316,7 @@ if (pub)
 
 /* -------------------------------------------------------------------------- */
 
-void
+static void
 pdkim_free_sig(pdkim_signature *sig)
 {
 if (sig)
@@ -330,18 +332,13 @@ if (sig)
     free(c);
     }
 
-/*  if (sig->sigdata         ) free(sig->sigdata); */
-/*  if (sig->bodyhash        ) free(sig->bodyhash); */
   if (sig->selector        ) free(sig->selector);
   if (sig->domain          ) free(sig->domain);
   if (sig->identity        ) free(sig->identity);
-  if (sig->headernames     ) free(sig->headernames);
   if (sig->copiedheaders   ) free(sig->copiedheaders);
   if (sig->rsa_privkey     ) free(sig->rsa_privkey);
   if (sig->sign_headers    ) free(sig->sign_headers);
   if (sig->signature_header) free(sig->signature_header);
-  if (sig->sha1_body       ) free(sig->sha1_body);
-  if (sig->sha2_body       ) free(sig->sha2_body);
 
   if (sig->pubkey) pdkim_free_pubkey(sig->pubkey);
 
@@ -379,7 +376,7 @@ if (ctx)
    "start". Returns the position of the header name in
    the list. */
 
-int
+static int
 header_name_match(const char *header,
                       char       *tick,
                       int         do_tick)
@@ -442,7 +439,7 @@ return rc;
 /* Performs "relaxed" canonicalization of a header. The returned pointer needs
    to be free()d. */
 
-char *
+static char *
 pdkim_relax_header (char *header, int crlf)
 {
 BOOL past_field_name = FALSE;
@@ -518,7 +515,7 @@ return initial_pos;
 
 /* -------------------------------------------------------------------------- */
 
-char *
+static char *
 pdkim_decode_qp(char *str)
 {
 int nchar = 0;
@@ -552,37 +549,26 @@ return n;
 
 /* -------------------------------------------------------------------------- */
 
-char *
-pdkim_decode_base64(char *str, int *num_decoded)
+static void
+pdkim_decode_base64(uschar *str, blob * b)
 {
-int dlen = 0;
+int dlen;
 char *res;
-int old_pool = store_pool;
-
-/* There is a store-reset between header & body reception
-so cannot use the main pool */
-
-store_pool = POOL_PERM;
-dlen = b64decode(US str, USS &res);
-store_pool = old_pool;
-
-if (dlen < 0) return NULL;
-
-if (num_decoded) *num_decoded = dlen;
-return res;
+dlen = b64decode(str, &b->data);
+if (dlen < 0) b->data = NULL;
+b->len = dlen;
 }
 
-
 /* -------------------------------------------------------------------------- */
 
-char *
-pdkim_encode_base64(char *str, int num)
+static char *
+pdkim_encode_base64(blob * b)
 {
 char * ret;
 int old_pool = store_pool;
 
 store_pool = POOL_PERM;
-ret = CS b64encode(US str, num);
+ret = CS b64encode(b->data, b->len);
 store_pool = old_pool;
 return ret;
 }
@@ -593,7 +579,7 @@ return ret;
 #define PDKIM_HDR_TAG   1
 #define PDKIM_HDR_VALUE 2
 
-pdkim_signature *
+static pdkim_signature *
 pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr)
 {
 pdkim_signature *sig ;
@@ -604,6 +590,13 @@ BOOL past_hname = FALSE;
 BOOL in_b_val = FALSE;
 int where = PDKIM_HDR_LIMBO;
 int i;
+int old_pool = store_pool;
+
+/* There is a store-reset between header & body reception
+so cannot use the main pool. Any allocs done by Exim
+memory-handling must use the perm pool. */
+
+store_pool = POOL_PERM;
 
 if (!(sig = malloc(sizeof(pdkim_signature)))) return NULL;
 memset(sig, 0, sizeof(pdkim_signature));
@@ -681,11 +674,9 @@ for (p = raw_hdr; ; p++)
          {
          case 'b':
            if (cur_tag->str[1] == 'h')
-             sig->bodyhash = pdkim_decode_base64(cur_val->str,
-                 &sig->bodyhash_len);
+             pdkim_decode_base64(US cur_val->str, &sig->bodyhash);
            else
-             sig->sigdata = pdkim_decode_base64(cur_val->str,
-                 &sig->sigdata_len);
+             pdkim_decode_base64(US cur_val->str, &sig->sigdata);
            break;
          case 'v':
              /* We only support version 1, and that is currently the
@@ -731,7 +722,7 @@ for (p = raw_hdr; ; p++)
          case 'l':
            sig->bodylength = strtol(cur_val->str, NULL, 10); break;
          case 'h':
-           sig->headernames = strdup(cur_val->str); break;
+           sig->headernames = string_copy(cur_val->str); break;
          case 'z':
            sig->copiedheaders = pdkim_decode_qp(cur_val->str); break;
          default:
@@ -756,12 +747,12 @@ NEXT_CHAR:
     *q++ = c;
   }
 
+store_pool = old_pool;
+
 /* Make sure the most important bits are there. */
 if (!(sig->domain      && (*(sig->domain)      != '\0') &&
       sig->selector    && (*(sig->selector)    != '\0') &&
       sig->headernames && (*(sig->headernames) != '\0') &&
-      sig->bodyhash    &&
-      sig->sigdata     &&
       sig->version))
   {
   pdkim_free_sig(sig);
@@ -778,31 +769,21 @@ DEBUG(D_acl)
   {
   debug_printf(
          "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
-  pdkim_quoteprint(sig->rawsig_no_b_val, strlen(sig->rawsig_no_b_val), 1);
+  pdkim_quoteprint(sig->rawsig_no_b_val, strlen(sig->rawsig_no_b_val));
   debug_printf(
-         "PDKIM >> Sig size: %4d bits\n", sig->sigdata_len*8);
+         "PDKIM >> Sig size: %4d bits\n", sig->sigdata.len*8);
   debug_printf(
          "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
   }
 
-if (  !(sig->sha1_body = malloc(sizeof(sha1_context)))
-   || !(sig->sha2_body = malloc(sizeof(sha2_context)))
-   )
-  {
-  pdkim_free_sig(sig);
-  return NULL;
-  }
-
-sha1_starts(sig->sha1_body);
-sha2_starts(sig->sha2_body, 0);
-
+exim_sha_init(&sig->body_hash, sig->algo == PDKIM_ALGO_RSA_SHA1);
 return sig;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
-pdkim_pubkey *
+static pdkim_pubkey *
 pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record)
 {
 pdkim_pubkey *pub;
@@ -876,7 +857,8 @@ for (p = raw_record; ; p++)
          case 'n':
            pub->notes = pdkim_decode_qp(cur_val->str); break;
          case 'p':
-           pub->key = pdkim_decode_base64(cur_val->str, &(pub->key_len)); break;
+           pdkim_decode_base64(US cur_val->str, &pub->key);
+            break;
          case 'k':
            pub->hashes = strdup(cur_val->str); break;
          case 's':
@@ -909,7 +891,7 @@ if (!pub->keytype    ) pub->keytype     = strdup("rsa");
 if (!pub->srvtype    ) pub->srvtype     = strdup("*");
 
 /* p= is required */
-if (pub->key)
+if (pub->key.data)
   return pub;
 
 pdkim_free_pubkey(pub);
@@ -919,7 +901,7 @@ return NULL;
 
 /* -------------------------------------------------------------------------- */
 
-int
+static int
 pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len)
 {
 pdkim_signature *sig = ctx->sig;
@@ -980,13 +962,9 @@ while (sig)
 
   if (canon_len > 0)
     {
-    if (sig->algo == PDKIM_ALGO_RSA_SHA1)
-      sha1_update(sig->sha1_body, (unsigned char *)canon_data, canon_len);
-    else
-      sha2_update(sig->sha2_body, (unsigned char *)canon_data, canon_len);
-
+    exim_sha_update(&sig->body_hash, canon_data, canon_len);
     sig->signed_body_bytes += canon_len;
-    DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len, 1);
+    DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len);
     }
 
   sig = sig->next;
@@ -999,7 +977,7 @@ return PDKIM_OK;
 
 /* -------------------------------------------------------------------------- */
 
-int
+static int
 pdkim_finish_bodyhash(pdkim_ctx *ctx)
 {
 pdkim_signature *sig;
@@ -1007,27 +985,22 @@ pdkim_signature *sig;
 /* Traverse all signatures */
 for (sig = ctx->sig; sig; sig = sig->next)
   {                                    /* Finish hashes */
-  unsigned char bh[32]; /* SHA-256 = 32 Bytes,  SHA-1 = 20 Bytes */
+  blob bh;
 
-  if (sig->algo == PDKIM_ALGO_RSA_SHA1)
-    sha1_finish(sig->sha1_body, bh);
-  else
-    sha2_finish(sig->sha2_body, bh);
+  exim_sha_finish(&sig->body_hash, &bh);
 
   DEBUG(D_acl)
     {
     debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
                 "PDKIM [%s] bh  computed: ",
                sig->domain, sig->signed_body_bytes, sig->domain);
-    pdkim_hexprint((char *)bh, sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32, 1);
+    pdkim_hexprint(CS bh.data, bh.len);
     }
 
   /* SIGNING -------------------------------------------------------------- */
   if (ctx->mode == PDKIM_MODE_SIGN)
     {
-    sig->bodyhash_len = (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32;
-
-    sig->bodyhash = string_copyn(US bh, sig->bodyhash_len);
+    sig->bodyhash = bh;
 
     /* If bodylength limit is set, and we have received less bytes
        than the requested amount, effectively remove the limit tag. */
@@ -1039,8 +1012,7 @@ for (sig = ctx->sig; sig; sig = sig->next)
   else
     {
     /* Compare bodyhash */
-    if (memcmp(bh, sig->bodyhash,
-              (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32) == 0)
+    if (memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
       {
       DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
       }
@@ -1049,8 +1021,8 @@ for (sig = ctx->sig; sig; sig = sig->next)
       DEBUG(D_acl)
         {
        debug_printf("PDKIM [%s] bh signature: ", sig->domain);
-       pdkim_hexprint(sig->bodyhash,
-                        sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32, 1);
+       pdkim_hexprint(sig->bodyhash.data,
+                        exim_sha_hashlen(&sig->body_hash));
        debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
        }
       sig->verify_status     = PDKIM_VERIFY_FAIL;
@@ -1148,7 +1120,7 @@ return PDKIM_OK;
 /* Callback from pdkim_feed below for processing complete headers */
 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
 
-int
+static int
 pdkim_header_complete(pdkim_ctx *ctx)
 {
 /* Special case: The last header can have an extra \r appended */
@@ -1318,7 +1290,7 @@ return PDKIM_OK;
  * "pad"
  *
  * no guarantees are made for output given out-of range input. like tag
- * names loinger than 78, or bogus col. Input is assumed to be free of line breaks.
+ * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
  */
 
 static char *
@@ -1424,8 +1396,8 @@ return str->str;
 
 /* -------------------------------------------------------------------------- */
 
-char *
-pdkim_create_header(pdkim_signature *sig, int final)
+static char *
+pdkim_create_header(pdkim_signature *sig, BOOL final)
 {
 char *rc = NULL;
 char *base64_bh = NULL;
@@ -1440,7 +1412,7 @@ if (!(hdr = pdkim_strnew("DKIM-Signature: v="PDKIM_SIGNATURE_VERSION)))
 if (!(canon_all = pdkim_strnew(pdkim_canons[sig->canon_headers])))
   goto BAIL;
 
-if (!(base64_bh = pdkim_encode_base64(sig->bodyhash, sig->bodyhash_len)))
+if (!(base64_bh = pdkim_encode_base64(&sig->bodyhash)))
   goto BAIL;
 
 col = strlen(hdr->str);
@@ -1455,9 +1427,9 @@ if (  pdkim_headcat(&col, hdr, ";", "a=", pdkim_algos[sig->algo])
    && pdkim_headcat(&col, hdr, ";", "s=", sig->selector)
    )
   {
-  /* list of eader names can be split between items. */
+  /* list of header names can be split between items. */
     {
-    char *n = strdup(sig->headernames);
+    char *n = CS string_copy(sig->headernames);
     char *f = n;
     char *i = "h=";
     char *s = ";";
@@ -1471,16 +1443,10 @@ if (  pdkim_headcat(&col, hdr, ";", "a=", pdkim_algos[sig->algo])
 
       if (!i)
        if (!pdkim_headcat(&col, hdr, NULL, NULL, ":"))
-         {
-         free(f);
          goto BAIL;
-         }
 
       if (!pdkim_headcat(&col, hdr, s, i, n))
-       {
-       free(f);
        goto BAIL;
-       }
 
       if (!c)
         break;
@@ -1489,7 +1455,6 @@ if (  pdkim_headcat(&col, hdr, ";", "a=", pdkim_algos[sig->algo])
       s = NULL;
       i = NULL;
       }
-    free(f);
     }
 
   if(!pdkim_headcat(&col, hdr, ";", "bh=", base64_bh))
@@ -1507,7 +1472,7 @@ if (  pdkim_headcat(&col, hdr, ";", "a=", pdkim_algos[sig->algo])
     snprintf(minibuf, 20, "%lu", sig->created);
     if(!pdkim_headcat(&col, hdr, ";", "t=", minibuf))
       goto BAIL;
-  }
+    }
 
   if (sig->expires > 0)
     {
@@ -1530,11 +1495,11 @@ if (  pdkim_headcat(&col, hdr, ";", "a=", pdkim_algos[sig->algo])
   /* Preliminary or final version? */
   if (final)
     {
-    if (!(base64_b = pdkim_encode_base64(sig->sigdata, sig->sigdata_len)))
+    if (!(base64_b = pdkim_encode_base64(&sig->sigdata)))
       goto BAIL;
     if (!pdkim_headcat(&col, hdr, ";", "b=", base64_b))
       goto BAIL;
-  }
+    }
   else 
     if(!pdkim_headcat(&col, hdr, ";", "b=", ""))
       goto BAIL;
@@ -1543,9 +1508,6 @@ if (  pdkim_headcat(&col, hdr, ";", "a=", pdkim_algos[sig->algo])
   if (!pdkim_headcat(&col, hdr, NULL, ";", ""))
     goto BAIL;
   }
-  else 
-    if(!pdkim_headcat(&col, hdr, ";", "b=", ""))
-      goto BAIL;
 
 rc = strdup(hdr->str);
 
@@ -1589,15 +1551,17 @@ if (ctx->mode == PDKIM_MODE_SIGN)
 
 while (sig)
   {
-  sha1_context sha1_headers;
-  sha2_context sha2_headers;
-  char *sig_hdr;
-  char headerhash[32];
+  BOOL is_sha1 = sig->algo == PDKIM_ALGO_RSA_SHA1;
+  hctx hhash_ctx;
+  char * sig_hdr;
+  blob hhash;
+  blob hdata;
+  int hdata_alloc = 0;
 
-  if (sig->algo == PDKIM_ALGO_RSA_SHA1)
-    sha1_starts(&sha1_headers);
-  else
-    sha2_starts(&sha2_headers, 0);
+  hdata.data = NULL;
+  hdata.len = 0;
+
+  exim_sha_init(&hhash_ctx, is_sha1);
 
   DEBUG(D_acl) debug_printf(
       "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
@@ -1612,28 +1576,27 @@ while (sig)
 
     for (p = sig->headers; p; p = p->next)
       {
-      char *rh = NULL;
+      uschar * rh;
       /* Collect header names (Note: colon presence is guaranteed here) */
-      char *q = strchr(p->value, ':');
+      uschar * q = Ustrchr(p->value, ':');
 
       if (!(pdkim_strncat(headernames, p->value,
-                       (q-(p->value)) + (p->next ? 1 : 0))))
+                       (q-US (p->value)) + (p->next ? 1 : 0))))
        return PDKIM_ERR_OOM;
 
       rh = sig->canon_headers == PDKIM_CANON_RELAXED
-       ? pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */
-       : strdup(p->value);              /* just copy it for simple canon */
+       ? US pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */
+       : string_copy(p->value);             /* just copy it for simple canon */
       if (!rh)
        return PDKIM_ERR_OOM;
 
       /* Feed header to the hash algorithm */
-      if (sig->algo == PDKIM_ALGO_RSA_SHA1)
-       sha1_update(&(sha1_headers), (unsigned char *)rh, strlen(rh));
-      else
-       sha2_update(&(sha2_headers), (unsigned char *)rh, strlen(rh));
+      exim_sha_update(&hhash_ctx, rh, strlen(rh));
+
+      /* Remember headers block for signing (when the library cannot do incremental)  */
+      (void) exim_rsa_data_append(&hdata, &hdata_alloc, rh);
 
-      DEBUG(D_acl) pdkim_quoteprint(rh, strlen(rh), 1);
-      free(rh);
+      DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
       }
     }
 
@@ -1642,10 +1605,10 @@ while (sig)
      add the headers to the hash in that order. */
   else
     {
-    char *b = strdup(sig->headernames);
-    char *p = b;
-    char *q = NULL;
-    pdkim_stringlist *hdrs;
+    uschar * b = string_copy(sig->headernames);
+    uschar * p = b;
+    uschar * q;
+    pdkim_stringlist * hdrs;
 
     if (!b) return PDKIM_ERR_OOM;
 
@@ -1655,31 +1618,25 @@ while (sig)
 
     while(1)
       {
-      if ((q = strchr(p, ':')))
+      if ((q = Ustrchr(p, ':')))
        *q = '\0';
 
       for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
        if (  hdrs->tag == 0
-          && strncasecmp(hdrs->value, p, strlen(p)) == 0
-          && (hdrs->value)[strlen(p)] == ':'
+          && strncasecmp(hdrs->value, CS p, Ustrlen(p)) == 0
+          && (hdrs->value)[Ustrlen(p)] == ':'
           )
          {
-         char *rh;
-
-         rh = sig->canon_headers == PDKIM_CANON_RELAXED
-           ? pdkim_relax_header(hdrs->value, 1) /* cook header for relaxed canon */
-           : strdup(hdrs->value);               /* just copy it for simple canon */
+         uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
+           ? US pdkim_relax_header(hdrs->value, 1) /* cook header for relaxed canon */
+           : string_copy(hdrs->value);             /* just copy it for simple canon */
          if (!rh)
            return PDKIM_ERR_OOM;
 
          /* Feed header to the hash algorithm */
-         if (sig->algo == PDKIM_ALGO_RSA_SHA1)
-           sha1_update(&sha1_headers, (unsigned char *)rh, strlen(rh));
-         else
-           sha2_update(&sha2_headers, (unsigned char *)rh, strlen(rh));
+         exim_sha_update(&hhash_ctx, rh, strlen(rh));
 
-         DEBUG(D_acl) pdkim_quoteprint(rh, strlen(rh), 1);
-         free(rh);
+         DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
          hdrs->tag = 1;
          break;
          }
@@ -1687,7 +1644,6 @@ while (sig)
       if (!q) break;
       p = q+1;
       }
-    free(b);
     }
 
   DEBUG(D_acl) debug_printf(
@@ -1697,11 +1653,11 @@ while (sig)
   if (ctx->mode == PDKIM_MODE_SIGN)
     {
     /* Copy headernames to signature struct */
-    sig->headernames = strdup(headernames->str);
+    sig->headernames = string_copy(US headernames->str);
     pdkim_strfree(headernames);
 
     /* Create signature header with b= omitted */
-    sig_hdr = pdkim_create_header(ctx->sig, 0);
+    sig_hdr = pdkim_create_header(ctx->sig, FALSE);
     }
 
   /* VERIFICATION ----------------------------------------------------------- */
@@ -1727,79 +1683,73 @@ while (sig)
     {
     debug_printf(
            "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
-    pdkim_quoteprint(sig_hdr, strlen(sig_hdr), 1);
+    pdkim_quoteprint(sig_hdr, strlen(sig_hdr));
     debug_printf(
            "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
     }
 
   /* Finalize header hash */
-  if (sig->algo == PDKIM_ALGO_RSA_SHA1)
-    {
-    sha1_update(&sha1_headers, (unsigned char *)sig_hdr, strlen(sig_hdr));
-    sha1_finish(&sha1_headers, (unsigned char *)headerhash);
+  exim_sha_update(&hhash_ctx, sig_hdr, strlen(sig_hdr));
+  exim_sha_finish(&hhash_ctx, &hhash);
 
-    DEBUG(D_acl)
-      {
-      debug_printf( "PDKIM [%s] hh computed: ", sig->domain);
-      pdkim_hexprint(headerhash, 20, 1);
-      }
-    }
-  else
+  DEBUG(D_acl)
     {
-    sha2_update(&sha2_headers, (unsigned char *)sig_hdr, strlen(sig_hdr));
-    sha2_finish(&sha2_headers, (unsigned char *)headerhash);
-
-    DEBUG(D_acl)
-      {
-      debug_printf("PDKIM [%s] hh computed: ", sig->domain);
-      pdkim_hexprint(headerhash, 32, 1);
-      }
+    debug_printf("PDKIM [%s] hh computed: ", sig->domain);
+    pdkim_hexprint(hhash.data, hhash.len);
     }
 
+  /* Remember headers block for signing (when the library cannot do incremental)  */
+  if (ctx->mode == PDKIM_MODE_SIGN)
+    (void) exim_rsa_data_append(&hdata, &hdata_alloc, sig_hdr);
+
   free(sig_hdr);
 
   /* SIGNING ---------------------------------------------------------------- */
   if (ctx->mode == PDKIM_MODE_SIGN)
     {
-    rsa_context rsa;
-
-    rsa_init(&rsa, RSA_PKCS_V15, 0);
+    es_ctx sctx;
+    const uschar * errstr;
 
-    /* Perform private key operation */
-    if (rsa_parse_key(&rsa, (unsigned char *)sig->rsa_privkey,
-                     strlen(sig->rsa_privkey), NULL, 0) != 0)
+    /* Import private key */
+    if ((errstr = exim_rsa_signing_init(sig->rsa_privkey, &sctx)))
+      {
+      DEBUG(D_acl) debug_printf("signing_init: %s\n", errstr);
       return PDKIM_ERR_RSA_PRIVKEY;
+      }
 
-    sig->sigdata_len = mpi_size(&(rsa.N));
-    sig->sigdata = store_get(sig->sigdata_len);
+    /* Do signing.  With OpenSSL we are signing the hash of headers just
+    calculated, with GnuTLS we have to sign an entire block of headers
+    (due to available interfaces) and it recalculates the hash internally. */
 
-    if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
-                       ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
-                          SIG_RSA_SHA1:SIG_RSA_SHA256),
-                       0,
-                       (unsigned char *)headerhash,
-                       (unsigned char *)sig->sigdata ) != 0)
-      return PDKIM_ERR_RSA_SIGNING;
+#if defined(RSA_OPENSSL) || defined(RSA_GCRYPT)
+    hdata = hhash;
+#endif
 
-    rsa_free(&rsa);
+    if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sigdata)))
+      {
+      DEBUG(D_acl) debug_printf("signing: %s\n", errstr);
+      return PDKIM_ERR_RSA_SIGNING;
+      }
 
     DEBUG(D_acl)
       {
       debug_printf( "PDKIM [%s] b computed: ", sig->domain);
-      pdkim_hexprint(sig->sigdata, sig->sigdata_len, 1);
+      pdkim_hexprint(sig->sigdata.data, sig->sigdata.len);
       }
 
-    if (!(sig->signature_header = pdkim_create_header(ctx->sig, 1)))
+    if (!(sig->signature_header = pdkim_create_header(ctx->sig, TRUE)))
       return PDKIM_ERR_OOM;
     }
 
   /* VERIFICATION ----------------------------------------------------------- */
   else
     {
-    rsa_context rsa;
+    ev_ctx vctx;
+    const uschar * errstr;
+
     char *dns_txt_name, *dns_txt_reply;
 
-    rsa_init(&rsa, RSA_PKCS_V15, 0);
+    /* Fetch public key for signing domain, from DNS */
 
     if (!(dns_txt_name  = malloc(PDKIM_DNS_TXT_MAX_NAMELEN)))
       return PDKIM_ERR_OOM;
@@ -1833,15 +1783,15 @@ while (sig)
     DEBUG(D_acl)
       {
       debug_printf(
-             "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
-             " Raw record: ");
-      pdkim_quoteprint(dns_txt_reply, strlen(dns_txt_reply), 1);
+          "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
+          " Raw record: ");
+      pdkim_quoteprint(dns_txt_reply, strlen(dns_txt_reply));
       }
 
     if (!(sig->pubkey = pdkim_parse_pubkey_record(ctx, dns_txt_reply)))
       {
       sig->verify_status =      PDKIM_VERIFY_INVALID;
-      sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
+      sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
 
       DEBUG(D_acl) debug_printf(
          " Error while parsing public key record\n"
@@ -1850,31 +1800,27 @@ while (sig)
       }
 
     DEBUG(D_acl) debug_printf(
-       "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+         "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
 
-    if (rsa_parse_public_key(&rsa,
-                           (unsigned char *)sig->pubkey->key,
-                            sig->pubkey->key_len) != 0)
+    /* Import public key */
+    if ((errstr = exim_rsa_verify_init(&sig->pubkey->key, &vctx)))
       {
+      DEBUG(D_acl) debug_printf("verify_init: %s\n", errstr);
       sig->verify_status =      PDKIM_VERIFY_INVALID;
-      sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
+      sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
       goto NEXT_VERIFY;
       }
 
     /* Check the signature */
-    if (rsa_pkcs1_verify(&rsa,
-                     RSA_PUBLIC,
-                     ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
-                          SIG_RSA_SHA1:SIG_RSA_SHA256),
-                     0,
-                     (unsigned char *)headerhash,
-                     (unsigned char *)sig->sigdata) != 0)
+    if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sigdata)))
       {
+      DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr);
       sig->verify_status =      PDKIM_VERIFY_FAIL;
       sig->verify_ext_status =  PDKIM_VERIFY_FAIL_MESSAGE;
       goto NEXT_VERIFY;
       }
 
+
     /* We have a winner! (if bodydhash was correct earlier) */
     if (sig->verify_status == PDKIM_VERIFY_NONE)
       sig->verify_status = PDKIM_VERIFY_PASS;
@@ -1892,7 +1838,6 @@ NEXT_VERIFY:
        debug_printf("\n");
       }
 
-    rsa_free(&rsa);
     free(dns_txt_name);
     free(dns_txt_reply);
     }
@@ -1935,7 +1880,7 @@ return ctx;
 /* -------------------------------------------------------------------------- */
 
 DLLEXPORT pdkim_ctx *
-pdkim_init_sign(char *domain, char *selector, char *rsa_privkey)
+pdkim_init_sign(char *domain, char *selector, char *rsa_privkey, int algo)
 {
 pdkim_ctx *ctx;
 pdkim_signature *sig;
@@ -1966,21 +1911,15 @@ sig->bodylength = -1;
 ctx->mode = PDKIM_MODE_SIGN;
 ctx->sig = sig;
 
-ctx->sig->domain = strdup(domain);
-ctx->sig->selector = strdup(selector);
-ctx->sig->rsa_privkey = strdup(rsa_privkey);
-
-if (!ctx->sig->domain || !ctx->sig->selector || !ctx->sig->rsa_privkey)
-  goto BAIL;
-
-if (!(ctx->sig->sha1_body = malloc(sizeof(sha1_context))))
-  goto BAIL;
-sha1_starts(ctx->sig->sha1_body);
+sig->domain = strdup(domain);
+sig->selector = strdup(selector);
+sig->rsa_privkey = strdup(rsa_privkey);
+sig->algo = algo;
 
-if (!(ctx->sig->sha2_body = malloc(sizeof(sha2_context))))
+if (!sig->domain || !sig->selector || !sig->rsa_privkey)
   goto BAIL;
-sha2_starts(ctx->sig->sha2_body, 0);
 
+exim_sha_init(&sig->body_hash, algo == PDKIM_ALGO_RSA_SHA1);
 return ctx;
 
 BAIL:
@@ -1988,6 +1927,7 @@ BAIL:
   return NULL;
 }
 
+
 /* -------------------------------------------------------------------------- */
 
 DLLEXPORT int
@@ -1997,11 +1937,9 @@ pdkim_set_optional(pdkim_ctx *ctx,
                        int canon_headers,
                        int canon_body,
                        long bodylength,
-                       int algo,
                        unsigned long created,
                        unsigned long expires)
 {
-
 if (identity)
   if (!(ctx->sig->identity = strdup(identity)))
     return PDKIM_ERR_OOM;
@@ -2013,7 +1951,6 @@ if (sign_headers)
 ctx->sig->canon_headers = canon_headers;
 ctx->sig->canon_body = canon_body;
 ctx->sig->bodylength = bodylength;
-ctx->sig->algo = algo;
 ctx->sig->created = created;
 ctx->sig->expires = expires;
 
@@ -2021,3 +1958,12 @@ return PDKIM_OK;
 }
 
 
+void
+pdkim_init(void)
+{
+exim_rsa_init();
+}
+
+
+
+#endif /*DISABLE_DKIM*/
index 4a7498db917a88aeb95546dc1c61d02e20ef851f..4de0a7ad60bd615a7dad7315dc8c5cef37ec0a0d 100644 (file)
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+#ifndef PDKIM_H
+#define PDKIM_H
+
+#include "blob.h"
+#include "hash.h"
 
 /* -------------------------------------------------------------------------- */
 /* Length of the preallocated buffer for the "answer" from the dns/txt
@@ -34,6 +39,8 @@
 #define PDKIM_ERR_RSA_SIGNING      -102
 #define PDKIM_ERR_LONG_LINE        -103
 #define PDKIM_ERR_BUFFER_TOO_SMALL -104
+#define PDKIM_SIGN_PRIVKEY_WRAP    -105
+#define PDKIM_SIGN_PRIVKEY_B64D    -106
 
 /* -------------------------------------------------------------------------- */
 /* Main/Extended verification status */
@@ -46,7 +53,8 @@
 #define PDKIM_VERIFY_FAIL_MESSAGE               2
 #define PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE 3
 #define PDKIM_VERIFY_INVALID_BUFFER_SIZE        4
-#define PDKIM_VERIFY_INVALID_PUBKEY_PARSING     5
+#define PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD   5
+#define PDKIM_VERIFY_INVALID_PUBKEY_IMPORT      6
 
 /* -------------------------------------------------------------------------- */
 /* Some parameter values */
@@ -95,8 +103,7 @@ typedef struct pdkim_pubkey {
   char *srvtype;                  /* s=  */
   char *notes;                    /* n=  */
 
-  char *key;                      /* p=  */
-  int   key_len;
+  blob  key;                      /* p=  */
 
   int   testing;                  /* t=y */
   int   no_subdomaining;          /* t=s */
@@ -148,18 +155,16 @@ typedef struct pdkim_signature {
 
   /* (h=) Colon-separated list of header names that are included in the
      signature */
-  char *headernames;
+  uschar *headernames;
 
   /* (z=) */
   char *copiedheaders;
 
   /* (b=) Raw signature data, along with its length in bytes */
-  char *sigdata;
-  int   sigdata_len;
+  blob sigdata;
 
   /* (bh=) Raw body hash data, along with its length in bytes */
-  char *bodyhash;
-  int   bodyhash_len;
+  blob bodyhash;
 
   /* Folded DKIM-Signature: header. Singing only, NULL for verifying.
      Ready for insertion into the message. Note: Folded using CRLFTB,
@@ -225,8 +230,8 @@ typedef struct pdkim_signature {
   /* Properties below this point are used internally only ------------- */
 
   /* Per-signature helper variables ----------------------------------- */
-  sha1_context *sha1_body; /* SHA1 block                                */
-  sha2_context *sha2_body; /* SHA256 block                              */
+  hctx         body_hash;
+
   unsigned long signed_body_bytes; /* How many body bytes we hashed     */
   pdkim_stringlist *headers; /* Raw headers included in the sig         */
   /* Signing specific ------------------------------------------------- */
@@ -273,15 +278,17 @@ typedef struct pdkim_ctx {
 extern "C" {
 #endif
 
+void      pdkim_init         (void);
+
 DLLEXPORT
-pdkim_ctx *pdkim_init_sign    (char *, char *, char *);
+pdkim_ctx *pdkim_init_sign    (char *, char *, char *, int);
 
 DLLEXPORT
 pdkim_ctx *pdkim_init_verify  (int(*)(char *, char *));
 
 DLLEXPORT
 int        pdkim_set_optional (pdkim_ctx *, char *, char *,int, int,
-                               long, int,
+                               long,
                                unsigned long,
                                unsigned long);
 
@@ -296,3 +303,5 @@ void       pdkim_free_ctx     (pdkim_ctx *);
 #ifdef __cplusplus
 }
 #endif
+
+#endif
diff --git a/src/src/pdkim/polarssl/bignum.h b/src/src/pdkim/polarssl/bignum.h
deleted file mode 100644 (file)
index 31aa15c..0000000
+++ /dev/null
@@ -1,533 +0,0 @@
-/**
- * \file bignum.h
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_BIGNUM_H
-#define POLARSSL_BIGNUM_H
-
-#include <stdio.h>
-
-#define POLARSSL_ERR_MPI_FILE_IO_ERROR                     0x0002
-#define POLARSSL_ERR_MPI_BAD_INPUT_DATA                    0x0004
-#define POLARSSL_ERR_MPI_INVALID_CHARACTER                 0x0006
-#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL                  0x0008
-#define POLARSSL_ERR_MPI_NEGATIVE_VALUE                    0x000A
-#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO                  0x000C
-#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE                    0x000E
-
-#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup
-
-/*
- * Define the base integer type, architecture-wise
- */
-#if defined(POLARSSL_HAVE_INT8)
-typedef unsigned char  t_int;
-typedef unsigned short t_dbl;
-#else
-#if defined(POLARSSL_HAVE_INT16)
-typedef unsigned short t_int;
-typedef unsigned long  t_dbl;
-#else
-  typedef unsigned long t_int;
-  #if defined(_MSC_VER) && defined(_M_IX86)
-  typedef unsigned __int64 t_dbl;
-  #else
-    #if defined(__amd64__) || defined(__x86_64__)    || \
-        defined(__ppc64__) || defined(__powerpc64__) || \
-        defined(__ia64__)  || defined(__alpha__)
-    typedef unsigned int t_dbl __attribute__((mode(TI)));
-    #else
-      #if defined(POLARSSL_HAVE_LONGLONG)
-      typedef unsigned long long t_dbl;
-      #endif
-    #endif
-  #endif
-#endif
-#endif
-
-/**
- * \brief          MPI structure
- */
-typedef struct
-{
-    int s;              /*!<  integer sign      */
-    int n;              /*!<  total # of limbs  */
-    t_int *p;           /*!<  pointer to limbs  */
-}
-mpi;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief          Initialize one or more mpi
- */
-void mpi_init( mpi *X, ... );
-
-/**
- * \brief          Unallocate one or more mpi
- */
-void mpi_free( mpi *X, ... );
-
-/**
- * \brief          Enlarge to the specified number of limbs
- *
- * \param X        MPI to grow
- * \param nblimbs  The target number of limbs
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_grow( mpi *X, int nblimbs );
-
-/**
- * \brief          Copy the contents of Y into X
- *
- * \param X        Destination MPI
- * \param Y        Source MPI
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_copy( mpi *X, const mpi *Y );
-
-/**
- * \brief          Swap the contents of X and Y
- *
- * \param X        First MPI value
- * \param Y        Second MPI value
- */
-void mpi_swap( mpi *X, mpi *Y );
-
-/**
- * \brief          Set value from integer
- *
- * \param X        MPI to set
- * \param z        Value to use
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_lset( mpi *X, int z );
-
-/**
- * \brief          Return the number of least significant bits
- *
- * \param X        MPI to use
- */
-int mpi_lsb( const mpi *X );
-
-/**
- * \brief          Return the number of most significant bits
- *
- * \param X        MPI to use
- */
-int mpi_msb( const mpi *X );
-
-/**
- * \brief          Return the total size in bytes
- *
- * \param X        MPI to use
- */
-int mpi_size( const mpi *X );
-
-/**
- * \brief          Import from an ASCII string
- *
- * \param X        Destination MPI
- * \param radix    Input numeric base
- * \param s        Null-terminated string buffer
- *
- * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code
- */
-int mpi_read_string( mpi *X, int radix, const char *s );
-
-/**
- * \brief          Export into an ASCII string
- *
- * \param X        Source MPI
- * \param radix    Output numeric base
- * \param s        String buffer
- * \param slen     String buffer size
- *
- * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code.
- *                 *slen is always updated to reflect the amount
- *                 of data that has (or would have) been written.
- *
- * \note           Call this function with *slen = 0 to obtain the
- *                 minimum required buffer size in *slen.
- */
-int mpi_write_string( const mpi *X, int radix, char *s, int *slen );
-
-/**
- * \brief          Read X from an opened file
- *
- * \param X        Destination MPI
- * \param radix    Input numeric base
- * \param fin      Input file handle
- *
- * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code
- */
-int mpi_read_file( mpi *X, int radix, FILE *fin );
-
-/**
- * \brief          Write X into an opened file, or stdout if fout is NULL
- *
- * \param p        Prefix, can be NULL
- * \param X        Source MPI
- * \param radix    Output numeric base
- * \param fout     Output file handle (can be NULL)
- *
- * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code
- *
- * \note           Set fout == NULL to print X on the console.
- */
-int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
-
-/**
- * \brief          Import X from unsigned binary data, big endian
- *
- * \param X        Destination MPI
- * \param buf      Input buffer
- * \param buflen   Input buffer size
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_read_binary( mpi *X, const unsigned char *buf, int buflen );
-
-/**
- * \brief          Export X into unsigned binary data, big endian
- *
- * \param X        Source MPI
- * \param buf      Output buffer
- * \param buflen   Output buffer size
- *
- * \return         0 if successful,
- *                 POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
- */
-int mpi_write_binary( const mpi *X, unsigned char *buf, int buflen );
-
-/**
- * \brief          Left-shift: X <<= count
- *
- * \param X        MPI to shift
- * \param count    Amount to shift
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_shift_l( mpi *X, int count );
-
-/**
- * \brief          Right-shift: X >>= count
- *
- * \param X        MPI to shift
- * \param count    Amount to shift
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_shift_r( mpi *X, int count );
-
-/**
- * \brief          Compare unsigned values
- *
- * \param X        Left-hand MPI
- * \param Y        Right-hand MPI
- *
- * \return         1 if |X| is greater than |Y|,
- *                -1 if |X| is lesser  than |Y| or
- *                 0 if |X| is equal to |Y|
- */
-int mpi_cmp_abs( const mpi *X, const mpi *Y );
-
-/**
- * \brief          Compare signed values
- *
- * \param X        Left-hand MPI
- * \param Y        Right-hand MPI
- *
- * \return         1 if X is greater than Y,
- *                -1 if X is lesser  than Y or
- *                 0 if X is equal to Y
- */
-int mpi_cmp_mpi( const mpi *X, const mpi *Y );
-
-/**
- * \brief          Compare signed values
- *
- * \param X        Left-hand MPI
- * \param z        The integer value to compare to
- *
- * \return         1 if X is greater than z,
- *                -1 if X is lesser  than z or
- *                 0 if X is equal to z
- */
-int mpi_cmp_int( const mpi *X, int z );
-
-/**
- * \brief          Unsigned addition: X = |A| + |B|
- *
- * \param X        Destination MPI
- * \param A        Left-hand MPI
- * \param B        Right-hand MPI
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_add_abs( mpi *X, const mpi *A, const mpi *B );
-
-/**
- * \brief          Unsigned substraction: X = |A| - |B|
- *
- * \param X        Destination MPI
- * \param A        Left-hand MPI
- * \param B        Right-hand MPI
- *
- * \return         0 if successful,
- *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
- */
-int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B );
-
-/**
- * \brief          Signed addition: X = A + B
- *
- * \param X        Destination MPI
- * \param A        Left-hand MPI
- * \param B        Right-hand MPI
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B );
-
-/**
- * \brief          Signed substraction: X = A - B
- *
- * \param X        Destination MPI
- * \param A        Left-hand MPI
- * \param B        Right-hand MPI
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B );
-
-/**
- * \brief          Signed addition: X = A + b
- *
- * \param X        Destination MPI
- * \param A        Left-hand MPI
- * \param b        The integer value to add
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_add_int( mpi *X, const mpi *A, int b );
-
-/**
- * \brief          Signed substraction: X = A - b
- *
- * \param X        Destination MPI
- * \param A        Left-hand MPI
- * \param b        The integer value to subtract
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_sub_int( mpi *X, const mpi *A, int b );
-
-/**
- * \brief          Baseline multiplication: X = A * B
- *
- * \param X        Destination MPI
- * \param A        Left-hand MPI
- * \param B        Right-hand MPI
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
-
-/**
- * \brief          Baseline multiplication: X = A * b
- *                 Note: b is an unsigned integer type, thus
- *                 Negative values of b are ignored.
- *
- * \param X        Destination MPI
- * \param A        Left-hand MPI
- * \param b        The integer value to multiply with
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_mul_int( mpi *X, const mpi *A, t_int b );
-
-/**
- * \brief          Division by mpi: A = Q * B + R
- *
- * \param Q        Destination MPI for the quotient
- * \param R        Destination MPI for the rest value
- * \param A        Left-hand MPI
- * \param B        Right-hand MPI
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed,
- *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
- *
- * \note           Either Q or R can be NULL.
- */
-int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B );
-
-/**
- * \brief          Division by int: A = Q * b + R
- *
- * \param Q        Destination MPI for the quotient
- * \param R        Destination MPI for the rest value
- * \param A        Left-hand MPI
- * \param b        Integer to divide by
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed,
- *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
- *
- * \note           Either Q or R can be NULL.
- */
-int mpi_div_int( mpi *Q, mpi *R, const mpi *A, int b );
-
-/**
- * \brief          Modulo: R = A mod B
- *
- * \param R        Destination MPI for the rest value
- * \param A        Left-hand MPI
- * \param B        Right-hand MPI
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed,
- *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0,
- *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0
- */
-int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B );
-
-/**
- * \brief          Modulo: r = A mod b
- *
- * \param r        Destination t_int
- * \param A        Left-hand MPI
- * \param b        Integer to divide by
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed,
- *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0,
- *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0
- */
-int mpi_mod_int( t_int *r, const mpi *A, int b );
-
-/**
- * \brief          Sliding-window exponentiation: X = A^E mod N
- *
- * \param X        Destination MPI
- * \param A        Left-hand MPI
- * \param E        Exponent MPI
- * \param N        Modular MPI
- * \param _RR      Speed-up MPI used for recalculations
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed,
- *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even
- *
- * \note           _RR is used to avoid re-computing R*R mod N across
- *                 multiple calls, which speeds up things a bit. It can
- *                 be set to NULL if the extra performance is unneeded.
- */
-int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR );
-
-/**
- * \brief          Greatest common divisor: G = gcd(A, B)
- *
- * \param G        Destination MPI
- * \param A        Left-hand MPI
- * \param B        Right-hand MPI
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed
- */
-int mpi_gcd( mpi *G, const mpi *A, const mpi *B );
-
-/**
- * \brief          Modular inverse: X = A^-1 mod N
- *
- * \param X        Destination MPI
- * \param A        Left-hand MPI
- * \param N        Right-hand MPI
- *
- * \return         0 if successful,
- *                 1 if memory allocation failed,
- *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
-                   POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
- */
-int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N );
-
-/**
- * \brief          Miller-Rabin primality test
- *
- * \param X        MPI to check
- * \param f_rng    RNG function
- * \param p_rng    RNG parameter
- *
- * \return         0 if successful (probably prime),
- *                 1 if memory allocation failed,
- *                 POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
- */
-int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng );
-
-/**
- * \brief          Prime number generation
- *
- * \param X        Destination MPI
- * \param nbits    Required size of X in bits
- * \param dh_flag  If 1, then (X-1)/2 will be prime too
- * \param f_rng    RNG function
- * \param p_rng    RNG parameter
- *
- * \return         0 if successful (probably prime),
- *                 1 if memory allocation failed,
- *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
- */
-int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
-                   int (*f_rng)(void *), void *p_rng );
-
-/**
- * \brief          Checkup routine
- *
- * \return         0 if successful, or 1 if the test failed
- */
-int mpi_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* bignum.h */
diff --git a/src/src/pdkim/polarssl/bn_mul.h b/src/src/pdkim/polarssl/bn_mul.h
deleted file mode 100644 (file)
index 03558b4..0000000
+++ /dev/null
@@ -1,1472 +0,0 @@
-/**
- * \file bn_mul.h
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- *      Multiply source vector [s] with b, add result
- *       to destination vector [d] and set carry c.
- *
- *      Currently supports:
- *
- *         . IA-32 (386+)         . AMD64 / EM64T
- *         . IA-32 (SSE2)         . Motorola 68000
- *         . PowerPC, 32-bit      . MicroBlaze
- *         . PowerPC, 64-bit      . TriCore
- *         . SPARC v8             . ARM v3+
- *         . Alpha                . MIPS32
- *         . C, longlong          . C, generic
- */
-#ifndef POLARSSL_BN_MUL_H
-#define POLARSSL_BN_MUL_H
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_HAVE_ASM)
-
-#if defined(__GNUC__)
-#if defined(__i386__)
-
-#define MULADDC_INIT                \
-    asm( "                          \
-        movl   %%ebx, %0;           \
-        movl   %5, %%esi;           \
-        movl   %6, %%edi;           \
-        movl   %7, %%ecx;           \
-        movl   %8, %%ebx;           \
-        "
-
-#define MULADDC_CORE                \
-        "                           \
-        lodsl;                      \
-        mull   %%ebx;               \
-        addl   %%ecx,   %%eax;      \
-        adcl   $0,      %%edx;      \
-        addl   (%%edi), %%eax;      \
-        adcl   $0,      %%edx;      \
-        movl   %%edx,   %%ecx;      \
-        stosl;                      \
-        "
-
-#if defined(POLARSSL_HAVE_SSE2)
-
-#define MULADDC_HUIT                    \
-        "                               \
-        movd     %%ecx,     %%mm1;      \
-        movd     %%ebx,     %%mm0;      \
-        movd     (%%edi),   %%mm3;      \
-        paddq    %%mm3,     %%mm1;      \
-        movd     (%%esi),   %%mm2;      \
-        pmuludq  %%mm0,     %%mm2;      \
-        movd     4(%%esi),  %%mm4;      \
-        pmuludq  %%mm0,     %%mm4;      \
-        movd     8(%%esi),  %%mm6;      \
-        pmuludq  %%mm0,     %%mm6;      \
-        movd     12(%%esi), %%mm7;      \
-        pmuludq  %%mm0,     %%mm7;      \
-        paddq    %%mm2,     %%mm1;      \
-        movd     4(%%edi),  %%mm3;      \
-        paddq    %%mm4,     %%mm3;      \
-        movd     8(%%edi),  %%mm5;      \
-        paddq    %%mm6,     %%mm5;      \
-        movd     12(%%edi), %%mm4;      \
-        paddq    %%mm4,     %%mm7;      \
-        movd     %%mm1,     (%%edi);    \
-        movd     16(%%esi), %%mm2;      \
-        pmuludq  %%mm0,     %%mm2;      \
-        psrlq    $32,       %%mm1;      \
-        movd     20(%%esi), %%mm4;      \
-        pmuludq  %%mm0,     %%mm4;      \
-        paddq    %%mm3,     %%mm1;      \
-        movd     24(%%esi), %%mm6;      \
-        pmuludq  %%mm0,     %%mm6;      \
-        movd     %%mm1,     4(%%edi);   \
-        psrlq    $32,       %%mm1;      \
-        movd     28(%%esi), %%mm3;      \
-        pmuludq  %%mm0,     %%mm3;      \
-        paddq    %%mm5,     %%mm1;      \
-        movd     16(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm2;      \
-        movd     %%mm1,     8(%%edi);   \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm7,     %%mm1;      \
-        movd     20(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm4;      \
-        movd     %%mm1,     12(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm2,     %%mm1;      \
-        movd     24(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm6;      \
-        movd     %%mm1,     16(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm4,     %%mm1;      \
-        movd     28(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm3;      \
-        movd     %%mm1,     20(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm6,     %%mm1;      \
-        movd     %%mm1,     24(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm3,     %%mm1;      \
-        movd     %%mm1,     28(%%edi);  \
-        addl     $32,       %%edi;      \
-        addl     $32,       %%esi;      \
-        psrlq    $32,       %%mm1;      \
-        movd     %%mm1,     %%ecx;      \
-        "
-
-#define MULADDC_STOP            \
-        "                       \
-        emms;                   \
-        movl   %4, %%ebx;       \
-        movl   %%ecx, %1;       \
-        movl   %%edi, %2;       \
-        movl   %%esi, %3;       \
-        "                       \
-        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
-        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
-        : "eax", "ecx", "edx", "esi", "edi"             \
-    );
-
-#else
-
-#define MULADDC_STOP            \
-        "                       \
-        movl   %4, %%ebx;       \
-        movl   %%ecx, %1;       \
-        movl   %%edi, %2;       \
-        movl   %%esi, %3;       \
-        "                       \
-        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
-        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
-        : "eax", "ecx", "edx", "esi", "edi"             \
-    );
-#endif /* SSE2 */
-#endif /* i386 */
-
-#if defined(__amd64__) || defined (__x86_64__)
-
-#define MULADDC_INIT                            \
-    asm( "movq   %0, %%rsi      " :: "m" (s));  \
-    asm( "movq   %0, %%rdi      " :: "m" (d));  \
-    asm( "movq   %0, %%rcx      " :: "m" (c));  \
-    asm( "movq   %0, %%rbx      " :: "m" (b));  \
-    asm( "xorq   %r8, %r8       " );
-
-#define MULADDC_CORE                            \
-    asm( "movq  (%rsi),%rax     " );            \
-    asm( "mulq   %rbx           " );            \
-    asm( "addq   $8,   %rsi     " );            \
-    asm( "addq   %rcx, %rax     " );            \
-    asm( "movq   %r8,  %rcx     " );            \
-    asm( "adcq   $0,   %rdx     " );            \
-    asm( "nop                   " );            \
-    asm( "addq   %rax, (%rdi)   " );            \
-    asm( "adcq   %rdx, %rcx     " );            \
-    asm( "addq   $8,   %rdi     " );
-
-#define MULADDC_STOP                            \
-    asm( "movq   %%rcx, %0      " : "=m" (c));  \
-    asm( "movq   %%rdi, %0      " : "=m" (d));  \
-    asm( "movq   %%rsi, %0      " : "=m" (s) :: \
-    "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
-
-#endif /* AMD64 */
-
-#if defined(__mc68020__) || defined(__mcpu32__)
-
-#define MULADDC_INIT                            \
-    asm( "movl   %0, %%a2       " :: "m" (s));  \
-    asm( "movl   %0, %%a3       " :: "m" (d));  \
-    asm( "movl   %0, %%d3       " :: "m" (c));  \
-    asm( "movl   %0, %%d2       " :: "m" (b));  \
-    asm( "moveq  #0, %d0        " );
-
-#define MULADDC_CORE                            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addl   %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "moveq  #0,  %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "addxl  %d4, %d3       " );
-
-#define MULADDC_STOP                            \
-    asm( "movl   %%d3, %0       " : "=m" (c));  \
-    asm( "movl   %%a3, %0       " : "=m" (d));  \
-    asm( "movl   %%a2, %0       " : "=m" (s) :: \
-    "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
-
-#define MULADDC_HUIT                            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "addxl  %d0, %d3       " );
-
-#endif /* MC68000 */
-
-#if defined(__powerpc__)   || defined(__ppc__)
-#if defined(__powerpc64__) || defined(__ppc64__)
-
-#if defined(__MACH__) && defined(__APPLE__)
-
-#define MULADDC_INIT                            \
-    asm( "ld     r3, %0         " :: "m" (s));  \
-    asm( "ld     r4, %0         " :: "m" (d));  \
-    asm( "ld     r5, %0         " :: "m" (c));  \
-    asm( "ld     r6, %0         " :: "m" (b));  \
-    asm( "addi   r3, r3, -8     " );            \
-    asm( "addi   r4, r4, -8     " );            \
-    asm( "addic  r5, r5,  0     " );
-
-#define MULADDC_CORE                            \
-    asm( "ldu    r7, 8(r3)      " );            \
-    asm( "mulld  r8, r7, r6     " );            \
-    asm( "mulhdu r9, r7, r6     " );            \
-    asm( "adde   r8, r8, r5     " );            \
-    asm( "ld     r7, 8(r4)      " );            \
-    asm( "addze  r5, r9         " );            \
-    asm( "addc   r8, r8, r7     " );            \
-    asm( "stdu   r8, 8(r4)      " );
-
-#define MULADDC_STOP                            \
-    asm( "addze  r5, r5         " );            \
-    asm( "addi   r4, r4, 8      " );            \
-    asm( "addi   r3, r3, 8      " );            \
-    asm( "std    r5, %0         " : "=m" (c));  \
-    asm( "std    r4, %0         " : "=m" (d));  \
-    asm( "std    r3, %0         " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#else
-
-#define MULADDC_INIT                            \
-    asm( "ld     %%r3, %0       " :: "m" (s));  \
-    asm( "ld     %%r4, %0       " :: "m" (d));  \
-    asm( "ld     %%r5, %0       " :: "m" (c));  \
-    asm( "ld     %%r6, %0       " :: "m" (b));  \
-    asm( "addi   %r3, %r3, -8   " );            \
-    asm( "addi   %r4, %r4, -8   " );            \
-    asm( "addic  %r5, %r5,  0   " );
-
-#define MULADDC_CORE                            \
-    asm( "ldu    %r7, 8(%r3)    " );            \
-    asm( "mulld  %r8, %r7, %r6  " );            \
-    asm( "mulhdu %r9, %r7, %r6  " );            \
-    asm( "adde   %r8, %r8, %r5  " );            \
-    asm( "ld     %r7, 8(%r4)    " );            \
-    asm( "addze  %r5, %r9       " );            \
-    asm( "addc   %r8, %r8, %r7  " );            \
-    asm( "stdu   %r8, 8(%r4)    " );
-
-#define MULADDC_STOP                            \
-    asm( "addze  %r5, %r5       " );            \
-    asm( "addi   %r4, %r4, 8    " );            \
-    asm( "addi   %r3, %r3, 8    " );            \
-    asm( "std    %%r5, %0       " : "=m" (c));  \
-    asm( "std    %%r4, %0       " : "=m" (d));  \
-    asm( "std    %%r3, %0       " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#endif
-
-#else /* PPC32 */
-
-#if defined(__MACH__) && defined(__APPLE__)
-
-#define MULADDC_INIT                            \
-    asm( "lwz    r3, %0         " :: "m" (s));  \
-    asm( "lwz    r4, %0         " :: "m" (d));  \
-    asm( "lwz    r5, %0         " :: "m" (c));  \
-    asm( "lwz    r6, %0         " :: "m" (b));  \
-    asm( "addi   r3, r3, -4     " );            \
-    asm( "addi   r4, r4, -4     " );            \
-    asm( "addic  r5, r5,  0     " );
-
-#define MULADDC_CORE                            \
-    asm( "lwzu   r7, 4(r3)      " );            \
-    asm( "mullw  r8, r7, r6     " );            \
-    asm( "mulhwu r9, r7, r6     " );            \
-    asm( "adde   r8, r8, r5     " );            \
-    asm( "lwz    r7, 4(r4)      " );            \
-    asm( "addze  r5, r9         " );            \
-    asm( "addc   r8, r8, r7     " );            \
-    asm( "stwu   r8, 4(r4)      " );
-
-#define MULADDC_STOP                            \
-    asm( "addze  r5, r5         " );            \
-    asm( "addi   r4, r4, 4      " );            \
-    asm( "addi   r3, r3, 4      " );            \
-    asm( "stw    r5, %0         " : "=m" (c));  \
-    asm( "stw    r4, %0         " : "=m" (d));  \
-    asm( "stw    r3, %0         " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#else
-
-#define MULADDC_INIT                            \
-    asm( "lwz    %%r3, %0       " :: "m" (s));  \
-    asm( "lwz    %%r4, %0       " :: "m" (d));  \
-    asm( "lwz    %%r5, %0       " :: "m" (c));  \
-    asm( "lwz    %%r6, %0       " :: "m" (b));  \
-    asm( "addi   %r3, %r3, -4   " );            \
-    asm( "addi   %r4, %r4, -4   " );            \
-    asm( "addic  %r5, %r5,  0   " );
-
-#define MULADDC_CORE                            \
-    asm( "lwzu   %r7, 4(%r3)    " );            \
-    asm( "mullw  %r8, %r7, %r6  " );            \
-    asm( "mulhwu %r9, %r7, %r6  " );            \
-    asm( "adde   %r8, %r8, %r5  " );            \
-    asm( "lwz    %r7, 4(%r4)    " );            \
-    asm( "addze  %r5, %r9       " );            \
-    asm( "addc   %r8, %r8, %r7  " );            \
-    asm( "stwu   %r8, 4(%r4)    " );
-
-#define MULADDC_STOP                            \
-    asm( "addze  %r5, %r5       " );            \
-    asm( "addi   %r4, %r4, 4    " );            \
-    asm( "addi   %r3, %r3, 4    " );            \
-    asm( "stw    %%r5, %0       " : "=m" (c));  \
-    asm( "stw    %%r4, %0       " : "=m" (d));  \
-    asm( "stw    %%r3, %0       " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#endif
-
-#endif /* PPC32 */
-#endif /* PPC64 */
-
-#if defined(__sparc__)
-
-#define MULADDC_INIT                            \
-    asm( "ld     %0, %%o0       " :: "m" (s));  \
-    asm( "ld     %0, %%o1       " :: "m" (d));  \
-    asm( "ld     %0, %%o2       " :: "m" (c));  \
-    asm( "ld     %0, %%o3       " :: "m" (b));
-
-#define MULADDC_CORE                            \
-    asm( "ld    [%o0], %o4      " );            \
-    asm( "inc      4,  %o0      " );            \
-    asm( "ld    [%o1], %o5      " );            \
-    asm( "umul   %o3,  %o4, %o4 " );            \
-    asm( "addcc  %o4,  %o2, %o4 " );            \
-    asm( "rd      %y,  %g1      " );            \
-    asm( "addx   %g1,    0, %g1 " );            \
-    asm( "addcc  %o4,  %o5, %o4 " );            \
-    asm( "st     %o4, [%o1]     " );            \
-    asm( "addx   %g1,    0, %o2 " );            \
-    asm( "inc      4,  %o1      " );
-
-#define MULADDC_STOP                            \
-    asm( "st     %%o2, %0       " : "=m" (c));  \
-    asm( "st     %%o1, %0       " : "=m" (d));  \
-    asm( "st     %%o0, %0       " : "=m" (s) :: \
-    "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
-
-#endif /* SPARCv8 */
-
-#if defined(__microblaze__) || defined(microblaze)
-
-#define MULADDC_INIT                            \
-    asm( "lwi   r3,   %0        " :: "m" (s));  \
-    asm( "lwi   r4,   %0        " :: "m" (d));  \
-    asm( "lwi   r5,   %0        " :: "m" (c));  \
-    asm( "lwi   r6,   %0        " :: "m" (b));  \
-    asm( "andi  r7,   r6, 0xffff" );            \
-    asm( "bsrli r6,   r6, 16    " );
-
-#define MULADDC_CORE                            \
-    asm( "lhui  r8,   r3,   0   " );            \
-    asm( "addi  r3,   r3,   2   " );            \
-    asm( "lhui  r9,   r3,   0   " );            \
-    asm( "addi  r3,   r3,   2   " );            \
-    asm( "mul   r10,  r9,  r6   " );            \
-    asm( "mul   r11,  r8,  r7   " );            \
-    asm( "mul   r12,  r9,  r7   " );            \
-    asm( "mul   r13,  r8,  r6   " );            \
-    asm( "bsrli  r8, r10,  16   " );            \
-    asm( "bsrli  r9, r11,  16   " );            \
-    asm( "add   r13, r13,  r8   " );            \
-    asm( "add   r13, r13,  r9   " );            \
-    asm( "bslli r10, r10,  16   " );            \
-    asm( "bslli r11, r11,  16   " );            \
-    asm( "add   r12, r12, r10   " );            \
-    asm( "addc  r13, r13,  r0   " );            \
-    asm( "add   r12, r12, r11   " );            \
-    asm( "addc  r13, r13,  r0   " );            \
-    asm( "lwi   r10,  r4,   0   " );            \
-    asm( "add   r12, r12, r10   " );            \
-    asm( "addc  r13, r13,  r0   " );            \
-    asm( "add   r12, r12,  r5   " );            \
-    asm( "addc   r5, r13,  r0   " );            \
-    asm( "swi   r12,  r4,   0   " );            \
-    asm( "addi   r4,  r4,   4   " );
-
-#define MULADDC_STOP                            \
-    asm( "swi   r5,   %0        " : "=m" (c));  \
-    asm( "swi   r4,   %0        " : "=m" (d));  \
-    asm( "swi   r3,   %0        " : "=m" (s) :: \
-     "r3", "r4" , "r5" , "r6" , "r7" , "r8" ,   \
-     "r9", "r10", "r11", "r12", "r13" );
-
-#endif /* MicroBlaze */
-
-#if defined(__tricore__)
-
-#define MULADDC_INIT                            \
-    asm( "ld.a   %%a2, %0       " :: "m" (s));  \
-    asm( "ld.a   %%a3, %0       " :: "m" (d));  \
-    asm( "ld.w   %%d4, %0       " :: "m" (c));  \
-    asm( "ld.w   %%d1, %0       " :: "m" (b));  \
-    asm( "xor    %d5, %d5       " );
-
-#define MULADDC_CORE                            \
-    asm( "ld.w   %d0,   [%a2+]      " );        \
-    asm( "madd.u %e2, %e4, %d0, %d1 " );        \
-    asm( "ld.w   %d0,   [%a3]       " );        \
-    asm( "addx   %d2,    %d2,  %d0  " );        \
-    asm( "addc   %d3,    %d3,    0  " );        \
-    asm( "mov    %d4,    %d3        " );        \
-    asm( "st.w  [%a3+],  %d2        " );
-
-#define MULADDC_STOP                            \
-    asm( "st.w   %0, %%d4       " : "=m" (c));  \
-    asm( "st.a   %0, %%a3       " : "=m" (d));  \
-    asm( "st.a   %0, %%a2       " : "=m" (s) :: \
-    "d0", "d1", "e2", "d4", "a2", "a3" );
-
-#endif /* TriCore */
-
-#if defined(__arm__)
-
-#define MULADDC_INIT                            \
-    asm( "ldr    r0, %0         " :: "m" (s));  \
-    asm( "ldr    r1, %0         " :: "m" (d));  \
-    asm( "ldr    r2, %0         " :: "m" (c));  \
-    asm( "ldr    r3, %0         " :: "m" (b));
-
-#define MULADDC_CORE                            \
-    asm( "ldr    r4, [r0], #4   " );            \
-    asm( "mov    r5, #0         " );            \
-    asm( "ldr    r6, [r1]       " );            \
-    asm( "umlal  r2, r5, r3, r4 " );            \
-    asm( "adds   r7, r6, r2     " );            \
-    asm( "adc    r2, r5, #0     " );            \
-    asm( "str    r7, [r1], #4   " );
-
-#define MULADDC_STOP                            \
-    asm( "str    r2, %0         " : "=m" (c));  \
-    asm( "str    r1, %0         " : "=m" (d));  \
-    asm( "str    r0, %0         " : "=m" (s) :: \
-    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
-
-#endif /* ARMv3 */
-
-#if defined(__alpha__)
-
-#define MULADDC_INIT                            \
-    asm( "ldq    $1, %0         " :: "m" (s));  \
-    asm( "ldq    $2, %0         " :: "m" (d));  \
-    asm( "ldq    $3, %0         " :: "m" (c));  \
-    asm( "ldq    $4, %0         " :: "m" (b));
-
-#define MULADDC_CORE                            \
-    asm( "ldq    $6,  0($1)     " );            \
-    asm( "addq   $1,  8, $1     " );            \
-    asm( "mulq   $6, $4, $7     " );            \
-    asm( "umulh  $6, $4, $6     " );            \
-    asm( "addq   $7, $3, $7     " );            \
-    asm( "cmpult $7, $3, $3     " );            \
-    asm( "ldq    $5,  0($2)     " );            \
-    asm( "addq   $7, $5, $7     " );            \
-    asm( "cmpult $7, $5, $5     " );            \
-    asm( "stq    $7,  0($2)     " );            \
-    asm( "addq   $2,  8, $2     " );            \
-    asm( "addq   $6, $3, $3     " );            \
-    asm( "addq   $5, $3, $3     " );
-
-#define MULADDC_STOP                            \
-    asm( "stq    $3, %0         " : "=m" (c));  \
-    asm( "stq    $2, %0         " : "=m" (d));  \
-    asm( "stq    $1, %0         " : "=m" (s) :: \
-    "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
-
-#endif /* Alpha */
-
-#if defined(__mips__)
-
-#define MULADDC_INIT                            \
-    asm( "lw     $10, %0        " :: "m" (s));  \
-    asm( "lw     $11, %0        " :: "m" (d));  \
-    asm( "lw     $12, %0        " :: "m" (c));  \
-    asm( "lw     $13, %0        " :: "m" (b));
-
-#define MULADDC_CORE                            \
-    asm( "lw     $14, 0($10)    " );            \
-    asm( "multu  $13, $14       " );            \
-    asm( "addi   $10, $10, 4    " );            \
-    asm( "mflo   $14            " );            \
-    asm( "mfhi   $9             " );            \
-    asm( "addu   $14, $12, $14  " );            \
-    asm( "lw     $15, 0($11)    " );            \
-    asm( "sltu   $12, $14, $12  " );            \
-    asm( "addu   $15, $14, $15  " );            \
-    asm( "sltu   $14, $15, $14  " );            \
-    asm( "addu   $12, $12, $9   " );            \
-    asm( "sw     $15, 0($11)    " );            \
-    asm( "addu   $12, $12, $14  " );            \
-    asm( "addi   $11, $11, 4    " );
-
-#define MULADDC_STOP                            \
-    asm( "sw     $12, %0        " : "=m" (c));  \
-    asm( "sw     $11, %0        " : "=m" (d));  \
-    asm( "sw     $10, %0        " : "=m" (s) :: \
-    "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
-
-#endif /* MIPS */
-#endif /* GNUC */
-
-#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
-
-#define MULADDC_INIT                            \
-    __asm   mov     esi, s                      \
-    __asm   mov     edi, d                      \
-    __asm   mov     ecx, c                      \
-    __asm   mov     ebx, b
-
-#define MULADDC_CORE                            \
-    __asm   lodsd                               \
-    __asm   mul     ebx                         \
-    __asm   add     eax, ecx                    \
-    __asm   adc     edx, 0                      \
-    __asm   add     eax, [edi]                  \
-    __asm   adc     edx, 0                      \
-    __asm   mov     ecx, edx                    \
-    __asm   stosd
-
-#if defined(POLARSSL_HAVE_SSE2)
-
-#define EMIT __asm _emit
-
-#define MULADDC_HUIT                            \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0xC9             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0xC3             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x1F             \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x16             \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x04  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x08  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x7E  EMIT 0x0C  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xF8             \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x5F  EMIT 0x04  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xDC             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x08  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xEE             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x67  EMIT 0x0C  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xFC             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x0F             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x56  EMIT 0x10  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x14  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x18  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x04  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x5E  EMIT 0x1C  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xD8             \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCD             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x10  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xD5             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x08  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCF             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x14  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xE5             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x0C  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x18  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xF5             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x10  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCC             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x1C  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xDD             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x14  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCE             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x18  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x1C  \
-    EMIT 0x83  EMIT 0xC7  EMIT 0x20             \
-    EMIT 0x83  EMIT 0xC6  EMIT 0x20             \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0xC9
-
-#define MULADDC_STOP                            \
-    EMIT 0x0F  EMIT 0x77                        \
-    __asm   mov     c, ecx                      \
-    __asm   mov     d, edi                      \
-    __asm   mov     s, esi                      \
-
-#else
-
-#define MULADDC_STOP                            \
-    __asm   mov     c, ecx                      \
-    __asm   mov     d, edi                      \
-    __asm   mov     s, esi                      \
-
-#endif /* SSE2 */
-#endif /* MSVC */
-
-#endif /* POLARSSL_HAVE_ASM */
-
-#if !defined(MULADDC_CORE)
-#if defined(POLARSSL_HAVE_LONGLONG)
-
-#define MULADDC_INIT                    \
-{                                       \
-    t_dbl r;                            \
-    t_int r0, r1;
-
-#define MULADDC_CORE                    \
-    r   = *(s++) * (t_dbl) b;           \
-    r0  = r;                            \
-    r1  = r >> biL;                     \
-    r0 += c;  r1 += (r0 <  c);          \
-    r0 += *d; r1 += (r0 < *d);          \
-    c = r1; *(d++) = r0;
-
-#define MULADDC_STOP                    \
-}
-
-#else
-#define MULADDC_INIT                    \
-{                                       \
-    t_int s0, s1, b0, b1;               \
-    t_int r0, r1, rx, ry;               \
-    b0 = ( b << biH ) >> biH;           \
-    b1 = ( b >> biH );
-
-#define MULADDC_CORE                    \
-    s0 = ( *s << biH ) >> biH;          \
-    s1 = ( *s >> biH ); s++;            \
-    rx = s0 * b1; r0 = s0 * b0;         \
-    ry = s1 * b0; r1 = s1 * b1;         \
-    r1 += ( rx >> biH );                \
-    r1 += ( ry >> biH );                \
-    rx <<= biH; ry <<= biH;             \
-    r0 += rx; r1 += (r0 < rx);          \
-    r0 += ry; r1 += (r0 < ry);          \
-    r0 +=  c; r1 += (r0 <  c);          \
-    r0 += *d; r1 += (r0 < *d);          \
-    c = r1; *(d++) = r0;
-
-#define MULADDC_STOP                    \
-}
-
-#endif /* C (generic)  */
-#endif /* C (longlong) */
-
-#endif /* bn_mul.h */
-/**
- * \file bn_mul.h
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- *      Multiply source vector [s] with b, add result
- *       to destination vector [d] and set carry c.
- *
- *      Currently supports:
- *
- *         . IA-32 (386+)         . AMD64 / EM64T
- *         . IA-32 (SSE2)         . Motorola 68000
- *         . PowerPC, 32-bit      . MicroBlaze
- *         . PowerPC, 64-bit      . TriCore
- *         . SPARC v8             . ARM v3+
- *         . Alpha                . MIPS32
- *         . C, longlong          . C, generic
- */
-#ifndef POLARSSL_BN_MUL_H
-#define POLARSSL_BN_MUL_H
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_HAVE_ASM)
-
-#if defined(__GNUC__)
-#if defined(__i386__)
-
-#define MULADDC_INIT                \
-    asm( "                          \
-        movl   %%ebx, %0;           \
-        movl   %5, %%esi;           \
-        movl   %6, %%edi;           \
-        movl   %7, %%ecx;           \
-        movl   %8, %%ebx;           \
-        "
-
-#define MULADDC_CORE                \
-        "                           \
-        lodsl;                      \
-        mull   %%ebx;               \
-        addl   %%ecx,   %%eax;      \
-        adcl   $0,      %%edx;      \
-        addl   (%%edi), %%eax;      \
-        adcl   $0,      %%edx;      \
-        movl   %%edx,   %%ecx;      \
-        stosl;                      \
-        "
-
-#if defined(POLARSSL_HAVE_SSE2)
-
-#define MULADDC_HUIT                    \
-        "                               \
-        movd     %%ecx,     %%mm1;      \
-        movd     %%ebx,     %%mm0;      \
-        movd     (%%edi),   %%mm3;      \
-        paddq    %%mm3,     %%mm1;      \
-        movd     (%%esi),   %%mm2;      \
-        pmuludq  %%mm0,     %%mm2;      \
-        movd     4(%%esi),  %%mm4;      \
-        pmuludq  %%mm0,     %%mm4;      \
-        movd     8(%%esi),  %%mm6;      \
-        pmuludq  %%mm0,     %%mm6;      \
-        movd     12(%%esi), %%mm7;      \
-        pmuludq  %%mm0,     %%mm7;      \
-        paddq    %%mm2,     %%mm1;      \
-        movd     4(%%edi),  %%mm3;      \
-        paddq    %%mm4,     %%mm3;      \
-        movd     8(%%edi),  %%mm5;      \
-        paddq    %%mm6,     %%mm5;      \
-        movd     12(%%edi), %%mm4;      \
-        paddq    %%mm4,     %%mm7;      \
-        movd     %%mm1,     (%%edi);    \
-        movd     16(%%esi), %%mm2;      \
-        pmuludq  %%mm0,     %%mm2;      \
-        psrlq    $32,       %%mm1;      \
-        movd     20(%%esi), %%mm4;      \
-        pmuludq  %%mm0,     %%mm4;      \
-        paddq    %%mm3,     %%mm1;      \
-        movd     24(%%esi), %%mm6;      \
-        pmuludq  %%mm0,     %%mm6;      \
-        movd     %%mm1,     4(%%edi);   \
-        psrlq    $32,       %%mm1;      \
-        movd     28(%%esi), %%mm3;      \
-        pmuludq  %%mm0,     %%mm3;      \
-        paddq    %%mm5,     %%mm1;      \
-        movd     16(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm2;      \
-        movd     %%mm1,     8(%%edi);   \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm7,     %%mm1;      \
-        movd     20(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm4;      \
-        movd     %%mm1,     12(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm2,     %%mm1;      \
-        movd     24(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm6;      \
-        movd     %%mm1,     16(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm4,     %%mm1;      \
-        movd     28(%%edi), %%mm5;      \
-        paddq    %%mm5,     %%mm3;      \
-        movd     %%mm1,     20(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm6,     %%mm1;      \
-        movd     %%mm1,     24(%%edi);  \
-        psrlq    $32,       %%mm1;      \
-        paddq    %%mm3,     %%mm1;      \
-        movd     %%mm1,     28(%%edi);  \
-        addl     $32,       %%edi;      \
-        addl     $32,       %%esi;      \
-        psrlq    $32,       %%mm1;      \
-        movd     %%mm1,     %%ecx;      \
-        "
-
-#define MULADDC_STOP            \
-        "                       \
-        emms;                   \
-        movl   %4, %%ebx;       \
-        movl   %%ecx, %1;       \
-        movl   %%edi, %2;       \
-        movl   %%esi, %3;       \
-        "                       \
-        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
-        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
-        : "eax", "ecx", "edx", "esi", "edi"             \
-    );
-
-#else
-
-#define MULADDC_STOP            \
-        "                       \
-        movl   %4, %%ebx;       \
-        movl   %%ecx, %1;       \
-        movl   %%edi, %2;       \
-        movl   %%esi, %3;       \
-        "                       \
-        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
-        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
-        : "eax", "ecx", "edx", "esi", "edi"             \
-    );
-#endif /* SSE2 */
-#endif /* i386 */
-
-#if defined(__amd64__) || defined (__x86_64__)
-
-#define MULADDC_INIT                            \
-    asm( "movq   %0, %%rsi      " :: "m" (s));  \
-    asm( "movq   %0, %%rdi      " :: "m" (d));  \
-    asm( "movq   %0, %%rcx      " :: "m" (c));  \
-    asm( "movq   %0, %%rbx      " :: "m" (b));  \
-    asm( "xorq   %r8, %r8       " );
-
-#define MULADDC_CORE                            \
-    asm( "movq  (%rsi),%rax     " );            \
-    asm( "mulq   %rbx           " );            \
-    asm( "addq   $8,   %rsi     " );            \
-    asm( "addq   %rcx, %rax     " );            \
-    asm( "movq   %r8,  %rcx     " );            \
-    asm( "adcq   $0,   %rdx     " );            \
-    asm( "nop                   " );            \
-    asm( "addq   %rax, (%rdi)   " );            \
-    asm( "adcq   %rdx, %rcx     " );            \
-    asm( "addq   $8,   %rdi     " );
-
-#define MULADDC_STOP                            \
-    asm( "movq   %%rcx, %0      " : "=m" (c));  \
-    asm( "movq   %%rdi, %0      " : "=m" (d));  \
-    asm( "movq   %%rsi, %0      " : "=m" (s) :: \
-    "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
-
-#endif /* AMD64 */
-
-#if defined(__mc68020__) || defined(__mcpu32__)
-
-#define MULADDC_INIT                            \
-    asm( "movl   %0, %%a2       " :: "m" (s));  \
-    asm( "movl   %0, %%a3       " :: "m" (d));  \
-    asm( "movl   %0, %%d3       " :: "m" (c));  \
-    asm( "movl   %0, %%d2       " :: "m" (b));  \
-    asm( "moveq  #0, %d0        " );
-
-#define MULADDC_CORE                            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addl   %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "moveq  #0,  %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "addxl  %d4, %d3       " );
-
-#define MULADDC_STOP                            \
-    asm( "movl   %%d3, %0       " : "=m" (c));  \
-    asm( "movl   %%a3, %0       " : "=m" (d));  \
-    asm( "movl   %%a2, %0       " : "=m" (s) :: \
-    "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
-
-#define MULADDC_HUIT                            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d4:%d1   " );            \
-    asm( "addxl  %d3, %d1       " );            \
-    asm( "addxl  %d0, %d4       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "movel  %a2@+, %d1     " );            \
-    asm( "mulul  %d2, %d3:%d1   " );            \
-    asm( "addxl  %d4, %d1       " );            \
-    asm( "addxl  %d0, %d3       " );            \
-    asm( "addl   %d1, %a3@+     " );            \
-    asm( "addxl  %d0, %d3       " );
-
-#endif /* MC68000 */
-
-#if defined(__powerpc__)   || defined(__ppc__)
-#if defined(__powerpc64__) || defined(__ppc64__)
-
-#if defined(__MACH__) && defined(__APPLE__)
-
-#define MULADDC_INIT                            \
-    asm( "ld     r3, %0         " :: "m" (s));  \
-    asm( "ld     r4, %0         " :: "m" (d));  \
-    asm( "ld     r5, %0         " :: "m" (c));  \
-    asm( "ld     r6, %0         " :: "m" (b));  \
-    asm( "addi   r3, r3, -8     " );            \
-    asm( "addi   r4, r4, -8     " );            \
-    asm( "addic  r5, r5,  0     " );
-
-#define MULADDC_CORE                            \
-    asm( "ldu    r7, 8(r3)      " );            \
-    asm( "mulld  r8, r7, r6     " );            \
-    asm( "mulhdu r9, r7, r6     " );            \
-    asm( "adde   r8, r8, r5     " );            \
-    asm( "ld     r7, 8(r4)      " );            \
-    asm( "addze  r5, r9         " );            \
-    asm( "addc   r8, r8, r7     " );            \
-    asm( "stdu   r8, 8(r4)      " );
-
-#define MULADDC_STOP                            \
-    asm( "addze  r5, r5         " );            \
-    asm( "addi   r4, r4, 8      " );            \
-    asm( "addi   r3, r3, 8      " );            \
-    asm( "std    r5, %0         " : "=m" (c));  \
-    asm( "std    r4, %0         " : "=m" (d));  \
-    asm( "std    r3, %0         " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#else
-
-#define MULADDC_INIT                            \
-    asm( "ld     %%r3, %0       " :: "m" (s));  \
-    asm( "ld     %%r4, %0       " :: "m" (d));  \
-    asm( "ld     %%r5, %0       " :: "m" (c));  \
-    asm( "ld     %%r6, %0       " :: "m" (b));  \
-    asm( "addi   %r3, %r3, -8   " );            \
-    asm( "addi   %r4, %r4, -8   " );            \
-    asm( "addic  %r5, %r5,  0   " );
-
-#define MULADDC_CORE                            \
-    asm( "ldu    %r7, 8(%r3)    " );            \
-    asm( "mulld  %r8, %r7, %r6  " );            \
-    asm( "mulhdu %r9, %r7, %r6  " );            \
-    asm( "adde   %r8, %r8, %r5  " );            \
-    asm( "ld     %r7, 8(%r4)    " );            \
-    asm( "addze  %r5, %r9       " );            \
-    asm( "addc   %r8, %r8, %r7  " );            \
-    asm( "stdu   %r8, 8(%r4)    " );
-
-#define MULADDC_STOP                            \
-    asm( "addze  %r5, %r5       " );            \
-    asm( "addi   %r4, %r4, 8    " );            \
-    asm( "addi   %r3, %r3, 8    " );            \
-    asm( "std    %%r5, %0       " : "=m" (c));  \
-    asm( "std    %%r4, %0       " : "=m" (d));  \
-    asm( "std    %%r3, %0       " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#endif
-
-#else /* PPC32 */
-
-#if defined(__MACH__) && defined(__APPLE__)
-
-#define MULADDC_INIT                            \
-    asm( "lwz    r3, %0         " :: "m" (s));  \
-    asm( "lwz    r4, %0         " :: "m" (d));  \
-    asm( "lwz    r5, %0         " :: "m" (c));  \
-    asm( "lwz    r6, %0         " :: "m" (b));  \
-    asm( "addi   r3, r3, -4     " );            \
-    asm( "addi   r4, r4, -4     " );            \
-    asm( "addic  r5, r5,  0     " );
-
-#define MULADDC_CORE                            \
-    asm( "lwzu   r7, 4(r3)      " );            \
-    asm( "mullw  r8, r7, r6     " );            \
-    asm( "mulhwu r9, r7, r6     " );            \
-    asm( "adde   r8, r8, r5     " );            \
-    asm( "lwz    r7, 4(r4)      " );            \
-    asm( "addze  r5, r9         " );            \
-    asm( "addc   r8, r8, r7     " );            \
-    asm( "stwu   r8, 4(r4)      " );
-
-#define MULADDC_STOP                            \
-    asm( "addze  r5, r5         " );            \
-    asm( "addi   r4, r4, 4      " );            \
-    asm( "addi   r3, r3, 4      " );            \
-    asm( "stw    r5, %0         " : "=m" (c));  \
-    asm( "stw    r4, %0         " : "=m" (d));  \
-    asm( "stw    r3, %0         " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#else
-
-#define MULADDC_INIT                            \
-    asm( "lwz    %%r3, %0       " :: "m" (s));  \
-    asm( "lwz    %%r4, %0       " :: "m" (d));  \
-    asm( "lwz    %%r5, %0       " :: "m" (c));  \
-    asm( "lwz    %%r6, %0       " :: "m" (b));  \
-    asm( "addi   %r3, %r3, -4   " );            \
-    asm( "addi   %r4, %r4, -4   " );            \
-    asm( "addic  %r5, %r5,  0   " );
-
-#define MULADDC_CORE                            \
-    asm( "lwzu   %r7, 4(%r3)    " );            \
-    asm( "mullw  %r8, %r7, %r6  " );            \
-    asm( "mulhwu %r9, %r7, %r6  " );            \
-    asm( "adde   %r8, %r8, %r5  " );            \
-    asm( "lwz    %r7, 4(%r4)    " );            \
-    asm( "addze  %r5, %r9       " );            \
-    asm( "addc   %r8, %r8, %r7  " );            \
-    asm( "stwu   %r8, 4(%r4)    " );
-
-#define MULADDC_STOP                            \
-    asm( "addze  %r5, %r5       " );            \
-    asm( "addi   %r4, %r4, 4    " );            \
-    asm( "addi   %r3, %r3, 4    " );            \
-    asm( "stw    %%r5, %0       " : "=m" (c));  \
-    asm( "stw    %%r4, %0       " : "=m" (d));  \
-    asm( "stw    %%r3, %0       " : "=m" (s) :: \
-    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
-
-#endif
-
-#endif /* PPC32 */
-#endif /* PPC64 */
-
-#if defined(__sparc__)
-
-#define MULADDC_INIT                            \
-    asm( "ld     %0, %%o0       " :: "m" (s));  \
-    asm( "ld     %0, %%o1       " :: "m" (d));  \
-    asm( "ld     %0, %%o2       " :: "m" (c));  \
-    asm( "ld     %0, %%o3       " :: "m" (b));
-
-#define MULADDC_CORE                            \
-    asm( "ld    [%o0], %o4      " );            \
-    asm( "inc      4,  %o0      " );            \
-    asm( "ld    [%o1], %o5      " );            \
-    asm( "umul   %o3,  %o4, %o4 " );            \
-    asm( "addcc  %o4,  %o2, %o4 " );            \
-    asm( "rd      %y,  %g1      " );            \
-    asm( "addx   %g1,    0, %g1 " );            \
-    asm( "addcc  %o4,  %o5, %o4 " );            \
-    asm( "st     %o4, [%o1]     " );            \
-    asm( "addx   %g1,    0, %o2 " );            \
-    asm( "inc      4,  %o1      " );
-
-#define MULADDC_STOP                            \
-    asm( "st     %%o2, %0       " : "=m" (c));  \
-    asm( "st     %%o1, %0       " : "=m" (d));  \
-    asm( "st     %%o0, %0       " : "=m" (s) :: \
-    "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
-
-#endif /* SPARCv8 */
-
-#if defined(__microblaze__) || defined(microblaze)
-
-#define MULADDC_INIT                            \
-    asm( "lwi   r3,   %0        " :: "m" (s));  \
-    asm( "lwi   r4,   %0        " :: "m" (d));  \
-    asm( "lwi   r5,   %0        " :: "m" (c));  \
-    asm( "lwi   r6,   %0        " :: "m" (b));  \
-    asm( "andi  r7,   r6, 0xffff" );            \
-    asm( "bsrli r6,   r6, 16    " );
-
-#define MULADDC_CORE                            \
-    asm( "lhui  r8,   r3,   0   " );            \
-    asm( "addi  r3,   r3,   2   " );            \
-    asm( "lhui  r9,   r3,   0   " );            \
-    asm( "addi  r3,   r3,   2   " );            \
-    asm( "mul   r10,  r9,  r6   " );            \
-    asm( "mul   r11,  r8,  r7   " );            \
-    asm( "mul   r12,  r9,  r7   " );            \
-    asm( "mul   r13,  r8,  r6   " );            \
-    asm( "bsrli  r8, r10,  16   " );            \
-    asm( "bsrli  r9, r11,  16   " );            \
-    asm( "add   r13, r13,  r8   " );            \
-    asm( "add   r13, r13,  r9   " );            \
-    asm( "bslli r10, r10,  16   " );            \
-    asm( "bslli r11, r11,  16   " );            \
-    asm( "add   r12, r12, r10   " );            \
-    asm( "addc  r13, r13,  r0   " );            \
-    asm( "add   r12, r12, r11   " );            \
-    asm( "addc  r13, r13,  r0   " );            \
-    asm( "lwi   r10,  r4,   0   " );            \
-    asm( "add   r12, r12, r10   " );            \
-    asm( "addc  r13, r13,  r0   " );            \
-    asm( "add   r12, r12,  r5   " );            \
-    asm( "addc   r5, r13,  r0   " );            \
-    asm( "swi   r12,  r4,   0   " );            \
-    asm( "addi   r4,  r4,   4   " );
-
-#define MULADDC_STOP                            \
-    asm( "swi   r5,   %0        " : "=m" (c));  \
-    asm( "swi   r4,   %0        " : "=m" (d));  \
-    asm( "swi   r3,   %0        " : "=m" (s) :: \
-     "r3", "r4" , "r5" , "r6" , "r7" , "r8" ,   \
-     "r9", "r10", "r11", "r12", "r13" );
-
-#endif /* MicroBlaze */
-
-#if defined(__tricore__)
-
-#define MULADDC_INIT                            \
-    asm( "ld.a   %%a2, %0       " :: "m" (s));  \
-    asm( "ld.a   %%a3, %0       " :: "m" (d));  \
-    asm( "ld.w   %%d4, %0       " :: "m" (c));  \
-    asm( "ld.w   %%d1, %0       " :: "m" (b));  \
-    asm( "xor    %d5, %d5       " );
-
-#define MULADDC_CORE                            \
-    asm( "ld.w   %d0,   [%a2+]      " );        \
-    asm( "madd.u %e2, %e4, %d0, %d1 " );        \
-    asm( "ld.w   %d0,   [%a3]       " );        \
-    asm( "addx   %d2,    %d2,  %d0  " );        \
-    asm( "addc   %d3,    %d3,    0  " );        \
-    asm( "mov    %d4,    %d3        " );        \
-    asm( "st.w  [%a3+],  %d2        " );
-
-#define MULADDC_STOP                            \
-    asm( "st.w   %0, %%d4       " : "=m" (c));  \
-    asm( "st.a   %0, %%a3       " : "=m" (d));  \
-    asm( "st.a   %0, %%a2       " : "=m" (s) :: \
-    "d0", "d1", "e2", "d4", "a2", "a3" );
-
-#endif /* TriCore */
-
-#if defined(__arm__)
-
-#define MULADDC_INIT                            \
-    asm( "ldr    r0, %0         " :: "m" (s));  \
-    asm( "ldr    r1, %0         " :: "m" (d));  \
-    asm( "ldr    r2, %0         " :: "m" (c));  \
-    asm( "ldr    r3, %0         " :: "m" (b));
-
-#define MULADDC_CORE                            \
-    asm( "ldr    r4, [r0], #4   " );            \
-    asm( "mov    r5, #0         " );            \
-    asm( "ldr    r6, [r1]       " );            \
-    asm( "umlal  r2, r5, r3, r4 " );            \
-    asm( "adds   r7, r6, r2     " );            \
-    asm( "adc    r2, r5, #0     " );            \
-    asm( "str    r7, [r1], #4   " );
-
-#define MULADDC_STOP                            \
-    asm( "str    r2, %0         " : "=m" (c));  \
-    asm( "str    r1, %0         " : "=m" (d));  \
-    asm( "str    r0, %0         " : "=m" (s) :: \
-    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
-
-#endif /* ARMv3 */
-
-#if defined(__alpha__)
-
-#define MULADDC_INIT                            \
-    asm( "ldq    $1, %0         " :: "m" (s));  \
-    asm( "ldq    $2, %0         " :: "m" (d));  \
-    asm( "ldq    $3, %0         " :: "m" (c));  \
-    asm( "ldq    $4, %0         " :: "m" (b));
-
-#define MULADDC_CORE                            \
-    asm( "ldq    $6,  0($1)     " );            \
-    asm( "addq   $1,  8, $1     " );            \
-    asm( "mulq   $6, $4, $7     " );            \
-    asm( "umulh  $6, $4, $6     " );            \
-    asm( "addq   $7, $3, $7     " );            \
-    asm( "cmpult $7, $3, $3     " );            \
-    asm( "ldq    $5,  0($2)     " );            \
-    asm( "addq   $7, $5, $7     " );            \
-    asm( "cmpult $7, $5, $5     " );            \
-    asm( "stq    $7,  0($2)     " );            \
-    asm( "addq   $2,  8, $2     " );            \
-    asm( "addq   $6, $3, $3     " );            \
-    asm( "addq   $5, $3, $3     " );
-
-#define MULADDC_STOP                            \
-    asm( "stq    $3, %0         " : "=m" (c));  \
-    asm( "stq    $2, %0         " : "=m" (d));  \
-    asm( "stq    $1, %0         " : "=m" (s) :: \
-    "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
-
-#endif /* Alpha */
-
-#if defined(__mips__)
-
-#define MULADDC_INIT                            \
-    asm( "lw     $10, %0        " :: "m" (s));  \
-    asm( "lw     $11, %0        " :: "m" (d));  \
-    asm( "lw     $12, %0        " :: "m" (c));  \
-    asm( "lw     $13, %0        " :: "m" (b));
-
-#define MULADDC_CORE                            \
-    asm( "lw     $14, 0($10)    " );            \
-    asm( "multu  $13, $14       " );            \
-    asm( "addi   $10, $10, 4    " );            \
-    asm( "mflo   $14            " );            \
-    asm( "mfhi   $9             " );            \
-    asm( "addu   $14, $12, $14  " );            \
-    asm( "lw     $15, 0($11)    " );            \
-    asm( "sltu   $12, $14, $12  " );            \
-    asm( "addu   $15, $14, $15  " );            \
-    asm( "sltu   $14, $15, $14  " );            \
-    asm( "addu   $12, $12, $9   " );            \
-    asm( "sw     $15, 0($11)    " );            \
-    asm( "addu   $12, $12, $14  " );            \
-    asm( "addi   $11, $11, 4    " );
-
-#define MULADDC_STOP                            \
-    asm( "sw     $12, %0        " : "=m" (c));  \
-    asm( "sw     $11, %0        " : "=m" (d));  \
-    asm( "sw     $10, %0        " : "=m" (s) :: \
-    "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
-
-#endif /* MIPS */
-#endif /* GNUC */
-
-#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
-
-#define MULADDC_INIT                            \
-    __asm   mov     esi, s                      \
-    __asm   mov     edi, d                      \
-    __asm   mov     ecx, c                      \
-    __asm   mov     ebx, b
-
-#define MULADDC_CORE                            \
-    __asm   lodsd                               \
-    __asm   mul     ebx                         \
-    __asm   add     eax, ecx                    \
-    __asm   adc     edx, 0                      \
-    __asm   add     eax, [edi]                  \
-    __asm   adc     edx, 0                      \
-    __asm   mov     ecx, edx                    \
-    __asm   stosd
-
-#if defined(POLARSSL_HAVE_SSE2)
-
-#define EMIT __asm _emit
-
-#define MULADDC_HUIT                            \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0xC9             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0xC3             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x1F             \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x16             \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x04  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x08  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x7E  EMIT 0x0C  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xF8             \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x5F  EMIT 0x04  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xDC             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x08  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xEE             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x67  EMIT 0x0C  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xFC             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x0F             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x56  EMIT 0x10  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x14  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x18  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x04  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x5E  EMIT 0x1C  \
-    EMIT 0x0F  EMIT 0xF4  EMIT 0xD8             \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCD             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x10  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xD5             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x08  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCF             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x14  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xE5             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x0C  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x18  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xF5             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x10  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCC             \
-    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x1C  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xDD             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x14  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCE             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x18  \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x1C  \
-    EMIT 0x83  EMIT 0xC7  EMIT 0x20             \
-    EMIT 0x83  EMIT 0xC6  EMIT 0x20             \
-    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
-    EMIT 0x0F  EMIT 0x7E  EMIT 0xC9
-
-#define MULADDC_STOP                            \
-    EMIT 0x0F  EMIT 0x77                        \
-    __asm   mov     c, ecx                      \
-    __asm   mov     d, edi                      \
-    __asm   mov     s, esi                      \
-
-#else
-
-#define MULADDC_STOP                            \
-    __asm   mov     c, ecx                      \
-    __asm   mov     d, edi                      \
-    __asm   mov     s, esi                      \
-
-#endif /* SSE2 */
-#endif /* MSVC */
-
-#endif /* POLARSSL_HAVE_ASM */
-
-#if !defined(MULADDC_CORE)
-#if defined(POLARSSL_HAVE_LONGLONG)
-
-#define MULADDC_INIT                    \
-{                                       \
-    t_dbl r;                            \
-    t_int r0, r1;
-
-#define MULADDC_CORE                    \
-    r   = *(s++) * (t_dbl) b;           \
-    r0  = r;                            \
-    r1  = r >> biL;                     \
-    r0 += c;  r1 += (r0 <  c);          \
-    r0 += *d; r1 += (r0 < *d);          \
-    c = r1; *(d++) = r0;
-
-#define MULADDC_STOP                    \
-}
-
-#else
-#define MULADDC_INIT                    \
-{                                       \
-    t_int s0, s1, b0, b1;               \
-    t_int r0, r1, rx, ry;               \
-    b0 = ( b << biH ) >> biH;           \
-    b1 = ( b >> biH );
-
-#define MULADDC_CORE                    \
-    s0 = ( *s << biH ) >> biH;          \
-    s1 = ( *s >> biH ); s++;            \
-    rx = s0 * b1; r0 = s0 * b0;         \
-    ry = s1 * b0; r1 = s1 * b1;         \
-    r1 += ( rx >> biH );                \
-    r1 += ( ry >> biH );                \
-    rx <<= biH; ry <<= biH;             \
-    r0 += rx; r1 += (r0 < rx);          \
-    r0 += ry; r1 += (r0 < ry);          \
-    r0 +=  c; r1 += (r0 <  c);          \
-    r0 += *d; r1 += (r0 < *d);          \
-    c = r1; *(d++) = r0;
-
-#define MULADDC_STOP                    \
-}
-
-#endif /* C (generic)  */
-#endif /* C (longlong) */
-
-#endif /* bn_mul.h */
diff --git a/src/src/pdkim/polarssl/config.h b/src/src/pdkim/polarssl/config.h
deleted file mode 100644 (file)
index bfe1557..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#define POLARSSL_BASE64_C
-#define POLARSSL_BIGNUM_C
-#define POLARSSL_SHA1_C
-#define POLARSSL_SHA2_C
-#define POLARSSL_RSA_C
diff --git a/src/src/pdkim/polarssl/part-x509.h b/src/src/pdkim/polarssl/part-x509.h
deleted file mode 100644 (file)
index 991d0ac..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/* *************** begin copy from x509.h  ************************/
-/**
- * \file x509.h
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef POLARSSL_PART_X509_H
-#define POLARSSL_PART_X509_H
-
-/*
- * ASN1 Error codes
- *
- * These error codes will be OR'ed to X509 error codes for
- * higher error granularity.
- */
-#define POLARSSL_ERR_ASN1_OUT_OF_DATA                      0x0014
-#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG                   0x0016
-#define POLARSSL_ERR_ASN1_INVALID_LENGTH                   0x0018
-#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH                  0x001A
-#define POLARSSL_ERR_ASN1_INVALID_DATA                     0x001C
-
-/*
- * X509 Error codes
- */
-#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE              -0x0020
-#define POLARSSL_ERR_X509_CERT_INVALID_PEM                 -0x0040
-#define POLARSSL_ERR_X509_CERT_INVALID_FORMAT              -0x0060
-#define POLARSSL_ERR_X509_CERT_INVALID_VERSION             -0x0080
-#define POLARSSL_ERR_X509_CERT_INVALID_SERIAL              -0x00A0
-#define POLARSSL_ERR_X509_CERT_INVALID_ALG                 -0x00C0
-#define POLARSSL_ERR_X509_CERT_INVALID_NAME                -0x00E0
-#define POLARSSL_ERR_X509_CERT_INVALID_DATE                -0x0100
-#define POLARSSL_ERR_X509_CERT_INVALID_PUBKEY              -0x0120
-#define POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE           -0x0140
-#define POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS          -0x0160
-#define POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION             -0x0180
-#define POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG             -0x01A0
-#define POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG              -0x01C0
-#define POLARSSL_ERR_X509_CERT_SIG_MISMATCH                -0x01E0
-#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED               -0x0200
-#define POLARSSL_ERR_X509_KEY_INVALID_PEM                  -0x0220
-#define POLARSSL_ERR_X509_KEY_INVALID_VERSION              -0x0240
-#define POLARSSL_ERR_X509_KEY_INVALID_FORMAT               -0x0260
-#define POLARSSL_ERR_X509_KEY_INVALID_ENC_IV               -0x0280
-#define POLARSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG              -0x02A0
-#define POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED            -0x02C0
-#define POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH            -0x02E0
-#define POLARSSL_ERR_X509_POINT_ERROR                      -0x0300
-#define POLARSSL_ERR_X509_VALUE_TO_LENGTH                  -0x0320
-
-/*
- * DER constants
- */
-#define ASN1_BOOLEAN                 0x01
-#define ASN1_INTEGER                 0x02
-#define ASN1_BIT_STRING              0x03
-#define ASN1_OCTET_STRING            0x04
-#define ASN1_NULL                    0x05
-#define ASN1_OID                     0x06
-#define ASN1_UTF8_STRING             0x0C
-#define ASN1_SEQUENCE                0x10
-#define ASN1_SET                     0x11
-#define ASN1_PRINTABLE_STRING        0x13
-#define ASN1_T61_STRING              0x14
-#define ASN1_IA5_STRING              0x16
-#define ASN1_UTC_TIME                0x17
-#define ASN1_GENERALIZED_TIME        0x18
-#define ASN1_UNIVERSAL_STRING        0x1C
-#define ASN1_BMP_STRING              0x1E
-#define ASN1_PRIMITIVE               0x00
-#define ASN1_CONSTRUCTED             0x20
-#define ASN1_CONTEXT_SPECIFIC        0x80
-/* ***************   end copy from x509.h  ************************/
-
-#endif /* part-x509.h */
diff --git a/src/src/pdkim/polarssl/private-x509parse_c.h b/src/src/pdkim/polarssl/private-x509parse_c.h
deleted file mode 100644 (file)
index 112a114..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Functions defined in x509parse.c, which are not exported (static there) */
-/*
- *  X.509 certificate and private key decoding
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- *  The ITU-T X.509 standard defines a certificat format for PKI.
- *
- *  http://www.ietf.org/rfc/rfc2459.txt
- *  http://www.ietf.org/rfc/rfc3279.txt
- *
- *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
- *
- *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
- *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
- */
-
-
-
-int asn1_get_mpi( unsigned char **p,
-                         const unsigned char *end,
-                         mpi *X );
-
-int asn1_get_tag( unsigned char **p,
-                         const unsigned char *end,
-                         int *len, int tag );
-
-int asn1_get_int( unsigned char **p,
-                         const unsigned char *end,
-                         int *val );
diff --git a/src/src/pdkim/polarssl/rsa.h b/src/src/pdkim/polarssl/rsa.h
deleted file mode 100644 (file)
index 5fae794..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-/**
- * \file rsa.h
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_RSA_H
-#define POLARSSL_RSA_H
-
-#include "polarssl/bignum.h"
-
-/*
- * RSA Error codes
- */
-#define POLARSSL_ERR_RSA_BAD_INPUT_DATA                    -0x0400
-#define POLARSSL_ERR_RSA_INVALID_PADDING                   -0x0410
-#define POLARSSL_ERR_RSA_KEY_GEN_FAILED                    -0x0420
-#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED                  -0x0430
-#define POLARSSL_ERR_RSA_PUBLIC_FAILED                     -0x0440
-#define POLARSSL_ERR_RSA_PRIVATE_FAILED                    -0x0450
-#define POLARSSL_ERR_RSA_VERIFY_FAILED                     -0x0460
-#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE                  -0x0470
-#define POLARSSL_ERR_RSA_RNG_FAILED                        -0x0480
-
-/*
- * PKCS#1 constants
- */
-#define SIG_RSA_RAW     0
-#define SIG_RSA_MD2     2
-#define SIG_RSA_MD4     3
-#define SIG_RSA_MD5     4
-#define SIG_RSA_SHA1   5
-#define SIG_RSA_SHA224 14
-#define SIG_RSA_SHA256 11
-#define        SIG_RSA_SHA384  12
-#define SIG_RSA_SHA512 13
-
-#define RSA_PUBLIC      0
-#define RSA_PRIVATE     1
-
-#define RSA_PKCS_V15    0
-#define RSA_PKCS_V21    1
-
-#define RSA_SIGN        1
-#define RSA_CRYPT       2
-
-#define ASN1_STR_CONSTRUCTED_SEQUENCE  "\x30"
-#define ASN1_STR_NULL                          "\x05"
-#define ASN1_STR_OID                           "\x06"
-#define ASN1_STR_OCTET_STRING              "\x04"
-
-#define OID_DIGEST_ALG_MDX             "\x2A\x86\x48\x86\xF7\x0D\x02\x00"
-#define OID_HASH_ALG_SHA1              "\x2b\x0e\x03\x02\x1a"
-#define OID_HASH_ALG_SHA2X             "\x60\x86\x48\x01\x65\x03\x04\x02\x00"
-
-#define OID_ISO_MEMBER_BODIES      "\x2a"
-#define OID_ISO_IDENTIFIED_ORG     "\x2b"
-
-/*
- * ISO Member bodies OID parts
- */
-#define OID_COUNTRY_US                 "\x86\x48"
-#define OID_RSA_DATA_SECURITY      "\x86\xf7\x0d"
-
-/*
- * ISO Identified organization OID parts
- */
-#define OID_OIW_SECSIG_SHA1            "\x0e\x03\x02\x1a"
-
-/*
- * DigestInfo ::= SEQUENCE {
- *   digestAlgorithm DigestAlgorithmIdentifier,
- *   digest Digest }
- *
- * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
- *
- * Digest ::= OCTET STRING
- */
-#define ASN1_HASH_MDX                                          \
-(                                                                          \
-    ASN1_STR_CONSTRUCTED_SEQUENCE "\x20"               \
-      ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C"             \
-        ASN1_STR_OID "\x08"                                    \
-         OID_DIGEST_ALG_MDX                                    \
-       ASN1_STR_NULL "\x00"                                    \
-      ASN1_STR_OCTET_STRING "\x10"                         \
-)
-
-#define ASN1_HASH_SHA1                                         \
-    ASN1_STR_CONSTRUCTED_SEQUENCE "\x21"               \
-      ASN1_STR_CONSTRUCTED_SEQUENCE "\x09"             \
-        ASN1_STR_OID "\x05"                                    \
-         OID_HASH_ALG_SHA1                                         \
-        ASN1_STR_NULL "\x00"                               \
-      ASN1_STR_OCTET_STRING "\x14"
-
-#define ASN1_HASH_SHA2X                                                \
-    ASN1_STR_CONSTRUCTED_SEQUENCE "\x11"               \
-      ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d"             \
-        ASN1_STR_OID "\x09"                                    \
-         OID_HASH_ALG_SHA2X                                    \
-        ASN1_STR_NULL "\x00"                               \
-      ASN1_STR_OCTET_STRING "\x00"
-
-/**
- * \brief          RSA context structure
- */
-typedef struct
-{
-    int ver;                    /*!<  always 0          */
-    int len;                    /*!<  size(N) in chars  */
-
-    mpi N;                      /*!<  public modulus    */
-    mpi E;                      /*!<  public exponent   */
-
-    mpi D;                      /*!<  private exponent  */
-    mpi P;                      /*!<  1st prime factor  */
-    mpi Q;                      /*!<  2nd prime factor  */
-    mpi DP;                     /*!<  D % (P - 1)       */
-    mpi DQ;                     /*!<  D % (Q - 1)       */
-    mpi QP;                     /*!<  1 / (Q % P)       */
-
-    mpi RN;                     /*!<  cached R^2 mod N  */
-    mpi RP;                     /*!<  cached R^2 mod P  */
-    mpi RQ;                     /*!<  cached R^2 mod Q  */
-
-    int padding;                /*!<  1.5 or OAEP/PSS   */
-    int hash_id;                /*!<  hash identifier   */
-}
-rsa_context;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief          Initialize an RSA context
- *
- * \param ctx      RSA context to be initialized
- * \param padding  RSA_PKCS_V15 or RSA_PKCS_V21
- * \param hash_id  RSA_PKCS_V21 hash identifier
- *
- * \note           The hash_id parameter is actually ignored
- *                 when using RSA_PKCS_V15 padding.
- *
- * \note           Currently, RSA_PKCS_V21 padding
- *                 is not supported.
- */
-void rsa_init( rsa_context *ctx,
-               int padding,
-               int hash_id);
-
-/**
- * \brief          Generate an RSA keypair
- *
- * \param ctx      RSA context that will hold the key
- * \param f_rng    RNG function
- * \param p_rng    RNG parameter
- * \param nbits    size of the public key in bits
- * \param exponent public exponent (e.g., 65537)
- *
- * \note           rsa_init() must be called beforehand to setup
- *                 the RSA context.
- *
- * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- */
-int rsa_gen_key( rsa_context *ctx,
-                 int (*f_rng)(void *),
-                 void *p_rng,
-                 int nbits, int exponent );
-
-/**
- * \brief          Check a public RSA key
- *
- * \param ctx      RSA context to be checked
- *
- * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- */
-int rsa_check_pubkey( const rsa_context *ctx );
-
-/**
- * \brief          Check a private RSA key
- *
- * \param ctx      RSA context to be checked
- *
- * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- */
-int rsa_check_privkey( const rsa_context *ctx );
-
-/**
- * \brief          Do an RSA public key operation
- *
- * \param ctx      RSA context
- * \param input    input buffer
- * \param output   output buffer
- *
- * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note           This function does NOT take care of message
- *                 padding. Also, be sure to set input[0] = 0 or assure that
- *                 input is smaller than N.
- *
- * \note           The input and output buffers must be large
- *                 enough (eg. 128 bytes if RSA-1024 is used).
- */
-int rsa_public( rsa_context *ctx,
-                const unsigned char *input,
-                unsigned char *output );
-
-/**
- * \brief          Do an RSA private key operation
- *
- * \param ctx      RSA context
- * \param input    input buffer
- * \param output   output buffer
- *
- * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note           The input and output buffers must be large
- *                 enough (eg. 128 bytes if RSA-1024 is used).
- */
-int rsa_private( rsa_context *ctx,
-                 const unsigned char *input,
-                 unsigned char *output );
-
-/**
- * \brief          Add the message padding, then do an RSA operation
- *
- * \param ctx      RSA context
- * \param f_rng    RNG function
- * \param p_rng    RNG parameter
- * \param mode     RSA_PUBLIC or RSA_PRIVATE
- * \param ilen     contains the plaintext length
- * \param input    buffer holding the data to be encrypted
- * \param output   buffer that will hold the ciphertext
- *
- * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note           The output buffer must be as large as the size
- *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
- */
-int rsa_pkcs1_encrypt( rsa_context *ctx,
-                       int (*f_rng)(void *),
-                       void *p_rng,
-                       int mode, int  ilen,
-                       const unsigned char *input,
-                       unsigned char *output );
-
-/**
- * \brief          Do an RSA operation, then remove the message padding
- *
- * \param ctx      RSA context
- * \param mode     RSA_PUBLIC or RSA_PRIVATE
- * \param input    buffer holding the encrypted data
- * \param output   buffer that will hold the plaintext
- * \param olen     will contain the plaintext length
- * \param output_max_len       maximum length of the output buffer
- *
- * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note           The output buffer must be as large as the size
- *                 of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
- *                 an error is thrown.
- */
-int rsa_pkcs1_decrypt( rsa_context *ctx,
-                       int mode, int *olen,
-                       const unsigned char *input,
-                       unsigned char *output,
-                              int output_max_len );
-
-/**
- * \brief          Do a private RSA to sign a message digest
- *
- * \param ctx      RSA context
- * \param mode     RSA_PUBLIC or RSA_PRIVATE
- * \param hash_id  SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
- * \param hashlen  message digest length (for SIG_RSA_RAW only)
- * \param hash     buffer holding the message digest
- * \param sig      buffer that will hold the ciphertext
- *
- * \return         0 if the signing operation was successful,
- *                 or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note           The "sig" buffer must be as large as the size
- *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
- */
-int rsa_pkcs1_sign( rsa_context *ctx,
-                    int mode,
-                    int hash_id,
-                    int hashlen,
-                    const unsigned char *hash,
-                    unsigned char *sig );
-
-/**
- * \brief          Do a public RSA and check the message digest
- *
- * \param ctx      points to an RSA public key
- * \param mode     RSA_PUBLIC or RSA_PRIVATE
- * \param hash_id  SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
- * \param hashlen  message digest length (for SIG_RSA_RAW only)
- * \param hash     buffer holding the message digest
- * \param sig      buffer holding the ciphertext
- *
- * \return         0 if the verify operation was successful,
- *                 or an POLARSSL_ERR_RSA_XXX error code
- *
- * \note           The "sig" buffer must be as large as the size
- *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
- */
-int rsa_pkcs1_verify( rsa_context *ctx,
-                      int mode,
-                      int hash_id,
-                      int hashlen,
-                      const unsigned char *hash,
-                      unsigned char *sig );
-
-/**
- * \brief          Free the components of an RSA key
- *
- * \param ctx      RSA Context to free
- */
-void rsa_free( rsa_context *ctx );
-
-/**
- * \brief          Checkup routine
- *
- * \return         0 if successful, or 1 if the test failed
- */
-int rsa_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* rsa.h */
diff --git a/src/src/pdkim/polarssl/sha1.h b/src/src/pdkim/polarssl/sha1.h
deleted file mode 100644 (file)
index 98e8cc4..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * \file sha1.h
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_SHA1_H
-#define POLARSSL_SHA1_H
-
-/**
- * \brief          SHA-1 context structure
- */
-#ifndef HAVE_SHA1_CONTEXT
-#define HAVE_SHA1_CONTEXT
-typedef struct sha1_context sha1_context;
-#endif
-struct sha1_context
-{
-    unsigned long total[2];     /*!< number of bytes processed  */
-    unsigned long state[5];     /*!< intermediate digest state  */
-    unsigned char buffer[64];   /*!< data block being processed */
-
-    unsigned char ipad[64];     /*!< HMAC: inner padding        */
-    unsigned char opad[64];     /*!< HMAC: outer padding        */
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief          SHA-1 context setup
- *
- * \param ctx      context to be initialized
- */
-void sha1_starts( sha1_context *ctx );
-
-/**
- * \brief          SHA-1 process buffer
- *
- * \param ctx      SHA-1 context
- * \param input    buffer holding the  data
- * \param ilen     length of the input data
- */
-void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen );
-
-/**
- * \brief          SHA-1 final digest
- *
- * \param ctx      SHA-1 context
- * \param output   SHA-1 checksum result
- */
-void sha1_finish( sha1_context *ctx, unsigned char output[20] );
-
-/**
- * \brief          Output = SHA-1( input buffer )
- *
- * \param input    buffer holding the  data
- * \param ilen     length of the input data
- * \param output   SHA-1 checksum result
- */
-void polarssl_sha1( const unsigned char *input, int ilen, unsigned char output[20] );
-
-/**
- * \brief          Output = SHA-1( file contents )
- *
- * \param path     input file name
- * \param output   SHA-1 checksum result
- *
- * \return         0 if successful, 1 if fopen failed,
- *                 or 2 if fread failed
- */
-int sha1_file( const char *path, unsigned char output[20] );
-
-/**
- * \brief          SHA-1 HMAC context setup
- *
- * \param ctx      HMAC context to be initialized
- * \param key      HMAC secret key
- * \param keylen   length of the HMAC key
- */
-void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, int keylen );
-
-/**
- * \brief          SHA-1 HMAC process buffer
- *
- * \param ctx      HMAC context
- * \param input    buffer holding the  data
- * \param ilen     length of the input data
- */
-void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, int ilen );
-
-/**
- * \brief          SHA-1 HMAC final digest
- *
- * \param ctx      HMAC context
- * \param output   SHA-1 HMAC checksum result
- */
-void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] );
-
-/**
- * \brief          SHA-1 HMAC context reset
- *
- * \param ctx      HMAC context to be reset
- */
-void sha1_hmac_reset( sha1_context *ctx );
-
-/**
- * \brief          Output = HMAC-SHA-1( hmac key, input buffer )
- *
- * \param key      HMAC secret key
- * \param keylen   length of the HMAC key
- * \param input    buffer holding the  data
- * \param ilen     length of the input data
- * \param output   HMAC-SHA-1 result
- */
-void sha1_hmac( const unsigned char *key, int keylen,
-                const unsigned char *input, int ilen,
-                unsigned char output[20] );
-
-/**
- * \brief          Checkup routine
- *
- * \return         0 if successful, or 1 if the test failed
- */
-int sha1_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* sha1.h */
diff --git a/src/src/pdkim/polarssl/sha2.h b/src/src/pdkim/polarssl/sha2.h
deleted file mode 100644 (file)
index 26a6f1c..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * \file sha2.h
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef POLARSSL_SHA2_H
-#define POLARSSL_SHA2_H
-
-/**
- * \brief          SHA-256 context structure
- */
-#ifndef HAVE_SHA2_CONTEXT
-#define HAVE_SHA2_CONTEXT
-typedef struct sha2_context sha2_context;
-#endif
-
-struct sha2_context
-{
-    unsigned long total[2];     /*!< number of bytes processed  */
-    unsigned long state[8];     /*!< intermediate digest state  */
-    unsigned char buffer[64];   /*!< data block being processed */
-
-    unsigned char ipad[64];     /*!< HMAC: inner padding        */
-    unsigned char opad[64];     /*!< HMAC: outer padding        */
-    int is224;                  /*!< 0 => SHA-256, else SHA-224 */
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \brief          SHA-256 context setup
- *
- * \param ctx      context to be initialized
- * \param is224    0 = use SHA256, 1 = use SHA224
- */
-void sha2_starts( sha2_context *ctx, int is224 );
-
-/**
- * \brief          SHA-256 process buffer
- *
- * \param ctx      SHA-256 context
- * \param input    buffer holding the  data
- * \param ilen     length of the input data
- */
-void sha2_update( sha2_context *ctx, const unsigned char *input, int ilen );
-
-/**
- * \brief          SHA-256 final digest
- *
- * \param ctx      SHA-256 context
- * \param output   SHA-224/256 checksum result
- */
-void sha2_finish( sha2_context *ctx, unsigned char output[32] );
-
-/**
- * \brief          Output = SHA-256( input buffer )
- *
- * \param input    buffer holding the  data
- * \param ilen     length of the input data
- * \param output   SHA-224/256 checksum result
- * \param is224    0 = use SHA256, 1 = use SHA224
- */
-void sha2( const unsigned char *input, int ilen,
-           unsigned char output[32], int is224 );
-
-/**
- * \brief          Output = SHA-256( file contents )
- *
- * \param path     input file name
- * \param output   SHA-224/256 checksum result
- * \param is224    0 = use SHA256, 1 = use SHA224
- *
- * \return         0 if successful, 1 if fopen failed,
- *                 or 2 if fread failed
- */
-int sha2_file( const char *path, unsigned char output[32], int is224 );
-
-/**
- * \brief          SHA-256 HMAC context setup
- *
- * \param ctx      HMAC context to be initialized
- * \param key      HMAC secret key
- * \param keylen   length of the HMAC key
- * \param is224    0 = use SHA256, 1 = use SHA224
- */
-void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, int keylen,
-                       int is224 );
-
-/**
- * \brief          SHA-256 HMAC process buffer
- *
- * \param ctx      HMAC context
- * \param input    buffer holding the  data
- * \param ilen     length of the input data
- */
-void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, int ilen );
-
-/**
- * \brief          SHA-256 HMAC final digest
- *
- * \param ctx      HMAC context
- * \param output   SHA-224/256 HMAC checksum result
- */
-void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] );
-
-/**
- * \brief          SHA-256 HMAC context reset
- *
- * \param ctx      HMAC context to be reset
- */
-void sha2_hmac_reset( sha2_context *ctx );
-
-/**
- * \brief          Output = HMAC-SHA-256( hmac key, input buffer )
- *
- * \param key      HMAC secret key
- * \param keylen   length of the HMAC key
- * \param input    buffer holding the  data
- * \param ilen     length of the input data
- * \param output   HMAC-SHA-224/256 result
- * \param is224    0 = use SHA256, 1 = use SHA224
- */
-void sha2_hmac( const unsigned char *key, int keylen,
-                const unsigned char *input, int ilen,
-                unsigned char output[32], int is224 );
-
-/**
- * \brief          Checkup routine
- *
- * \return         0 if successful, or 1 if the test failed
- */
-int sha2_self_test( int verbose );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* sha2.h */
index 86d9f2ffe487e9447140a556ade754e2d5775897..c5d4c2efa2f0f114c040d5fd69b387c3fa92e1c5 100644 (file)
 /*
- *  The RSA public-key cryptosystem
+ *  PDKIM - a RFC4871 (DKIM) implementation
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2016  Exim maintainers
  *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- *  RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
- *
- *  http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
- *  http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
+ *  RSA signing/verification interface
  */
 
-#include "polarssl/config.h"
+#include "../exim.h"
 
-#if defined(POLARSSL_RSA_C)
+#ifndef DISABLE_DKIM   /* entire file */
 
-#include "polarssl/rsa.h"
+#ifndef SUPPORT_TLS
+# error Need SUPPORT_TLS for DKIM
+#endif
 
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
+#include "crypt_ver.h"
+#include "rsa.h"
 
-/*
- * Initialize an RSA context
- */
-void rsa_init( rsa_context *ctx,
-               int padding,
-               int hash_id )
-{
-    memset( ctx, 0, sizeof( rsa_context ) );
 
-    ctx->padding = padding;
-    ctx->hash_id = hash_id;
+/******************************************************************************/
+#ifdef RSA_GNUTLS
+
+void
+exim_rsa_init(void)
+{
 }
 
-#if defined(POLARSSL_GENPRIME)
 
-/*
- * Generate an RSA keypair
- */
-int rsa_gen_key( rsa_context *ctx,
-        int (*f_rng)(void *),
-        void *p_rng,
-        int nbits, int exponent )
+/* accumulate data (gnutls-only).  String to be appended must be nul-terminated. */
+blob *
+exim_rsa_data_append(blob * b, int * alloc, uschar * s)
 {
-    int ret;
-    mpi P1, Q1, H, G;
+int len = b->len;
+b->data = string_append(b->data, alloc, &len, 1, s);
+b->len = len;
+return b;
+}
 
-    if( f_rng == NULL || nbits < 128 || exponent < 3 )
-        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
-    mpi_init( &P1, &Q1, &H, &G, NULL );
 
-    /*
-     * find primes P and Q with Q < P so that:
-     * GCD( E, (P-1)*(Q-1) ) == 1
-     */
-    MPI_CHK( mpi_lset( &ctx->E, exponent ) );
+/* import private key from PEM string in memory.
+Return: NULL for success, or an error string */
 
-    do
-    {
-        MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
-                                f_rng, p_rng ) );
+const uschar *
+exim_rsa_signing_init(uschar * privkey_pem, es_ctx * sign_ctx)
+{
+gnutls_datum_t k;
+int rc;
 
-        MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
-                                f_rng, p_rng ) );
+k.data = privkey_pem;
+k.size = strlen(privkey_pem);
 
-        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
-            mpi_swap( &ctx->P, &ctx->Q );
+if (  (rc = gnutls_x509_privkey_init(&sign_ctx->rsa)) != GNUTLS_E_SUCCESS
+   /*|| (rc = gnutls_x509_privkey_import(sign_ctx->rsa, &k,
+         GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS */
+   )
+  return gnutls_strerror(rc);
 
-        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
-            continue;
+if (  /* (rc = gnutls_x509_privkey_init(&sign_ctx->rsa)) != GNUTLS_E_SUCCESS
+   ||*/ (rc = gnutls_x509_privkey_import(sign_ctx->rsa, &k,
+         GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS
+   )
+  return gnutls_strerror(rc);
 
-        MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
-        if( mpi_msb( &ctx->N ) != nbits )
-            continue;
+return NULL;
+}
 
-        MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
-        MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
-        MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
-        MPI_CHK( mpi_gcd( &G, &ctx->E, &H  ) );
-    }
-    while( mpi_cmp_int( &G, 1 ) != 0 );
 
-    /*
-     * D  = E^-1 mod ((P-1)*(Q-1))
-     * DP = D mod (P - 1)
-     * DQ = D mod (Q - 1)
-     * QP = Q^-1 mod P
-     */
-    MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H  ) );
-    MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
-    MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
-    MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
 
-    ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
+/* allocate mem for signature (when signing) */
+/* sign data (gnutls_only)
+OR
+sign hash.
 
-cleanup:
+Return: NULL for success, or an error string */
 
-    mpi_free( &G, &H, &Q1, &P1, NULL );
+const uschar *
+exim_rsa_sign(es_ctx * sign_ctx, BOOL is_sha1, blob * data, blob * sig)
+{
+gnutls_datum_t k;
+size_t sigsize = 0;
+int rc;
+const uschar * ret = NULL;
+
+/* Allocate mem for signature */
+k.data = data->data;
+k.size = data->len;
+(void) gnutls_x509_privkey_sign_data(sign_ctx->rsa,
+  is_sha1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256,
+  0, &k, NULL, &sigsize);
+
+sig->data = store_get(sigsize);
+sig->len = sigsize;
+
+/* Do signing */
+if ((rc = gnutls_x509_privkey_sign_data(sign_ctx->rsa,
+           is_sha1 ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_SHA256,
+           0, &k, sig->data, &sigsize)) != GNUTLS_E_SUCCESS
+   )
+  ret = gnutls_strerror(rc);
+
+gnutls_x509_privkey_deinit(sign_ctx->rsa);
+return ret;
+}
 
-    if( ret != 0 )
-    {
-        rsa_free( ctx );
-        return( POLARSSL_ERR_RSA_KEY_GEN_FAILED | ret );
-    }
 
-    return( 0 );
-}
 
-#endif
+/* import public key (from DER in memory)
+Return: NULL for success, or an error string */
 
-/*
- * Check a public RSA key
- */
-int rsa_check_pubkey( const rsa_context *ctx )
+const uschar *
+exim_rsa_verify_init(blob * pubkey_der, ev_ctx * verify_ctx)
 {
-    if( !ctx->N.p || !ctx->E.p )
-        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
-
-    if( ( ctx->N.p[0] & 1 ) == 0 ||
-        ( ctx->E.p[0] & 1 ) == 0 )
-        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+gnutls_datum_t k;
+int rc;
+const uschar * ret = NULL;
 
-    if( mpi_msb( &ctx->N ) < 128 ||
-        mpi_msb( &ctx->N ) > 4096 )
-        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+gnutls_pubkey_init(&verify_ctx->rsa);
 
-    if( mpi_msb( &ctx->E ) < 2 ||
-        mpi_msb( &ctx->E ) > 64 )
-        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+k.data = pubkey_der->data;
+k.size = pubkey_der->len;
 
-    return( 0 );
+if ((rc = gnutls_pubkey_import(verify_ctx->rsa, &k, GNUTLS_X509_FMT_DER))
+       != GNUTLS_E_SUCCESS)
+  ret = gnutls_strerror(rc);
+return ret;
 }
 
-/*
- * Check a private RSA key
- */
-int rsa_check_privkey( const rsa_context *ctx )
-{
-    int ret;
-    mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2;
 
-    if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
-        return( ret );
+/* verify signature (of hash)  (given pubkey & alleged sig)
+Return: NULL for success, or an error string */
 
-    if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
-        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+const uschar *
+exim_rsa_verify(ev_ctx * verify_ctx, BOOL is_sha1, blob * data_hash, blob * sig)
+{
+gnutls_datum_t k, s;
+int rc;
+const uschar * ret = NULL;
+
+k.data = data_hash->data;
+k.size = data_hash->len;
+s.data = sig->data;
+s.size = sig->len;
+if ((rc = gnutls_pubkey_verify_hash2(verify_ctx->rsa,
+           is_sha1 ? GNUTLS_SIGN_RSA_SHA1 : GNUTLS_SIGN_RSA_SHA256,
+           0, &k, &s)) < 0)
+  ret = gnutls_strerror(rc);
+
+gnutls_pubkey_deinit(verify_ctx->rsa);
+return ret;
+}
 
-    mpi_init( &PQ, &DE, &P1, &Q1, &H, &I, &G, &G2, &L1, &L2, NULL );
 
-    MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
-    MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
-    MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
-    MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
-    MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
-    MPI_CHK( mpi_gcd( &G, &ctx->E, &H  ) );
 
-    MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) );
-    MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) );
-    MPI_CHK( mpi_mod_mpi( &I, &DE, &L1  ) );
 
-    /*
-     * Check for a valid PKCS1v2 private key
-     */
-    if( mpi_cmp_mpi( &PQ, &ctx->N ) == 0 &&
-        mpi_cmp_int( &L2, 0 ) == 0 &&
-        mpi_cmp_int( &I, 1 ) == 0 &&
-        mpi_cmp_int( &G, 1 ) == 0 )
-    {
-        mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL );
-        return( 0 );
-    }
+#elif defined(RSA_GCRYPT)
+/******************************************************************************/
 
 
-cleanup:
+/* Internal service routine:
+Read and move past an asn.1 header, checking class & tag,
+optionally returning the data-length */
 
-    mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL );
-    return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED | ret );
-}
-
-/*
- * Do an RSA public key operation
- */
-int rsa_public( rsa_context *ctx,
-                const unsigned char *input,
-                unsigned char *output )
+static int
+as_tag(blob * der, uschar req_cls, long req_tag, long * alen)
 {
-    int ret, olen;
-    mpi T;
-
-    mpi_init( &T, NULL );
-
-    MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+int rc;
+uschar tag_class;
+int taglen;
+long tag, len;
 
-    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
-    {
-        mpi_free( &T, NULL );
-        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-    }
+/* debug_printf("as_tag: %02x %02x %02x %02x\n",
+       der->data[0], der->data[1], der->data[2], der->data[3]); */
 
-    olen = ctx->len;
-    MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
-    MPI_CHK( mpi_write_binary( &T, output, olen ) );
+if ((rc = asn1_get_tag_der(der->data++, der->len--, &tag_class, &taglen, &tag))
+    != ASN1_SUCCESS)
+  return rc;
 
-cleanup:
+if (tag_class != req_cls || tag != req_tag) return ASN1_ELEMENT_NOT_FOUND;
 
-    mpi_free( &T, NULL );
+if ((len = asn1_get_length_der(der->data, der->len, &taglen)) < 0)
+  return ASN1_DER_ERROR;
+if (alen) *alen = len;
 
-    if( ret != 0 )
-        return( POLARSSL_ERR_RSA_PUBLIC_FAILED | ret );
+/* debug_printf("as_tag:  tlen %d dlen %d\n", taglen, (int)len); */
 
-    return( 0 );
+der->data += taglen;
+der->len -= taglen;
+return rc;
 }
 
-/*
- * Do an RSA private key operation
- */
-int rsa_private( rsa_context *ctx,
-                 const unsigned char *input,
-                 unsigned char *output )
+/* Internal service routine:
+Read and move over an asn.1 integer, setting an MPI to the value
+*/
+
+static uschar *
+as_mpi(blob * der, gcry_mpi_t * mpi)
 {
-    int ret, olen;
-    mpi T, T1, T2;
-
-    mpi_init( &T, &T1, &T2, NULL );
-
-    MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
-
-    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
-    {
-        mpi_free( &T, NULL );
-        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-    }
-
-#if 0
-    MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
-#else
-    /*
-     * faster decryption using the CRT
-     *
-     * T1 = input ^ dP mod P
-     * T2 = input ^ dQ mod Q
-     */
-    MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
-    MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
-
-    /*
-     * T = (T1 - T2) * (Q^-1 mod P) mod P
-     */
-    MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
-    MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
-    MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
-
-    /*
-     * output = T2 + T * Q
-     */
-    MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
-    MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
-#endif
+long alen;
+int rc;
+gcry_error_t gerr;
 
-    olen = ctx->len;
-    MPI_CHK( mpi_write_binary( &T, output, olen ) );
+/* integer; move past the header */
+if ((rc = as_tag(der, 0, ASN1_TAG_INTEGER, &alen)) != ASN1_SUCCESS)
+  return US asn1_strerror(rc);
 
-cleanup:
+/* read to an MPI */
+if ((gerr = gcry_mpi_scan(mpi, GCRYMPI_FMT_STD, der->data, alen, NULL)))
+  return US gcry_strerror(gerr);
 
-    mpi_free( &T, &T1, &T2, NULL );
+/* move over the data */
+der->data += alen; der->len -= alen;
+return NULL;
+}
 
-    if( ret != 0 )
-        return( POLARSSL_ERR_RSA_PRIVATE_FAILED | ret );
 
-    return( 0 );
-}
 
-/*
- * Add the message padding, then do an RSA operation
- */
-int rsa_pkcs1_encrypt( rsa_context *ctx,
-                       int (*f_rng)(void *),
-                       void *p_rng,
-                       int mode, int  ilen,
-                       const unsigned char *input,
-                       unsigned char *output )
+void
+exim_rsa_init(void)
 {
-    int nb_pad, olen;
-    unsigned char *p = output;
+/* Version check should be the very first call because it
+makes sure that important subsystems are initialized. */
+if (!gcry_check_version (GCRYPT_VERSION))
+  {
+  fputs ("libgcrypt version mismatch\n", stderr);
+  exit (2);
+  }
 
-    olen = ctx->len;
+/* We don't want to see any warnings, e.g. because we have not yet
+parsed program options which might be used to suppress such
+warnings. */
+gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
 
-    switch( ctx->padding )
-    {
-        case RSA_PKCS_V15:
+/* ... If required, other initialization goes here.  Note that the
+process might still be running with increased privileges and that
+the secure memory has not been initialized.  */
 
-            if( ilen < 0 || olen < ilen + 11 || f_rng == NULL )
-                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+/* Allocate a pool of 16k secure memory.  This make the secure memory
+available and also drops privileges where needed.  */
+gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
 
-            nb_pad = olen - 3 - ilen;
+/* It is now okay to let Libgcrypt complain when there was/is
+a problem with the secure memory. */
+gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
 
-            *p++ = 0;
-            *p++ = RSA_CRYPT;
+/* ... If required, other initialization goes here.  */
 
-            while( nb_pad-- > 0 )
-            {
-                int rng_dl = 100;
+/* Tell Libgcrypt that initialization has completed. */
+gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
 
-                do {
-                    *p = (unsigned char) f_rng( p_rng );
-                } while( *p == 0 && --rng_dl );
-
-                // Check if RNG failed to generate data
-                //
-                if( rng_dl == 0 )
-                    return POLARSSL_ERR_RSA_RNG_FAILED;
+return;
+}
 
-                p++;
-            }
-            *p++ = 0;
-            memcpy( p, input, ilen );
-            break;
 
-        default:
 
-            return( POLARSSL_ERR_RSA_INVALID_PADDING );
-    }
 
-    return( ( mode == RSA_PUBLIC )
-            ? rsa_public(  ctx, output, output )
-            : rsa_private( ctx, output, output ) );
-}
+/* Accumulate data (gnutls-only).
+String to be appended must be nul-terminated. */
 
-/*
- * Do an RSA operation, then remove the message padding
- */
-int rsa_pkcs1_decrypt( rsa_context *ctx,
-                       int mode, int *olen,
-                       const unsigned char *input,
-                       unsigned char *output,
-                       int output_max_len)
+blob *
+exim_rsa_data_append(blob * b, int * alloc, uschar * s)
 {
-    int ret, ilen;
-    unsigned char *p;
-    unsigned char buf[1024];
-
-    ilen = ctx->len;
+return b;      /*dummy*/
+}
 
-    if( ilen < 16 || ilen > (int) sizeof( buf ) )
-        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
 
-    ret = ( mode == RSA_PUBLIC )
-          ? rsa_public(  ctx, input, buf )
-          : rsa_private( ctx, input, buf );
 
-    if( ret != 0 )
-        return( ret );
+/* import private key from PEM string in memory.
+Return: NULL for success, or an error string */
 
-    p = buf;
+const uschar *
+exim_rsa_signing_init(uschar * privkey_pem, es_ctx * sign_ctx)
+{
+uschar * s1, * s2;
+blob der;
+long alen;
+int rc;
 
-    switch( ctx->padding )
-    {
-        case RSA_PKCS_V15:
+/*
+ *  RSAPrivateKey ::= SEQUENCE
+ *      version           Version,
+ *      modulus           INTEGER,  -- n
+ *      publicExponent    INTEGER,  -- e
+ *      privateExponent   INTEGER,  -- d
+ *      prime1            INTEGER,  -- p
+ *      prime2            INTEGER,  -- q
+ *      exponent1         INTEGER,  -- d mod (p-1)
+ *      exponent2         INTEGER,  -- d mod (q-1)
+ *      coefficient       INTEGER,  -- (inverse of q) mod p
+ *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
+ */
+if (  !(s1 = Ustrstr(CS privkey_pem, "-----BEGIN RSA PRIVATE KEY-----"))
+   || !(s2 = Ustrstr(CS (s1+=31),    "-----END RSA PRIVATE KEY-----" ))
+   )
+  return US"Bad PEM wrapper";
+
+*s2 = '\0';
+
+if ((der.len = b64decode(s1, &der.data)) < 0)
+  return US"Bad PEM-DER b64 decode";
+
+/* untangle asn.1 */
+
+/* sequence; just move past the header */
+if ((rc = as_tag(&der, ASN1_CLASS_STRUCTURED, ASN1_TAG_SEQUENCE, NULL))
+   != ASN1_SUCCESS) goto asn_err;
+
+/* integer version; move past the header, check is zero */
+if ((rc = as_tag(&der, 0, ASN1_TAG_INTEGER, &alen)) != ASN1_SUCCESS)
+  goto asn_err;
+if (alen != 1 || *der.data != 0)
+  return US"Bad version number";
+der.data++; der.len--;
+
+if (  (s1 = as_mpi(&der, &sign_ctx->n))
+   || (s1 = as_mpi(&der, &sign_ctx->e))
+   || (s1 = as_mpi(&der, &sign_ctx->d))
+   || (s1 = as_mpi(&der, &sign_ctx->p))
+   || (s1 = as_mpi(&der, &sign_ctx->q))
+   || (s1 = as_mpi(&der, &sign_ctx->dp))
+   || (s1 = as_mpi(&der, &sign_ctx->dq))
+   || (s1 = as_mpi(&der, &sign_ctx->qp))
+   )
+  return s1;
+
+DEBUG(D_acl) debug_printf("rsa_signing_init:\n");
+  {
+  uschar * s;
+  gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, sign_ctx->n);
+  debug_printf(" N : %s\n", s);
+  gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, sign_ctx->e);
+  debug_printf(" E : %s\n", s);
+  gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, sign_ctx->d);
+  debug_printf(" D : %s\n", s);
+  gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, sign_ctx->p);
+  debug_printf(" P : %s\n", s);
+  gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, sign_ctx->q);
+  debug_printf(" Q : %s\n", s);
+  gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, sign_ctx->dp);
+  debug_printf(" DP: %s\n", s);
+  gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, sign_ctx->dq);
+  debug_printf(" DQ: %s\n", s);
+  gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, sign_ctx->qp);
+  debug_printf(" QP: %s\n", s);
+  }
+return NULL;
+
+asn_err: return US asn1_strerror(rc);
+}
 
-            if( *p++ != 0 || *p++ != RSA_CRYPT )
-                return( POLARSSL_ERR_RSA_INVALID_PADDING );
 
-            while( *p != 0 )
-            {
-                if( p >= buf + ilen - 1 )
-                    return( POLARSSL_ERR_RSA_INVALID_PADDING );
-                p++;
-            }
-            p++;
-            break;
 
-        default:
+/* allocate mem for signature (when signing) */
+/* sign data (gnutls_only)
+OR
+sign hash.
 
-            return( POLARSSL_ERR_RSA_INVALID_PADDING );
-    }
+Return: NULL for success, or an error string */
 
-    if (ilen - (int)(p - buf) > output_max_len)
-       return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+const uschar *
+exim_rsa_sign(es_ctx * sign_ctx, BOOL is_sha1, blob * data, blob * sig)
+{
+gcry_sexp_t s_hash = NULL, s_key = NULL, s_sig = NULL;
+gcry_mpi_t m_sig;
+uschar * errstr;
+gcry_error_t gerr;
+
+#define SIGSPACE 128
+sig->data = store_get(SIGSPACE);
+
+if (gcry_mpi_cmp (sign_ctx->p, sign_ctx->q) > 0)
+  {
+  gcry_mpi_swap (sign_ctx->p, sign_ctx->q);
+  gcry_mpi_invm (sign_ctx->qp, sign_ctx->p, sign_ctx->q);
+  }
+
+if (  (gerr = gcry_sexp_build (&s_key, NULL,
+               "(private-key (rsa (n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
+               sign_ctx->n, sign_ctx->e,
+               sign_ctx->d, sign_ctx->p,
+               sign_ctx->q, sign_ctx->qp))
+   || (gerr = gcry_sexp_build (&s_hash, NULL,
+               is_sha1
+               ? "(data(flags pkcs1)(hash sha1 %b))"
+               : "(data(flags pkcs1)(hash sha256 %b))",
+               (int) data->len, CS data->data))
+   ||  (gerr = gcry_pk_sign (&s_sig, s_hash, s_key))
+   )
+  return US gcry_strerror(gerr);
+
+/* gcry_sexp_dump(s_sig); */
+
+if (  !(s_sig = gcry_sexp_find_token(s_sig, "s", 0))
+   )
+  return US"no sig result";
+
+m_sig = gcry_sexp_nth_mpi(s_sig, 1, GCRYMPI_FMT_USG);
+
+DEBUG(D_acl)
+  {
+  uschar * s;
+  gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, m_sig);
+  debug_printf(" SG: %s\n", s);
+  }
+
+gerr = gcry_mpi_print(GCRYMPI_FMT_USG, sig->data, SIGSPACE, &sig->len, m_sig);
+if (gerr)
+  {
+  debug_printf("signature conversion from MPI to buffer failed\n");
+  return US gcry_strerror(gerr);
+  }
+#undef SIGSPACE
+
+return NULL;
+}
 
-    *olen = ilen - (int)(p - buf);
-    memcpy( output, p, *olen );
 
-    return( 0 );
-}
+/* import public key (from DER in memory)
+Return: NULL for success, or an error string */
 
-/*
- * Do an RSA operation to sign the message digest
- */
-int rsa_pkcs1_sign( rsa_context *ctx,
-                    int mode,
-                    int hash_id,
-                    int hashlen,
-                    const unsigned char *hash,
-                    unsigned char *sig )
+const uschar *
+exim_rsa_verify_init(blob * pubkey_der, ev_ctx * verify_ctx)
 {
-    int nb_pad, olen;
-    unsigned char *p = sig;
-
-    olen = ctx->len;
-
-    switch( ctx->padding )
-    {
-        case RSA_PKCS_V15:
-
-            switch( hash_id )
-            {
-                case SIG_RSA_RAW:
-                    nb_pad = olen - 3 - hashlen;
-                    break;
-
-                case SIG_RSA_MD2:
-                case SIG_RSA_MD4:
-                case SIG_RSA_MD5:
-                    nb_pad = olen - 3 - 34;
-                    break;
-
-                case SIG_RSA_SHA1:
-                    nb_pad = olen - 3 - 35;
-                    break;
-
-                case SIG_RSA_SHA224:
-                    nb_pad = olen - 3 - 47;
-                    break;
-
-                case SIG_RSA_SHA256:
-                    nb_pad = olen - 3 - 51;
-                    break;
-
-                case SIG_RSA_SHA384:
-                    nb_pad = olen - 3 - 67;
-                    break;
-
-                case SIG_RSA_SHA512:
-                    nb_pad = olen - 3 - 83;
-                    break;
-
-
-                default:
-                    return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-            }
-
-            if( nb_pad < 8 )
-                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
-            *p++ = 0;
-            *p++ = RSA_SIGN;
-            memset( p, 0xFF, nb_pad );
-            p += nb_pad;
-            *p++ = 0;
-            break;
-
-        default:
-
-            return( POLARSSL_ERR_RSA_INVALID_PADDING );
-    }
-
-    switch( hash_id )
-    {
-        case SIG_RSA_RAW:
-            memcpy( p, hash, hashlen );
-            break;
-
-        case SIG_RSA_MD2:
-            memcpy( p, ASN1_HASH_MDX, 18 );
-            memcpy( p + 18, hash, 16 );
-            p[13] = 2; break;
-
-        case SIG_RSA_MD4:
-            memcpy( p, ASN1_HASH_MDX, 18 );
-            memcpy( p + 18, hash, 16 );
-            p[13] = 4; break;
-
-        case SIG_RSA_MD5:
-            memcpy( p, ASN1_HASH_MDX, 18 );
-            memcpy( p + 18, hash, 16 );
-            p[13] = 5; break;
-
-        case SIG_RSA_SHA1:
-            memcpy( p, ASN1_HASH_SHA1, 15 );
-            memcpy( p + 15, hash, 20 );
-            break;
-
-        case SIG_RSA_SHA224:
-            memcpy( p, ASN1_HASH_SHA2X, 19 );
-            memcpy( p + 19, hash, 28 );
-            p[1] += 28; p[14] = 4; p[18] += 28; break;
-
-        case SIG_RSA_SHA256:
-            memcpy( p, ASN1_HASH_SHA2X, 19 );
-            memcpy( p + 19, hash, 32 );
-            p[1] += 32; p[14] = 1; p[18] += 32; break;
-
-        case SIG_RSA_SHA384:
-            memcpy( p, ASN1_HASH_SHA2X, 19 );
-            memcpy( p + 19, hash, 48 );
-            p[1] += 48; p[14] = 2; p[18] += 48; break;
-
-        case SIG_RSA_SHA512:
-            memcpy( p, ASN1_HASH_SHA2X, 19 );
-            memcpy( p + 19, hash, 64 );
-            p[1] += 64; p[14] = 3; p[18] += 64; break;
-
-        default:
-            return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-    }
-
-    return( ( mode == RSA_PUBLIC )
-            ? rsa_public(  ctx, sig, sig )
-            : rsa_private( ctx, sig, sig ) );
-}
-
 /*
- * Do an RSA operation and check the message digest
- */
-int rsa_pkcs1_verify( rsa_context *ctx,
-                      int mode,
-                      int hash_id,
-                      int hashlen,
-                      const unsigned char *hash,
-                      unsigned char *sig )
-{
-    int ret, len, siglen;
-    unsigned char *p, c;
-    unsigned char buf[1024];
-
-    siglen = ctx->len;
-
-    if( siglen < 16 || siglen > (int) sizeof( buf ) )
-        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
-
-    ret = ( mode == RSA_PUBLIC )
-          ? rsa_public(  ctx, sig, buf )
-          : rsa_private( ctx, sig, buf );
-
-    if( ret != 0 )
-        return( ret );
-
-    p = buf;
-
-    switch( ctx->padding )
-    {
-        case RSA_PKCS_V15:
-
-            if( *p++ != 0 || *p++ != RSA_SIGN )
-                return( POLARSSL_ERR_RSA_INVALID_PADDING );
-
-            while( *p != 0 )
-            {
-                if( p >= buf + siglen - 1 || *p != 0xFF )
-                    return( POLARSSL_ERR_RSA_INVALID_PADDING );
-                p++;
-            }
-            p++;
-            break;
-
-        default:
-
-            return( POLARSSL_ERR_RSA_INVALID_PADDING );
-    }
-
-    len = siglen - (int)( p - buf );
-
-    if( len == 34 )
-    {
-        c = p[13];
-        p[13] = 0;
-
-        if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
-            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
-
-        if( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
-            ( c == 4 && hash_id == SIG_RSA_MD4 ) ||
-            ( c == 5 && hash_id == SIG_RSA_MD5 ) )
-        {
-            if( memcmp( p + 18, hash, 16 ) == 0 )
-                return( 0 );
-            else
-                return( POLARSSL_ERR_RSA_VERIFY_FAILED );
-        }
-    }
-
-    if( len == 35 && hash_id == SIG_RSA_SHA1 )
-    {
-        if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
-            memcmp( p + 15, hash, 20 ) == 0 )
-            return( 0 );
-        else
-            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
-    }
-    if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
-        ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
-        ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
-        ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
-    {
-       c = p[1] - 17;
-        p[1] = 17;
-        p[14] = 0;
-
-        if( p[18] == c &&
-                memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
-                memcmp( p + 19, hash, c ) == 0 )
-            return( 0 );
-        else
-            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
-    }
-
-    if( len == hashlen && hash_id == SIG_RSA_RAW )
-    {
-        if( memcmp( p, hash, hashlen ) == 0 )
-            return( 0 );
-        else
-            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
-    }
-
-    return( POLARSSL_ERR_RSA_INVALID_PADDING );
-}
+in code sequence per b81207d2bfa92 rsa_parse_public_key() and asn1_get_mpi()
+*/
+uschar tag_class;
+int taglen;
+long alen;
+int rc;
+uschar * errstr;
+gcry_error_t gerr;
+uschar * stage = US"S1";
 
 /*
- * Free the components of an RSA key
- */
-void rsa_free( rsa_context *ctx )
-{
-    mpi_free( &ctx->RQ, &ctx->RP, &ctx->RN,
-              &ctx->QP, &ctx->DQ, &ctx->DP,
-              &ctx->Q,  &ctx->P,  &ctx->D,
-              &ctx->E,  &ctx->N,  NULL );
+sequence
+ sequence
+  OBJECT:rsaEncryption
+  NULL
+ BIT STRING:RSAPublicKey
+  sequence
+   INTEGER:Public modulus
+   INTEGER:Public exponent
+
+openssl rsa -in aux-fixed/dkim/dkim.private -pubout -outform DER | od -t x1 | head;
+openssl rsa -in aux-fixed/dkim/dkim.private -pubout | openssl asn1parse -dump;
+openssl rsa -in aux-fixed/dkim/dkim.private -pubout | openssl asn1parse -dump -offset 22;
+*/
+
+/* sequence; just move past the header */
+if ((rc = as_tag(pubkey_der, ASN1_CLASS_STRUCTURED, ASN1_TAG_SEQUENCE, NULL))
+   != ASN1_SUCCESS) goto asn_err;
+
+/* sequence; skip the entire thing */
+DEBUG(D_acl) stage = US"S2";
+if ((rc = as_tag(pubkey_der, ASN1_CLASS_STRUCTURED, ASN1_TAG_SEQUENCE, &alen))
+   != ASN1_SUCCESS) goto asn_err;
+pubkey_der->data += alen; pubkey_der->len -= alen;
+
+
+/* bitstring: limit range to size of bitstring;
+move over header + content wrapper */
+DEBUG(D_acl) stage = US"BS";
+if ((rc = as_tag(pubkey_der, 0, ASN1_TAG_BIT_STRING, &alen)) != ASN1_SUCCESS)
+  goto asn_err;
+pubkey_der->len = alen;
+pubkey_der->data++; pubkey_der->len--;
+
+/* sequence; just move past the header */
+DEBUG(D_acl) stage = US"S3";
+if ((rc = as_tag(pubkey_der, ASN1_CLASS_STRUCTURED, ASN1_TAG_SEQUENCE, NULL))
+   != ASN1_SUCCESS) goto asn_err;
+
+/* read two integers */
+DEBUG(D_acl) stage = US"MPI";
+if (  (errstr = as_mpi(pubkey_der, &verify_ctx->n))
+   || (errstr = as_mpi(pubkey_der, &verify_ctx->e))
+   )
+  return errstr;
+
+DEBUG(D_acl) debug_printf("rsa_verify_init:\n");
+       {
+       uschar * s;
+       gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, verify_ctx->n);
+       debug_printf(" N : %s\n", s);
+       gcry_mpi_aprint (GCRYMPI_FMT_HEX, &s, NULL, verify_ctx->e);
+       debug_printf(" E : %s\n", s);
+       }
+
+return NULL;
+
+asn_err:
+DEBUG(D_acl) return string_sprintf("%s: %s", stage, asn1_strerror(rc));
+            return US asn1_strerror(rc);
 }
 
-#if defined(POLARSSL_SELF_TEST)
 
-#include "polarssl/sha1.h"
+/* verify signature (of hash)  (given pubkey & alleged sig)
+Return: NULL for success, or an error string */
 
-/*
- * Example RSA-1024 keypair, for test purposes
- */
-#define KEY_LEN 128
-
-#define RSA_N   "9292758453063D803DD603D5E777D788" \
-                "8ED1D5BF35786190FA2F23EBC0848AEA" \
-                "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
-                "7130B9CED7ACDF54CFC7555AC14EEBAB" \
-                "93A89813FBF3C4F8066D2D800F7C38A8" \
-                "1AE31942917403FF4946B0A83D3D3E05" \
-                "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
-                "5E94BB77B07507233A0BC7BAC8F90F79"
-
-#define RSA_E   "10001"
-
-#define RSA_D   "24BF6185468786FDD303083D25E64EFC" \
-                "66CA472BC44D253102F8B4A9D3BFA750" \
-                "91386C0077937FE33FA3252D28855837" \
-                "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
-                "DF79C5CE07EE72C7F123142198164234" \
-                "CABB724CF78B8173B9F880FC86322407" \
-                "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
-                "071513A1E85B5DFA031F21ECAE91A34D"
-
-#define RSA_P   "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
-                "2C01CAD19EA484A87EA4377637E75500" \
-                "FCB2005C5C7DD6EC4AC023CDA285D796" \
-                "C3D9E75E1EFC42488BB4F1D13AC30A57"
-
-#define RSA_Q   "C000DF51A7C77AE8D7C7370C1FF55B69" \
-                "E211C2B9E5DB1ED0BF61D0D9899620F4" \
-                "910E4168387E3C30AA1E00C339A79508" \
-                "8452DD96A9A5EA5D9DCA68DA636032AF"
-
-#define RSA_DP  "C1ACF567564274FB07A0BBAD5D26E298" \
-                "3C94D22288ACD763FD8E5600ED4A702D" \
-                "F84198A5F06C2E72236AE490C93F07F8" \
-                "3CC559CD27BC2D1CA488811730BB5725"
-
-#define RSA_DQ  "4959CBF6F8FEF750AEE6977C155579C7" \
-                "D8AAEA56749EA28623272E4F7D0592AF" \
-                "7C1F1313CAC9471B5C523BFE592F517B" \
-                "407A1BD76C164B93DA2D32A383E58357"
-
-#define RSA_QP  "9AE7FBC99546432DF71896FC239EADAE" \
-                "F38D18D2B2F0E2DD275AA977E2BF4411" \
-                "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
-                "A74206CEC169D74BF5A8C50D6F48EA08"
-
-#define PT_LEN  24
-#define RSA_PT  "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
-                "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
-
-static int myrand( void *rng_state )
+const uschar *
+exim_rsa_verify(ev_ctx * verify_ctx, BOOL is_sha1, blob * data_hash, blob * sig)
 {
-    if( rng_state != NULL )
-        rng_state  = NULL;
-
-    return( rand() );
-}
-
 /*
- * Checkup routine
- */
-int rsa_self_test( int verbose )
-{
-    int len;
-    rsa_context rsa;
-    unsigned char sha1sum[20];
-    unsigned char rsa_plaintext[PT_LEN];
-    unsigned char rsa_decrypted[PT_LEN];
-    unsigned char rsa_ciphertext[KEY_LEN];
+cf. libgnutls 2.8.5 _wrap_gcry_pk_verify()
+*/
+gcry_mpi_t m_sig;
+gcry_sexp_t s_sig = NULL, s_hash = NULL, s_pkey = NULL;
+gcry_error_t gerr;
+uschar * stage;
+
+if (  (stage = US"pkey sexp build",
+       gerr = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%m)(e%m)))",
+                       verify_ctx->n, verify_ctx->e))
+   || (stage = US"data sexp build",
+       gerr = gcry_sexp_build (&s_hash, NULL,
+               is_sha1
+               ? "(data(flags pkcs1)(hash sha1 %b))"
+               : "(data(flags pkcs1)(hash sha256 %b))",
+               (int) data_hash->len, CS data_hash->data))
+   || (stage = US"sig mpi scan",
+       gerr = gcry_mpi_scan(&m_sig, GCRYMPI_FMT_USG, sig->data, sig->len, NULL))
+   || (stage = US"sig sexp build",
+       gerr = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", m_sig))
+   || (stage = US"verify",
+       gerr = gcry_pk_verify (s_sig, s_hash, s_pkey))
+   )
+  {
+  DEBUG(D_acl) debug_printf("verify: error in stage '%s'\n", stage);
+  return US gcry_strerror(gerr);
+  }
+
+if (s_sig) gcry_sexp_release (s_sig);
+if (s_hash) gcry_sexp_release (s_hash);
+if (s_pkey) gcry_sexp_release (s_pkey);
+gcry_mpi_release (m_sig);
+gcry_mpi_release (verify_ctx->n);
+gcry_mpi_release (verify_ctx->e);
+
+return NULL;
+}
 
-    rsa_init( &rsa, RSA_PKCS_V15, 0 );
 
-    rsa.len = KEY_LEN;
-    mpi_read_string( &rsa.N , 16, RSA_N  );
-    mpi_read_string( &rsa.E , 16, RSA_E  );
-    mpi_read_string( &rsa.D , 16, RSA_D  );
-    mpi_read_string( &rsa.P , 16, RSA_P  );
-    mpi_read_string( &rsa.Q , 16, RSA_Q  );
-    mpi_read_string( &rsa.DP, 16, RSA_DP );
-    mpi_read_string( &rsa.DQ, 16, RSA_DQ );
-    mpi_read_string( &rsa.QP, 16, RSA_QP );
 
-    if( verbose != 0 )
-        printf( "  RSA key validation: " );
 
-    if( rsa_check_pubkey(  &rsa ) != 0 ||
-        rsa_check_privkey( &rsa ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
+#elif defined(RSA_OPENSSL)
+/******************************************************************************/
 
-        return( 1 );
-    }
+void
+exim_rsa_init(void)
+{
+}
 
-    if( verbose != 0 )
-        printf( "passed\n  PKCS#1 encryption : " );
 
-    memcpy( rsa_plaintext, RSA_PT, PT_LEN );
+/* accumulate data (gnutls-only) */
+blob *
+exim_rsa_data_append(blob * b, int * alloc, uschar * s)
+{
+return b;      /*dummy*/
+}
 
-    if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN,
-                           rsa_plaintext, rsa_ciphertext ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
 
-        return( 1 );
-    }
+/* import private key from PEM string in memory.
+Return: NULL for success, or an error string */
 
-    if( verbose != 0 )
-        printf( "passed\n  PKCS#1 decryption : " );
+const uschar *
+exim_rsa_signing_init(uschar * privkey_pem, es_ctx * sign_ctx)
+{
+uschar * p, * q;
+int len;
+
+/* Convert PEM to DER */
+if (  !(p = Ustrstr(privkey_pem, "-----BEGIN RSA PRIVATE KEY-----"))
+   || !(q = Ustrstr(p+=31,       "-----END RSA PRIVATE KEY-----"))
+   )
+  return US"Bad PEM wrapping";
+
+*q = '\0';
+if ((len = b64decode(p, &p)) < 0)
+  return US"b64decode failed";
+
+if (!(sign_ctx->rsa = d2i_RSAPrivateKey(NULL, CUSS &p, len)))
+  {
+  char ssl_errstring[256];
+  ERR_load_crypto_strings();   /*XXX move to a startup routine */
+  ERR_error_string(ERR_get_error(), ssl_errstring);
+  return string_copy(ssl_errstring);
+  }
+
+return NULL;
+}
 
-    if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len,
-                           rsa_ciphertext, rsa_decrypted,
-                          sizeof(rsa_decrypted) ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
 
-        return( 1 );
-    }
 
-    if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
+/* allocate mem for signature (when signing) */
+/* sign data (gnutls_only)
+OR
+sign hash.
 
-        return( 1 );
-    }
+Return: NULL for success, or an error string */
 
-    if( verbose != 0 )
-        printf( "passed\n  PKCS#1 data sign  : " );
+const uschar *
+exim_rsa_sign(es_ctx * sign_ctx, BOOL is_sha1, blob * data, blob * sig)
+{
+uint len;
+const uschar * ret = NULL;
+
+/* Allocate mem for signature */
+len = RSA_size(sign_ctx->rsa);
+sig->data = store_get(len);
+sig->len = len;
+
+/* Do signing */
+if (RSA_sign(is_sha1 ? NID_sha1 : NID_sha256,
+      CUS data->data, data->len,
+      US sig->data, &len, sign_ctx->rsa) != 1)
+  {
+  char ssl_errstring[256];
+  ERR_load_crypto_strings();   /*XXX move to a startup routine */
+  ERR_error_string(ERR_get_error(), ssl_errstring);
+  ret = string_copy(ssl_errstring);
+  }
+
+RSA_free(sign_ctx->rsa);
+return ret;;
+}
 
-    polarssl_sha1( rsa_plaintext, PT_LEN, sha1sum );
 
-    if( rsa_pkcs1_sign( &rsa, RSA_PRIVATE, SIG_RSA_SHA1, 20,
-                        sha1sum, rsa_ciphertext ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
 
-        return( 1 );
-    }
+/* import public key (from DER in memory)
+Return: nULL for success, or an error string */
 
-    if( verbose != 0 )
-        printf( "passed\n  PKCS#1 sig. verify: " );
+const uschar *
+exim_rsa_verify_init(blob * pubkey_der, ev_ctx * verify_ctx)
+{
+const uschar * p = CUS pubkey_der->data;
+const uschar * ret = NULL;
+
+if (!(verify_ctx->rsa = d2i_RSA_PUBKEY(NULL, &p, (long) pubkey_der->len)))
+  {
+  char ssl_errstring[256];
+  ERR_load_crypto_strings();   /*XXX move to a startup routine */
+  ERR_error_string(ERR_get_error(), ssl_errstring);
+  ret = string_copy(ssl_errstring);
+  }
+return ret;
+}
 
-    if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20,
-                          sha1sum, rsa_ciphertext ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
 
-        return( 1 );
-    }
 
-    if( verbose != 0 )
-        printf( "passed\n\n" );
 
-    rsa_free( &rsa );
+/* verify signature (of hash)  (given pubkey & alleged sig)
+Return: NULL for success, or an error string */
 
-    return( 0 );
+const uschar *
+exim_rsa_verify(ev_ctx * verify_ctx, BOOL is_sha1, blob * data_hash, blob * sig)
+{
+const uschar * ret = NULL;
+
+if (RSA_verify(is_sha1 ? NID_sha1 : NID_sha256,
+      CUS data_hash->data, data_hash->len,
+      US sig->data, (uint) sig->len, verify_ctx->rsa) != 1)
+  {
+  char ssl_errstring[256];
+  ERR_load_crypto_strings();   /*XXX move to a startup routine */
+  ERR_error_string(ERR_get_error(), ssl_errstring);
+  ret = string_copy(ssl_errstring);
+  }
+return ret;
 }
 
-#endif
 
 #endif
+/******************************************************************************/
+
+#endif /*DISABLE_DKIM*/
+/* End of File */
diff --git a/src/src/pdkim/rsa.h b/src/src/pdkim/rsa.h
new file mode 100644 (file)
index 0000000..32631fd
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  PDKIM - a RFC4871 (DKIM) implementation
+ *
+ *  Copyright (C) 2016  Exim maintainers
+ *
+ *  RSA signing/verification interface
+ */
+
+#include "../exim.h"
+
+#ifndef DISABLE_DKIM   /* entire file */
+
+#include "crypt_ver.h"
+
+#ifdef RSA_OPENSSL
+# include <openssl/rsa.h>
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#elif defined(RSA_GNUTLS)
+# include <gnutls/gnutls.h>
+# include <gnutls/x509.h>
+#  include <gnutls/abstract.h>
+#elif defined(RSA_GCRYPT)
+#  include <gcrypt.h>
+#  include <libtasn1.h>
+#endif
+
+#include "blob.h"
+
+
+#ifdef RSA_OPENSSL
+
+typedef struct {
+  RSA * rsa;
+} es_ctx;
+
+typedef struct {
+  RSA * rsa;
+} ev_ctx;
+
+#elif defined(RSA_GNUTLS)
+
+typedef struct {
+  gnutls_x509_privkey_t rsa;
+} es_ctx;
+
+typedef struct {
+  gnutls_pubkey_t rsa;
+} ev_ctx;
+
+#elif defined(RSA_GCRYPT)
+
+typedef struct {
+  gcry_mpi_t n;
+  gcry_mpi_t e;
+  gcry_mpi_t d;
+  gcry_mpi_t p;
+  gcry_mpi_t q;
+  gcry_mpi_t dp;
+  gcry_mpi_t dq;
+  gcry_mpi_t qp;
+} es_ctx;
+
+typedef struct {
+  gcry_mpi_t n;
+  gcry_mpi_t e;
+} ev_ctx;
+
+#endif
+
+
+extern void exim_rsa_init(void);
+extern blob * exim_rsa_data_append(blob *, int *, uschar *);
+
+extern const uschar * exim_rsa_signing_init(uschar *, es_ctx *);
+extern const uschar * exim_rsa_sign(es_ctx *, BOOL, blob *, blob *);
+extern const uschar * exim_rsa_verify_init(blob *, ev_ctx *);
+extern const uschar * exim_rsa_verify(ev_ctx *, BOOL, blob *, blob *);
+
+#endif /*DISABLE_DKIM*/
+/* End of File */
diff --git a/src/src/pdkim/sha1.c b/src/src/pdkim/sha1.c
deleted file mode 100644 (file)
index 8204888..0000000
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- *  FIPS-180-1 compliant SHA-1 implementation
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- *  The SHA-1 standard was published by NIST in 1993.
- *
- *  http://www.itl.nist.gov/fipspubs/fip180-1.htm
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_SHA1_C)
-
-#include "polarssl/sha1.h"
-
-#include <string.h>
-#include <stdio.h>
-
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_ULONG_BE
-#define GET_ULONG_BE(n,b,i)                             \
-{                                                       \
-    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
-        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
-        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
-        | ( (unsigned long) (b)[(i) + 3]       );       \
-}
-#endif
-
-#ifndef PUT_ULONG_BE
-#define PUT_ULONG_BE(n,b,i)                             \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-}
-#endif
-
-/*
- * SHA-1 context setup
- */
-void sha1_starts( sha1_context *ctx )
-{
-    ctx->total[0] = 0;
-    ctx->total[1] = 0;
-
-    ctx->state[0] = 0x67452301;
-    ctx->state[1] = 0xEFCDAB89;
-    ctx->state[2] = 0x98BADCFE;
-    ctx->state[3] = 0x10325476;
-    ctx->state[4] = 0xC3D2E1F0;
-}
-
-static void sha1_process( sha1_context *ctx, const unsigned char data[64] )
-{
-    unsigned long temp, W[16], A, B, C, D, E;
-
-    GET_ULONG_BE( W[ 0], data,  0 );
-    GET_ULONG_BE( W[ 1], data,  4 );
-    GET_ULONG_BE( W[ 2], data,  8 );
-    GET_ULONG_BE( W[ 3], data, 12 );
-    GET_ULONG_BE( W[ 4], data, 16 );
-    GET_ULONG_BE( W[ 5], data, 20 );
-    GET_ULONG_BE( W[ 6], data, 24 );
-    GET_ULONG_BE( W[ 7], data, 28 );
-    GET_ULONG_BE( W[ 8], data, 32 );
-    GET_ULONG_BE( W[ 9], data, 36 );
-    GET_ULONG_BE( W[10], data, 40 );
-    GET_ULONG_BE( W[11], data, 44 );
-    GET_ULONG_BE( W[12], data, 48 );
-    GET_ULONG_BE( W[13], data, 52 );
-    GET_ULONG_BE( W[14], data, 56 );
-    GET_ULONG_BE( W[15], data, 60 );
-
-#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
-
-#define R(t)                                            \
-(                                                       \
-    temp = W[(t -  3) & 0x0F] ^ W[(t - 8) & 0x0F] ^     \
-           W[(t - 14) & 0x0F] ^ W[ t      & 0x0F],      \
-    ( W[t & 0x0F] = S(temp,1) )                         \
-)
-
-#define P(a,b,c,d,e,x)                                  \
-{                                                       \
-    e += S(a,5) + F(b,c,d) + K + x; b = S(b,30);        \
-}
-
-    A = ctx->state[0];
-    B = ctx->state[1];
-    C = ctx->state[2];
-    D = ctx->state[3];
-    E = ctx->state[4];
-
-#define F(x,y,z) (z ^ (x & (y ^ z)))
-#define K 0x5A827999
-
-    P( A, B, C, D, E, W[0]  );
-    P( E, A, B, C, D, W[1]  );
-    P( D, E, A, B, C, W[2]  );
-    P( C, D, E, A, B, W[3]  );
-    P( B, C, D, E, A, W[4]  );
-    P( A, B, C, D, E, W[5]  );
-    P( E, A, B, C, D, W[6]  );
-    P( D, E, A, B, C, W[7]  );
-    P( C, D, E, A, B, W[8]  );
-    P( B, C, D, E, A, W[9]  );
-    P( A, B, C, D, E, W[10] );
-    P( E, A, B, C, D, W[11] );
-    P( D, E, A, B, C, W[12] );
-    P( C, D, E, A, B, W[13] );
-    P( B, C, D, E, A, W[14] );
-    P( A, B, C, D, E, W[15] );
-    P( E, A, B, C, D, R(16) );
-    P( D, E, A, B, C, R(17) );
-    P( C, D, E, A, B, R(18) );
-    P( B, C, D, E, A, R(19) );
-
-#undef K
-#undef F
-
-#define F(x,y,z) (x ^ y ^ z)
-#define K 0x6ED9EBA1
-
-    P( A, B, C, D, E, R(20) );
-    P( E, A, B, C, D, R(21) );
-    P( D, E, A, B, C, R(22) );
-    P( C, D, E, A, B, R(23) );
-    P( B, C, D, E, A, R(24) );
-    P( A, B, C, D, E, R(25) );
-    P( E, A, B, C, D, R(26) );
-    P( D, E, A, B, C, R(27) );
-    P( C, D, E, A, B, R(28) );
-    P( B, C, D, E, A, R(29) );
-    P( A, B, C, D, E, R(30) );
-    P( E, A, B, C, D, R(31) );
-    P( D, E, A, B, C, R(32) );
-    P( C, D, E, A, B, R(33) );
-    P( B, C, D, E, A, R(34) );
-    P( A, B, C, D, E, R(35) );
-    P( E, A, B, C, D, R(36) );
-    P( D, E, A, B, C, R(37) );
-    P( C, D, E, A, B, R(38) );
-    P( B, C, D, E, A, R(39) );
-
-#undef K
-#undef F
-
-#define F(x,y,z) ((x & y) | (z & (x | y)))
-#define K 0x8F1BBCDC
-
-    P( A, B, C, D, E, R(40) );
-    P( E, A, B, C, D, R(41) );
-    P( D, E, A, B, C, R(42) );
-    P( C, D, E, A, B, R(43) );
-    P( B, C, D, E, A, R(44) );
-    P( A, B, C, D, E, R(45) );
-    P( E, A, B, C, D, R(46) );
-    P( D, E, A, B, C, R(47) );
-    P( C, D, E, A, B, R(48) );
-    P( B, C, D, E, A, R(49) );
-    P( A, B, C, D, E, R(50) );
-    P( E, A, B, C, D, R(51) );
-    P( D, E, A, B, C, R(52) );
-    P( C, D, E, A, B, R(53) );
-    P( B, C, D, E, A, R(54) );
-    P( A, B, C, D, E, R(55) );
-    P( E, A, B, C, D, R(56) );
-    P( D, E, A, B, C, R(57) );
-    P( C, D, E, A, B, R(58) );
-    P( B, C, D, E, A, R(59) );
-
-#undef K
-#undef F
-
-#define F(x,y,z) (x ^ y ^ z)
-#define K 0xCA62C1D6
-
-    P( A, B, C, D, E, R(60) );
-    P( E, A, B, C, D, R(61) );
-    P( D, E, A, B, C, R(62) );
-    P( C, D, E, A, B, R(63) );
-    P( B, C, D, E, A, R(64) );
-    P( A, B, C, D, E, R(65) );
-    P( E, A, B, C, D, R(66) );
-    P( D, E, A, B, C, R(67) );
-    P( C, D, E, A, B, R(68) );
-    P( B, C, D, E, A, R(69) );
-    P( A, B, C, D, E, R(70) );
-    P( E, A, B, C, D, R(71) );
-    P( D, E, A, B, C, R(72) );
-    P( C, D, E, A, B, R(73) );
-    P( B, C, D, E, A, R(74) );
-    P( A, B, C, D, E, R(75) );
-    P( E, A, B, C, D, R(76) );
-    P( D, E, A, B, C, R(77) );
-    P( C, D, E, A, B, R(78) );
-    P( B, C, D, E, A, R(79) );
-
-#undef K
-#undef F
-
-    ctx->state[0] += A;
-    ctx->state[1] += B;
-    ctx->state[2] += C;
-    ctx->state[3] += D;
-    ctx->state[4] += E;
-}
-
-/*
- * SHA-1 process buffer
- */
-void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen )
-{
-    int fill;
-    unsigned long left;
-
-    if( ilen <= 0 )
-        return;
-
-    left = ctx->total[0] & 0x3F;
-    fill = 64 - left;
-
-    ctx->total[0] += ilen;
-    ctx->total[0] &= 0xFFFFFFFF;
-
-    if( ctx->total[0] < (unsigned long) ilen )
-        ctx->total[1]++;
-
-    if( left && ilen >= fill )
-    {
-        memcpy( (void *) (ctx->buffer + left),
-                (void *) input, fill );
-        sha1_process( ctx, ctx->buffer );
-        input += fill;
-        ilen  -= fill;
-        left = 0;
-    }
-
-    while( ilen >= 64 )
-    {
-        sha1_process( ctx, input );
-        input += 64;
-        ilen  -= 64;
-    }
-
-    if( ilen > 0 )
-    {
-        memcpy( (void *) (ctx->buffer + left),
-                (void *) input, ilen );
-    }
-}
-
-static const unsigned char sha1_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/*
- * SHA-1 final digest
- */
-void sha1_finish( sha1_context *ctx, unsigned char output[20] )
-{
-    unsigned long last, padn;
-    unsigned long high, low;
-    unsigned char msglen[8];
-
-    high = ( ctx->total[0] >> 29 )
-         | ( ctx->total[1] <<  3 );
-    low  = ( ctx->total[0] <<  3 );
-
-    PUT_ULONG_BE( high, msglen, 0 );
-    PUT_ULONG_BE( low,  msglen, 4 );
-
-    last = ctx->total[0] & 0x3F;
-    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
-    sha1_update( ctx, (unsigned char *) sha1_padding, padn );
-    sha1_update( ctx, msglen, 8 );
-
-    PUT_ULONG_BE( ctx->state[0], output,  0 );
-    PUT_ULONG_BE( ctx->state[1], output,  4 );
-    PUT_ULONG_BE( ctx->state[2], output,  8 );
-    PUT_ULONG_BE( ctx->state[3], output, 12 );
-    PUT_ULONG_BE( ctx->state[4], output, 16 );
-}
-
-/*
- * output = SHA-1( input buffer )
- */
-void polarssl_sha1( const unsigned char *input, int ilen, unsigned char output[20] )
-{
-    sha1_context ctx;
-
-    sha1_starts( &ctx );
-    sha1_update( &ctx, input, ilen );
-    sha1_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha1_context ) );
-}
-
-/*
- * output = SHA-1( file contents )
- */
-int sha1_file( const char *path, unsigned char output[20] )
-{
-    FILE *f;
-    size_t n;
-    sha1_context ctx;
-    unsigned char buf[1024];
-
-    if( ( f = fopen( path, "rb" ) ) == NULL )
-        return( 1 );
-
-    sha1_starts( &ctx );
-
-    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
-        sha1_update( &ctx, buf, (int) n );
-
-    sha1_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha1_context ) );
-
-    if( ferror( f ) != 0 )
-    {
-        fclose( f );
-        return( 2 );
-    }
-
-    fclose( f );
-    return( 0 );
-}
-
-/*
- * SHA-1 HMAC context setup
- */
-void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, int keylen )
-{
-    int i;
-    unsigned char sum[20];
-
-    if( keylen > 64 )
-    {
-        polarssl_sha1( key, keylen, sum );
-        keylen = 20;
-        key = sum;
-    }
-
-    memset( ctx->ipad, 0x36, 64 );
-    memset( ctx->opad, 0x5C, 64 );
-
-    for( i = 0; i < keylen; i++ )
-    {
-        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
-        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
-    }
-
-    sha1_starts( ctx );
-    sha1_update( ctx, ctx->ipad, 64 );
-
-    memset( sum, 0, sizeof( sum ) );
-}
-
-/*
- * SHA-1 HMAC process buffer
- */
-void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, int ilen )
-{
-    sha1_update( ctx, input, ilen );
-}
-
-/*
- * SHA-1 HMAC final digest
- */
-void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] )
-{
-    unsigned char tmpbuf[20];
-
-    sha1_finish( ctx, tmpbuf );
-    sha1_starts( ctx );
-    sha1_update( ctx, ctx->opad, 64 );
-    sha1_update( ctx, tmpbuf, 20 );
-    sha1_finish( ctx, output );
-
-    memset( tmpbuf, 0, sizeof( tmpbuf ) );
-}
-
-/*
- * SHA1 HMAC context reset
- */
-void sha1_hmac_reset( sha1_context *ctx )
-{
-    sha1_starts( ctx );
-    sha1_update( ctx, ctx->ipad, 64 );
-}
-
-/*
- * output = HMAC-SHA-1( hmac key, input buffer )
- */
-void sha1_hmac( const unsigned char *key, int keylen,
-                const unsigned char *input, int ilen,
-                unsigned char output[20] )
-{
-    sha1_context ctx;
-
-    sha1_hmac_starts( &ctx, key, keylen );
-    sha1_hmac_update( &ctx, input, ilen );
-    sha1_hmac_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha1_context ) );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-/*
- * FIPS-180-1 test vectors
- */
-static unsigned char sha1_test_buf[3][57] =
-{
-    { "abc" },
-    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
-    { "" }
-};
-
-static const int sha1_test_buflen[3] =
-{
-    3, 56, 1000
-};
-
-static const unsigned char sha1_test_sum[3][20] =
-{
-    { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
-      0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
-    { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
-      0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
-    { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
-      0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
-};
-
-/*
- * RFC 2202 test vectors
- */
-static unsigned char sha1_hmac_test_key[7][26] =
-{
-    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
-      "\x0B\x0B\x0B\x0B" },
-    { "Jefe" },
-    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
-      "\xAA\xAA\xAA\xAA" },
-    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
-      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
-    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
-      "\x0C\x0C\x0C\x0C" },
-    { "" }, /* 0xAA 80 times */
-    { "" }
-};
-
-static const int sha1_hmac_test_keylen[7] =
-{
-    20, 4, 20, 25, 20, 80, 80
-};
-
-static unsigned char sha1_hmac_test_buf[7][74] =
-{
-    { "Hi There" },
-    { "what do ya want for nothing?" },
-    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
-      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
-      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
-      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
-      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
-    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
-      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
-      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
-      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
-      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
-    { "Test With Truncation" },
-    { "Test Using Larger Than Block-Size Key - Hash Key First" },
-    { "Test Using Larger Than Block-Size Key and Larger"
-      " Than One Block-Size Data" }
-};
-
-static const int sha1_hmac_test_buflen[7] =
-{
-    8, 28, 50, 50, 20, 54, 73
-};
-
-static const unsigned char sha1_hmac_test_sum[7][20] =
-{
-    { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
-      0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 },
-    { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
-      0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 },
-    { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
-      0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 },
-    { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
-      0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA },
-    { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
-      0x7B, 0xE1 },
-    { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
-      0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 },
-    { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
-      0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 }
-};
-
-/*
- * Checkup routine
- */
-int sha1_self_test( int verbose )
-{
-    int i, j, buflen;
-    unsigned char buf[1024];
-    unsigned char sha1sum[20];
-    sha1_context ctx;
-
-    /*
-     * SHA-1
-     */
-    for( i = 0; i < 3; i++ )
-    {
-        if( verbose != 0 )
-            printf( "  SHA-1 test #%d: ", i + 1 );
-
-        sha1_starts( &ctx );
-
-        if( i == 2 )
-        {
-            memset( buf, 'a', buflen = 1000 );
-
-            for( j = 0; j < 1000; j++ )
-                sha1_update( &ctx, buf, buflen );
-        }
-        else
-            sha1_update( &ctx, sha1_test_buf[i],
-                               sha1_test_buflen[i] );
-
-        sha1_finish( &ctx, sha1sum );
-
-        if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
-        {
-            if( verbose != 0 )
-                printf( "failed\n" );
-
-            return( 1 );
-        }
-
-        if( verbose != 0 )
-            printf( "passed\n" );
-    }
-
-    if( verbose != 0 )
-        printf( "\n" );
-
-    for( i = 0; i < 7; i++ )
-    {
-        if( verbose != 0 )
-            printf( "  HMAC-SHA-1 test #%d: ", i + 1 );
-
-        if( i == 5 || i == 6 )
-        {
-            memset( buf, '\xAA', buflen = 80 );
-            sha1_hmac_starts( &ctx, buf, buflen );
-        }
-        else
-            sha1_hmac_starts( &ctx, sha1_hmac_test_key[i],
-                                    sha1_hmac_test_keylen[i] );
-
-        sha1_hmac_update( &ctx, sha1_hmac_test_buf[i],
-                                sha1_hmac_test_buflen[i] );
-
-        sha1_hmac_finish( &ctx, sha1sum );
-
-        buflen = ( i == 4 ) ? 12 : 20;
-
-        if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 )
-        {
-            if( verbose != 0 )
-                printf( "failed\n" );
-
-            return( 1 );
-        }
-
-        if( verbose != 0 )
-            printf( "passed\n" );
-    }
-
-    if( verbose != 0 )
-        printf( "\n" );
-
-    return( 0 );
-}
-
-#endif
-
-#endif
diff --git a/src/src/pdkim/sha2.c b/src/src/pdkim/sha2.c
deleted file mode 100644 (file)
index f225c09..0000000
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- *  FIPS-180-2 compliant SHA-256 implementation
- *
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
- *
- *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
- */
-
-#include "polarssl/config.h"
-
-#if defined(POLARSSL_SHA2_C)
-
-#include "polarssl/sha2.h"
-
-#include <string.h>
-#include <stdio.h>
-
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_ULONG_BE
-#define GET_ULONG_BE(n,b,i)                             \
-{                                                       \
-    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
-        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
-        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
-        | ( (unsigned long) (b)[(i) + 3]       );       \
-}
-#endif
-
-#ifndef PUT_ULONG_BE
-#define PUT_ULONG_BE(n,b,i)                             \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-}
-#endif
-
-/*
- * SHA-256 context setup
- */
-void sha2_starts( sha2_context *ctx, int is224 )
-{
-    ctx->total[0] = 0;
-    ctx->total[1] = 0;
-
-    if( is224 == 0 )
-    {
-        /* SHA-256 */
-        ctx->state[0] = 0x6A09E667;
-        ctx->state[1] = 0xBB67AE85;
-        ctx->state[2] = 0x3C6EF372;
-        ctx->state[3] = 0xA54FF53A;
-        ctx->state[4] = 0x510E527F;
-        ctx->state[5] = 0x9B05688C;
-        ctx->state[6] = 0x1F83D9AB;
-        ctx->state[7] = 0x5BE0CD19;
-    }
-    else
-    {
-        /* SHA-224 */
-        ctx->state[0] = 0xC1059ED8;
-        ctx->state[1] = 0x367CD507;
-        ctx->state[2] = 0x3070DD17;
-        ctx->state[3] = 0xF70E5939;
-        ctx->state[4] = 0xFFC00B31;
-        ctx->state[5] = 0x68581511;
-        ctx->state[6] = 0x64F98FA7;
-        ctx->state[7] = 0xBEFA4FA4;
-    }
-
-    ctx->is224 = is224;
-}
-
-static void sha2_process( sha2_context *ctx, const unsigned char data[64] )
-{
-    unsigned long temp1, temp2, W[64];
-    unsigned long A, B, C, D, E, F, G, H;
-
-    GET_ULONG_BE( W[ 0], data,  0 );
-    GET_ULONG_BE( W[ 1], data,  4 );
-    GET_ULONG_BE( W[ 2], data,  8 );
-    GET_ULONG_BE( W[ 3], data, 12 );
-    GET_ULONG_BE( W[ 4], data, 16 );
-    GET_ULONG_BE( W[ 5], data, 20 );
-    GET_ULONG_BE( W[ 6], data, 24 );
-    GET_ULONG_BE( W[ 7], data, 28 );
-    GET_ULONG_BE( W[ 8], data, 32 );
-    GET_ULONG_BE( W[ 9], data, 36 );
-    GET_ULONG_BE( W[10], data, 40 );
-    GET_ULONG_BE( W[11], data, 44 );
-    GET_ULONG_BE( W[12], data, 48 );
-    GET_ULONG_BE( W[13], data, 52 );
-    GET_ULONG_BE( W[14], data, 56 );
-    GET_ULONG_BE( W[15], data, 60 );
-
-#define  SHR(x,n) ((x & 0xFFFFFFFF) >> n)
-#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
-
-#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))
-#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))
-
-#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
-#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
-
-#define F0(x,y,z) ((x & y) | (z & (x | y)))
-#define F1(x,y,z) (z ^ (x & (y ^ z)))
-
-#define R(t)                                    \
-(                                               \
-    W[t] = S1(W[t -  2]) + W[t -  7] +          \
-           S0(W[t - 15]) + W[t - 16]            \
-)
-
-#define P(a,b,c,d,e,f,g,h,x,K)                  \
-{                                               \
-    temp1 = h + S3(e) + F1(e,f,g) + K + x;      \
-    temp2 = S2(a) + F0(a,b,c);                  \
-    d += temp1; h = temp1 + temp2;              \
-}
-
-    A = ctx->state[0];
-    B = ctx->state[1];
-    C = ctx->state[2];
-    D = ctx->state[3];
-    E = ctx->state[4];
-    F = ctx->state[5];
-    G = ctx->state[6];
-    H = ctx->state[7];
-
-    P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
-    P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
-    P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
-    P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
-    P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
-    P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
-    P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
-    P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
-    P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
-    P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
-    P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
-    P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
-    P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
-    P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
-    P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
-    P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
-    P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
-    P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
-    P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
-    P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
-    P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
-    P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
-    P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
-    P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
-    P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
-    P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
-    P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
-    P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
-    P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
-    P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
-    P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
-    P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
-    P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
-    P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
-    P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
-    P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
-    P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
-    P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
-    P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
-    P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
-    P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
-    P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
-    P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
-    P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
-    P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
-    P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
-    P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
-    P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
-    P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
-    P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
-    P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
-    P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
-    P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
-    P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
-    P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
-    P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
-    P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
-    P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
-    P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
-    P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
-    P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
-    P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
-    P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
-    P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
-
-    ctx->state[0] += A;
-    ctx->state[1] += B;
-    ctx->state[2] += C;
-    ctx->state[3] += D;
-    ctx->state[4] += E;
-    ctx->state[5] += F;
-    ctx->state[6] += G;
-    ctx->state[7] += H;
-}
-
-/*
- * SHA-256 process buffer
- */
-void sha2_update( sha2_context *ctx, const unsigned char *input, int ilen )
-{
-    int fill;
-    unsigned long left;
-
-    if( ilen <= 0 )
-        return;
-
-    left = ctx->total[0] & 0x3F;
-    fill = 64 - left;
-
-    ctx->total[0] += ilen;
-    ctx->total[0] &= 0xFFFFFFFF;
-
-    if( ctx->total[0] < (unsigned long) ilen )
-        ctx->total[1]++;
-
-    if( left && ilen >= fill )
-    {
-        memcpy( (void *) (ctx->buffer + left),
-                (void *) input, fill );
-        sha2_process( ctx, ctx->buffer );
-        input += fill;
-        ilen  -= fill;
-        left = 0;
-    }
-
-    while( ilen >= 64 )
-    {
-        sha2_process( ctx, input );
-        input += 64;
-        ilen  -= 64;
-    }
-
-    if( ilen > 0 )
-    {
-        memcpy( (void *) (ctx->buffer + left),
-                (void *) input, ilen );
-    }
-}
-
-static const unsigned char sha2_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/*
- * SHA-256 final digest
- */
-void sha2_finish( sha2_context *ctx, unsigned char output[32] )
-{
-    unsigned long last, padn;
-    unsigned long high, low;
-    unsigned char msglen[8];
-
-    high = ( ctx->total[0] >> 29 )
-         | ( ctx->total[1] <<  3 );
-    low  = ( ctx->total[0] <<  3 );
-
-    PUT_ULONG_BE( high, msglen, 0 );
-    PUT_ULONG_BE( low,  msglen, 4 );
-
-    last = ctx->total[0] & 0x3F;
-    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
-    sha2_update( ctx, (unsigned char *) sha2_padding, padn );
-    sha2_update( ctx, msglen, 8 );
-
-    PUT_ULONG_BE( ctx->state[0], output,  0 );
-    PUT_ULONG_BE( ctx->state[1], output,  4 );
-    PUT_ULONG_BE( ctx->state[2], output,  8 );
-    PUT_ULONG_BE( ctx->state[3], output, 12 );
-    PUT_ULONG_BE( ctx->state[4], output, 16 );
-    PUT_ULONG_BE( ctx->state[5], output, 20 );
-    PUT_ULONG_BE( ctx->state[6], output, 24 );
-
-    if( ctx->is224 == 0 )
-        PUT_ULONG_BE( ctx->state[7], output, 28 );
-}
-
-/*
- * output = SHA-256( input buffer )
- */
-void sha2( const unsigned char *input, int ilen,
-           unsigned char output[32], int is224 )
-{
-    sha2_context ctx;
-
-    sha2_starts( &ctx, is224 );
-    sha2_update( &ctx, input, ilen );
-    sha2_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha2_context ) );
-}
-
-/*
- * output = SHA-256( file contents )
- */
-int sha2_file( const char *path, unsigned char output[32], int is224 )
-{
-    FILE *f;
-    size_t n;
-    sha2_context ctx;
-    unsigned char buf[1024];
-
-    if( ( f = fopen( path, "rb" ) ) == NULL )
-        return( 1 );
-
-    sha2_starts( &ctx, is224 );
-
-    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
-        sha2_update( &ctx, buf, (int) n );
-
-    sha2_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha2_context ) );
-
-    if( ferror( f ) != 0 )
-    {
-        fclose( f );
-        return( 2 );
-    }
-
-    fclose( f );
-    return( 0 );
-}
-
-/*
- * SHA-256 HMAC context setup
- */
-void sha2_hmac_starts( sha2_context *ctx, const unsigned char *key, int keylen,
-                       int is224 )
-{
-    int i;
-    unsigned char sum[32];
-
-    if( keylen > 64 )
-    {
-        sha2( key, keylen, sum, is224 );
-        keylen = ( is224 ) ? 28 : 32;
-        key = sum;
-    }
-
-    memset( ctx->ipad, 0x36, 64 );
-    memset( ctx->opad, 0x5C, 64 );
-
-    for( i = 0; i < keylen; i++ )
-    {
-        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
-        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
-    }
-
-    sha2_starts( ctx, is224 );
-    sha2_update( ctx, ctx->ipad, 64 );
-
-    memset( sum, 0, sizeof( sum ) );
-}
-
-/*
- * SHA-256 HMAC process buffer
- */
-void sha2_hmac_update( sha2_context *ctx, const unsigned char *input, int ilen )
-{
-    sha2_update( ctx, input, ilen );
-}
-
-/*
- * SHA-256 HMAC final digest
- */
-void sha2_hmac_finish( sha2_context *ctx, unsigned char output[32] )
-{
-    int is224, hlen;
-    unsigned char tmpbuf[32];
-
-    is224 = ctx->is224;
-    hlen = ( is224 == 0 ) ? 32 : 28;
-
-    sha2_finish( ctx, tmpbuf );
-    sha2_starts( ctx, is224 );
-    sha2_update( ctx, ctx->opad, 64 );
-    sha2_update( ctx, tmpbuf, hlen );
-    sha2_finish( ctx, output );
-
-    memset( tmpbuf, 0, sizeof( tmpbuf ) );
-}
-
-/*
- * SHA-256 HMAC context reset
- */
-void sha2_hmac_reset( sha2_context *ctx )
-{
-    sha2_starts( ctx, ctx->is224 );
-    sha2_update( ctx, ctx->ipad, 64 );
-}
-
-/*
- * output = HMAC-SHA-256( hmac key, input buffer )
- */
-void sha2_hmac( const unsigned char *key, int keylen,
-                const unsigned char *input, int ilen,
-                unsigned char output[32], int is224 )
-{
-    sha2_context ctx;
-
-    sha2_hmac_starts( &ctx, key, keylen, is224 );
-    sha2_hmac_update( &ctx, input, ilen );
-    sha2_hmac_finish( &ctx, output );
-
-    memset( &ctx, 0, sizeof( sha2_context ) );
-}
-
-#if defined(POLARSSL_SELF_TEST)
-/*
- * FIPS-180-2 test vectors
- */
-static unsigned char sha2_test_buf[3][57] =
-{
-    { "abc" },
-    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
-    { "" }
-};
-
-static const int sha2_test_buflen[3] =
-{
-    3, 56, 1000
-};
-
-static const unsigned char sha2_test_sum[6][32] =
-{
-    /*
-     * SHA-224 test vectors
-     */
-    { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
-      0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
-      0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
-      0xE3, 0x6C, 0x9D, 0xA7 },
-    { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
-      0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
-      0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
-      0x52, 0x52, 0x25, 0x25 },
-    { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
-      0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
-      0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
-      0x4E, 0xE7, 0xAD, 0x67 },
-
-    /*
-     * SHA-256 test vectors
-     */
-    { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
-      0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
-      0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
-      0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
-    { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
-      0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
-      0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
-      0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
-    { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
-      0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
-      0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
-      0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
-};
-
-/*
- * RFC 4231 test vectors
- */
-static unsigned char sha2_hmac_test_key[7][26] =
-{
-    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
-      "\x0B\x0B\x0B\x0B" },
-    { "Jefe" },
-    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
-      "\xAA\xAA\xAA\xAA" },
-    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
-      "\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
-    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
-      "\x0C\x0C\x0C\x0C" },
-    { "" }, /* 0xAA 131 times */
-    { "" }
-};
-
-static const int sha2_hmac_test_keylen[7] =
-{
-    20, 4, 20, 25, 20, 131, 131
-};
-
-static unsigned char sha2_hmac_test_buf[7][153] =
-{
-    { "Hi There" },
-    { "what do ya want for nothing?" },
-    { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
-      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
-      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
-      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
-      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
-    { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
-      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
-      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
-      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
-      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
-    { "Test With Truncation" },
-    { "Test Using Larger Than Block-Size Key - Hash Key First" },
-    { "This is a test using a larger than block-size key "
-      "and a larger than block-size data. The key needs to "
-      "be hashed before being used by the HMAC algorithm." }
-};
-
-static const int sha2_hmac_test_buflen[7] =
-{
-    8, 28, 50, 50, 20, 54, 152
-};
-
-static const unsigned char sha2_hmac_test_sum[14][32] =
-{
-    /*
-     * HMAC-SHA-224 test vectors
-     */
-    { 0x89, 0x6F, 0xB1, 0x12, 0x8A, 0xBB, 0xDF, 0x19,
-      0x68, 0x32, 0x10, 0x7C, 0xD4, 0x9D, 0xF3, 0x3F,
-      0x47, 0xB4, 0xB1, 0x16, 0x99, 0x12, 0xBA, 0x4F,
-      0x53, 0x68, 0x4B, 0x22 },
-    { 0xA3, 0x0E, 0x01, 0x09, 0x8B, 0xC6, 0xDB, 0xBF,
-      0x45, 0x69, 0x0F, 0x3A, 0x7E, 0x9E, 0x6D, 0x0F,
-      0x8B, 0xBE, 0xA2, 0xA3, 0x9E, 0x61, 0x48, 0x00,
-      0x8F, 0xD0, 0x5E, 0x44 },
-    { 0x7F, 0xB3, 0xCB, 0x35, 0x88, 0xC6, 0xC1, 0xF6,
-      0xFF, 0xA9, 0x69, 0x4D, 0x7D, 0x6A, 0xD2, 0x64,
-      0x93, 0x65, 0xB0, 0xC1, 0xF6, 0x5D, 0x69, 0xD1,
-      0xEC, 0x83, 0x33, 0xEA },
-    { 0x6C, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3C, 0xAC,
-      0x6A, 0x2A, 0xBC, 0x1B, 0xB3, 0x82, 0x62, 0x7C,
-      0xEC, 0x6A, 0x90, 0xD8, 0x6E, 0xFC, 0x01, 0x2D,
-      0xE7, 0xAF, 0xEC, 0x5A },
-    { 0x0E, 0x2A, 0xEA, 0x68, 0xA9, 0x0C, 0x8D, 0x37,
-      0xC9, 0x88, 0xBC, 0xDB, 0x9F, 0xCA, 0x6F, 0xA8 },
-    { 0x95, 0xE9, 0xA0, 0xDB, 0x96, 0x20, 0x95, 0xAD,
-      0xAE, 0xBE, 0x9B, 0x2D, 0x6F, 0x0D, 0xBC, 0xE2,
-      0xD4, 0x99, 0xF1, 0x12, 0xF2, 0xD2, 0xB7, 0x27,
-      0x3F, 0xA6, 0x87, 0x0E },
-    { 0x3A, 0x85, 0x41, 0x66, 0xAC, 0x5D, 0x9F, 0x02,
-      0x3F, 0x54, 0xD5, 0x17, 0xD0, 0xB3, 0x9D, 0xBD,
-      0x94, 0x67, 0x70, 0xDB, 0x9C, 0x2B, 0x95, 0xC9,
-      0xF6, 0xF5, 0x65, 0xD1 },
-
-    /*
-     * HMAC-SHA-256 test vectors
-     */
-    { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
-      0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
-      0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
-      0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 },
-    { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,
-      0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,
-      0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,
-      0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 },
-    { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,
-      0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,
-      0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,
-      0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE },
-    { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,
-      0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,
-      0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,
-      0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B },
-    { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,
-      0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B },
-    { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,
-      0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,
-      0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,
-      0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 },
-    { 0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
-      0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
-      0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
-      0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2 }
-};
-
-/*
- * Checkup routine
- */
-int sha2_self_test( int verbose )
-{
-    int i, j, k, buflen;
-    unsigned char buf[1024];
-    unsigned char sha2sum[32];
-    sha2_context ctx;
-
-    for( i = 0; i < 6; i++ )
-    {
-        j = i % 3;
-        k = i < 3;
-
-        if( verbose != 0 )
-            printf( "  SHA-%d test #%d: ", 256 - k * 32, j + 1 );
-
-        sha2_starts( &ctx, k );
-
-        if( j == 2 )
-        {
-            memset( buf, 'a', buflen = 1000 );
-
-            for( j = 0; j < 1000; j++ )
-                sha2_update( &ctx, buf, buflen );
-        }
-        else
-            sha2_update( &ctx, sha2_test_buf[j],
-                               sha2_test_buflen[j] );
-
-        sha2_finish( &ctx, sha2sum );
-
-        if( memcmp( sha2sum, sha2_test_sum[i], 32 - k * 4 ) != 0 )
-        {
-            if( verbose != 0 )
-                printf( "failed\n" );
-
-            return( 1 );
-        }
-
-        if( verbose != 0 )
-            printf( "passed\n" );
-    }
-
-    if( verbose != 0 )
-        printf( "\n" );
-
-    for( i = 0; i < 14; i++ )
-    {
-        j = i % 7;
-        k = i < 7;
-
-        if( verbose != 0 )
-            printf( "  HMAC-SHA-%d test #%d: ", 256 - k * 32, j + 1 );
-
-        if( j == 5 || j == 6 )
-        {
-            memset( buf, '\xAA', buflen = 131 );
-            sha2_hmac_starts( &ctx, buf, buflen, k );
-        }
-        else
-            sha2_hmac_starts( &ctx, sha2_hmac_test_key[j],
-                                    sha2_hmac_test_keylen[j], k );
-
-        sha2_hmac_update( &ctx, sha2_hmac_test_buf[j],
-                                sha2_hmac_test_buflen[j] );
-
-        sha2_hmac_finish( &ctx, sha2sum );
-
-        buflen = ( j == 4 ) ? 16 : 32 - k * 4;
-
-        if( memcmp( sha2sum, sha2_hmac_test_sum[i], buflen ) != 0 )
-        {
-            if( verbose != 0 )
-                printf( "failed\n" );
-
-            return( 1 );
-        }
-
-        if( verbose != 0 )
-            printf( "passed\n" );
-    }
-
-    if( verbose != 0 )
-        printf( "\n" );
-
-    return( 0 );
-}
-
-#endif
-
-#endif
index e52f45fcaa268b3c6abcdc78533f0355e2229d02..9de064d958f877f83b92dd7dd3b0b1e650b3b6f5 100644 (file)
@@ -194,6 +194,7 @@ static optionlist optionlist_config[] = {
   { "bounce_message_file",      opt_stringptr,   &bounce_message_file },
   { "bounce_message_text",      opt_stringptr,   &bounce_message_text },
   { "bounce_return_body",       opt_bool,        &bounce_return_body },
+  { "bounce_return_linesize_limit", opt_mkint,   &bounce_return_linesize_limit },
   { "bounce_return_message",    opt_bool,        &bounce_return_message },
   { "bounce_return_size_limit", opt_mkint,       &bounce_return_size_limit },
   { "bounce_sender_authentication",opt_stringptr,&bounce_sender_authentication },
@@ -4297,7 +4298,7 @@ for (i = config_lines; i; i = i->next)
       ;
 
     if (next - p > 1)
-      memmove(p+1, next, strlen(next)+1);
+      memmove(p+1, next, Ustrlen(next)+1);
 
     if (*next == '"' || *next == '\'' || *next == '$')
       break;
index 585cb902529fb8a600a67c0f0663f92509212a4a..a479e12cda152c7ffe036f1b5637b8902796384b 100644 (file)
@@ -525,7 +525,7 @@ static void
 smtp_user_msg(uschar *code, uschar *user_msg)
 {
 int len = 3;
-smtp_message_code(&code, &len, &user_msg, NULL);
+smtp_message_code(&code, &len, &user_msg, NULL, TRUE);
 smtp_respond(code, len, TRUE, user_msg);
 }
 #endif
@@ -835,7 +835,15 @@ while ((ch = (receive_getc)()) != EOF)
       ch_state = 4;
       continue;
       }
-    ch_state = 1;                       /* The dot itself is removed */
+    /* The dot was removed at state 3. For a doubled dot, here, reinstate
+    it to cutthrough. The current ch, dot or not, is passed both to cutthrough
+    and to file below. */
+    if (ch == '.')
+      {
+      uschar c= ch;
+      (void) cutthrough_puts(&c, 1);
+      }
+    ch_state = 1;
     break;
 
     case 4:                             /* After [CR] LF . CR */
@@ -1279,10 +1287,12 @@ else if (rc != OK)
 #ifdef EXPERIMENTAL_DCC
   dcc_ok = 0;
 #endif
-  if (smtp_input && smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0) {
+  if (  smtp_input
+     && smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0)
+    {
     *smtp_yield_ptr = FALSE;    /* No more messsages after dropped connection */
     *smtp_reply_ptr = US"";     /* Indicate reply already sent */
-  }
+    }
   message_id[0] = 0;            /* Indicate no message accepted */
   return FALSE;                 /* Cause skip to end of receive function */
   }
@@ -4078,7 +4088,7 @@ if (smtp_input)
         {
         uschar *code = US"250";
         int len = 3;
-        smtp_message_code(&code, &len, &user_msg, NULL);
+        smtp_message_code(&code, &len, &user_msg, NULL, TRUE);
         smtp_respond(code, len, TRUE, user_msg);
         }
 
index 8c79d9c64cadab87a35ad3784c076271f1db5724..1a2e9c7583fbf97544a15edc188800e7e7361af8 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* This file contains a function for decoding message header lines that may
index b48e436e3c0d8ae3d89aa59c4b6c22b3da875b60..0498ecb18d8399c643f1b70e043ebb403f5dd1ff 100644 (file)
@@ -2364,7 +2364,7 @@ else
   {
   int codelen = 3;
   s = user_msg;
-  smtp_message_code(&code, &codelen, &s, NULL);
+  smtp_message_code(&code, &codelen, &s, NULL, TRUE);
   if (codelen > 4)
     {
     esc = code + 4;
@@ -2626,23 +2626,24 @@ Arguments:
   codelen       length of smtp code; if > 4 there's an ESC
   msg           message text
   log_msg       optional log message, to be adjusted with the new SMTP code
+  check_valid   if true, verify the response code
 
 Returns:        nothing
 */
 
 void
-smtp_message_code(uschar **code, int *codelen, uschar **msg, uschar **log_msg)
+smtp_message_code(uschar **code, int *codelen, uschar **msg, uschar **log_msg,
+  BOOL check_valid)
 {
 int n;
 int ovector[3];
 
-if (msg == NULL || *msg == NULL) return;
+if (!msg || !*msg) return;
 
-n = pcre_exec(regex_smtp_code, NULL, CS *msg, Ustrlen(*msg), 0,
-  PCRE_EOPT, ovector, sizeof(ovector)/sizeof(int));
-if (n < 0) return;
+if ((n = pcre_exec(regex_smtp_code, NULL, CS *msg, Ustrlen(*msg), 0,
+  PCRE_EOPT, ovector, sizeof(ovector)/sizeof(int))) < 0) return;
 
-if ((*msg)[0] != (*code)[0])
+if (check_valid && (*msg)[0] != (*code)[0])
   {
   log_write(0, LOG_MAIN|LOG_PANIC, "configured error code starts with "
     "incorrect digit (expected %c) in \"%s\"", (*code)[0], *msg);
@@ -2677,18 +2678,19 @@ defaults disabled in Exim. However, discussion in connection with RFC 821bis
 (aka RFC 2821) has concluded that the response should be 252 in the disabled
 state, because there are broken clients that try VRFY before RCPT. A 5xx
 response should be given only when the address is positively known to be
-undeliverable. Sigh. Also, for ETRN, 458 is given on refusal, and for AUTH,
-503.
+undeliverable. Sigh. We return 252 if there is no VRFY ACL or it provides
+no explicit code, but if there is one we let it know best.
+Also, for ETRN, 458 is given on refusal, and for AUTH, 503.
 
 From Exim 4.63, it is possible to override the response code details by
 providing a suitable response code string at the start of the message provided
 in user_msg. The code's first digit is checked for validity.
 
 Arguments:
-  where      where the ACL was called from
-  rc         the failure code
-  user_msg   a message that can be included in an SMTP response
-  log_msg    a message for logging
+  where        where the ACL was called from
+  rc           the failure code
+  user_msg     a message that can be included in an SMTP response
+  log_msg      a message for logging
 
 Returns:     0 in most cases
              2 if the failure code was FAIL_DROP, in which case the
@@ -2721,8 +2723,9 @@ if (drop) rc = FAIL;
 
 /* Set the default SMTP code, and allow a user message to change it. */
 
-smtp_code = (rc != FAIL)? US"451" : acl_wherecodes[where];
-smtp_message_code(&smtp_code, &codelen, &user_msg, &log_msg);
+smtp_code = rc == FAIL ? acl_wherecodes[where] : US"451";
+smtp_message_code(&smtp_code, &codelen, &user_msg, &log_msg,
+  where != ACL_WHERE_VRFY);
 
 /* We used to have sender_address here; however, there was a bug that was not
 updating sender_address after a rewrite during a verify. When this bug was
@@ -3096,7 +3099,7 @@ static void
 smtp_user_msg(uschar *code, uschar *user_msg)
 {
 int len = 3;
-smtp_message_code(&code, &len, &user_msg, NULL);
+smtp_message_code(&code, &len, &user_msg, NULL, TRUE);
 smtp_respond(code, len, TRUE, user_msg);
 }
 
@@ -3305,14 +3308,13 @@ while (done <= 0)
      )
     {
     cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = FALSE;
-    if (acl_smtp_auth)
+    if (  acl_smtp_auth
+       && (rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth,
+                 &user_msg, &log_msg)) != OK
+       )
       {
-      rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth, &user_msg, &log_msg);
-      if (rc != OK)
-        {
-        done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg);
-        continue;
-        }
+      done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg);
+      continue;
       }
 
     for (au = auths; au; au = au->next)
@@ -3371,14 +3373,13 @@ while (done <= 0)
 
     /* Check the ACL */
 
-    if (acl_smtp_auth)
+    if (  acl_smtp_auth
+       && (rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth,
+                 &user_msg, &log_msg)) != OK
+       )
       {
-      rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth, &user_msg, &log_msg);
-      if (rc != OK)
-        {
-        done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg);
-        break;
-        }
+      done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg);
+      break;
       }
 
     /* Find the name of the requested authentication mechanism. */
@@ -3550,10 +3551,9 @@ while (done <= 0)
     /* Apply an ACL check if one is defined; afterwards, recheck
     synchronization in case the client started sending in a delay. */
 
-    if (acl_smtp_helo != NULL)
-      {
-      rc = acl_check(ACL_WHERE_HELO, NULL, acl_smtp_helo, &user_msg, &log_msg);
-      if (rc != OK)
+    if (acl_smtp_helo)
+      if ((rc = acl_check(ACL_WHERE_HELO, NULL, acl_smtp_helo,
+               &user_msg, &log_msg)) != OK)
         {
         done = smtp_handle_acl_fail(ACL_WHERE_HELO, rc, user_msg, log_msg);
         sender_helo_name = NULL;
@@ -3561,7 +3561,6 @@ while (done <= 0)
         break;
         }
       else if (!check_sync()) goto SYNC_FAILURE;
-      }
 
     /* Generate an OK reply. The default string includes the ident if present,
     and also the IP address if present. Reflecting back the ident is intended
@@ -3609,7 +3608,7 @@ while (done <= 0)
       {
       char *ss;
       int codelen = 4;
-      smtp_message_code(&smtp_code, &codelen, &user_msg, NULL);
+      smtp_message_code(&smtp_code, &codelen, &user_msg, NULL, TRUE);
       s = string_sprintf("%.*s%s", codelen, smtp_code, user_msg);
       if ((ss = strpbrk(CS s, "\r\n")) != NULL)
         {
@@ -4581,51 +4580,49 @@ while (done <= 0)
 
 
     case VRFY_CMD:
-    HAD(SCH_VRFY);
-    rc = acl_check(ACL_WHERE_VRFY, NULL, acl_smtp_vrfy, &user_msg, &log_msg);
-    if (rc != OK)
-      done = smtp_handle_acl_fail(ACL_WHERE_VRFY, rc, user_msg, log_msg);
-    else
       {
-      uschar *address;
-      uschar *s = NULL;
+      uschar * address;
 
-      /* rfc821_domains = TRUE; << no longer needed */
-      address = parse_extract_address(smtp_cmd_data, &errmess, &start, &end,
-        &recipient_domain, FALSE);
-      /* rfc821_domains = FALSE; << no longer needed */
+      HAD(SCH_VRFY);
 
-      if (address == NULL)
-        s = string_sprintf("501 %s", errmess);
+      if(!(address = parse_extract_address(smtp_cmd_data, &errmess, &start, &end,
+           &recipient_domain, FALSE)))
+       smtp_printf("501 %s\r\n", errmess);
+
+      else if ((rc = acl_check(ACL_WHERE_VRFY, address, acl_smtp_vrfy,
+                   &user_msg, &log_msg)) != OK)
+       done = smtp_handle_acl_fail(ACL_WHERE_VRFY, rc, user_msg, log_msg);
       else
-        {
-        address_item *addr = deliver_make_addr(address, FALSE);
-        switch(verify_address(addr, NULL, vopt_is_recipient | vopt_qualify, -1,
-               -1, -1, NULL, NULL, NULL))
-          {
-          case OK:
-          s = string_sprintf("250 <%s> is deliverable", address);
-          break;
+       {
+       uschar *s = NULL;
 
-          case DEFER:
-          s = (addr->user_message != NULL)?
-            string_sprintf("451 <%s> %s", address, addr->user_message) :
-            string_sprintf("451 Cannot resolve <%s> at this time", address);
-          break;
+       address_item *addr = deliver_make_addr(address, FALSE);
+       switch(verify_address(addr, NULL, vopt_is_recipient | vopt_qualify, -1,
+              -1, -1, NULL, NULL, NULL))
+         {
+         case OK:
+           s = string_sprintf("250 <%s> is deliverable", address);
+           break;
 
-          case FAIL:
-          s = (addr->user_message != NULL)?
-            string_sprintf("550 <%s> %s", address, addr->user_message) :
-            string_sprintf("550 <%s> is not deliverable", address);
-          log_write(0, LOG_MAIN, "VRFY failed for %s %s",
-            smtp_cmd_argument, host_and_ident(TRUE));
-          break;
-          }
-        }
+         case DEFER:
+           s = (addr->user_message != NULL)?
+             string_sprintf("451 <%s> %s", address, addr->user_message) :
+             string_sprintf("451 Cannot resolve <%s> at this time", address);
+           break;
 
-      smtp_printf("%s\r\n", s);
+         case FAIL:
+           s = (addr->user_message != NULL)?
+             string_sprintf("550 <%s> %s", address, addr->user_message) :
+             string_sprintf("550 <%s> is not deliverable", address);
+           log_write(0, LOG_MAIN, "VRFY failed for %s %s",
+             smtp_cmd_argument, host_and_ident(TRUE));
+           break;
+         }
+
+       smtp_printf("%s\r\n", s);
+       }
+      break;
       }
-    break;
 
 
     case EXPN_CMD:
@@ -4659,15 +4656,13 @@ while (done <= 0)
 
     /* Apply an ACL check if one is defined */
 
-    if (acl_smtp_starttls != NULL)
+    if (  acl_smtp_starttls
+       && (rc = acl_check(ACL_WHERE_STARTTLS, NULL, acl_smtp_starttls,
+                 &user_msg, &log_msg)) != OK
+       )
       {
-      rc = acl_check(ACL_WHERE_STARTTLS, NULL, acl_smtp_starttls, &user_msg,
-        &log_msg);
-      if (rc != OK)
-        {
-        done = smtp_handle_acl_fail(ACL_WHERE_STARTTLS, rc, user_msg, log_msg);
-        break;
-        }
+      done = smtp_handle_acl_fail(ACL_WHERE_STARTTLS, rc, user_msg, log_msg);
+      break;
       }
 
     /* RFC 2487 is not clear on when this command may be sent, though it
@@ -4910,8 +4905,8 @@ while (done <= 0)
     log_write(L_etrn, LOG_MAIN, "ETRN %s received from %s", smtp_cmd_argument,
       host_and_ident(FALSE));
 
-    rc = acl_check(ACL_WHERE_ETRN, NULL, acl_smtp_etrn, &user_msg, &log_msg);
-    if (rc != OK)
+    if ((rc = acl_check(ACL_WHERE_ETRN, NULL, acl_smtp_etrn,
+               &user_msg, &log_msg)) != OK)
       {
       done = smtp_handle_acl_fail(ACL_WHERE_ETRN, rc, user_msg, log_msg);
       break;
index 8d04f8e17ea5f77030255c320a4c88de7c1ee1ab..12603757498444f518f3781c33c1b2981f199b64 100644 (file)
@@ -29,198 +29,220 @@ uschar spooled_message_id[17];
 FILE *
 spool_mbox(unsigned long *mbox_file_size, const uschar *source_file_override)
 {
-  uschar message_subdir[2];
-  uschar buffer[16384];
-  uschar *temp_string;
-  uschar *mbox_path;
-  FILE *mbox_file = NULL;
-  FILE *data_file = NULL;
-  FILE *yield = NULL;
-  header_line *my_headerlist;
-  struct stat statbuf;
-  int i, j;
-  void *reset_point = store_get(0);
-
-  mbox_path = string_sprintf("%s/scan/%s/%s.eml", spool_directory, message_id,
-    message_id);
-
-  /* Skip creation if already spooled out as mbox file */
-  if (!spool_mbox_ok) {
-    /* create temp directory inside scan dir, directory_make works recursively */
-    temp_string = string_sprintf("scan/%s", message_id);
-    if (!directory_make(spool_directory, temp_string, 0750, FALSE)) {
-      log_write(0, LOG_MAIN|LOG_PANIC, "%s", string_open_failed(errno,
-        "scan directory %s/scan/%s", spool_directory, temp_string));
-      goto OUT;
-    };
+uschar message_subdir[2];
+uschar buffer[16384];
+uschar *temp_string;
+uschar *mbox_path;
+FILE *mbox_file = NULL;
+FILE *data_file = NULL;
+FILE *yield = NULL;
+header_line *my_headerlist;
+struct stat statbuf;
+int i, j;
+void *reset_point = store_get(0);
+
+mbox_path = string_sprintf("%s/scan/%s/%s.eml", spool_directory, message_id,
+  message_id);
+
+/* Skip creation if already spooled out as mbox file */
+if (!spool_mbox_ok)
+  {
+  /* create temp directory inside scan dir, directory_make works recursively */
+  temp_string = string_sprintf("scan/%s", message_id);
+  if (!directory_make(spool_directory, temp_string, 0750, FALSE))
+    {
+    log_write(0, LOG_MAIN|LOG_PANIC, "%s", string_open_failed(errno,
+      "scan directory %s/scan/%s", spool_directory, temp_string));
+    goto OUT;
+    }
 
-    /* open [message_id].eml file for writing */
-    mbox_file = modefopen(mbox_path, "wb", SPOOL_MODE);
-    if (mbox_file == NULL) {
-      log_write(0, LOG_MAIN|LOG_PANIC, "%s", string_open_failed(errno,
-        "scan file %s", mbox_path));
-      goto OUT;
-    };
-
-    /* Generate mailbox headers. The $received_for variable is (up to at least
-    Exim 4.64) never set here, because it is only set when expanding the
-    contents of the Received: header line. However, the code below will use it
-    if it should become available in future. */
-
-    temp_string = expand_string(
-      US"From ${if def:return_path{$return_path}{MAILER-DAEMON}} ${tod_bsdinbox}\n"
-      "${if def:sender_address{X-Envelope-From: <${sender_address}>\n}}"
-      "${if def:recipients{X-Envelope-To: ${recipients}\n}}");
-
-    if (temp_string != NULL) {
-      i = fwrite(temp_string, Ustrlen(temp_string), 1, mbox_file);
-      if (i != 1) {
-        log_write(0, LOG_MAIN|LOG_PANIC, "Error/short write while writing \
-            mailbox headers to %s", mbox_path);
-        goto OUT;
-      };
-    };
-
-    /* write all header lines to mbox file */
-    my_headerlist = header_list;
-    for (my_headerlist = header_list; my_headerlist != NULL;
-      my_headerlist = my_headerlist->next)
+  /* open [message_id].eml file for writing */
+  mbox_file = modefopen(mbox_path, "wb", SPOOL_MODE);
+  if (mbox_file == NULL)
+    {
+    log_write(0, LOG_MAIN|LOG_PANIC, "%s", string_open_failed(errno,
+      "scan file %s", mbox_path));
+    goto OUT;
+    }
+
+  /* Generate mailbox headers. The $received_for variable is (up to at least
+  Exim 4.64) never set here, because it is only set when expanding the
+  contents of the Received: header line. However, the code below will use it
+  if it should become available in future. */
+
+  temp_string = expand_string(
+    US"From ${if def:return_path{$return_path}{MAILER-DAEMON}} ${tod_bsdinbox}\n"
+    "${if def:sender_address{X-Envelope-From: <${sender_address}>\n}}"
+    "${if def:recipients{X-Envelope-To: ${recipients}\n}}");
+
+  if (temp_string != NULL)
     {
-      /* skip deleted headers */
-      if (my_headerlist->type == '*') continue;
-
-      i = fwrite(my_headerlist->text, my_headerlist->slen, 1, mbox_file);
-      if (i != 1) {
-        log_write(0, LOG_MAIN|LOG_PANIC, "Error/short write while writing \
-            message headers to %s", mbox_path);
-        goto OUT;
-      };
-    };
-
-    /* End headers */
-    if (fwrite("\n", 1, 1, mbox_file) != 1) {
+    i = fwrite(temp_string, Ustrlen(temp_string), 1, mbox_file);
+    if (i != 1)
+      {
       log_write(0, LOG_MAIN|LOG_PANIC, "Error/short write while writing \
-        message headers to %s", mbox_path);
+         mailbox headers to %s", mbox_path);
       goto OUT;
+      }
     }
 
-    /* copy body file */
-    if (source_file_override == NULL) {
-      message_subdir[1] = '\0';
-      for (i = 0; i < 2; i++) {
-        message_subdir[0] = (split_spool_directory == (i == 0))? message_id[5] : 0;
-        temp_string = string_sprintf("%s/input/%s/%s-D", spool_directory,
-          message_subdir, message_id);
-        data_file = Ufopen(temp_string, "rb");
-        if (data_file != NULL) break;
-      };
-    } else {
-      data_file = Ufopen(source_file_override, "rb");
-    };
-
-    if (data_file == NULL) {
-      log_write(0, LOG_MAIN|LOG_PANIC, "Could not open datafile for message %s",
-        message_id);
+  /* write all header lines to mbox file */
+  my_headerlist = header_list;
+  for (my_headerlist = header_list; my_headerlist != NULL;
+    my_headerlist = my_headerlist->next)
+    {
+    /* skip deleted headers */
+    if (my_headerlist->type == '*') continue;
+
+    i = fwrite(my_headerlist->text, my_headerlist->slen, 1, mbox_file);
+    if (i != 1)
+      {
+      log_write(0, LOG_MAIN|LOG_PANIC, "Error/short write while writing \
+         message headers to %s", mbox_path);
       goto OUT;
-    };
-
-    /* The code used to use this line, but it doesn't work in Cygwin.
-     *
-     *  (void)fread(data_buffer, 1, 18, data_file);
-     *
-     * What's happening is that spool_mbox used to use an fread to jump over the
-     * file header. That fails under Cygwin because the header is locked, but
-     * doing an fseek succeeds. We have to output the leading newline
-     * explicitly, because the one in the file is parted of the locked area.
-     */
-
-    if (!source_file_override)
-      (void)fseek(data_file, SPOOL_DATA_START_OFFSET, SEEK_SET);
-
-    do {
-      j = fread(buffer, 1, sizeof(buffer), data_file);
-
-      if (j > 0) {
-        i = fwrite(buffer, j, 1, mbox_file);
-        if (i != 1) {
-          log_write(0, LOG_MAIN|LOG_PANIC, "Error/short write while writing \
-              message body to %s", mbox_path);
-          goto OUT;
-        };
-      };
-    } while (j > 0);
+      }
+    }
 
-    (void)fclose(mbox_file);
-    mbox_file = NULL;
+  /* End headers */
+  if (fwrite("\n", 1, 1, mbox_file) != 1)
+    {
+    log_write(0, LOG_MAIN|LOG_PANIC, "Error/short write while writing \
+      message headers to %s", mbox_path);
+    goto OUT;
+    }
 
-    Ustrcpy(spooled_message_id, message_id);
-    spool_mbox_ok = 1;
-  };
+  /* copy body file */
+  if (source_file_override == NULL)
+    {
+    message_subdir[1] = '\0';
+    for (i = 0; i < 2; i++)
+      {
+      message_subdir[0] = (split_spool_directory == (i == 0))? message_id[5] : 0;
+      temp_string = string_sprintf("%s/input/%s/%s-D", spool_directory,
+       message_subdir, message_id);
+      data_file = Ufopen(temp_string, "rb");
+      if (data_file != NULL) break;
+      }
+    }
+  else
+    data_file = Ufopen(source_file_override, "rb");
 
-  /* get the size of the mbox message and open [message_id].eml file for reading*/
-  if (Ustat(mbox_path, &statbuf) != 0 ||
-      (yield = Ufopen(mbox_path,"rb")) == NULL) {
-    log_write(0, LOG_MAIN|LOG_PANIC, "%s", string_open_failed(errno,
-      "scan file %s", mbox_path));
+  if (data_file == NULL)
+    {
+    log_write(0, LOG_MAIN|LOG_PANIC, "Could not open datafile for message %s",
+      message_id);
     goto OUT;
-  };
+    }
+
+  /* The code used to use this line, but it doesn't work in Cygwin.
 
-  *mbox_file_size = statbuf.st_size;
+      (void)fread(data_buffer, 1, 18, data_file);
+    
+     What's happening is that spool_mbox used to use an fread to jump over the
+     file header. That fails under Cygwin because the header is locked, but
+     doing an fseek succeeds. We have to output the leading newline
+     explicitly, because the one in the file is parted of the locked area.  */
 
-  OUT:
-  if (data_file) (void)fclose(data_file);
-  if (mbox_file) (void)fclose(mbox_file);
-  store_reset(reset_point);
-  return yield;
+  if (!source_file_override)
+    (void)fseek(data_file, SPOOL_DATA_START_OFFSET, SEEK_SET);
+
+  do
+    {
+    j = fread(buffer, 1, sizeof(buffer), data_file);
+
+    if (j > 0)
+      {
+      i = fwrite(buffer, j, 1, mbox_file);
+      if (i != 1)
+        {
+       log_write(0, LOG_MAIN|LOG_PANIC, "Error/short write while writing \
+           message body to %s", mbox_path);
+       goto OUT;
+       }
+      }
+    } while (j > 0);
+
+  (void)fclose(mbox_file);
+  mbox_file = NULL;
+
+  Ustrcpy(spooled_message_id, message_id);
+  spool_mbox_ok = 1;
+  }
+
+/* get the size of the mbox message and open [message_id].eml file for reading*/
+if (Ustat(mbox_path, &statbuf) != 0 ||
+    (yield = Ufopen(mbox_path,"rb")) == NULL)
+  {
+  log_write(0, LOG_MAIN|LOG_PANIC, "%s", string_open_failed(errno,
+    "scan file %s", mbox_path));
+  goto OUT;
+  }
+
+*mbox_file_size = statbuf.st_size;
+
+OUT:
+if (data_file) (void)fclose(data_file);
+if (mbox_file) (void)fclose(mbox_file);
+store_reset(reset_point);
+return yield;
 }
 
+
+
+
 /* remove mbox spool file, demimed files and temp directory */
-void unspool_mbox(void) {
-
-  /* reset all exiscan state variables */
-  #ifdef WITH_OLD_DEMIME
-  demime_ok = 0;
-  demime_errorlevel = 0;
-  demime_reason = NULL;
-  file_extensions = NULL;
-  #endif
-
-  spam_ok = 0;
-  malware_ok = 0;
-
-  if (spool_mbox_ok && !no_mbox_unspool) {
-    uschar *mbox_path;
-    uschar *file_path;
-    int n;
-    struct dirent *entry;
-    DIR *tempdir;
-
-    mbox_path = string_sprintf("%s/scan/%s", spool_directory, spooled_message_id);
-
-    tempdir = opendir(CS mbox_path);
-    if (!tempdir) {
-      debug_printf("Unable to opendir(%s): %s\n", mbox_path, strerror(errno));
-      /* Just in case we still can: */
-      rmdir(CS mbox_path);
-      return;
-    }
-    /* loop thru dir & delete entries */
-    while((entry = readdir(tempdir)) != NULL) {
-      uschar *name = US entry->d_name;
-      if (Ustrcmp(name, US".") == 0 || Ustrcmp(name, US"..") == 0) continue;
 
-      file_path = string_sprintf("%s/%s", mbox_path, name);
-      debug_printf("unspool_mbox(): unlinking '%s'\n", file_path);
-      n = unlink(CS file_path);
-    };
+void
+unspool_mbox(void)
+{
+
+/* reset all exiscan state variables */
+#ifdef WITH_OLD_DEMIME
+demime_ok = 0;
+demime_errorlevel = 0;
+demime_reason = NULL;
+file_extensions = NULL;
+#endif
 
-    closedir(tempdir);
+spam_ok = 0;
+malware_ok = 0;
 
-    /* remove directory */
+if (spool_mbox_ok && !no_mbox_unspool)
+  {
+  uschar *mbox_path;
+  uschar *file_path;
+  int n;
+  struct dirent *entry;
+  DIR *tempdir;
+
+  mbox_path = string_sprintf("%s/scan/%s", spool_directory, spooled_message_id);
+
+  tempdir = opendir(CS mbox_path);
+  if (!tempdir)
+    {
+    debug_printf("Unable to opendir(%s): %s\n", mbox_path, strerror(errno));
+    /* Just in case we still can: */
     rmdir(CS mbox_path);
-    store_reset(mbox_path);
-  };
-  spool_mbox_ok = 0;
+    return;
+    }
+  /* loop thru dir & delete entries */
+  while((entry = readdir(tempdir)) != NULL)
+    {
+    uschar *name = US entry->d_name;
+    if (Ustrcmp(name, US".") == 0 || Ustrcmp(name, US"..") == 0) continue;
+
+    file_path = string_sprintf("%s/%s", mbox_path, name);
+    debug_printf("unspool_mbox(): unlinking '%s'\n", file_path);
+    n = unlink(CS file_path);
+    }
+
+  closedir(tempdir);
+
+  /* remove directory */
+  rmdir(CS mbox_path);
+  store_reset(mbox_path);
+  }
+spool_mbox_ok = 0;
 }
 
 #endif
index 2bb3490e18b611d644d2b7d5a878516c84110a6b..e402835c7d8890c229313d147ee4a44bca6b0fdd 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2015 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Exim gets and frees all its store through these functions. In the original
index d01383f65711d50fd4e62e87932f5db23b6e2120..c0dfd04b6de31852b986e5e024b9d57f8b28827b 100644 (file)
@@ -970,7 +970,7 @@ return buffer;
 
 #ifndef COMPILE_UTILITY
 /************************************************
-*      Add element to seperated list           *
+*      Add element to separated list           *
 ************************************************/
 /* This function is used to build a list, returning
 an allocated null-terminated growable string. The
index 9944a8f60db944eef640830e15ef247e72a922f7..f45daa767386b1eb768d0b136150b835ed527dcb 100644 (file)
@@ -521,7 +521,7 @@ else
   int err = X509_STORE_CTX_get_error(x509ctx);
   DEBUG(D_tls)
     debug_printf(" - err %d '%s'\n", err, X509_verify_cert_error_string(err));
-  if (err = X509_V_ERR_APPLICATION_VERIFICATION)
+  if (err == X509_V_ERR_APPLICATION_VERIFICATION)
     preverify_ok = 1;
   }
 return preverify_ok;
@@ -2751,6 +2751,9 @@ result = 0L;
 #ifdef SSL_OP_NO_SSLv2
 result |= SSL_OP_NO_SSLv2;
 #endif
+#ifdef SSL_OP_SINGLE_DH_USE
+result |= SSL_OP_SINGLE_DH_USE;
+#endif
 
 if (option_spec == NULL)
   {
index d00258b9e250dcbe0734f2f8079a0a5941051ebb..80b6fb142ccae4c59617ffc1469083ef1f6cebd6 100644 (file)
@@ -418,6 +418,28 @@ for(index = 0;; index++)
 /*****************************************************
 *  Certificate operator routines
 *****************************************************/
+uschar *
+tls_cert_der_b64(void * cert)
+{
+size_t len = 0;
+uschar * cp = NULL;
+int fail;
+
+if (  (fail = gnutls_x509_crt_export((gnutls_x509_crt_t)cert,
+       GNUTLS_X509_FMT_DER, cp, &len)) != GNUTLS_E_SHORT_MEMORY_BUFFER
+   || !(cp = store_get((int)len))
+   || (fail = gnutls_x509_crt_export((gnutls_x509_crt_t)cert,
+        GNUTLS_X509_FMT_DER, cp, &len))
+   )
+  {
+  log_write(0, LOG_MAIN, "TLS error in certificate export: %s",
+    gnutls_strerror(fail));
+  return NULL;
+  }
+return b64encode(cp, (int)len);
+}
+
+
 static uschar *
 fingerprint(gnutls_x509_crt_t cert, gnutls_digest_algorithm_t algo)
 {
index 94534d8082c507d82094504c367db4403fb96932..4d45ad9f91b7dd127fcba16085fadf3075bac9fd 100644 (file)
@@ -464,6 +464,26 @@ return list;
 /*****************************************************
 *  Certificate operator routines
 *****************************************************/
+uschar *
+tls_cert_der_b64(void * cert)
+{
+BIO * bp = BIO_new(BIO_s_mem());
+uschar * cp = NULL;
+
+if (!i2d_X509_bio(bp, (X509 *)cert))
+  log_write(0, LOG_MAIN, "TLS error in certificate export: %s",
+    ERR_error_string(ERR_get_error(), NULL));
+else
+  {
+  long len = BIO_get_mem_data(bp, &cp);
+  cp = b64encode(cp, (int)len);
+  }
+
+BIO_free(bp);
+return cp;
+}
+
+
 static uschar *
 fingerprint(X509 * cert, const EVP_MD * fdig)
 {
index 8f095aec661acae74af398ba4b1fbc212e8fff94..5f451ba96de445e6b52a60b01f5a04a9ed4bc8dd 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* A function for returning the time of day in various formats */
index 93bbba455c1a91675ecf46e171783e65153a66f6..0fbb77243f7912b28e3a92fb55607a9575a870ed 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions in support of the use of maildirsize files for handling quotas in
index d986a47cbdeaebc60861e953ca62bed94b8dcae5..a856e2e1688929a84a59a00da955699395192daa 100644 (file)
@@ -3,8 +3,8 @@ EXPORTABLE EXIM TEST SUITE
 
 This document last updated for:
 
-Test Suite Version: 4.67
-Date: 20 February 2007
+Test Suite Version: 4.87
+Date: 30 January 2016
 
 
 BACKGROUND
index 6220015aec08b916087c28f99a5fea60b71adb89..a08f38f5628db73633fe36512c086c72a89089b8 100644 (file)
@@ -6,16 +6,18 @@ use Getopt::Long;
 my $method = "simple/simple";
 my $selector = "sel";
 my $keyfile = "aux-fixed/dkim/dkim.private";
+my $algorithm = "rsa-sha1";
 
 GetOptions(
        "method=s" => \$method,
        "selector=s" => \$selector,
        "keyfile=s" => \$keyfile,
+       "algorithm=s" => \$algorithm,
 );
 
 # create a signer object
 my $dkim = Mail::DKIM::Signer->new(
-                  Algorithm => "rsa-sha1",
+                  Algorithm => $algorithm,
                   Method => $method,
                   Domain => "test.ex",
                   Selector => $selector,
index 2b53c094234c8871b33e3932d952cf7ad1f2f4ce..5350ba463f4cdfd260f9b97b164cc4cb1f64af00 100644 (file)
@@ -38,6 +38,7 @@ bounce_return_body = false
 no_bounce_return_message
 return_size_limit = 12K
 bounce_return_size_limit = 10K
+bounce_return_linesize_limit = 997
 callout_domain_negative_expire = 1h
 callout_domain_positive_expire = 1d
 callout_negative_expire = 5h
index 51cba04acc5c01ef58fb4df8a61aa9ba761e1395..ec1067584443df435271984a437ec69ef8029bd5 100644 (file)
@@ -12,6 +12,7 @@ tls_advertise_hosts =
 
 domainlist local_domains = test.ex
 
+acl_smtp_vrfy = check_vrfy
 acl_smtp_expn = check_expn
 qualify_domain = test.ex
 no_write_rejectlog
@@ -21,6 +22,10 @@ no_write_rejectlog
 
 begin acl
 
+check_vrfy:
+  deny  local_parts = hardfail
+         message = 599 custom reject
+
 check_expn:
   accept hosts = 2.2.2.2
 
deleted file mode 120000 (symlink)
index 4af051ca9853af8dd2cdb2f81c10ec428d7deaaf..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1 +0,0 @@
-4020
\ No newline at end of file
new file mode 100644 (file)
index 0000000000000000000000000000000000000000..2cce49c3856e3295d77fad37682529429557c1c0
--- /dev/null
@@ -0,0 +1,47 @@
+# Exim test configuration 0572
+
+OPT =
+
+exim_path = EXIM_PATH
+hide host_lookup_order = bydns
+primary_hostname = myhost.test.ex
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+tls_advertise_hosts =
+
+# ----- Main settings -----
+
+log_selector = +outgoing_port
+
+domainlist local_domains = test.ex : *.test.ex
+acl_smtp_rcpt = accept
+
+
+# ----- Routers -----
+
+begin routers
+
+my_main_router:
+  driver = manualroute
+  route_list = * 127.0.0.1
+  self = send
+  transport = my_smtp
+  debug_print = router_name <$router_name>
+  no_more
+
+
+# ----- Transports -----
+
+begin transports
+
+my_smtp:
+  driver = smtp
+  interface = HOSTIPV4
+  port = PORT_S
+  hide socks_proxy = 127.0.0.1 port=PORT_D OPT
+  debug_print = transport_name <$transport_name>
+
+
+# End
diff --git a/test/confs/0573 b/test/confs/0573
new file mode 100644 (file)
index 0000000..c3c7a6b
--- /dev/null
@@ -0,0 +1,37 @@
+# Exim test configuration 0573
+
+exim_path = EXIM_PATH
+hide host_lookup_order = bydns
+primary_hostname = myhost.test.ex
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+tls_advertise_hosts =
+
+# ----- Main settings -----
+
+trusted_users = CALLER
+bounce_return_linesize_limit = 20
+acl_smtp_rcpt = accept
+
+
+# ----- Routers -----
+
+begin routers
+
+my_main_router:
+  driver = accept
+  domains = myhost.test.ex
+  transport = t1
+
+# ----- Transports -----
+
+begin transports
+
+t1:
+  driver = appendfile
+  file = DIR/test-mail/$local_part
+  user = CALLER
+
+# End
index 7299122e8fa2c1cd05304a695262c19e9392eafb..76e6f1eec0f0dd8a48af2caf2168ee1487f5ec8a 100644 (file)
@@ -64,6 +64,7 @@ check_recipient:
          logwrite =  md5    fingerprint ${md5:$tls_in_peercert}
          logwrite =  sha1 fingerprint ${sha1:$tls_in_peercert}
          logwrite =  sha256 fingerprint ${sha256:$tls_in_peercert}
+         logwrite =  der_b64 ${base64:$tls_in_peercert}
 
 
 # ----- Routers -----
index 804a846bf0e11c4961c98c92cd181d81542312fa..1de92e96296bcea5deef3a93121774c8dc4d56fb 100644 (file)
@@ -68,6 +68,7 @@ check_recipient:
          logwrite =  md5    fingerprint ${md5:$tls_in_peercert}
          logwrite =  sha1   fingerprint ${sha1:$tls_in_peercert}
          logwrite =  sha256 fingerprint ${sha256:$tls_in_peercert}
+         logwrite =  der_b64 ${base64:$tls_in_peercert}
 
 
 # ----- Routers -----
diff --git a/test/confs/4503 b/test/confs/4503
new file mode 100644 (file)
index 0000000..ddd87d0
--- /dev/null
@@ -0,0 +1,48 @@
+# Exim test configuration 4503
+
+SERVER=
+
+exim_path = EXIM_PATH
+host_lookup_order = bydns
+primary_hostname = myhost.test.ex
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/SERVER%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+tls_advertise_hosts =
+
+# ----- Main settings -----
+
+log_selector = +outgoing_port
+acl_smtp_rcpt = accept
+acl_smtp_dkim = accept logwrite = signer: $dkim_cur_signer bits: $dkim_key_length
+
+# ----- Routers
+
+begin routers
+
+server_dump:
+  driver = redirect
+  condition = ${if eq {SERVER}{server}{yes}{no}}
+  data = :blackhole:
+
+client:
+  driver = accept
+  transport = send_to_server
+
+# ----- Transports
+
+begin transports
+
+send_to_server:
+  driver = smtp
+  allow_localhost
+  hosts = HOSTIPV4
+  port = PORT_D
+
+  dkim_domain =                test.ex
+  dkim_selector =      sel
+  dkim_private_key =   DIR/aux-fixed/dkim/dkim.private
+  dkim_sign_headers =  From
+
+# End
index 85962610650145f7fb094c986911d1b972f43a0b..cde5b432106d4165184c2f5462a1eda418a606c1 100644 (file)
@@ -472,7 +472,7 @@ DELAY=1500 delay1500 A HOSTIPV4
 
 ; ------- DKIM ---------
 
-; public key, base64 - matches private key in aux-fixed/dkim/dkim/private
+; public key, base64 - matches private key in aux-fixed/dkim/dkim.private
 ;  openssl genrsa -out aux-fixed/dkim/dkim.private 1024
 ;  openssl rsa -in aux-fixed/dkim/dkim.private -out /dev/stdout -pubout -outform PEM
 ;
index 43b67db11ab6c72078ff07081788664e63a931b8..0f19e9cf45afa829a822f1a9a0ee19b179fc8850 100644 (file)
@@ -6,10 +6,7 @@
 1999-03-02 09:44:33 NOTQUIT reason: 'connection-lost'
 1999-03-02 09:44:33 NOTQUIT reason: 'bad-commands'
 1999-03-02 09:44:33 SMTP call from [127.0.0.1] dropped: too many unrecognized commands (last was "unknown")
-1999-03-02 09:44:33 H=[127.0.0.1] rejected VRFY 
-1999-03-02 09:44:33 H=[127.0.0.1] rejected VRFY 
-1999-03-02 09:44:33 H=[127.0.0.1] rejected VRFY 
-1999-03-02 09:44:33 H=[127.0.0.1] rejected VRFY 
+1999-03-02 09:44:33 H=[127.0.0.1] rejected VRFY foo@bar
 1999-03-02 09:44:33 SMTP call from [127.0.0.1] dropped: too many nonmail commands (last was "vrfy")
 1999-03-02 09:44:33 NOTQUIT reason: 'bad-commands'
 1999-03-02 09:44:33 10HmaX-0005vi-00 H=(abcd) [127.0.0.1] F=<userx@test.ex> rejected after DATA
diff --git a/test/log/0573 b/test/log/0573
new file mode 100644 (file)
index 0000000..528f697
--- /dev/null
@@ -0,0 +1,12 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= not_limited@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 ** fred@undeliverable.org: Unrouteable address
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> R=10HmaX-0005vi-00 U=EXIMUSER P=local S=sss
+1999-03-02 09:44:33 10HmaY-0005vi-00 => not_limited <not_limited@myhost.test.ex> R=my_main_router T=t1
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= limited@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaZ-0005vi-00 ** fred@undeliverable.org: Unrouteable address
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> R=10HmaZ-0005vi-00 U=EXIMUSER P=local S=sss
+1999-03-02 09:44:33 10HmbA-0005vi-00 => limited <limited@myhost.test.ex> R=my_main_router T=t1
+1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
index e0eb36ccb96cb3991ccfbe5eb281b859cae8685a..933905460ed80f2d582ccf7073bfaba5a92b361a 100644 (file)
@@ -23,6 +23,7 @@
 1999-03-02 09:44:33 md5    fingerprint 33728C89BBE99028425D137F7508F74A
 1999-03-02 09:44:33 sha1 fingerprint 1A420D865B90068FB822E71567A456A3578D26AA
 1999-03-02 09:44:33 sha256 fingerprint 7E194665AE12FD9AF8E604427D512E846E75EC96032BF78BAD707426F01CFF17
+1999-03-02 09:44:33 der_b64 MIICiDCCAfGgAwIBAgICAMkwDQYJKoZIhvcNAQELBQAwMzEUMBIGA1UEChMLZXhhbXBsZS5jb20xGzAZBgNVBAMTEmNsaWNhIFNpZ25pbmcgQ2VydDAeFw0xMjExMDExMjM0MzhaFw0zODAxMDExMjM0MzhaMB4xHDAaBgNVBAMTE3NlcnZlcjIuZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALoxxS9eRRSkEJF5CmlLToLY3886wsCOc+vuBo+2V69Q7aCC3Wa13UTZ7SVPhliw29gl48Ua7Go5E6E4+6n7SNL+VfuMtNg2zs4BIhXTfiPZ9U2YF77+Y64MFPBxK98F/RB/wjqAiWf5aigaQCSGX7Bf1bb1s3UwCi0M/wXHYj7TAgMBAAGjgb8wgbwwDgYDVR0PAQH/BAQDAgTwMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vY3JsLmV4YW1wbGUuY29tL2xhdGVzdC5jcmwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb3NjcC9leGFtcGxlLmNvbS8wHgYDVR0RBBcwFYITc2VydmVyMi5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOBgQCZCepTW/JRRZlxxEIcQVlQLpdcxuJnYvNbZwzn7Os0K7og1S7jl4PDncao6APk6f4WAfFjb4ZZc1NytSHPLuodWToY1bUzIBMKwk9Jof2yw2mr/3ElyzRDlVmXri+6b0X5WmfMeWI7npeb6Pl6n18tTYKkGGcFwsFsC+CeuLOzNw==
 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@test.ex H=[ip4.ip4.ip4.ip4] P=smtps X=TLS1.x:xxxxRSA_AES_256_CBC_SHAnnn:256 CV=yes DN="CN=server2.example.com" S=sss
 1999-03-02 09:44:33 Start queue run: pid=pppp -qf
 1999-03-02 09:44:33 10HmaX-0005vi-00 => CALLER <CALLER@test.ex> R=abc T=local_delivery
index 48e58605392781c92cf0d2724f984e582f3b82a0..838930a8241bca84ff570984e0b34a1e2600c162 100644 (file)
@@ -26,6 +26,7 @@
 1999-03-02 09:44:33 md5    fingerprint 33728C89BBE99028425D137F7508F74A
 1999-03-02 09:44:33 sha1   fingerprint 1A420D865B90068FB822E71567A456A3578D26AA
 1999-03-02 09:44:33 sha256 fingerprint 7E194665AE12FD9AF8E604427D512E846E75EC96032BF78BAD707426F01CFF17
+1999-03-02 09:44:33 der_b64 MIICiDCCAfGgAwIBAgICAMkwDQYJKoZIhvcNAQELBQAwMzEUMBIGA1UEChMLZXhhbXBsZS5jb20xGzAZBgNVBAMTEmNsaWNhIFNpZ25pbmcgQ2VydDAeFw0xMjExMDExMjM0MzhaFw0zODAxMDExMjM0MzhaMB4xHDAaBgNVBAMTE3NlcnZlcjIuZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALoxxS9eRRSkEJF5CmlLToLY3886wsCOc+vuBo+2V69Q7aCC3Wa13UTZ7SVPhliw29gl48Ua7Go5E6E4+6n7SNL+VfuMtNg2zs4BIhXTfiPZ9U2YF77+Y64MFPBxK98F/RB/wjqAiWf5aigaQCSGX7Bf1bb1s3UwCi0M/wXHYj7TAgMBAAGjgb8wgbwwDgYDVR0PAQH/BAQDAgTwMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vY3JsLmV4YW1wbGUuY29tL2xhdGVzdC5jcmwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb3NjcC9leGFtcGxlLmNvbS8wHgYDVR0RBBcwFYITc2VydmVyMi5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOBgQCZCepTW/JRRZlxxEIcQVlQLpdcxuJnYvNbZwzn7Os0K7og1S7jl4PDncao6APk6f4WAfFjb4ZZc1NytSHPLuodWToY1bUzIBMKwk9Jof2yw2mr/3ElyzRDlVmXri+6b0X5WmfMeWI7npeb6Pl6n18tTYKkGGcFwsFsC+CeuLOzNw==
 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@test.ex H=[ip4.ip4.ip4.ip4] P=smtps X=TLSv1:AES256-SHA:256 CV=yes DN="/CN=server2.example.com" S=sss
 1999-03-02 09:44:33 Start queue run: pid=pppp -qf
 1999-03-02 09:44:33 10HmaX-0005vi-00 => CALLER <CALLER@test.ex> R=abc T=local_delivery
index 4787e64230ea20434697375c5778530057fa4a5f..0e0f8400d30afb51e83ebaec385b284ca7e41a88 100644 (file)
@@ -7,3 +7,6 @@
 1999-03-02 09:44:33 10HmaY-0005vi-00 DKIM: d=test.ex s=ses c=simple/simple a=rsa-sha1 b=512 [verification succeeded]
 1999-03-02 09:44:33 10HmaY-0005vi-00 signer: test.ex bits: 512
 1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss id=qwerty1234@disco-zombie.net
+1999-03-02 09:44:33 10HmaZ-0005vi-00 DKIM: d=test.ex s=sel c=simple/simple a=rsa-sha256 b=1024 [verification succeeded]
+1999-03-02 09:44:33 10HmaZ-0005vi-00 signer: test.ex bits: 1024
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss id=qwerty1234@disco-zombie.net
diff --git a/test/log/4503 b/test/log/4503
new file mode 100644 (file)
index 0000000..39b918a
--- /dev/null
@@ -0,0 +1,11 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 => a@test.ex R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4]:1225 C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 10HmaY-0005vi-00 DKIM: d=test.ex s=sel c=relaxed/relaxed a=rsa-sha256 b=1024 [verification succeeded]
+1999-03-02 09:44:33 10HmaY-0005vi-00 signer: test.ex bits: 1024
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: <a@test.ex> R=server_dump
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
index a72dfeeadf5cc320f4b08b61e7b7f84a52b63dbe..f8d7c9e8ff9429dae8a4f145e6fad73eac342e26 100644 (file)
@@ -52,3 +52,7 @@
 1999-03-02 09:44:33 10HmbG-0005vi-00 >> userx@localhost4.test.ex R=dns T=smtp H=localhost4.test.ex [127.0.0.1] C="250 OK"
 1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userx@localhost4.test.ex usery@thishost.test.ex
 1999-03-02 09:44:33 10HmbG-0005vi-00 Completed
+1999-03-02 09:44:33 rcpt for userx@domain.com
+1999-03-02 09:44:33 10HmbH-0005vi-00 >> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss for userx@domain.com
+1999-03-02 09:44:33 10HmbH-0005vi-00 Completed
diff --git a/test/mail/0573.limited b/test/mail/0573.limited
new file mode 100644 (file)
index 0000000..25ddebc
--- /dev/null
@@ -0,0 +1,51 @@
+From MAILER-DAEMON Tue Mar 02 09:44:33 1999
+Received: from EXIMUSER by myhost.test.ex with local (Exim x.yz)
+       id 10HmbA-0005vi-00
+       for limited@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+X-Failed-Recipients: fred@undeliverable.org
+Auto-Submitted: auto-replied
+From: Mail Delivery System <Mailer-Daemon@myhost.test.ex>
+To: limited@myhost.test.ex
+Content-Type: multipart/report; report-type=delivery-status; boundary=NNNNNNNNNN-eximdsn-MMMMMMMMMM
+MIME-Version: 1.0
+Subject: Mail delivery failed: returning message to sender
+Message-Id: <E10HmbA-0005vi-00@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: text/plain; charset=us-ascii
+
+This message was created automatically by mail delivery software.
+
+A message that you sent could not be delivered to one or more of its
+recipients. This is a permanent error. The following address(es) failed:
+
+  fred@undeliverable.org
+    Unrouteable address
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: message/delivery-status
+
+Reporting-MTA: dns; myhost.test.ex
+
+Action: failed
+Final-Recipient: rfc822;fred@undeliverable.org
+Status: 5.0.0
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: text/rfc822-headers
+
+Return-path: <limited@myhost.test.ex>
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+       (envelope-from <limited@myhost.test.ex>)
+       id 10HmaZ-0005vi-00
+       for fred@undeliverable.org; Tue, 2 Mar 1999 09:44:33 +0000
+Subject: test
+Message-Id: <E10HmaZ-0005vi-00@myhost.test.ex>
+From: limited@myhost.test.ex
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+X-Exim-DSN-Information: Due to administrative limits only headers are returned
+
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM--
+
diff --git a/test/mail/0573.not_limited b/test/mail/0573.not_limited
new file mode 100644 (file)
index 0000000..62f89f0
--- /dev/null
@@ -0,0 +1,53 @@
+From MAILER-DAEMON Tue Mar 02 09:44:33 1999
+Received: from EXIMUSER by myhost.test.ex with local (Exim x.yz)
+       id 10HmaY-0005vi-00
+       for not_limited@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+X-Failed-Recipients: fred@undeliverable.org
+Auto-Submitted: auto-replied
+From: Mail Delivery System <Mailer-Daemon@myhost.test.ex>
+To: not_limited@myhost.test.ex
+Content-Type: multipart/report; report-type=delivery-status; boundary=NNNNNNNNNN-eximdsn-MMMMMMMMMM
+MIME-Version: 1.0
+Subject: Mail delivery failed: returning message to sender
+Message-Id: <E10HmaY-0005vi-00@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: text/plain; charset=us-ascii
+
+This message was created automatically by mail delivery software.
+
+A message that you sent could not be delivered to one or more of its
+recipients. This is a permanent error. The following address(es) failed:
+
+  fred@undeliverable.org
+    Unrouteable address
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: message/delivery-status
+
+Reporting-MTA: dns; myhost.test.ex
+
+Action: failed
+Final-Recipient: rfc822;fred@undeliverable.org
+Status: 5.0.0
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM
+Content-type: message/rfc822
+
+Return-path: <not_limited@myhost.test.ex>
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+       (envelope-from <not_limited@myhost.test.ex>)
+       id 10HmaX-0005vi-00
+       for fred@undeliverable.org; Tue, 2 Mar 1999 09:44:33 +0000
+Subject: test
+Message-Id: <E10HmaX-0005vi-00@myhost.test.ex>
+From: not_limited@myhost.test.ex
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+msg with ok lines
+00000000001111111
+01234567890123456
+
+--NNNNNNNNNN-eximdsn-MMMMMMMMMM--
+
index d10c450f63d98ac9b47627a816878aa072caca1b..951f79e39c6129543eec58cfa6006a2b926682a9 100644 (file)
@@ -1,8 +1,5 @@
 1999-03-02 09:44:33 SMTP call from [127.0.0.1] dropped: too many unrecognized commands (last was "unknown")
-1999-03-02 09:44:33 H=[127.0.0.1] rejected VRFY 
-1999-03-02 09:44:33 H=[127.0.0.1] rejected VRFY 
-1999-03-02 09:44:33 H=[127.0.0.1] rejected VRFY 
-1999-03-02 09:44:33 H=[127.0.0.1] rejected VRFY 
+1999-03-02 09:44:33 H=[127.0.0.1] rejected VRFY foo@bar
 1999-03-02 09:44:33 SMTP call from [127.0.0.1] dropped: too many nonmail commands (last was "vrfy")
 1999-03-02 09:44:33 10HmaX-0005vi-00 H=(abcd) [127.0.0.1] F=<userx@test.ex> rejected after DATA
 Envelope-from: <userx@test.ex>
index d060fda921119d00c7d3efc80689f73c4dd3af6b..2b19f52e3f511bdf88f72bfd0e0f08902b6ba9d0 100755 (executable)
@@ -1393,6 +1393,15 @@ $munges =
     { 'mail' => '/^(X-(Remote-MTA-(smtp-greeting|helo-response)|Exim-Diagnostic|(body|message)-linecount):|Remote-MTA: X-ip;)/'
     },
 
+    'optional_nossl' =>
+    { 'stdout' => '/^(
+                  dkim_(canon|domain|private_key|selector|sign_headers|strict)
+                  |gnutls_require_(kx|mac|protocols)
+                  |hosts_(requ(est|ire)|try)_(dane|ocsp)
+                  |hosts_(avoid|nopass|require|verify_avoid)_tls
+                  |tls_[^ ]*
+                  )($|[ ]=)/x' },
+
     'sys_bindir' =>
     { 'mainlog' => 's%/(usr/)?bin/%SYSBINDIR/%' },
 
index bf2c1068c039afa36e5573f0591a39f40c048c90..105134da33c9fd2f659c2bfa4d6166f84b9fd9fc 100644 (file)
@@ -258,6 +258,10 @@ substr: ${s_1:}
 substr: ${substr_10:abc}
 str2b64:${str2b64:abcd}
 str2b64:${str2b64:The quick brown \n fox}
+base64: ${base64:abcd}
+base64: ${base64:The quick brown \n fox}
+base64d:${base64d:YWJjZA==}
+base64d:${base64d:VGhlIHF1aWNrIGJyb3duIAogZm94}
 strlen: ${strlen:}
 strlen: ${strlen:a}
 strlen: ${strlen:abcdefgh}
index 5601d650615c061ab5a4b146a57c3aedb1f47d06..3495375cbf75a4b775f66a461d451e7a28f5848c 100644 (file)
@@ -1,6 +1,7 @@
 # VRFY & EXPN blocking
 exim -bh 1.1.1.1
 vrfy userx@test.ex
+vrfy hardfail@test.ex
 expn postmaster
 quit
 ****
index 9355c46fcc5d82324282aaa928c480dacb5d36e4..b829dff30a0184c9e52fdae4610cf01193f396b4 100644 (file)
@@ -39,13 +39,13 @@ unknown
 client 127.0.0.1 PORT_D
 ??? 220
 vrfy
+??? 501
+vrfy foo@bar
 ??? 252
 vrfy
-??? 252
-vrfy
-??? 252
+??? 501
 vrfy
-??? 252
+??? 501
 vrfy
 ??? 554
 ****
index 3525333c6148e9a0963663578d47d12e4dffceef..05ba658f7e9f373d4ab25c5b142016a262e76c85 100644 (file)
@@ -3,6 +3,7 @@
 # Ought to test a non-priv user, checking "hide", but
 # the testsuite cannot do that...
 #
+munge optional_nossl
 exim -bP spool_directory
 ****
 perl -e 'print "\n";'
diff --git a/test/scripts/0000-Basic/0573 b/test/scripts/0000-Basic/0573
new file mode 100644 (file)
index 0000000..88606d2
--- /dev/null
@@ -0,0 +1,18 @@
+# bounce_return_linesize_limit
+#
+exim -odi -f not_limited fred@undeliverable.org
+Subject: test
+
+msg with ok lines
+00000000001111111
+01234567890123456
+****
+#
+exim -odi -f limited fred@undeliverable.org
+Subject: test
+
+msg with long lines
+000000000011111111112222222222
+012345678901234567890123456789
+****
+no_msglog_check
index b352893e30fc06d97f25faf99afe7e93958dfbc9..56283992b8715945c235947465fede795bcd50d5 100644 (file)
@@ -4,6 +4,7 @@ exim -DSERVER=server -bd -oX PORT_D
 ****
 #
 # This should pass.
+#  - sha1, 1024b
 # Mail original in aux-fixed/4500.msg1.txt
 # Sig generated by: perl aux-fixed/dkim/sign.pl --method=simple/simple < aux-fixed/4500.msg1.txt
 client 127.0.0.1 PORT_D
@@ -35,6 +36,7 @@ QUIT
 ****
 #
 # This should pass.
+#  - sha1, 512b
 # Mail original in aux-fixed/4500.msg1.txt
 # Sig generated by: perl aux-fixed/dkim/sign.pl --method=simple/simple --selector=ses \
 #                      --keyfile=aux-fixed/dkim/dkim512.private < aux-fixed/4500.msg1.txt
@@ -58,6 +60,39 @@ Date: Thu, 19 Nov 2015 17:00:07 -0700
 Message-ID: <qwerty1234@disco-zombie.net>
 Subject: simple test
 
+This is a simple test.
+.
+??? 250
+QUIT
+??? 221
+****
+#
+# This should pass.
+#  - sha256, 1024b
+# Mail original in aux-fixed/4500.msg1.txt
+# Sig generated by: perl aux-fixed/dkim/sign.pl --algorithm=rsa-sha256 \
+#                      --method=simple/simple < aux-fixed/4500.msg1.txt
+client 127.0.0.1 PORT_D
+??? 220
+HELO xxx
+??? 250
+MAIL FROM:<CALLER@bloggs.com>
+??? 250
+RCPT TO:<a@test.ex>
+??? 250
+DATA
+??? 354
+DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=test.ex; h=from:to
+       :date:message-id:subject; s=sel; bh=3UbbJTudPxmejzh7U1Zg33U3QT+1
+       6kfV2eOTvMeiEis=; b=xQSD/JMqz0C+xKf0A1NTkPTbkDuDdJbpBuyjjT9iYvyP
+       Zez+xl0TkoPobFGVa6EN8+ZeYV18zjifhtWYLSsNmPinUtcpKQLG1zxAKmmS0JEh
+       +qihlWbeGJ5+tK588ugUzXHPj+4JBW0H6kxHvdH0l2SlQE5xs/cdggnx5QX5USY=
+From: mrgus@text.ex
+To: bakawolf@yahoo.com
+Date: Thu, 19 Nov 2015 17:00:07 -0700
+Message-ID: <qwerty1234@disco-zombie.net>
+Subject: simple test
+
 This is a simple test.
 .
 ??? 250
diff --git a/test/scripts/4500-Domain-Keys-Identified-Mail/4503 b/test/scripts/4500-Domain-Keys-Identified-Mail/4503
new file mode 100644 (file)
index 0000000..cebc62d
--- /dev/null
@@ -0,0 +1,12 @@
+# DKIM signing
+#
+exim -bd -DSERVER=server -oX PORT_D
+****
+exim a@test.ex
+From: nobody@example.com
+
+content
+****
+millisleep 500
+killdaemon
+no_msglog_check
index 5344ba51c6db4cd77ce0bbb5bd3f42be580a2405..109b43928a4d9daa455c35f0010f2dbfc921f15b 100644 (file)
@@ -414,5 +414,39 @@ QUIT
 #
 #
 #
+# data having line with (logical, doubled on wire) single dot
+server PORT_S
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 Recipient OK
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+****
+exim -bs -odf
+EHLO myhost.test.ex
+MAIL FROM:<CALLER@myhost.test.ex>
+RCPT TO:<userx@domain.com>
+DATA
+Subject: singledot test
+
+This data has a line with a single dot... next:
+..
+and this is the line right after.
+Next we have a line with a leading dot:
+..test
+and this is the next line.
+
+.
+QUIT
+****
+#
 #
 # End
index 521f8fd7190cee7ba897374d235ab55e7a4fedbc..f06bba7e25be60384a6b92094febe5d798d88a22 100644 (file)
@@ -55,6 +55,7 @@ test message.
 ****
 sleep 1
 killdaemon
+millisleep 200
 #
 #
 #
index 4aacae8838c0604a54335580b86fa4c9937a3761..b0030521234f926e3905192581b9d0d4a09a3c11 100644 (file)
@@ -7,8 +7,21 @@
 >>> host in helo_try_verify_hosts? no (option unset)
 >>> host in helo_accept_junk_hosts? no (option unset)
 >>> host in smtp_accept_max_nonmail_hosts? yes (matched "*")
->>> ACL is NULL: implicit DENY
+>>> using ACL "check_vrfy"
+>>> processing "deny"
+>>> check local_parts = hardfail
+>>> userx in "hardfail"? no (end of list)
+>>> deny: condition test failed in ACL "check_vrfy"
+>>> end of ACL "check_vrfy": implicit DENY
 LOG: H=[1.1.1.1] rejected VRFY userx@test.ex
+>>> using ACL "check_vrfy"
+>>> processing "deny"
+>>> check local_parts = hardfail
+>>> hardfail in "hardfail"? yes (matched "hardfail")
+>>>   message: 599 custom reject
+>>> deny: condition test succeeded in ACL "check_vrfy"
+>>> end of ACL "check_vrfy": DENY
+LOG: H=[1.1.1.1] rejected VRFY hardfail@test.ex: 599 custom reject
 >>> using ACL "check_expn"
 >>> processing "accept"
 >>> check hosts = 2.2.2.2
index 3018dce1f947047e5f95a62d86ec6125a9d1f5dc..ee351a2784b92597350deed1ea48bbfcadaf3bf6 100644 (file)
@@ -72,7 +72,7 @@
 > listextract: 
 > listextract: 
 > listextract: fail
-> Failed: "extract" failed and "fail" requested
+> Failed: "listextract" failed and "fail" requested
 > 
 > sort: 1:2:3:4
 > sort: 4,3,2,1
 > substr: 
 > str2b64:YWJjZA==
 > str2b64:VGhlIHF1aWNrIGJyb3duIAogZm94
+> base64: YWJjZA==
+> base64: VGhlIHF1aWNrIGJyb3duIAogZm94
+> base64d:abcd
+> base64d:The quick brown 
+ fox
 > strlen: 0
 > strlen: 1
 > strlen: 8
index d43b4501a68f8ddaeeafb44cc7e4f62878817044..b88c93ac70d681552d977b2bb9f920ed772bf0ce 100644 (file)
@@ -5,6 +5,7 @@
 
 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
 252 Administrative prohibition\r
+599 custom reject\r
 550 Administrative prohibition\r
 221 the.local.host.name closing connection\r
 
index 693fddace4aa1c5cf56c567f08793ddbc1d1a827..a32896899889dd339f371c034aeb52a7908792c6 100644 (file)
@@ -51,17 +51,17 @@ Connecting to 127.0.0.1 port 1225 ... connected
 ??? 220
 <<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
 >>> vrfy
+??? 501
+<<< 501 empty address
+>>> vrfy foo@bar
 ??? 252
 <<< 252 Administrative prohibition
 >>> vrfy
-??? 252
-<<< 252 Administrative prohibition
+??? 501
+<<< 501 empty address
 >>> vrfy
-??? 252
-<<< 252 Administrative prohibition
->>> vrfy
-??? 252
-<<< 252 Administrative prohibition
+??? 501
+<<< 501 empty address
 >>> vrfy
 ??? 554
 <<< 554 Too many nonmail commands
index ec427ae623718f4ae4a32f11c55858725ecd94be..240a2332a0d64fc8196ae3bbfc9c5ee6a20732fb 100644 (file)
@@ -39,12 +39,6 @@ connect_timeout = 5m
 connection_max_messages = 500
 data_timeout = 5m
 delay_after_cutoff
-dkim_canon = 
-dkim_domain = 
-dkim_private_key = 
-dkim_selector = 
-dkim_sign_headers = 
-dkim_strict = 
 dns_qualify_single
 no_dns_search_parents
 dnssec_request_domains = 
@@ -53,28 +47,17 @@ dscp =
 fallback_hosts = 
 final_timeout = 10m
 no_gethostbyname
-gnutls_require_kx = 
-gnutls_require_mac = 
-gnutls_require_protocols = 
 helo_data = $primary_hostname
 hosts = 
 hosts_avoid_esmtp = 
 hosts_avoid_pipelining = 
-hosts_avoid_tls = 
 hosts_max_try = 5
 hosts_max_try_hardlimit = 50
-hosts_nopass_tls = 
 no_hosts_override
 no_hosts_randomize
-hosts_request_ocsp = *
 hosts_require_auth = 
-hosts_require_dane = 
-hosts_require_ocsp = 
-hosts_require_tls = 
 hosts_try_auth = 
-hosts_try_dane = 
 hosts_try_prdr = *
-hosts_verify_avoid_tls = 
 interface = ip4.ip4.ip4.ip4
 keepalive
 no_lmtp_ignore_quota
@@ -86,17 +69,6 @@ retry_include_ip_address
 serialize_hosts = 
 size_addition = 1024
 socks_proxy = 127.0.0.1 port=1225
-tls_certificate = 
-tls_crl = 
-tls_dh_min_bits = 1024
-tls_privatekey = 
-tls_require_ciphers = 
-tls_sni = 
-tls_tempfail_tryclear
-tls_try_verify_hosts = *
-tls_verify_cert_hostnames = *
-tls_verify_certificates = system
-tls_verify_hosts = 
 
 # Exim Configuration (X)
 # 1 "TESTSUITE/test-config"
@@ -108,8 +80,7 @@ spool_directory = TESTSUITE/spool
 log_file_path = TESTSUITE/spool/log/%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
-tls_advertise_hosts =
-log_selector = +proxy +outgoing_port
+log_selector = +outgoing_port
 domainlist local_domains = test.ex : *.test.ex
 acl_smtp_rcpt = accept
 
index 05f2ef037735871fb2c1171f8ff61b7a720503f4..20de2df0981f1bebb11e1853cf900a8861dbcdfe 100644 (file)
 354 Enter message, ending with "." on a line by itself\r
 250 OK id=10HmbG-0005vi-00\r
 221 myhost.test.ex closing connection\r
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-myhost.test.ex Hello CALLER at myhost.test.ex\r
+250-SIZE 52428800\r
+250-8BITMIME\r
+250-PIPELINING\r
+250 HELP\r
+250 OK\r
+250 Accepted\r
+354 Enter message, ending with "." on a line by itself\r
+250 OK id=10HmbH-0005vi-00\r
+221 myhost.test.ex closing connection\r
 
 ******** SERVER ********
 Listening on port 1224 ... 
@@ -508,3 +519,37 @@ Date: Tue, 2 Mar 1999 09:44:33 +0000
 QUIT
 250 OK
 End of script
+Listening on port 1224 ... 
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<userx@domain.com>
+250 Recipient OK
+DATA
+354 Send data
+Received: from CALLER (helo=myhost.test.ex)
+       by myhost.test.ex with local-esmtp (Exim x.yz)
+       (envelope-from <CALLER@myhost.test.ex>)
+       id 10HmbH-0005vi-00
+       for userx@domain.com; Tue, 2 Mar 1999 09:44:33 +0000
+Subject: singledot test
+Message-Id: <E10HmbH-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+X-hdr-rtr-new: +++
+
+This data has a line with a single dot... next:
+..
+and this is the line right after.
+Next we have a line with a leading dot:
+..test
+and this is the next line.
+
+.
+250 OK
+QUIT
+250 OK
+End of script