Index: freeswan/README.ipsec_alg
diff -u /dev/null freeswan/README.ipsec_alg:1.1.2.21
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/README.ipsec_alg	Fri Jul 12 15:58:26 2002
@@ -0,0 +1,171 @@
+READMe-ipsec_alg.txt       --Juanjo <jjo-ipsec@mendoza.gov.ar> 16/05/02
+====================         Linux IP Aliasing creator, IPMASQ 2.2 Maintainer
+
+Modular ALGO support version 0.8.0 for freeswan-1.98b.
+PLEASE read CHANGES.ipsec_alg file for updates.
+
+* New IKE (Phase1) algos:
+  Encrypt : AES, Twofish, Serpent, Blowfish, CAST
+  Auth:     SHA2
+
+* New ESP (Phase2 or manual) kernel algos:
+  Encrypt : AES [*] , Twofish, Serpent, Blowfish [*], CAST [*]
+  Auth:     SHA2, MD5 [*], SHA1 [*].
+
+  [*] uses x86 assembler implementation if possible
+
+* New DH and PFS groups: 2048, 3072, 4096
+
+***                                                     ***
+*** AES ESP achieves 2x to 3x SPEED INCREASE over 3DES  ***
+***                                                     ***
+
+All algorithms (including DH groups) _per_connection_ selectable.
+Alternative x509 pluto patch with same features.
+
+Tested on linux 2.4.18/i386, 2.4.9-31/i386; 2.2.16/s390 (surprise! :)
+
+* Known userbase:
+  + Debian 3.0 distro, since Mar 2002 
+  + Devil-linux distro, since Jun 2002 <heiko@zuerker.org>
+
+* Highlights
+  + *optimized* AES cipher can achieve 2x to 3x SPEED INCREASE (or CPU unhog),
+    thus converting (see docs/performance.html) CPU=C*25 to 
+
+       CPU [mhz]= C [mbit/s] *10 
+
+    thus, you can almost saturate a 100mbit/s link with 1GHz PIII with
+    these new ESP cipher modules.
+
+  + interop: patched/stock freeswan, OpenBSD 3.0, FreeBSD-4.5 and SSH Sentinel
+    * PLEASE READ AHEAD (TABLE) *
+
+  + IKE encrypt algos: AES, Twofish, Serpent, Blowfish.
+    with configurable keylen, eg: aes128 ... aes256
+
+  + IKE hash algos: SHA2.
+
+  + ESP modular ciphers and authenticators (generic KLIPS hooks)
+    ie. just do:  modprobe ipsec_aes
+
+  + ESP encrypt algos: AES, Serpent, Twofish, Blowfish, CAST and
+    (modularized) 3DES; configurable keylen, eg: aes128 ... aes256
+
+  + ESP auth algos: SHA2, SHA1, MD5, RIPEMD  and (experimental) XCBC_MAC_AES
+
+  + x509 coexistance  (alternative pluto patch)
+
+  + timing tests support (raw algo speed):
+
+  	modprobe ipsec_aes test=1; dmesg | tail -10
+	modprobe ipsec_3des test=1; dmesg | tail -10
+
+  + New pluto features
+    . create P1 proposals from ike= config parameter (eg: ike=aes128-sha)
+    . create P2 proposals from esp= config parameters (eg: esp=aes128-sha1 ) ANDed
+      with kernel algos actually present.
+    . IKE: show algos status (ipsec auto --status | egrep IKE)
+    . ESP: show algos status (ipsec auto --status | egrep ESP)
+    . IKE, ESP: show algos for each conn. 
+    	  ipsec auto --status | egrep algo.*newe
+    . ESP: get informed of new runtime algos available upon
+      module loading/unloading (from kernel SADB_REGISTER)
+    . new IKE algos get added from ./pluto/alg/*ike_alg*
+
+  + manual conn support for all algorithms (with same esp string)
+    . allow manual conns with same algorithm strings as pluto, reads
+      /proc/net/pf_key_supported to validate algorithm "presence" and
+      key sizes (and thus "predict" EINVAL errors).
+
+* KLIPS Changes (for developers):
+  + truely non-invasive patch
+  + generalized algo hook for ESP encrypt and auth
+  + ipsec_alg object linked (pointed) from ipsec_sa
+  + generic ESP algo [un]registration dispatches SADB_REGISTER msg
+    with new algos info, which is fully parsed by patched pluto.
+  + loaded modules will "override" stock ones (get linked and called first)
+  + actual WORKING implemented algos: 
+    encrypt: AES, Twofish, Serpent, Blowfish, 3DES (discont'd: CAST)
+    auth:    SHA2, SHA1, MD5, XCBC_MAC_AES (discont'd: RIPEMD)
+
+************************************************************************
+Interop TESTS (besides self-to-self)
+  FSW           : stock freeswan 1.98b
+  OBSD          : OpenBSD 3.0
+  FBSD		: FreeBSD 4.5 (KAME)
+  SSHs          : SSH Sentinel 1.3
+
+-------------- ----------------------------------------------------------------
+#ESP encryption algos:                                     
+-Algorithm x86asm module-name    dotconf            interop tests
+ AES           y  ipsec_aes      esp=aes                OBSD FBSD SSHs *(3,4)
+ 3DES          y  ipsec_3des     esp=3des           FSW OBSD FBSD SSHs
+ SERPENT       n  ipsec_serpent  esp=serpent        -
+ NULL          -  ipsec_null     esp=null           -
+ BLOWFISH      y  ipsec_blowfish esp=blowfish           OBSD FBSD SSHs *(3,5)
+ CAST          y  ipsec_cast     esp=cast               OBSD FBSD SSHs *(3,6)
+ TWOFISH       n  ipsec_twofish  esp=twofish                  --  SSHs
+--------------
+#ESP authentication algos:
+-Algorithm x86asm module-name    dotconf            interop tests
+ SHA2_256      n  ipsec_sha2     esp=<enc>-sha2_256 -
+ SHA2_512      n  ipsec_sha2     esp=<enc>-sha2_512 -
+ SHA1          y  ipsec_sha1     esp=<enc>-sha1     FSW OBSD FBSD SSHs
+ MD5           y  ipsec_md5      esp=<enc>-md5      FSW OBSD FBSD SSHs
+ RIPEMD        y  ipsec_ripemd   esp=<enc>-ripemd       OBSD             (*1)
+ XCBC_MAC_AES  y  ipsec_aes      esp=<enc>-id9      -                    (*2)
+-------------- ---------------------------------------------------------------
+#IKE encryption algos:
+-Algorithm x86asm  dotconf            interop tests
+ AES           -   ike=aes128              --  FBSD SSHs
+ BLOWFISH      -   ike=blowfish128        OBSD FBSD SSHs
+ CAST          -   ike=cast128            OBSD FBSD SSHs (*3)
+ TWOFISH       -   ike=twofish128          --   --  SSHs
+ 3DES          -   ike=3des              ---stock-algo---
+--------------
+#IKE hash algos:
+-Algorithm x86asm  dotconf            interop tests
+ MD5           -   ike=<enc>-md5         ---stock-algo---
+ SHA1          -   ike=<enc>-sha         ---stock-algo---
+ SHA2_256      -   ike=<enc>-sha2_256      --  FBSD  -- 
+ SHA2_512      -   ike=<enc>-sha2_512      --   --   --  FBSD/KAME fails
+-------------- ---------------------------------------------------------------
+x86-asm       : if arch==i586/i686 it uses optimized assembler 
+                you can disable with   env NO_ASM=1 make ...
+
+(*1) only with OBSD as initiatior, fails if passive
+(*2) experimental  (draft-ietf-ipsec-ciph-aes-xcbc-mac-00.txt), working Ok
+     enable with:  "modprobe ipsec_aes auth_id=<n>" and n<=8, 
+     I privately test with n=9, and put  "esp=aes-id9" in dotconf.
+(*3) only with SSHs as responder because SSHs makes a proposal with 
+     OAKLEY_ENCRYPTION_ALGORITHM=65289.
+     SOLUTION: apply extras/patch-ssh-sentinel-IKE2.diff to allow
+     SSHs originated SAs (it justs make pluto know about 65289),
+     of course, will still negotiate OAKLEY_3DES_CBC.
+     ^^THIS INFO MAYBE OUTDATED^^
+     
+(*4) for SSHs and FBSD: specify "esp=aes128" in dotconf
+(*5) for FBSD and OBSD: specify "esp=blowfish128" in dotconf
+(*6) dis-continued after 0.7.3
+
+
+_Algorithm sources taken from_:
+OpenSSL      : sha1, md5, ripemd, blowfish, cast
+Brian Gladman: aes
+Crypto-API   : twofish, serpent
+FreeSWAN     : 3des
+Jari Ruusu   : aes (gnu asm), sha2
+Nigel Metheringham: aes-opt (asm) at libaes.sourceforge.net
+************************************************************************
+
+Available under GPL at
+Original sites:
+	http://www.irrigacion.gov.ar/juanjo/ipsec/
+	http://www.osep.mendoza.gov.ar/juanjo/ipsec/
+Mirrors:
+	(CA)    http://nyetwork.org/ipsec/aes/
+	(UK)    ftp://zeniii.linux.org.uk/pub/linux/crypto/ipsec/
+	(BR)	http://ipsecaes.fase.com.br/
+
+$Id: README.ipsec_alg,v 1.1.2.21 2002/07/12 18:58:26 jjo Exp $
Index: freeswan/CHANGES.ipsec_alg
diff -u /dev/null freeswan/CHANGES.ipsec_alg:1.1.2.22
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/CHANGES.ipsec_alg	Fri Jul 12 15:58:26 2002
@@ -0,0 +1,286 @@
+CHANGES.ipsec_alg,v 1.1.2.22 2002/07/12 18:58:26 jjo Exp
+
+v0.8.0: Phase1 cipher algorithms support, plus MODP2048-4096
+	 - final: releases testing, random docs update
+	 - rc2:   pluto/db_ops.c allocation stats (debugging)
+	 - rc1:   no user visible changes (polishing)
+	 - pre14: whack.c: force initialization of new vars
+	 - pre13: fixed make *go, different CFLAGS in libcrypto for pluto
+	          and KLIPS
+	 - pre11: accept IKE algo keylens
+	
+ * PLUTO: 
+   +    NEW: added Phase1 (IKE) algorithms:
+    	     AES, twofish, serpent, blowfish; SHA2_256, SHA2_512
+
+   +    NEW: IKE algorithm selection 
+        	ike="aes128-sha,aes128-md5"
+		ike="aes256-sha,aes256-md5"
+   + 	NEW: IKE DH group selection (if not selected will default
+             to current 1536,1024) eg:
+		ike="aes128-sha-modp2048"
+	     if no PFS group is specified, it will default to P1's DH
+	     (as current pluto does).
+   +	NEW: support for OAKLEY_MODP2048, 3072 and 4096
+   	     *only* by explicit selection in ike string
+	     NOTE: Additionally pluto will warn if it takes "too" long to 
+	           compute_dh_shared, eg (PIII 1.4GHz):
+		     003 "uml2-fbsd" #4: WARNING: compute_dh_shared(): \
+		     for OAKLEY_GROUP_MODP4096 (extension) took 223155 usec
+
+   +	NEW: pfsgroup support
+   	     new parameter in dotconf, eg:
+		pfsgroup=modp2048
+   +	NEW: auto --status full algorithm info (ESP ciphers, IKE ciphers,
+   	     DH groups)
+   +	(pre11+) fixed proposals for RSASIGs
+
+   + 	keylen handling fixes for ESP proposals
+   +	show algos for newest connection state (IKE and ESP)
+   		+ ipsec auto --status | grep algo.*newe
+   +    added patches from Mathieu Lafon - Arkoon Network Security,
+        for ESP proposals:
+        . (optional, me) strict response with esp= only algos by
+	  adding '!' to esp string, eg:   esp=aes128-sha1,aes128-md5!
+        . NULL esp= string handling: propose everything.
+   +    massive cipher code reorganization, new ./libcrypto/lib<algo>
+   	hierachy, almost no code changes.
+
+   +	[OT] contributed SHA2 patch to KAME project (typo error
+   	in sha2 array setup)
+
+ * KLIPS
+   + 	IMPORTANT: **possibly esp= string incompatible change**
+
+        Bumped AES,Serpent,twofish to 128-256 keys, so now you
+   	*MUST* specify keylength in alg string
+		esp=aes-md5       (OLD)
+	should be 
+		esp=aes128-md5    (explicit keylen)
+
+v0.7.3: KLIPS ext->alg rename, manual conn support
+
+ The most user visible change is just 1 AES option, no more CAST and manual
+ connection support (tested Ok with cloned scripts from ./testing/ ).
+
+ Changes from previous release:
+ * KLIPS: the big rename
+   - 	renamed *ipsec_ext* to *ipsec_alg*, *IPSEC_EXT* to *IPSEC_ALG*, 
+	everywhere: in filenames, interface and Config*.in => you must
+	re-select kernel build configuration for IPSEC_ALG_* 
+	(former IPSEC_EXT_*)
+   -	implemented 2linked list ipsec_alg registration instead
+	of fixed arrays => some space savings and better scalability
+	(debugged from previous available beta ).
+   -	more documentation in ipsec_alg.[ch]
+   - 	CAST discontinued, AES: only 1 impl (mailing list discussion)
+	
+ * KLIPS UTILS: manual connection support
+   -	manual conn support (klips/utils/spi.c)
+	. same pluto parser for esp strings
+	. debug flag support
+	. Makefile trickery to allow compilation "from" some pluto sources
+	  (constants.c, kernel_alg.c, alg_info.c)
+
+ * PLUTO: stricter runtime kernel algo checking
+   - 	stricter runtime algo checking in spdb.c, makes proposal
+	selection as responder more robust by avoiding *falsely* accepting
+	proposals for stock algos (3DES, MD5, SHA1) if not present.
+
+v0.7.2b:
+ Changes from v0.7.2a
+ 	* PLUTO
+	- make pluto patch for x509 patched freeswan.
+	- fixed pluto crash for RW cases (alg_info ref_cnt).
+
+v0.7.2a: "spawn of the missing link"
+ Changes from v0.6.3: 
+ 	* User visible:
+	- ipsec auto --status gives verbose info about discovered algos:
+	  Eg:
+	  + ipsec auto --status | egrep ESP
+	  000   algorithm ESP encrypt: id=3, name=ESP_3DES
+	  000   algorithm ESP encrypt: id=12, name=ESP_AES
+	  000   algorithm ESP auth attr: id=1, name=AUTH_ALGORITHM_HMAC_MD5
+	  000   algorithm ESP auth attr: id=2, name=AUTH_ALGORITHM_HMAC_SHA1
+	  000   algorithm ESP auth attr: id=5, name=AUTH_ALGORITHM_HMAC_SHA2_256
+	  000   algorithm ESP auth attr: id=7, name=AUTH_ALGORITHM_HMAC_SHA2_512
+	  000 "quark-nkosa":   ESP algorithms wanted: 12/000-2/000,    \
+	       253/000-2/000, 252/000-2/000, 7/000-2/000, 6/000-2/000, \
+	       11/000-2/000, 3/000-2/000,
+	  000 "quark-nkosa":   ESP algorithms loaded: 12/128-2/160, 3/168-2/160,
+
+	- ESP auth modules: 
+	     . SHA2 (256, 512)
+	     . SHA1, MD5, RIPEMD (all with opt. x86 asm); 
+	     . experimental XCBC_MAC_AES
+
+	- tested over linux-2.2.x
+
+	- working STATIC compilation for all modules (with core ipsec.o
+	  static or modular)
+	  
+	- tested interop with SSH Sentinel for all common modules: 
+	  aes(rinjdael), twofish, blowfish, cast, 3des (module)
+	  
+	- ext modules (loaded or static) will prevail stock implementation:
+	  you can compile with all stock algos and insert modules (for 
+	  same algos: 3DES, SHA1, MD5) to test/benchmark them.
+
+ 	* KLIPS
+	- *NEW* ESP auth hooks (!)
+	- STATIC COMPILATION of any module (with static or modular ipsec.o)
+	  pretty bloody work... to cope with ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+	- Makefile changes (eg: make -C ext clean ... works recursely)
+	- changed hooking code and logic: 
+	  a loaded MODULE will hook BEFORE stock algo (3des, md5, sha1)
+	  ie. you can test the new modules by just loading them and
+	  doing down/up.
+	  This allows, eg. compiling ipsec.o WITHOUT any algo (and load
+	  them afterwards)
+	- ipsec_sa->ipsec_ext link:  ip_sa->ips_ext_{enc,auth}
+	  . no more lookups with enc_alg for each packet processing (obvious)
+	  . no more micro-locking: just count ipsec_sa' pointer for ref count
+	  . direct usage of ipsec_ext data from other places, eg:
+	    ipsec_tunnel.c:    ip_s->ipsec_ext_enc->blocksize
+	- new struct ipsec_ext_enc, ipsec_ext_auth "derived" from 
+	  struct ipsec_ext (thanks cpp :)
+	- BIG cleanup: about 20% less lines of code in ipsec_ext.c (450 lin)
+	- IV,esp_head functions eliminated, direct IV handling
+	  using ixt->blocksize
+	- tiny exported interface (ipsec_ext.h)
+	- INC/DEC MODULE usage count (you'll actually _see_ your algo module
+	  working :)
+	- namespace (structs, fields) re-arranged
+	- prefix all ipsec_ext fields with "ixt_", "ixt_e_" and "ixt_a_"
+	- NOT-YET: sadb 256 array alternative: linked list, etc
+
+      * PLUTO
+	- ipsec auto --status will show very useful info about algos loaded
+        - SADB_AALG_MAX=15, debug ESP auth registration 
+	- better diagnostics for absent kernel algos for esp selection
+	- changed logic in spdb.c to allow replacing any ESP proposal =>
+	  added "policy" parameter, used in kernel_alg_db_prop_new()
+	  (v0.7.2a)
+	
+  ************************************************************************
+  *   recall that from v0.6 pluto MUST have the esp= connection parameter 
+  *   in the dotconf connection section
+  *   eg.
+  *           esp=aes,3des  
+  *   to propose/use AES transform (_and_ 3DES).
+  *
+  *   Pluto WILL ONLY offer esp= list, checking 1-by-1 if
+  *   if kernel cipher support IS LOADED and skipping that one if not.
+  *   
+  *   So, if you want previous behaviour (offer-all-loaded-ciphers) just add:
+  *
+  *      conn %default
+  *           esp=aes,twofish,serpent,cast,blowfish,3des
+  *   
+  *   Some valid transform strings:
+  *          "aes"                    equiv. to   "aes128-md5,aes128-sha1"
+  *          "aes-sha1"               equiv. to   "aes128-sha1"
+  *          "aes128-sha1, 3des-sha1"
+  *          "aes128,blowfish96,3des"
+  *          "aes-sha2_256,aes-sha2_512"
+  *          
+  ***********************************************************************
+
+v0.6.3:
+ Changes from v0.6.3:
+	* KLIPS
+	- ext_aes: 
+		libaes pentium asm implementation: 2x speed !
+ 		(from loopAES-v1.5)
+	- ext_aes-opt:
+		alternative (also 2x) impl. upgraded to libaes-0.03
+		(from Nigel at libaes.sourceforge.net)
+	- some minor tweaks to minimize ipsec_ext_aes.c ipsec_ext_aes-opt.c diff
+v0.6.2:
+ Changes from v0.6.1:
+ 	* KLIPS
+	- added ipsec_aes-opt: AES optimized impl. from Nigel 
+	  (libaes.sourceforge.net)
+	* PLUTO
+	- enhanced and cleaned up esp= dotconf parsing code 
+
+v0.6.1:
+ Changes from v0.6.2:
+	* KLIPS:
+	- renamed blowfish: "bf" -> "blowfish" (ie: modprobe ipsec_blowfish)
+
+v0.6: "esp= support"
+ Changes from v0.5:
+	* KLIPS: _no_changes_
+	* PLUTO: esp= configurabilty
+	- added enum_search() to constants.c: returns value if strcmp()==0
+	  Used by parsing logic tricks to allow searching in enum_names
+	  arrays (thus avoiding yetanother duplication), eg:         
+	  	"3des"  -> "ESP_3DES"
+		"md5"   -> "AUTH_ALGORITHM_HMAC_MD5"
+	- added "esp" parsing to utils/auto, default=3des
+        - added msg.esp (string 7) to whack->pluto protocol 
+	- new file alg_info.c for esp algo parsing logic
+	  . build proposals with esp= ordered list only _ANDed_
+	    with registered (runtime kernel) ESP algos
+	  Eg: (assuming all these algos are loaded) in ipsec.conf
+	    connection section:
+	     <none> or esp=	# default: 3DES+{MD5,SHA1}
+	     esp=3des-sha1	# only this: 3DES+SHA1
+	     esp=aes,cast	# AES+{MD5,SHA1}, CAST+{MD5,SHA1}
+	- alg_info_test: test utility for esp algo parsing, eg:
+	      $ cd pluto
+	      $ make alg_info_test    
+	      $ ./alg_info_test  aes,cast,3des-sha1
+		(12 = "ESP_AES", 1 = "AUTH_ALGORITHM_HMAC_MD5")
+		(12 = "ESP_AES", 2 = "AUTH_ALGORITHM_HMAC_SHA1")
+		(6 = "ESP_CAST", 1 = "AUTH_ALGORITHM_HMAC_MD5")
+		(6 = "ESP_CAST", 2 = "AUTH_ALGORITHM_HMAC_SHA1")
+		(3 = "ESP_3DES", 2 = "AUTH_ALGORITHM_HMAC_SHA1")
+
+v0.5: "kidnapped CPU hero"
+ Changes from v0.4:
+  NOTE: you must _really_ clean the build area (*.o ) because some _MAX
+        values have changed.
+
+	* KLIPS
+	- Changed SADB_EALG_MAX from 12 to 256 (to accomodate ESP enc ids
+	  like ESP_SERPENT=252, ESP_TWOFISH=253)
+	- Added timing measurement tests (cipher "bandwidth"), eg:
+	   # modprobe ipsec_twofish test=1
+	   # dmesg | tail -9
+	   ipsec_twofish_init(enc_alg=253 name=twofish): ret=0
+	   klips_debug:ipsec_ext_test: enc_alg=253 blocksize=16 \
+	   		key_e_size=8892 keysize=16
+	   klips_debug:ipsec_ext_test: cbc_encrypt=1 ret=1024
+	   klips_debug:ipsec_ext_test: memcmp(enc, tmp) ret=1: OK.
+	   klips_debug:ipsec_ext_test: cbc_encrypt=0 ret=1024
+	   klips_debug:ipsec_ext_test: memcmp(dec,tmp) ret=0: OK.
+	   klips_debug:ipsec_ext_test: decrypt speed=25200 KB/s
+	   klips_debug:ipsec_ext_test: encrypt speed=28600 KB/s
+	   ipsec_twofish_init(enc_alg=253): test_ret=0
+
+	- Changed BLOWFISH to use asm versions if possible
+	- Added SERPENT, TWOFISH from
+		Dr Brian Gladman http://fp.gladman.plus.com/index.html
+		(nicely hacked to un-global-ize sources)
+	- Added CAST from 
+		OpenBSD sources ("public domain")
+		*tested Ok against OpenBSD 3.0*
+	- Added NULL from
+		me :)
+
+	* PLUTO
+	- (also touched by SADB_EALG_MAX changes) please _really_ clean
+	  lib/*.o pluto/*.o before recompiling
+	- esp_transform_name bumped to 256 entries (from about 12)
+	- first attr.key_len processing (be careful, may break)
+	  no negotiation, just use peers attr.key_len  if it's lower
+	  than maxkeybits
+	- patch from Nigel Metheringham to allow RH62/2.2.20 compilation
+
+v0.4: 
+	First release (should fill-in here :)
+ 
+
Index: freeswan/Makefile
diff -u freeswan/Makefile:1.1.1.2 freeswan/Makefile:1.1.1.1.2.3
--- freeswan/Makefile:1.1.1.2	Mon Jun 17 02:07:34 2002
+++ freeswan/Makefile	Tue Jul  2 17:24:29 2002
@@ -67,6 +67,9 @@
 	$(KLIPSLINK) `pwd`/klips/net/ipsec/Config.in $(KERNELKLIPS)
 	$(KLIPSLINK) `pwd`/klips/net/ipsec/defconfig $(KERNELKLIPS)
 	$(KLIPSLINK) `pwd`/klips/net/ipsec/*.[ch] $(KERNELKLIPS)
+	mkdir $(KERNELKLIPS)/alg
+	$(KLIPSLINK) `pwd`/klips/net/ipsec/alg/* $(KERNELKLIPS)/alg
+	$(KLIPSLINK) `pwd`/libcrypto $(KERNELKLIPS)/libcrypto
 	$(KLIPSLINK) `pwd`/lib/Makefile.kernel $(KERNELKLIPS)/libfreeswan/Makefile
 	$(KLIPSLINK) `pwd`/lib/*.[ch] $(KERNELKLIPS)/libfreeswan
 	$(KLIPSLINK) `pwd`/libdes/Makefile $(KERNELKLIPS)/libdes
Index: freeswan/doc/HOWTO.ipsec_alg
diff -u /dev/null freeswan/doc/HOWTO.ipsec_alg:1.1.2.12
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/doc/HOWTO.ipsec_alg	Fri Jul 12 15:41:54 2002
@@ -0,0 +1,185 @@
+Modular ALGO support version 0.8.0 for freeswan-1.98b
+$Id: HOWTO.ipsec_alg,v 1.1.2.12 2002/07/12 18:41:54 jjo Exp $
+
+HOWTO-ipsec_alg.txt       --Juanjo <jjo-ipsec@mendoza.gov.ar> 
+====================        Linux IP Aliasing creator, IPMASQ 2.2 Maintainer
+These patches provide additional algorithm support for (per connection
+selectable)
+- Phase1
+        IKE encrypt algorithms: AES, twofish, serpent, blowfish,
+        IKE hash algorithms:    SHA2
+        DH group:               2048, 3072, 4096
+- Phase2
+        ESP encrypt algorithms modules: AES, twofish, serpent, blowfish, 3DES
+        ESP auth algorithms modules: SHA2, SHA1, MD5.
+        PFS group:              2048, 3072, 4096
+
+See (1b) for more details
+
+Quickstart
+==========
+1) Patches:
+1a) Depeding of installation (stock or x509), use:
+  - Stock freeswan:
+     freeswan-alg-0.8.0-BASE-common.diff.gz
+     freeswan-alg-0.8.0-BASE-klips.diff.gz
+     freeswan-alg-0.8.0-BASE-pluto.diff.gz
+
+  - x509 (0.9.11) patched freeswan : 
+     freeswan-alg-0.8.0-BASE-common.diff.gz
+     freeswan-alg-0.8.0-BASE-klips.diff.gz
+     freeswan-alg-0.8.0-BASE-pluto_with_x509.diff.gz
+
+1b) Decide which ciphers you want (you can patch in any order)
+
+     --file--------------------------------- -phase-- --comment---------
+     freeswan-alg-0.8.0-enc-3des.diff.gz      -  P2   x86 optimized asm
+     freeswan-alg-0.8.0-enc-aes.diff.gz       P1 P2   128-256 bits
+     freeswan-alg-0.8.0-enc-blowfish.diff.gz  P1 P2   128-256 bits
+     freeswan-alg-0.8.0-enc-null.diff.gz      -  P2  
+     freeswan-alg-0.8.0-enc-serpent.diff.gz   P1 P2   128-256 bits
+     freeswan-alg-0.8.0-enc-twofish.diff.gz   P1 P2   128-256 bits
+                                                     
+     freeswan-alg-0.8.0-auth-md5.diff.gz      -  P2   x86 optimized asm
+     freeswan-alg-0.8.0-auth-sha1.diff.gz     -  P2   x86 optimized asm
+     freeswan-alg-0.8.0-auth-sha2.diff.gz     P1 P2   sha2_256 and sha2_512
+
+Eg: you want AES and TWOFISH ciphers:
+        cd /path/to/src/freeswan-1.98b
+        zcat freeswan-alg-0.8.0-BASE-common.diff.gz   | patch -p1 -s
+        zcat freeswan-alg-0.8.0-BASE-klips.diff.gz    | patch -p1 -s
+        zcat freeswan-alg-0.8.0-BASE-pluto.diff.gz    | patch -p1 -s
+        zcat freeswan-alg-0.8.0-enc-aes.diff.gz       | patch -p1 -s
+        zcat freeswan-alg-0.8.0-enc-twofish.diff.gz   | patch -p1 -s
+
+2) Proceed as always with freeswan configuration/compilation,
+   you MUST recompile KLIPS (kernel) _and_ pluto.
+
+   For kernel config., these new kernel config items will appear:
+    
+>>  IPSEC Modular Extensions (CONFIG_IPSEC_ALG) [Y/n/?] y
+>>       AES encryption algorithm (CONFIG_IPSEC_ALG_AES) [M/n/y/?] m
+>>       TWOFISH encryption algorithm (CONFIG_IPSEC_ALG_TWOFISH) [M/n/y/?] m
+>>       :
+
+   Compile, install, etc.
+   Don't forget to compile and also INSTALL PATCHED PLUTO (Phase1 algorithms
+   will be statically compiled into pluto).
+
+
+3) Reload ipsec/pluto and insert algo module
+        + modprobe ipsec_aes
+   Confirm algo is present with
+        + ipsec auto --status | egrep ESP
+        000 algorithm ESP encrypt: id=3, name=ESP_3DES, ...
+        000 algorithm ESP encrypt: id=12, name=ESP_AES, ...
+        000 algorithm ESP auth attr: id=1, name=AUTH_ALGORITHM_HMAC_MD5, ...
+        000 algorithm ESP auth attr: id=2, name=AUTH_ALGORITHM_HMAC_SHA1, ...
+        :
+        + ipsec auto --status | egrep IKE
+        000 algorithm IKE encrypt: id=65005, name=OAKLEY_TWOFISH_CBC, ...
+        000 algorithm IKE encrypt: id=7, name=OAKLEY_AES_CBC, ...
+        000 algorithm IKE encrypt: id=5, name=OAKLEY_3DES_CBC, ...
+        000 algorithm IKE hash: id=6, name=OAKLEY_SHA2_512, ...
+        000 algorithm IKE hash: id=4, name=OAKLEY_SHA2_256, ...
+        000 algorithm IKE hash: id=2, name=OAKLEY_SHA, ...
+        000 algorithm IKE hash: id=1, name=OAKLEY_MD5, ...
+
+       
+3) Edit connection parameters to select wanted algorithms and reload conn.
+
+3a) You should specify which algorithms you want for your connections.
+   NOTE: if you omit these parameters (esp=, ike= or pfsgroup=), pluto 
+         will behave as stock.
+   
+   Examples:
+
+3a1) - For Phase1 (IKE) algorithms:
+     . Add to your dotconf for the connection:
+
+        ike=aes128-sha,aes128-md5   
+        
+        NOTE: Phase1 sha1 string is "sha"
+
+     . which is the SAME AS ...
+
+        ike=aes128-sha-modp1536,aes128-sha-modp1024,\
+                aes128-md5-modp1536,aes128-md5-modp1024
+
+     . or you can be more specific ...
+
+        ike=aes128-sha-modp1536,aes128-md5-modp1536
+
+     . or more paranoid ...
+
+        ike=aes128-sha2_256-modp2048    
+        
+
+3a2) - For Phase2 (ESP) algorithms:
+
+       NOTE: missing pfsgroup=modpXXXX implies using
+             pfsgroup equal to Phase1' DH group
+   
+     . Add to your dotconf for the connection:
+
+        esp=aes128-sha1,aes128-md5
+
+     . which is the SAME AS ...
+
+        esp=aes128-sha1,aes128-md5
+
+     . or you can be more specific ...
+
+        esp=aes128-sha1
+        pfsgroup=modp1536
+
+     . or more paranoid ...
+
+        ike=aes128-sha2_256
+        pfsgroup=modp2048
+
+3b) - After editing reload that configuration
+
+        + ipsec auto --replace <connection>
+
+4) Bring up a connection against peer (with AES support, obviously)
+
+        + ipsec auto --up  <connection>
+
+   Confirm
+   - For ESP from kernel:
+
+        + ipsec spi | grep AES
+
+   - For IKE and ESP from pluto' view:
+
+        + ipsec auto --status | grep <connection>.*algo
+
+5) Additional testing
+   For ESP, all kernel modules accept test argument, eg:
+
+        + modprobe ipsec_aes test=1     # ask module to probe itself
+        + dmesg | tail -10              # show timing results
+
+   Recommended comparison:    ipsec_3des vs ipsec_aes   8)
+
+6) TIPS:
+   * You can permanently add ipsec_* algo modules loading in 
+     /etc/modules.conf:
+          add above ipsec ipsec_aes ipsec_3des ipsec_md5 ipsec_sha1
+
+Appendix A
+~~~~~~~~~~
+- if ike and esp strings are absent, pluto will use _same_ as original 
+  (unpatched) pluto, ie:
+
+  Phase1: if ike string is absent, it fallbacks to:
+
+     ike=3des-md5-modp1536,3des-md5-modp1024,\
+         3des-sha-modp1536,3des-sha-modp1024
+
+  Phase2: if esp string is absent, it fallbacks to:
+
+     esp=3des-md5,3des-sha1
+     [ no pfsgroup => use Phase1's DH group ]
+
Index: freeswan/lib/pfkey.h
diff -u freeswan/lib/pfkey.h:1.1.1.1 freeswan/lib/pfkey.h:1.1.1.1.2.1
--- freeswan/lib/pfkey.h:1.1.1.1	Mon Apr 15 12:08:57 2002
+++ freeswan/lib/pfkey.h	Mon Apr 15 12:13:43 2002
@@ -37,6 +37,11 @@
 extern struct socket_list *pfkey_open_sockets;
 extern struct socket_list *pfkey_registered_sockets[SADB_SATYPE_MAX+1];
 
+/* 
+ *	There is a field-by-field copy in klips/net/ipsec/ipsec_alg.h
+ *	please keep in sync until we migrate all support stuff
+ *	to ipsec_alg objects
+ */
 struct supported
 {
 	uint16_t supported_alg_exttype;
@@ -45,7 +50,6 @@
 	uint16_t supported_alg_minbits;
 	uint16_t supported_alg_maxbits;
 };
-
 extern struct supported_list *pfkey_supported_list[SADB_SATYPE_MAX+1];
 struct supported_list
 {
@@ -75,6 +79,7 @@
 	struct eroute *eroute;
 };
 
+extern int pfkey_register_reply(int satype, struct sadb_msg *);
 extern int pfkey_upmsg(struct socket *, struct sadb_msg *);
 extern int pfkey_expire(struct ipsec_sa *, int);
 extern int pfkey_acquire(struct ipsec_sa *);
Index: freeswan/lib/pfkeyv2.h
diff -u freeswan/lib/pfkeyv2.h:1.1.1.1 freeswan/lib/pfkeyv2.h:1.1.1.1.2.1
--- freeswan/lib/pfkeyv2.h:1.1.1.1	Mon Apr 15 12:08:57 2002
+++ freeswan/lib/pfkeyv2.h	Mon Apr 15 12:13:43 2002
@@ -252,13 +252,19 @@
 #define SADB_AALG_NONE        0
 #define SADB_AALG_MD5HMAC     2
 #define SADB_AALG_SHA1HMAC    3
-#define SADB_AALG_MAX         3
+#define	SADB_AALG_SHA256_HMAC    5
+#define	SADB_AALG_SHA384_HMAC    6
+#define	SADB_AALG_SHA512_HMAC    7
+#define	SADB_AALG_RIPEMD160HMAC      8
+#define	SADB_AALG_MAX         15
 
 #define SADB_EALG_NONE        0
 #define SADB_EALG_DESCBC      2
 #define SADB_EALG_3DESCBC     3
+#define SADB_EALG_BFCBC	      7
 #define SADB_EALG_NULL        11
-#define SADB_EALG_MAX         11
+#define SADB_EALG_AESCBC      12
+#define SADB_EALG_MAX         255
 
 #define SADB_X_CALG_NONE          0
 #define SADB_X_CALG_OUI           1
Index: freeswan/klips/patches2.3/net.Makefile-alg
diff -u /dev/null freeswan/klips/patches2.3/net.Makefile-alg:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/klips/patches2.3/net.Makefile-alg	Mon Apr 15 12:13:43 2002
@@ -0,0 +1,10 @@
+--- net/Makefile.dist	Mon Dec 17 12:18:26 2001
++++ net/Makefile	Tue Jan 22 11:10:24 2002
+@@ -8,6 +8,7 @@
+ O_TARGET :=	network.o
+ 
+ mod-subdirs :=	ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched
++mod-subdirs +=  ipsec
+ export-objs :=	netsyms.o
+ 
+ subdir-y :=	core ethernet
Index: freeswan/libcrypto/include/cbc_generic.h
diff -u /dev/null freeswan/libcrypto/include/cbc_generic.h:1.1.2.2
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/include/cbc_generic.h	Mon Jun  3 22:24:31 2002
@@ -0,0 +1,110 @@
+#ifndef _CBC_GENERIC_H
+#define _CBC_GENERIC_H
+/*
+ * CBC macro helpers
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ *
+ * 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.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * 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.
+ *
+ */
+
+/*
+ * 	Heavily inspired in loop_AES
+ */
+#define CBC_IMPL_BLK16(name, ctx_type, addr_type, enc_func, dec_func) \
+int name(ctx_type *ctx, const u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \
+	int ret=ilen, pos; \
+	const u_int32_t *iv_i; \
+	if ((ilen) % 16) return 0; \
+	if (encrypt) { \
+		pos=0; \
+		while(pos<ilen) { \
+			if (pos==0) \
+				iv_i=(const u_int32_t*) iv; \
+			else \
+				iv_i=(const u_int32_t*) (out-16); \
+			*((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); \
+			*((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); \
+			*((u_int32_t *)(&out[ 8])) = iv_i[2]^*((const u_int32_t *)(&in[ 8])); \
+			*((u_int32_t *)(&out[12])) = iv_i[3]^*((const u_int32_t *)(&in[12])); \
+			enc_func(ctx, (addr_type) out, (addr_type) out); \
+			in+=16; \
+			out+=16; \
+			pos+=16; \
+		} \
+	} else { \
+		pos=ilen-16; \
+		in+=pos; \
+		out+=pos; \
+		while(pos>=0) { \
+			dec_func(ctx, (const addr_type) in, (addr_type) out); \
+			if (pos==0) \
+				iv_i=(const u_int32_t*) (iv); \
+			else \
+				iv_i=(const u_int32_t*) (in-16); \
+			*((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \
+			*((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \
+			*((u_int32_t *)(&out[ 8])) ^= iv_i[2]; \
+			*((u_int32_t *)(&out[12])) ^= iv_i[3]; \
+			in-=16; \
+			out-=16; \
+			pos-=16; \
+		} \
+	} \
+	return ret; \
+} 
+#define CBC_IMPL_BLK8(name, ctx_type, addr_type,  enc_func, dec_func) \
+int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt) { \
+	int ret=ilen, pos; \
+	const u_int32_t *iv_i; \
+	if ((ilen) % 8) return 0; \
+	if (encrypt) { \
+		pos=0; \
+		while(pos<ilen) { \
+			if (pos==0) \
+				iv_i=(const u_int32_t*) iv; \
+			else \
+				iv_i=(const u_int32_t*) (out-8); \
+			*((u_int32_t *)(&out[ 0])) = iv_i[0]^*((const u_int32_t *)(&in[ 0])); \
+			*((u_int32_t *)(&out[ 4])) = iv_i[1]^*((const u_int32_t *)(&in[ 4])); \
+			enc_func(ctx, (addr_type)out, (addr_type)out); \
+			in+=8; \
+			out+=8; \
+			pos+=8; \
+		} \
+	} else { \
+		pos=ilen-8; \
+		in+=pos; \
+		out+=pos; \
+		while(pos>=0) { \
+			dec_func(ctx, (const addr_type)in, (addr_type)out); \
+			if (pos==0) \
+				iv_i=(const u_int32_t*) (iv); \
+			else \
+				iv_i=(const u_int32_t*) (in-8); \
+			*((u_int32_t *)(&out[ 0])) ^= iv_i[0]; \
+			*((u_int32_t *)(&out[ 4])) ^= iv_i[1]; \
+			in-=8; \
+			out-=8; \
+			pos-=8; \
+		} \
+	} \
+	return ret; \
+} 
+#define CBC_DECL(name, ctx_type) \
+int name(ctx_type *ctx, u_int8_t * in, u_int8_t * out, int ilen, const u_int8_t * iv, int encrypt)
+/*
+Eg.:
+CBC_IMPL_BLK16(AES_cbc_encrypt, aes_context, u_int8_t *, aes_encrypt, aes_decrypt);
+CBC_DECL(AES_cbc_encrypt, aes_context);
+*/
+#endif /* _CBC_GENERIC_H */
Index: freeswan/libcrypto/include/hmac_generic.h
diff -u /dev/null freeswan/libcrypto/include/hmac_generic.h:1.1.2.2
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/include/hmac_generic.h	Mon May 20 12:39:31 2002
@@ -0,0 +1,60 @@
+#ifndef _HMAC_GENERIC_H
+#define _HMAC_GENERIC_H
+/*
+ * HMAC macro helpers
+ *
+ * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
+ *
+ * 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.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ * 
+ * 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.
+ *
+ */
+
+#ifndef DIVUP
+#define DIVUP(x,y) ((x + y -1) / y) /* divide, rounding upwards */
+#endif
+#ifndef HMAC_IPAD
+#define		HMAC_IPAD	0x36
+#define		HMAC_OPAD	0x5C
+#endif
+#define HMAC_SET_KEY_IMPL(func_name, hctx_t, blocksize, func_init, func_update) \
+void func_name(hctx_t *hctx, const u_int8_t * key, int keylen) { \
+	int i;\
+	u_int8_t kb[blocksize];		\
+	for (i = 0; i < DIVUP(keylen*8, 8); i++) {	\
+		kb[i] = key[i] ^ HMAC_IPAD;	\
+	}					\
+	for (; i < blocksize; i++) {		\
+		kb[i] = HMAC_IPAD;		\
+	}					\
+	func_init(&hctx->ictx);			\
+	func_update(&hctx->ictx, kb, blocksize);	\
+	for (i = 0; i < blocksize; i++) {	\
+		kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD);	\
+	}					\
+	func_init(&hctx->octx);			\
+	func_update(&hctx->octx, kb, blocksize);	\
+}
+#define HMAC_HASH_IMPL(func_name, hctx_t, ctx_t, ahlen, func_update, func_result ) \
+void func_name(hctx_t *hctx, const u_int8_t * dat, int len, u_int8_t * hash, int hashlen) {	\
+	ctx_t ctx;	\
+	ctx=hctx->ictx;	\
+	if (dat) func_update(&ctx, dat, len);	\
+	if (hash) {				\
+		u_int8_t hash_buf[ahlen];			\
+		func_result(&ctx, hash_buf, ahlen);	\
+		ctx=hctx->octx;				\
+		func_update(&ctx, hash_buf, ahlen);	\
+		func_result(&ctx, hash, hashlen);	\
+		memset(&ctx, 0, sizeof (ctx));		\
+		memset(&hash_buf, 0, sizeof (hash_buf));\
+	}					\
+}
+#endif /* _HMAC_GENERIC_H */
Index: freeswan/libcrypto/include/md32_common.h
diff -u /dev/null freeswan/libcrypto/include/md32_common.h:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/include/md32_common.h	Mon Apr 15 12:13:42 2002
@@ -0,0 +1,607 @@
+/* crypto/md32_common.h */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+ * This is a generic 32 bit "collector" for message digest algorithms.
+ * Whenever needed it collects input character stream into chunks of
+ * 32 bit values and invokes a block function that performs actual hash
+ * calculations.
+ *
+ * Porting guide.
+ *
+ * Obligatory macros:
+ *
+ * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
+ *	this macro defines byte order of input stream.
+ * HASH_CBLOCK
+ *	size of a unit chunk HASH_BLOCK operates on.
+ * HASH_LONG
+ *	has to be at lest 32 bit wide, if it's wider, then
+ *	HASH_LONG_LOG2 *has to* be defined along
+ * HASH_CTX
+ *	context structure that at least contains following
+ *	members:
+ *		typedef struct {
+ *			...
+ *			HASH_LONG	Nl,Nh;
+ *			HASH_LONG	data[HASH_LBLOCK];
+ *			int		num;
+ *			...
+ *			} HASH_CTX;
+ * HASH_UPDATE
+ *	name of "Update" function, implemented here.
+ * HASH_TRANSFORM
+ *	name of "Transform" function, implemented here.
+ * HASH_FINAL
+ *	name of "Final" function, implemented here.
+ * HASH_BLOCK_HOST_ORDER
+ *	name of "block" function treating *aligned* input message
+ *	in host byte order, implemented externally.
+ * HASH_BLOCK_DATA_ORDER
+ *	name of "block" function treating *unaligned* input message
+ *	in original (data) byte order, implemented externally (it
+ *	actually is optional if data and host are of the same
+ *	"endianess").
+ * HASH_MAKE_STRING
+ *	macro convering context variables to an ASCII hash string.
+ *
+ * Optional macros:
+ *
+ * B_ENDIAN or L_ENDIAN
+ *	defines host byte-order.
+ * HASH_LONG_LOG2
+ *	defaults to 2 if not states otherwise.
+ * HASH_LBLOCK
+ *	assumed to be HASH_CBLOCK/4 if not stated otherwise.
+ * HASH_BLOCK_DATA_ORDER_ALIGNED
+ *	alternative "block" function capable of treating
+ *	aligned input message in original (data) order,
+ *	implemented externally.
+ *
+ * MD5 example:
+ *
+ *	#define DATA_ORDER_IS_LITTLE_ENDIAN
+ *
+ *	#define HASH_LONG		MD5_LONG
+ *	#define HASH_LONG_LOG2		MD5_LONG_LOG2
+ *	#define HASH_CTX		MD5_CTX
+ *	#define HASH_CBLOCK		MD5_CBLOCK
+ *	#define HASH_LBLOCK		MD5_LBLOCK
+ *	#define HASH_UPDATE		MD5_Update
+ *	#define HASH_TRANSFORM		MD5_Transform
+ *	#define HASH_FINAL		MD5_Final
+ *	#define HASH_BLOCK_HOST_ORDER	md5_block_host_order
+ *	#define HASH_BLOCK_DATA_ORDER	md5_block_data_order
+ *
+ *					<appro@fy.chalmers.se>
+ */
+
+#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#error "DATA_ORDER must be defined!"
+#endif
+
+#ifndef HASH_CBLOCK
+#error "HASH_CBLOCK must be defined!"
+#endif
+#ifndef HASH_LONG
+#error "HASH_LONG must be defined!"
+#endif
+#ifndef HASH_CTX
+#error "HASH_CTX must be defined!"
+#endif
+
+#ifndef HASH_UPDATE
+#error "HASH_UPDATE must be defined!"
+#endif
+#ifndef HASH_TRANSFORM
+#error "HASH_TRANSFORM must be defined!"
+#endif
+#ifndef HASH_FINAL
+#error "HASH_FINAL must be defined!"
+#endif
+
+#ifndef HASH_BLOCK_HOST_ORDER
+#error "HASH_BLOCK_HOST_ORDER must be defined!"
+#endif
+
+#if 0
+/*
+ * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED
+ * isn't defined.
+ */
+#ifndef HASH_BLOCK_DATA_ORDER
+#error "HASH_BLOCK_DATA_ORDER must be defined!"
+#endif
+#endif
+
+#ifndef HASH_LBLOCK
+#define HASH_LBLOCK	(HASH_CBLOCK/4)
+#endif
+
+#ifndef HASH_LONG_LOG2
+#define HASH_LONG_LOG2	2
+#endif
+
+/*
+ * Engage compiler specific rotate intrinsic function if available.
+ */
+#undef ROTATE
+#ifndef PEDANTIC
+# if defined(_MSC_VER)
+#  define ROTATE(a,n)	_lrotl(a,n)
+# elif defined(__MWERKS__)
+#  if defined(__POWERPC__)
+#   define ROTATE(a,n)	__rlwinm(a,n,0,31)
+#  elif defined(__MC68K__)
+    /* Motorola specific tweak. <appro@fy.chalmers.se> */
+#   define ROTATE(a,n)	( n<24 ? __rol(a,n) : __ror(a,32-n) )
+#  else
+#   define ROTATE(a,n)	__rol(a,n)
+#  endif
+# elif defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM)
+  /*
+   * Some GNU C inline assembler templates. Note that these are
+   * rotates by *constant* number of bits! But that's exactly
+   * what we need here...
+   *
+   * 					<appro@fy.chalmers.se>
+   */
+#  if defined(__i386)
+#   define ROTATE(a,n)	({ register unsigned int ret;	\
+				asm (			\
+				"roll %1,%0"		\
+				: "=r"(ret)		\
+				: "I"(n), "0"(a)	\
+				: "cc");		\
+			   ret;				\
+			})
+#  elif defined(__powerpc) || defined(__ppc)
+#   define ROTATE(a,n)	({ register unsigned int ret;	\
+				asm (			\
+				"rlwinm %0,%1,%2,0,31"	\
+				: "=r"(ret)		\
+				: "r"(a), "I"(n));	\
+			   ret;				\
+			})
+#  endif
+# endif
+
+/*
+ * Engage compiler specific "fetch in reverse byte order"
+ * intrinsic function if available.
+ */
+# if defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM)
+  /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */
+#  if defined(__i386) && !defined(I386_ONLY)
+#   define BE_FETCH32(a)	({ register unsigned int l=(a);\
+				asm (			\
+				"bswapl %0"		\
+				: "=r"(l) : "0"(l));	\
+			  l;				\
+			})
+#  elif defined(__powerpc)
+#   define LE_FETCH32(a)	({ register unsigned int l;	\
+				asm (			\
+				"lwbrx %0,0,%1"		\
+				: "=r"(l)		\
+				: "r"(a));		\
+			   l;				\
+			})
+
+#  elif defined(__sparc) && defined(ULTRASPARC)
+#  define LE_FETCH32(a)	({ register unsigned int l;		\
+				asm (				\
+				"lda [%1]#ASI_PRIMARY_LITTLE,%0"\
+				: "=r"(l)			\
+				: "r"(a));			\
+			   l;					\
+			})
+#  endif
+# endif
+#endif /* PEDANTIC */
+
+#if HASH_LONG_LOG2==2	/* Engage only if sizeof(HASH_LONG)== 4 */
+/* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
+#ifdef ROTATE
+/* 5 instructions with rotate instruction, else 9 */
+#define REVERSE_FETCH32(a,l)	(					\
+		l=*(const HASH_LONG *)(a),				\
+		((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24)))	\
+				)
+#else
+/* 6 instructions with rotate instruction, else 8 */
+#define REVERSE_FETCH32(a,l)	(				\
+		l=*(const HASH_LONG *)(a),			\
+		l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)),	\
+		ROTATE(l,16)					\
+				)
+/*
+ * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...
+ * It's rewritten as above for two reasons:
+ *	- RISCs aren't good at long constants and have to explicitely
+ *	  compose 'em with several (well, usually 2) instructions in a
+ *	  register before performing the actual operation and (as you
+ *	  already realized:-) having same constant should inspire the
+ *	  compiler to permanently allocate the only register for it;
+ *	- most modern CPUs have two ALUs, but usually only one has
+ *	  circuitry for shifts:-( this minor tweak inspires compiler
+ *	  to schedule shift instructions in a better way...
+ *
+ *				<appro@fy.chalmers.se>
+ */
+#endif
+#endif
+
+#ifndef ROTATE
+#define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
+#endif
+
+/*
+ * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
+ * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
+ * and host are of the same "endianess". It's possible to mask
+ * this with blank #define HASH_BLOCK_DATA_ORDER though...
+ *
+ *				<appro@fy.chalmers.se>
+ */
+#if defined(B_ENDIAN)
+#  if defined(DATA_ORDER_IS_BIG_ENDIAN)
+#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
+#      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER
+#    endif
+#  elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#    ifndef HOST_FETCH32
+#      ifdef LE_FETCH32
+#        define HOST_FETCH32(p,l)	LE_FETCH32(p)
+#      elif defined(REVERSE_FETCH32)
+#        define HOST_FETCH32(p,l)	REVERSE_FETCH32(p,l)
+#      endif
+#    endif
+#  endif
+#elif defined(L_ENDIAN)
+#  if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
+#      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER
+#    endif
+#  elif defined(DATA_ORDER_IS_BIG_ENDIAN)
+#    ifndef HOST_FETCH32
+#      ifdef BE_FETCH32
+#        define HOST_FETCH32(p,l)	BE_FETCH32(p)
+#      elif defined(REVERSE_FETCH32)
+#        define HOST_FETCH32(p,l)	REVERSE_FETCH32(p,l)
+#      endif
+#    endif
+#  endif
+#endif
+
+#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+#ifndef HASH_BLOCK_DATA_ORDER
+#error "HASH_BLOCK_DATA_ORDER must be defined!"
+#endif
+#endif
+
+#if defined(DATA_ORDER_IS_BIG_ENDIAN)
+
+#define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))<<24),		\
+			 l|=(((unsigned long)(*((c)++)))<<16),		\
+			 l|=(((unsigned long)(*((c)++)))<< 8),		\
+			 l|=(((unsigned long)(*((c)++)))    ),		\
+			 l)
+#define HOST_p_c2l(c,l,n)	{					\
+			switch (n) {					\
+			case 0: l =((unsigned long)(*((c)++)))<<24;	\
+			case 1: l|=((unsigned long)(*((c)++)))<<16;	\
+			case 2: l|=((unsigned long)(*((c)++)))<< 8;	\
+			case 3: l|=((unsigned long)(*((c)++)));		\
+				} }
+#define HOST_p_c2l_p(c,l,sc,len) {					\
+			switch (sc) {					\
+			case 0: l =((unsigned long)(*((c)++)))<<24;	\
+				if (--len == 0) break;			\
+			case 1: l|=((unsigned long)(*((c)++)))<<16;	\
+				if (--len == 0) break;			\
+			case 2: l|=((unsigned long)(*((c)++)))<< 8;	\
+				} }
+/* NOTE the pointer is not incremented at the end of this */
+#define HOST_c2l_p(c,l,n)	{					\
+			l=0; (c)+=n;					\
+			switch (n) {					\
+			case 3: l =((unsigned long)(*(--(c))))<< 8;	\
+			case 2: l|=((unsigned long)(*(--(c))))<<16;	\
+			case 1: l|=((unsigned long)(*(--(c))))<<24;	\
+				} }
+#define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)    )&0xff),	\
+			 l)
+
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+
+#define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))    ),		\
+			 l|=(((unsigned long)(*((c)++)))<< 8),		\
+			 l|=(((unsigned long)(*((c)++)))<<16),		\
+			 l|=(((unsigned long)(*((c)++)))<<24),		\
+			 l)
+#define HOST_p_c2l(c,l,n)	{					\
+			switch (n) {					\
+			case 0: l =((unsigned long)(*((c)++)));		\
+			case 1: l|=((unsigned long)(*((c)++)))<< 8;	\
+			case 2: l|=((unsigned long)(*((c)++)))<<16;	\
+			case 3: l|=((unsigned long)(*((c)++)))<<24;	\
+				} }
+#define HOST_p_c2l_p(c,l,sc,len) {					\
+			switch (sc) {					\
+			case 0: l =((unsigned long)(*((c)++)));		\
+				if (--len == 0) break;			\
+			case 1: l|=((unsigned long)(*((c)++)))<< 8;	\
+				if (--len == 0) break;			\
+			case 2: l|=((unsigned long)(*((c)++)))<<16;	\
+				} }
+/* NOTE the pointer is not incremented at the end of this */
+#define HOST_c2l_p(c,l,n)	{					\
+			l=0; (c)+=n;					\
+			switch (n) {					\
+			case 3: l =((unsigned long)(*(--(c))))<<16;	\
+			case 2: l|=((unsigned long)(*(--(c))))<< 8;	\
+			case 1: l|=((unsigned long)(*(--(c))));		\
+				} }
+#define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>24)&0xff),	\
+			 l)
+
+#endif
+
+/*
+ * Time for some action:-)
+ */
+
+void HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len)
+	{
+	const unsigned char *data=data_;
+	register HASH_LONG * p;
+	register unsigned long l;
+	int sw,sc,ew,ec;
+
+	if (len==0) return;
+
+	l=(c->Nl+(len<<3))&0xffffffffL;
+	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
+	 * Wei Dai <weidai@eskimo.com> for pointing it out. */
+	if (l < c->Nl) /* overflow */
+		c->Nh++;
+	c->Nh+=(len>>29);
+	c->Nl=l;
+
+	if (c->num != 0)
+		{
+		p=c->data;
+		sw=c->num>>2;
+		sc=c->num&0x03;
+
+		if ((c->num+len) >= HASH_CBLOCK)
+			{
+			l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
+			for (; sw<HASH_LBLOCK; sw++)
+				{
+				HOST_c2l(data,l); p[sw]=l;
+				}
+			HASH_BLOCK_HOST_ORDER (c,p,1);
+			len-=(HASH_CBLOCK-c->num);
+			c->num=0;
+			/* drop through and do the rest */
+			}
+		else
+			{
+			c->num+=len;
+			if ((sc+len) < 4) /* ugly, add char's to a word */
+				{
+				l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
+				}
+			else
+				{
+				ew=(c->num>>2);
+				ec=(c->num&0x03);
+				l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
+				for (; sw < ew; sw++)
+					{
+					HOST_c2l(data,l); p[sw]=l;
+					}
+				if (ec)
+					{
+					HOST_c2l_p(data,l,ec); p[sw]=l;
+					}
+				}
+			return;
+			}
+		}
+
+	sw=len/HASH_CBLOCK;
+	if (sw > 0)
+		{
+#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+		/*
+		 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
+		 * only if sizeof(HASH_LONG)==4.
+		 */
+		if ((((unsigned long)data)%4) == 0)
+			{
+			/* data is properly aligned so that we can cast it: */
+			HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw);
+			sw*=HASH_CBLOCK;
+			data+=sw;
+			len-=sw;
+			}
+		else
+#if !defined(HASH_BLOCK_DATA_ORDER)
+			while (sw--)
+				{
+				memcpy (p=c->data,data,HASH_CBLOCK);
+				HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);
+				data+=HASH_CBLOCK;
+				len-=HASH_CBLOCK;
+				}
+#endif
+#endif
+#if defined(HASH_BLOCK_DATA_ORDER)
+			{
+			HASH_BLOCK_DATA_ORDER(c,data,sw);
+			sw*=HASH_CBLOCK;
+			data+=sw;
+			len-=sw;
+			}
+#endif
+		}
+
+	if (len!=0)
+		{
+		p = c->data;
+		c->num = len;
+		ew=len>>2;	/* words to copy */
+		ec=len&0x03;
+		for (; ew; ew--,p++)
+			{
+			HOST_c2l(data,l); *p=l;
+			}
+		HOST_c2l_p(data,l,ec);
+		*p=l;
+		}
+	}
+
+
+void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
+	{
+#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+	if ((((unsigned long)data)%4) == 0)
+		/* data is properly aligned so that we can cast it: */
+		HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1);
+	else
+#if !defined(HASH_BLOCK_DATA_ORDER)
+		{
+		memcpy (c->data,data,HASH_CBLOCK);
+		HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);
+		}
+#endif
+#endif
+#if defined(HASH_BLOCK_DATA_ORDER)
+	HASH_BLOCK_DATA_ORDER (c,data,1);
+#endif
+	}
+
+
+void HASH_FINAL (unsigned char *md, HASH_CTX *c)
+	{
+	register HASH_LONG *p;
+	register unsigned long l;
+	register int i,j;
+	static const unsigned char end[4]={0x80,0x00,0x00,0x00};
+	const unsigned char *cp=end;
+
+	/* c->num should definitly have room for at least one more byte. */
+	p=c->data;
+	i=c->num>>2;
+	j=c->num&0x03;
+
+#if 0
+	/* purify often complains about the following line as an
+	 * Uninitialized Memory Read.  While this can be true, the
+	 * following p_c2l macro will reset l when that case is true.
+	 * This is because j&0x03 contains the number of 'valid' bytes
+	 * already in p[i].  If and only if j&0x03 == 0, the UMR will
+	 * occur but this is also the only time p_c2l will do
+	 * l= *(cp++) instead of l|= *(cp++)
+	 * Many thanks to Alex Tang <altitude@cic.net> for pickup this
+	 * 'potential bug' */
+#ifdef PURIFY
+	if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */
+#endif
+	l=p[i];
+#else
+	l = (j==0) ? 0 : p[i];
+#endif
+	HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */
+
+	if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */
+		{
+		if (i<HASH_LBLOCK) p[i]=0;
+		HASH_BLOCK_HOST_ORDER (c,p,1);
+		i=0;
+		}
+	for (; i<(HASH_LBLOCK-2); i++)
+		p[i]=0;
+
+#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
+	p[HASH_LBLOCK-2]=c->Nh;
+	p[HASH_LBLOCK-1]=c->Nl;
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+	p[HASH_LBLOCK-2]=c->Nl;
+	p[HASH_LBLOCK-1]=c->Nh;
+#endif
+	HASH_BLOCK_HOST_ORDER (c,p,1);
+
+#ifndef HASH_MAKE_STRING
+#error "HASH_MAKE_STRING must be defined!"
+#else
+	HASH_MAKE_STRING(c,md);
+#endif
+
+	c->num=0;
+	/* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
+	 * but I'm not worried :-)
+	memset((void *)c,0,sizeof(HASH_CTX));
+	 */
+	}
Index: freeswan/libcrypto/perlasm/LICENSE
diff -u /dev/null freeswan/libcrypto/perlasm/LICENSE:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/perlasm/LICENSE	Mon Apr 15 12:13:43 2002
@@ -0,0 +1,127 @@
+
+  LICENSE ISSUES
+  ==============
+
+  The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
+  the OpenSSL License and the original SSLeay license apply to the toolkit.
+  See below for the actual license texts. Actually both licenses are BSD-style
+  Open Source licenses. In case of any license issues related to OpenSSL
+  please contact openssl-core@openssl.org.
+
+  OpenSSL License
+  ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
Index: freeswan/libcrypto/perlasm/alpha.pl
diff -u /dev/null freeswan/libcrypto/perlasm/alpha.pl:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/perlasm/alpha.pl	Mon Apr 15 12:13:43 2002
@@ -0,0 +1,434 @@
+#!/usr/local/bin/perl
+
+package alpha;
+use Carp qw(croak cluck);
+
+$label="100";
+
+$n_debug=0;
+$smear_regs=1;
+$reg_alloc=1;
+
+$align="3";
+$com_start="#";
+
+sub main'asm_init_output { @out=(); }
+sub main'asm_get_output { return(@out); }
+sub main'get_labels { return(@labels); }
+sub main'external_label { push(@labels,@_); }
+
+# General registers
+
+%regs=(	'r0',	'$0',
+	'r1',	'$1',
+	'r2',	'$2',
+	'r3',	'$3',
+	'r4',	'$4',
+	'r5',	'$5',
+	'r6',	'$6',
+	'r7',	'$7',
+	'r8',	'$8',
+	'r9',	'$22',
+	'r10',	'$23',
+	'r11',	'$24',
+	'r12',	'$25',
+	'r13',	'$27',
+	'r14',	'$28',
+	'r15',	'$21', # argc == 5
+	'r16',	'$20', # argc == 4
+	'r17',	'$19', # argc == 3
+	'r18',	'$18', # argc == 2
+	'r19',	'$17', # argc == 1
+	'r20',	'$16', # argc == 0
+	'r21',	'$9',  # save 0
+	'r22',	'$10', # save 1
+	'r23',	'$11', # save 2
+	'r24',	'$12', # save 3
+	'r25',	'$13', # save 4
+	'r26',	'$14', # save 5
+
+	'a0',	'$16',
+	'a1',	'$17',
+	'a2',	'$18',
+	'a3',	'$19',
+	'a4',	'$20',
+	'a5',	'$21',
+
+	's0',	'$9',
+	's1',	'$10',
+	's2',	'$11',
+	's3',	'$12',
+	's4',	'$13',
+	's5',	'$14',
+	'zero',	'$31',
+	'sp',	'$30',
+	);
+
+$main'reg_s0="r21";
+$main'reg_s1="r22";
+$main'reg_s2="r23";
+$main'reg_s3="r24";
+$main'reg_s4="r25";
+$main'reg_s5="r26";
+
+@reg=(  '$0', '$1' ,'$2' ,'$3' ,'$4' ,'$5' ,'$6' ,'$7' ,'$8',
+	'$22','$23','$24','$25','$20','$21','$27','$28');
+
+
+sub main'sub	{ &out3("subq",@_); }
+sub main'add	{ &out3("addq",@_); }
+sub main'mov	{ &out3("bis",$_[0],$_[0],$_[1]); }
+sub main'or	{ &out3("bis",@_); }
+sub main'bis	{ &out3("bis",@_); }
+sub main'br	{ &out1("br",@_); }
+sub main'ld	{ &out2("ldq",@_); }
+sub main'st	{ &out2("stq",@_); }
+sub main'cmpult	{ &out3("cmpult",@_); }
+sub main'cmplt	{ &out3("cmplt",@_); }
+sub main'bgt	{ &out2("bgt",@_); }
+sub main'ble	{ &out2("ble",@_); }
+sub main'blt	{ &out2("blt",@_); }
+sub main'mul	{ &out3("mulq",@_); }
+sub main'muh	{ &out3("umulh",@_); }
+
+$main'QWS=8;
+
+sub main'asm_add
+	{
+	push(@out,@_);
+	}
+
+sub main'asm_finish
+	{
+	&main'file_end();
+	print &main'asm_get_output();
+	}
+
+sub main'asm_init
+	{
+	($type,$fn)=@_;
+	$filename=$fn;
+
+	&main'asm_init_output();
+	&main'comment("Don't even think of reading this code");
+	&main'comment("It was automatically generated by $filename");
+	&main'comment("Which is a perl program used to generate the alpha assember.");
+	&main'comment("eric <eay\@cryptsoft.com>");
+	&main'comment("");
+
+	$filename =~ s/\.pl$//;
+	&main'file($filename);
+	}
+
+sub conv
+	{
+	local($r)=@_;
+	local($v);
+
+	return($regs{$r}) if defined($regs{$r});
+	return($r);
+	}
+
+sub main'QWPw
+	{
+	local($off,$reg)=@_;
+
+	return(&main'QWP($off*8,$reg));
+	}
+
+sub main'QWP
+	{
+	local($off,$reg)=@_;
+
+	$ret="$off(".&conv($reg).")";
+	return($ret);
+	}
+
+sub out3
+	{
+	local($name,$p1,$p2,$p3)=@_;
+
+	$p1=&conv($p1);
+	$p2=&conv($p2);
+	$p3=&conv($p3);
+	push(@out,"\t$name\t");
+	$l=length($p1)+1;
+	push(@out,$p1.",");
+	$ll=3-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	$l=length($p2)+1;
+	push(@out,$p2.",");
+	$ll=3-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	push(@out,&conv($p3)."\n");
+	}
+
+sub out2
+	{
+	local($name,$p1,$p2,$p3)=@_;
+
+	$p1=&conv($p1);
+	$p2=&conv($p2);
+	push(@out,"\t$name\t");
+	$l=length($p1)+1;
+	push(@out,$p1.",");
+	$ll=3-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+
+	push(@out,&conv($p2)."\n");
+	}
+
+sub out1
+	{
+	local($name,$p1)=@_;
+
+	$p1=&conv($p1);
+	push(@out,"\t$name\t".$p1."\n");
+	}
+
+sub out0
+	{
+	push(@out,"\t$_[0]\n");
+	}
+
+sub main'file
+	{
+	local($file)=@_;
+
+	local($tmp)=<<"EOF";
+ # DEC Alpha assember
+ # Generated from perl scripts contains in SSLeay
+	.file	1 "$file.s"
+	.set noat
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_begin
+	{
+	local($func)=@_;
+
+print STDERR "$func\n";
+	local($tmp)=<<"EOF";
+	.text
+	.align $align
+	.globl $func
+	.ent $func
+${func}:
+${func}..ng:
+	.frame \$30,0,\$26,0
+	.prologue 0
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	}
+
+sub main'function_end
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	ret	\$31,(\$26),1
+	.end $func
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_A
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	ret	\$31,(\$26),1
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_end_B
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	push(@out,"\t.end $func\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main'wparam
+	{
+	local($num)=@_;
+
+	if ($num < 6)
+		{
+		$num=20-$num;
+		return("r$num");
+		}
+	else
+		{ return(&main'QWP($stack+$num*8,"sp")); }
+	}
+
+sub main'stack_push
+	{
+	local($num)=@_;
+	$stack+=$num*8;
+	&main'sub("sp",$num*8,"sp");
+	}
+
+sub main'stack_pop
+	{
+	local($num)=@_;
+	$stack-=$num*8;
+	&main'add("sp",$num*8,"sp");
+	}
+
+sub main'swtmp
+	{
+	return(&main'QWP(($_[0])*8,"sp"));
+	}
+
+# Should use swtmp, which is above sp.  Linix can trash the stack above esp
+#sub main'wtmp
+#	{
+#	local($num)=@_;
+#
+#	return(&main'QWP(-($num+1)*4,"esp","",0));
+#	}
+
+sub main'comment
+	{
+	foreach (@_)
+		{
+		if (/^\s*$/)
+			{ push(@out,"\n"); }
+		else
+			{ push(@out,"\t$com_start $_ $com_end\n"); }
+		}
+	}
+
+sub main'label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=$label;
+		$label++;
+		}
+	return('$'.$label{$_[0]});
+	}
+
+sub main'set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=$label;
+		$label++;
+		}
+#	push(@out,".align $align\n") if ($_[1] != 0);
+	push(@out,'$'."$label{$_[0]}:\n");
+	}
+
+sub main'file_end
+	{
+	}
+
+sub main'data_word
+	{
+	push(@out,"\t.long $_[0]\n");
+	}
+
+@pool_free=();
+@pool_taken=();
+$curr_num=0;
+$max=0;
+
+sub main'init_pool
+	{
+	local($args)=@_;
+	local($i);
+
+	@pool_free=();
+	for ($i=(14+(6-$args)); $i >= 0; $i--)
+		{
+		push(@pool_free,"r$i");
+		}
+	print STDERR "START :register pool:@pool_free\n";
+	$curr_num=$max=0;
+	}
+
+sub main'fin_pool
+	{
+	printf STDERR "END %2d:register pool:@pool_free\n",$max;
+	}
+
+sub main'GR
+	{
+	local($r)=@_;
+	local($i,@n,$_);
+
+	foreach (@pool_free)
+		{
+		if ($r ne $_)
+			{ push(@n,$_); }
+		else
+			{
+			$curr_num++;
+			$max=$curr_num if ($curr_num > $max);
+			}
+		}
+	@pool_free=@n;
+print STDERR "GR:@pool_free\n" if $reg_alloc;
+	return(@_);
+	}
+
+sub main'NR
+	{
+	local($num)=@_;
+	local(@ret);
+
+	$num=1 if $num == 0;
+	($#pool_free >= ($num-1)) || croak "out of registers: want $num, have @pool_free";
+	while ($num > 0)
+		{
+		push(@ret,pop @pool_free);
+		$curr_num++;
+		$max=$curr_num if ($curr_num > $max);
+		$num--
+		}
+	print STDERR "nr @ret\n" if $n_debug;
+print STDERR "NR:@pool_free\n" if $reg_alloc;
+	return(@ret);
+
+	}
+
+sub main'FR
+	{
+	local(@r)=@_;
+	local(@a,$v,$w);
+
+	print STDERR "fr @r\n" if $n_debug;
+#	cluck "fr @r";
+	for $w (@pool_free)
+		{
+		foreach $v (@r)
+			{
+			croak "double register free of $v (@pool_free)" if $w eq $v;
+			}
+		}
+	foreach $v (@r)
+		{
+		croak "bad argument to FR" if ($v !~ /^r\d+$/);
+		if ($smear_regs)
+			{ unshift(@pool_free,$v); }
+		else	{ push(@pool_free,$v); }
+		$curr_num--;
+		}
+print STDERR "FR:@pool_free\n" if $reg_alloc;
+	}
+1;
Index: freeswan/libcrypto/perlasm/cbc.pl
diff -u /dev/null freeswan/libcrypto/perlasm/cbc.pl:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/perlasm/cbc.pl	Mon Apr 15 12:13:43 2002
@@ -0,0 +1,342 @@
+#!/usr/local/bin/perl
+
+# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
+# des_cblock (*input);
+# des_cblock (*output);
+# long length;
+# des_key_schedule schedule;
+# des_cblock (*ivec);
+# int enc;
+#
+# calls 
+# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
+#
+
+#&cbc("des_ncbc_encrypt","des_encrypt",0);
+#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",
+#	1,4,5,3,5,-1);
+#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",
+#	0,4,5,3,5,-1);
+#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",
+#	0,6,7,3,4,5);
+#
+# When doing a cipher that needs bigendian order,
+# for encrypt, the iv is kept in bigendian form,
+# while for decrypt, it is kept in little endian.
+sub cbc
+	{
+	local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_;
+	# name is the function name
+	# enc_func and dec_func and the functions to call for encrypt/decrypt
+	# swap is true if byte order needs to be reversed
+	# iv_off is parameter number for the iv 
+	# enc_off is parameter number for the encrypt/decrypt flag
+	# p1,p2,p3 are the offsets for parameters to be passed to the
+	# underlying calls.
+
+	&function_begin_B($name,"");
+	&comment("");
+
+	$in="esi";
+	$out="edi";
+	$count="ebp";
+
+	&push("ebp");
+	&push("ebx");
+	&push("esi");
+	&push("edi");
+
+	$data_off=4;
+	$data_off+=4 if ($p1 > 0);
+	$data_off+=4 if ($p2 > 0);
+	$data_off+=4 if ($p3 > 0);
+
+	&mov($count,	&wparam(2));	# length
+
+	&comment("getting iv ptr from parameter $iv_off");
+	&mov("ebx",	&wparam($iv_off));	# Get iv ptr
+
+	&mov($in,	&DWP(0,"ebx","",0));#	iv[0]
+	&mov($out,	&DWP(4,"ebx","",0));#	iv[1]
+
+	&push($out);
+	&push($in);
+	&push($out);	# used in decrypt for iv[1]
+	&push($in);	# used in decrypt for iv[0]
+
+	&mov("ebx",	"esp");		# This is the address of tin[2]
+
+	&mov($in,	&wparam(0));	# in
+	&mov($out,	&wparam(1));	# out
+
+	# We have loaded them all, how lets push things
+	&comment("getting encrypt flag from parameter $enc_off");
+	&mov("ecx",	&wparam($enc_off));	# Get enc flag
+	if ($p3 > 0)
+		{
+		&comment("get and push parameter $p3");
+		if ($enc_off != $p3)
+			{ &mov("eax",	&wparam($p3)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	if ($p2 > 0)
+		{
+		&comment("get and push parameter $p2");
+		if ($enc_off != $p2)
+			{ &mov("eax",	&wparam($p2)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	if ($p1 > 0)
+		{
+		&comment("get and push parameter $p1");
+		if ($enc_off != $p1)
+			{ &mov("eax",	&wparam($p1)); &push("eax"); }
+		else	{ &push("ecx"); }
+		}
+	&push("ebx");		# push data/iv
+
+	&cmp("ecx",0);
+	&jz(&label("decrypt"));
+
+	&and($count,0xfffffff8);
+	&mov("eax",	&DWP($data_off,"esp","",0));	# load iv[0]
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	# load iv[1]
+
+	&jz(&label("encrypt_finish"));
+
+	#############################################################
+
+	&set_label("encrypt_loop");
+	# encrypt start 
+	# "eax" and "ebx" hold iv (or the last cipher text)
+
+	&mov("ecx",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("edx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&xor("eax",	"ecx");
+	&xor("ebx",	"edx");
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($enc_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP(0,$out,"",0),"eax");
+	&mov(&DWP(4,$out,"",0),"ebx");
+
+	# eax and ebx are the next iv.
+
+	&add($in,	8);
+	&add($out,	8);
+
+	&sub($count,	8);
+	&jnz(&label("encrypt_loop"));
+
+###################################################################3
+	&set_label("encrypt_finish");
+	&mov($count,	&wparam(2));	# length
+	&and($count,	7);
+	&jz(&label("finish"));
+	&xor("ecx","ecx");
+	&xor("edx","edx");
+	&mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4));
+	&jmp_ptr($count);
+
+&set_label("ej7");
+	&xor("edx",		"edx") if $ppro; # ppro friendly
+	&movb(&HB("edx"),	&BP(6,$in,"",0));
+	&shl("edx",8);
+&set_label("ej6");
+	&movb(&HB("edx"),	&BP(5,$in,"",0));
+&set_label("ej5");
+	&movb(&LB("edx"),	&BP(4,$in,"",0));
+&set_label("ej4");
+	&mov("ecx",		&DWP(0,$in,"",0));
+	&jmp(&label("ejend"));
+&set_label("ej3");
+	&movb(&HB("ecx"),	&BP(2,$in,"",0));
+	&xor("ecx",		"ecx") if $ppro; # ppro friendly
+	&shl("ecx",8);
+&set_label("ej2");
+	&movb(&HB("ecx"),	&BP(1,$in,"",0));
+&set_label("ej1");
+	&movb(&LB("ecx"),	&BP(0,$in,"",0));
+&set_label("ejend");
+
+	&xor("eax",	"ecx");
+	&xor("ebx",	"edx");
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($enc_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP(0,$out,"",0),"eax");
+	&mov(&DWP(4,$out,"",0),"ebx");
+
+	&jmp(&label("finish"));
+
+	#############################################################
+	#############################################################
+	&set_label("decrypt",1);
+	# decrypt start 
+	&and($count,0xfffffff8);
+	# The next 2 instructions are only for if the jz is taken
+	&mov("eax",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("ebx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+	&jz(&label("decrypt_finish"));
+
+	&set_label("decrypt_loop");
+	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($dec_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+
+	&xor("ecx",	"eax");
+	&xor("edx",	"ebx");
+
+	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
+	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
+
+	&mov(&DWP(0,$out,"",0),"ecx");
+	&mov(&DWP(4,$out,"",0),"edx");
+
+	&mov(&DWP($data_off+8,"esp","",0),	"eax");	# save iv
+	&mov(&DWP($data_off+12,"esp","",0),	"ebx");	#
+
+	&add($in,	8);
+	&add($out,	8);
+
+	&sub($count,	8);
+	&jnz(&label("decrypt_loop"));
+############################ ENDIT #######################3
+	&set_label("decrypt_finish");
+	&mov($count,	&wparam(2));	# length
+	&and($count,	7);
+	&jz(&label("finish"));
+
+	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
+	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
+	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
+
+	&call($dec_func);
+
+	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
+	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
+
+	&bswap("eax")	if $swap;
+	&bswap("ebx")	if $swap;
+
+	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
+	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
+
+	&xor("ecx",	"eax");
+	&xor("edx",	"ebx");
+
+	# this is for when we exit
+	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
+	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
+
+&set_label("dj7");
+	&rotr("edx",	16);
+	&movb(&BP(6,$out,"",0),	&LB("edx"));
+	&shr("edx",16);
+&set_label("dj6");
+	&movb(&BP(5,$out,"",0),	&HB("edx"));
+&set_label("dj5");
+	&movb(&BP(4,$out,"",0),	&LB("edx"));
+&set_label("dj4");
+	&mov(&DWP(0,$out,"",0),	"ecx");
+	&jmp(&label("djend"));
+&set_label("dj3");
+	&rotr("ecx",	16);
+	&movb(&BP(2,$out,"",0),	&LB("ecx"));
+	&shl("ecx",16);
+&set_label("dj2");
+	&movb(&BP(1,$in,"",0),	&HB("ecx"));
+&set_label("dj1");
+	&movb(&BP(0,$in,"",0),	&LB("ecx"));
+&set_label("djend");
+
+	# final iv is still in eax:ebx
+	&jmp(&label("finish"));
+
+
+############################ FINISH #######################3
+	&set_label("finish",1);
+	&mov("ecx",	&wparam($iv_off));	# Get iv ptr
+
+	#################################################
+	$total=16+4;
+	$total+=4 if ($p1 > 0);
+	$total+=4 if ($p2 > 0);
+	$total+=4 if ($p3 > 0);
+	&add("esp",$total);
+
+	&mov(&DWP(0,"ecx","",0),	"eax");	# save iv
+	&mov(&DWP(4,"ecx","",0),	"ebx");	# save iv
+
+	&function_end_A($name);
+
+	&set_label("cbc_enc_jmp_table",1);
+	&data_word("0");
+	&data_word(&label("ej1"));
+	&data_word(&label("ej2"));
+	&data_word(&label("ej3"));
+	&data_word(&label("ej4"));
+	&data_word(&label("ej5"));
+	&data_word(&label("ej6"));
+	&data_word(&label("ej7"));
+	&set_label("cbc_dec_jmp_table",1);
+	&data_word("0");
+	&data_word(&label("dj1"));
+	&data_word(&label("dj2"));
+	&data_word(&label("dj3"));
+	&data_word(&label("dj4"));
+	&data_word(&label("dj5"));
+	&data_word(&label("dj6"));
+	&data_word(&label("dj7"));
+
+	&function_end_B($name);
+	
+	}
+
+1;
Index: freeswan/libcrypto/perlasm/readme
diff -u /dev/null freeswan/libcrypto/perlasm/readme:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/perlasm/readme	Mon Apr 15 12:13:43 2002
@@ -0,0 +1,124 @@
+The perl scripts in this directory are my 'hack' to generate
+multiple different assembler formats via the one origional script.
+
+The way to use this library is to start with adding the path to this directory
+and then include it.
+
+push(@INC,"perlasm","../../perlasm");
+require "x86asm.pl";
+
+The first thing we do is setup the file and type of assember
+
+&asm_init($ARGV[0],$0);
+
+The first argument is the 'type'.  Currently
+'cpp', 'sol', 'a.out', 'elf' or 'win32'.
+Argument 2 is the file name.
+
+The reciprocal function is
+&asm_finish() which should be called at the end.
+
+There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler,
+and x86unix.pl which is the unix (gas) version.
+
+Functions of interest are:
+&external_label("des_SPtrans");	declare and external variable
+&LB(reg);			Low byte for a register
+&HB(reg);			High byte for a register
+&BP(off,base,index,scale)	Byte pointer addressing
+&DWP(off,base,index,scale)	Word pointer addressing
+&stack_push(num)		Basically a 'sub esp, num*4' with extra
+&stack_pop(num)			inverse of stack_push
+&function_begin(name,extra)	Start a function with pushing of
+				edi, esi, ebx and ebp.  extra is extra win32
+				external info that may be required.
+&function_begin_B(name,extra)	Same as norma function_begin but no pushing.
+&function_end(name)		Call at end of function.
+&function_end_A(name)		Standard pop and ret, for use inside functions
+&function_end_B(name)		Call at end but with poping or 'ret'.
+&swtmp(num)			Address on stack temp word.
+&wparam(num)			Parameter number num, that was push
+				in C convention.  This all works over pushes
+				and pops.
+&comment("hello there")		Put in a comment.
+&label("loop")			Refer to a label, normally a jmp target.
+&set_label("loop")		Set a label at this point.
+&data_word(word)		Put in a word of data.
+
+So how does this all hold together?  Given
+
+int calc(int len, int *data)
+	{
+	int i,j=0;
+
+	for (i=0; i<len; i++)
+		{
+		j+=other(data[i]);
+		}
+	}
+
+So a very simple version of this function could be coded as
+
+	push(@INC,"perlasm","../../perlasm");
+	require "x86asm.pl";
+	
+	&asm_init($ARGV[0],"cacl.pl");
+
+	&external_label("other");
+
+	$tmp1=	"eax";
+	$j=	"edi";
+	$data=	"esi";
+	$i=	"ebp";
+
+	&comment("a simple function");
+	&function_begin("calc");
+	&mov(	$data,		&wparam(1)); # data
+	&xor(	$j,		$j);
+	&xor(	$i,		$i);
+
+	&set_label("loop");
+	&cmp(	$i,		&wparam(0));
+	&jge(	&label("end"));
+
+	&mov(	$tmp1,		&DWP(0,$data,$i,4));
+	&push(	$tmp1);
+	&call(	"other");
+	&add(	$j,		"eax");
+	&pop(	$tmp1);
+	&inc(	$i);
+	&jmp(	&label("loop"));
+
+	&set_label("end");
+	&mov(	"eax",		$j);
+
+	&function_end("calc");
+
+	&asm_finish();
+
+The above example is very very unoptimised but gives an idea of how
+things work.
+
+There is also a cbc mode function generator in cbc.pl
+
+&cbc(	$name,
+	$encrypt_function_name,
+	$decrypt_function_name,
+	$true_if_byte_swap_needed,
+	$parameter_number_for_iv,
+	$parameter_number_for_encrypt_flag,
+	$first_parameter_to_pass,
+	$second_parameter_to_pass,
+	$third_parameter_to_pass);
+
+So for example, given
+void BF_encrypt(BF_LONG *data,BF_KEY *key);
+void BF_decrypt(BF_LONG *data,BF_KEY *key);
+void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
+        BF_KEY *ks, unsigned char *iv, int enc);
+
+&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
+
+&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
+&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
+
Index: freeswan/libcrypto/perlasm/version
diff -u /dev/null freeswan/libcrypto/perlasm/version:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/perlasm/version	Mon Apr 15 12:13:43 2002
@@ -0,0 +1,5 @@
+$Id: version,v 1.1 2002/01/07 12:34:23 cvs Exp $
+
+This version of perlasm was copied from the openssl 0.9.6c distribution
+
+The license applying to it is enclose in the LICENSE file
Index: freeswan/libcrypto/perlasm/x86asm.pl
diff -u /dev/null freeswan/libcrypto/perlasm/x86asm.pl:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/perlasm/x86asm.pl	Mon Apr 15 12:13:43 2002
@@ -0,0 +1,118 @@
+#!/usr/local/bin/perl
+
+# require 'x86asm.pl';
+# &asm_init("cpp","des-586.pl");
+# XXX
+# XXX
+# main'asm_finish
+
+sub main'asm_finish
+	{
+	&file_end();
+	&asm_finish_cpp() if $cpp;
+	print &asm_get_output();
+	}
+
+sub main'asm_init
+	{
+	($type,$fn,$i386)=@_;
+	$filename=$fn;
+
+	$cpp=$sol=$aout=$win32=$gaswin=0;
+	if (	($type eq "elf"))
+		{ require "x86unix.pl"; }
+	elsif (	($type eq "a.out"))
+		{ $aout=1; require "x86unix.pl"; }
+	elsif (	($type eq "gaswin"))
+		{ $gaswin=1; $aout=1; require "x86unix.pl"; }
+	elsif (	($type eq "sol"))
+		{ $sol=1; require "x86unix.pl"; }
+	elsif (	($type eq "cpp"))
+		{ $cpp=1; require "x86unix.pl"; }
+	elsif (	($type eq "win32"))
+		{ $win32=1; require "x86ms.pl"; }
+	elsif (	($type eq "win32n"))
+		{ $win32=1; require "x86nasm.pl"; }
+	else
+		{
+		print STDERR <<"EOF";
+Pick one target type from
+	elf	- linux, FreeBSD etc
+	a.out	- old linux
+	sol	- x86 solaris
+	cpp	- format so x86unix.cpp can be used
+	win32	- Windows 95/Windows NT
+	win32n	- Windows 95/Windows NT NASM format
+EOF
+		exit(1);
+		}
+
+	&asm_init_output();
+
+&comment("Don't even think of reading this code");
+&comment("It was automatically generated by $filename");
+&comment("Which is a perl program used to generate the x86 assember for");
+&comment("any of elf, a.out, BSDI, Win32, gaswin (for GNU as on Win32) or Solaris");
+&comment("eric <eay\@cryptsoft.com>");
+&comment("");
+
+	$filename =~ s/\.pl$//;
+	&file($filename);
+	}
+
+sub asm_finish_cpp
+	{
+	return unless $cpp;
+
+	local($tmp,$i);
+	foreach $i (&get_labels())
+		{
+		$tmp.="#define $i _$i\n";
+		}
+	print <<"EOF";
+/* Run the C pre-processor over this file with one of the following defined
+ * ELF - elf object files,
+ * OUT - a.out object files,
+ * BSDI - BSDI style a.out object files
+ * SOL - Solaris style elf
+ */
+
+#define TYPE(a,b)       .type   a,b
+#define SIZE(a,b)       .size   a,b
+
+#if defined(OUT) || (defined(BSDI) && !defined(ELF))
+$tmp
+#endif
+
+#ifdef OUT
+#define OK	1
+#define ALIGN	4
+#endif
+
+#if defined(BSDI) && !defined(ELF)
+#define OK              1
+#define ALIGN           4
+#undef SIZE
+#undef TYPE
+#define SIZE(a,b)
+#define TYPE(a,b)
+#endif
+
+#if defined(ELF) || defined(SOL)
+#define OK              1
+#define ALIGN           16
+#endif
+
+#ifndef OK
+You need to define one of
+ELF - elf systems - linux-elf, NetBSD and DG-UX
+OUT - a.out systems - linux-a.out and FreeBSD
+SOL - solaris systems, which are elf with strange comment lines
+BSDI - a.out with a very primative version of as.
+#endif
+
+/* Let the Assembler begin :-) */
+EOF
+	}
+
+1;
Index: freeswan/libcrypto/perlasm/x86ms.pl
diff -u /dev/null freeswan/libcrypto/perlasm/x86ms.pl:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/perlasm/x86ms.pl	Mon Apr 15 12:13:43 2002
@@ -0,0 +1,365 @@
+#!/usr/local/bin/perl
+
+package x86ms;
+
+$label="L000";
+
+%lb=(	'eax',	'al',
+	'ebx',	'bl',
+	'ecx',	'cl',
+	'edx',	'dl',
+	'ax',	'al',
+	'bx',	'bl',
+	'cx',	'cl',
+	'dx',	'dl',
+	);
+
+%hb=(	'eax',	'ah',
+	'ebx',	'bh',
+	'ecx',	'ch',
+	'edx',	'dh',
+	'ax',	'ah',
+	'bx',	'bh',
+	'cx',	'ch',
+	'dx',	'dh',
+	);
+
+sub main'asm_init_output { @out=(); }
+sub main'asm_get_output { return(@out); }
+sub main'get_labels { return(@labels); }
+sub main'external_label { push(@labels,@_); }
+
+sub main'LB
+	{
+	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
+	return($lb{$_[0]});
+	}
+
+sub main'HB
+	{
+	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
+	return($hb{$_[0]});
+	}
+
+sub main'BP
+	{
+	&get_mem("BYTE",@_);
+	}
+
+sub main'DWP
+	{
+	&get_mem("DWORD",@_);
+	}
+
+sub main'BC
+	{
+	return @_;
+	}
+
+sub main'DWC
+	{
+	return @_;
+	}
+
+sub main'stack_push
+	{
+	local($num)=@_;
+	$stack+=$num*4;
+	&main'sub("esp",$num*4);
+	}
+
+sub main'stack_pop
+	{
+	local($num)=@_;
+	$stack-=$num*4;
+	&main'add("esp",$num*4);
+	}
+
+sub get_mem
+	{
+	local($size,$addr,$reg1,$reg2,$idx)=@_;
+	local($t,$post);
+	local($ret)="$size PTR ";
+
+	$addr =~ s/^\s+//;
+	if ($addr =~ /^(.+)\+(.+)$/)
+		{
+		$reg2=&conv($1);
+		$addr="_$2";
+		}
+	elsif ($addr =~ /^[_a-zA-Z]/)
+		{
+		$addr="_$addr";
+		}
+
+	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+	if (($addr ne "") && ($addr ne 0))
+		{
+		if ($addr !~ /^-/)
+			{ $ret.=$addr; }
+		else	{ $post=$addr; }
+		}
+	if ($reg2 ne "")
+		{
+		$t="";
+		$t="*$idx" if ($idx != 0);
+		$reg1="+".$reg1 if ("$reg1$post" ne "");
+		$ret.="[$reg2$t$reg1$post]";
+		}
+	else
+		{
+		$ret.="[$reg1$post]"
+		}
+	return($ret);
+	}
+
+sub main'mov	{ &out2("mov",@_); }
+sub main'movb	{ &out2("mov",@_); }
+sub main'and	{ &out2("and",@_); }
+sub main'or	{ &out2("or",@_); }
+sub main'shl	{ &out2("shl",@_); }
+sub main'shr	{ &out2("shr",@_); }
+sub main'xor	{ &out2("xor",@_); }
+sub main'xorb	{ &out2("xor",@_); }
+sub main'add	{ &out2("add",@_); }
+sub main'adc	{ &out2("adc",@_); }
+sub main'sub	{ &out2("sub",@_); }
+sub main'rotl	{ &out2("rol",@_); }
+sub main'rotr	{ &out2("ror",@_); }
+sub main'exch	{ &out2("xchg",@_); }
+sub main'cmp	{ &out2("cmp",@_); }
+sub main'lea	{ &out2("lea",@_); }
+sub main'mul	{ &out1("mul",@_); }
+sub main'div	{ &out1("div",@_); }
+sub main'dec	{ &out1("dec",@_); }
+sub main'inc	{ &out1("inc",@_); }
+sub main'jmp	{ &out1("jmp",@_); }
+sub main'jmp_ptr { &out1p("jmp",@_); }
+sub main'je	{ &out1("je",@_); }
+sub main'jle	{ &out1("jle",@_); }
+sub main'jz	{ &out1("jz",@_); }
+sub main'jge	{ &out1("jge",@_); }
+sub main'jl	{ &out1("jl",@_); }
+sub main'jb	{ &out1("jb",@_); }
+sub main'jc	{ &out1("jc",@_); }
+sub main'jnc	{ &out1("jnc",@_); }
+sub main'jnz	{ &out1("jnz",@_); }
+sub main'jne	{ &out1("jne",@_); }
+sub main'jno	{ &out1("jno",@_); }
+sub main'push	{ &out1("push",@_); $stack+=4; }
+sub main'pop	{ &out1("pop",@_); $stack-=4; }
+sub main'bswap	{ &out1("bswap",@_); &using486(); }
+sub main'not	{ &out1("not",@_); }
+sub main'call	{ &out1("call",'_'.$_[0]); }
+sub main'ret	{ &out0("ret"); }
+sub main'nop	{ &out0("nop"); }
+
+sub out2
+	{
+	local($name,$p1,$p2)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t");
+	$t=&conv($p1).",";
+	$l=length($t);
+	push(@out,$t);
+	$l=4-($l+9)/8;
+	push(@out,"\t" x $l);
+	push(@out,&conv($p2));
+	push(@out,"\n");
+	}
+
+sub out0
+	{
+	local($name)=@_;
+
+	push(@out,"\t$name\n");
+	}
+
+sub out1
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t".&conv($p1)."\n");
+	}
+
+sub conv
+	{
+	local($p)=@_;
+
+	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
+	return $p;
+	}
+
+sub using486
+	{
+	return if $using486;
+	$using486++;
+	grep(s/\.386/\.486/,@out);
+	}
+
+sub main'file
+	{
+	local($file)=@_;
+
+	local($tmp)=<<"EOF";
+	TITLE	$file.asm
+        .386
+.model FLAT
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'function_begin
+	{
+	local($func,$extra)=@_;
+
+	push(@labels,$func);
+
+	local($tmp)=<<"EOF";
+_TEXT	SEGMENT
+PUBLIC	_$func
+$extra
+_$func PROC NEAR
+	push	ebp
+	push	ebx
+	push	esi
+	push	edi
+EOF
+	push(@out,$tmp);
+	$stack=20;
+	}
+
+sub main'function_begin_B
+	{
+	local($func,$extra)=@_;
+
+	local($tmp)=<<"EOF";
+_TEXT	SEGMENT
+PUBLIC	_$func
+$extra
+_$func PROC NEAR
+EOF
+	push(@out,$tmp);
+	$stack=4;
+	}
+
+sub main'function_end
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+_$func ENDP
+_TEXT	ENDS
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_B
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+_$func ENDP
+_TEXT	ENDS
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main'function_end_A
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+EOF
+	push(@out,$tmp);
+	}
+
+sub main'file_end
+	{
+	push(@out,"END\n");
+	}
+
+sub main'wparam
+	{
+	local($num)=@_;
+
+	return(&main'DWP($stack+$num*4,"esp","",0));
+	}
+
+sub main'swtmp
+	{
+	return(&main'DWP($_[0]*4,"esp","",0));
+	}
+
+# Should use swtmp, which is above esp.  Linix can trash the stack above esp
+#sub main'wtmp
+#	{
+#	local($num)=@_;
+#
+#	return(&main'DWP(-(($num+1)*4),"esp","",0));
+#	}
+
+sub main'comment
+	{
+	foreach (@_)
+		{
+		push(@out,"\t; $_\n");
+		}
+	}
+
+sub main'label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="\$${label}${_[0]}";
+		$label++;
+		}
+	return($label{$_[0]});
+	}
+
+sub main'set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="${label}${_[0]}";
+		$label++;
+		}
+	if((defined $_[2]) && ($_[2] == 1))
+		{
+		push(@out,"$label{$_[0]}::\n");
+		}
+	else
+		{
+		push(@out,"$label{$_[0]}:\n");
+		}
+	}
+
+sub main'data_word
+	{
+	push(@out,"\tDD\t$_[0]\n");
+	}
+
+sub out1p
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t ".&conv($p1)."\n");
+	}
Index: freeswan/libcrypto/perlasm/x86nasm.pl
diff -u /dev/null freeswan/libcrypto/perlasm/x86nasm.pl:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/perlasm/x86nasm.pl	Mon Apr 15 12:13:43 2002
@@ -0,0 +1,366 @@
+#!/usr/local/bin/perl
+
+package x86nasm;
+
+$label="L000";
+
+%lb=(	'eax',	'al',
+	'ebx',	'bl',
+	'ecx',	'cl',
+	'edx',	'dl',
+	'ax',	'al',
+	'bx',	'bl',
+	'cx',	'cl',
+	'dx',	'dl',
+	);
+
+%hb=(	'eax',	'ah',
+	'ebx',	'bh',
+	'ecx',	'ch',
+	'edx',	'dh',
+	'ax',	'ah',
+	'bx',	'bh',
+	'cx',	'ch',
+	'dx',	'dh',
+	);
+
+%regs=(	'eax',	'eax',
+	'ebx',	'ebx',
+	'ecx',	'ecx',
+	'edx',	'edx',
+	'esi',	'esi',
+	'edi',	'edi',
+	'ebp',	'ebp',
+	'esp',	'esp',
+	'mm0',  'mm0',
+	'mm1',  'mm1',
+	);
+
+sub main::asm_init_output { @out=(); }
+sub main::asm_get_output { return(@out); }
+sub main::get_labels { return(@labels); }
+
+sub main::external_label
+{
+	push(@labels,@_);
+	foreach (@_) {
+		push(@out, "extern\t_$_\n");
+	}
+}
+
+sub main::LB
+	{
+	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
+	return($lb{$_[0]});
+	}
+
+sub main::HB
+	{
+	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
+	return($hb{$_[0]});
+	}
+
+sub main::BP
+	{
+	&get_mem("BYTE",@_);
+	}
+
+sub main::DWP
+	{
+	&get_mem("DWORD",@_);
+	}
+
+sub main::BC
+	{
+	return "BYTE @_";
+	}
+
+sub main::DWC
+	{
+	return "DWORD @_";
+	}
+
+sub main::stack_push
+	{
+	my($num)=@_;
+	$stack+=$num*4;
+	&main::sub("esp",$num*4);
+	}
+
+sub main::stack_pop
+	{
+	my($num)=@_;
+	$stack-=$num*4;
+	&main::add("esp",$num*4);
+	}
+
+sub get_mem
+	{
+	my($size,$addr,$reg1,$reg2,$idx)=@_;
+	my($t,$post);
+	my($ret)="[";
+	$addr =~ s/^\s+//;
+	if ($addr =~ /^(.+)\+(.+)$/)
+		{
+		if (defined($regs{$reg2})) {
+		    $addr=join('+', &conv($1), "_$2");
+		} else {
+		    $reg2=&conv($1);
+		    $addr="_$2";
+		}
+		}
+	elsif ($addr =~ /^[_a-zA-Z]/)
+		{
+		$addr="_$addr";
+		}
+
+	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+	if (($addr ne "") && ($addr ne 0))
+		{
+		if ($addr !~ /^-/)
+			{ $ret.="${addr}+"; }
+		else	{ $post=$addr; }
+		}
+	if ($reg2 ne "")
+		{
+		$t="";
+		$t="*$idx" if ($idx != 0);
+		$reg1="+".$reg1 if ("$reg1$post" ne "");
+		$ret.="$reg2$t$reg1$post]";
+		}
+	else
+		{
+		$ret.="$reg1$post]"
+		}
+	return($ret);
+	}
+
+sub main::mov	{ &out2("mov",@_); }
+sub main::movb	{ &out2("mov",@_); }
+sub main::and	{ &out2("and",@_); }
+sub main::or	{ &out2("or",@_); }
+sub main::shl	{ &out2("shl",@_); }
+sub main::shr	{ &out2("shr",@_); }
+sub main::xor	{ &out2("xor",@_); }
+sub main::xorb	{ &out2("xor",@_); }
+sub main::add	{ &out2("add",@_); }
+sub main::adc	{ &out2("adc",@_); }
+sub main::sub	{ &out2("sub",@_); }
+sub main::rotl	{ &out2("rol",@_); }
+sub main::rotr	{ &out2("ror",@_); }
+sub main::exch	{ &out2("xchg",@_); }
+sub main::cmp	{ &out2("cmp",@_); }
+sub main::lea	{ &out2("lea",@_); }
+sub main::mul	{ &out1("mul",@_); }
+sub main::div	{ &out1("div",@_); }
+sub main::dec	{ &out1("dec",@_); }
+sub main::inc	{ &out1("inc",@_); }
+sub main::jmp	{ &out1("jmp",@_); }
+sub main::jmp_ptr { &out1p("jmp",@_); }
+
+# This is a bit of a kludge: declare all branches as NEAR.
+sub main::je	{ &out1("je NEAR",@_); }
+sub main::jle	{ &out1("jle NEAR",@_); }
+sub main::jz	{ &out1("jz NEAR",@_); }
+sub main::jge	{ &out1("jge NEAR",@_); }
+sub main::jl	{ &out1("jl NEAR",@_); }
+sub main::jb	{ &out1("jb NEAR",@_); }
+sub main::jc	{ &out1("jc NEAR",@_); }
+sub main::jnc	{ &out1("jnc NEAR",@_); }
+sub main::jnz	{ &out1("jnz NEAR",@_); }
+sub main::jne	{ &out1("jne NEAR",@_); }
+sub main::jno	{ &out1("jno NEAR",@_); }
+
+sub main::push	{ &out1("push",@_); $stack+=4; }
+sub main::pop	{ &out1("pop",@_); $stack-=4; }
+sub main::bswap	{ &out1("bswap",@_); &using486(); }
+sub main::not	{ &out1("not",@_); }
+sub main::call	{ &out1("call",'_'.$_[0]); }
+sub main::ret	{ &out0("ret"); }
+sub main::nop	{ &out0("nop"); }
+
+sub out2
+	{
+	my($name,$p1,$p2)=@_;
+	my($l,$t);
+
+	push(@out,"\t$name\t");
+	$t=&conv($p1).",";
+	$l=length($t);
+	push(@out,$t);
+	$l=4-($l+9)/8;
+	push(@out,"\t" x $l);
+	push(@out,&conv($p2));
+	push(@out,"\n");
+	}
+
+sub out0
+	{
+	my($name)=@_;
+
+	push(@out,"\t$name\n");
+	}
+
+sub out1
+	{
+	my($name,$p1)=@_;
+	my($l,$t);
+	push(@out,"\t$name\t".&conv($p1)."\n");
+	}
+
+sub conv
+	{
+	my($p)=@_;
+	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
+	return $p;
+	}
+
+sub using486
+	{
+	return if $using486;
+	$using486++;
+	grep(s/\.386/\.486/,@out);
+	}
+
+sub main::file
+	{
+	push(@out, "segment .text\n");
+	}
+
+sub main::function_begin
+	{
+	my($func,$extra)=@_;
+
+	push(@labels,$func);
+	my($tmp)=<<"EOF";
+global	_$func
+_$func:
+	push	ebp
+	push	ebx
+	push	esi
+	push	edi
+EOF
+	push(@out,$tmp);
+	$stack=20;
+	}
+
+sub main::function_begin_B
+	{
+	my($func,$extra)=@_;
+	my($tmp)=<<"EOF";
+global	_$func
+_$func:
+EOF
+	push(@out,$tmp);
+	$stack=4;
+	}
+
+sub main::function_end
+	{
+	my($func)=@_;
+
+	my($tmp)=<<"EOF";
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+EOF
+	push(@out,$tmp);
+	$stack=0;
+	%label=();
+	}
+
+sub main::function_end_B
+	{
+	$stack=0;
+	%label=();
+	}
+
+sub main::function_end_A
+	{
+	my($func)=@_;
+
+	my($tmp)=<<"EOF";
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+EOF
+	push(@out,$tmp);
+	}
+
+sub main::file_end
+	{
+	}
+
+sub main::wparam
+	{
+	my($num)=@_;
+
+	return(&main::DWP($stack+$num*4,"esp","",0));
+	}
+
+sub main::swtmp
+	{
+	return(&main::DWP($_[0]*4,"esp","",0));
+	}
+
+# Should use swtmp, which is above esp.  Linix can trash the stack above esp
+#sub main::wtmp
+#	{
+#	my($num)=@_;
+#
+#	return(&main::DWP(-(($num+1)*4),"esp","",0));
+#	}
+
+sub main::comment
+	{
+	foreach (@_)
+		{
+		push(@out,"\t; $_\n");
+		}
+	}
+
+sub main::label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="\$${label}${_[0]}";
+		$label++;
+		}
+	return($label{$_[0]});
+	}
+
+sub main::set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}="${label}${_[0]}";
+		$label++;
+		}
+	push(@out,"$label{$_[0]}:\n");
+	}
+
+sub main::data_word
+	{
+	push(@out,"\tDD\t$_[0]\n");
+	}
+
+sub out1p
+	{
+	my($name,$p1)=@_;
+	my($l,$t);
+
+	push(@out,"\t$name\t ".&conv($p1)."\n");
+	}
+
+##
+## Additional functions required for MMX and other ops
+##
+sub main::testb { &out2('test', @_) }
+sub main::movzx { &out2('movzx', @_) }
+sub main::movd { &out2('movd', @_) }
+sub main::emms { &out0('emms', @_) }
Index: freeswan/libcrypto/perlasm/x86unix.pl
diff -u /dev/null freeswan/libcrypto/perlasm/x86unix.pl:1.1.2.1
--- /dev/null	Fri Jul 12 16:03:46 2002
+++ freeswan/libcrypto/perlasm/x86unix.pl	Mon Apr 15 12:13:43 2002
@@ -0,0 +1,471 @@
+#!/usr/local/bin/perl
+
+package x86unix;
+
+$label="L000";
+
+$align=($main::aout)?"4":"16";
+$under=($main::aout)?"_":"";
+$com_start=($main::sol)?"/":"#";
+
+sub main::asm_init_output { @out=(); }
+sub main::asm_get_output { return(@out); }
+sub main::get_labels { return(@labels); }
+sub main::external_label { push(@labels,@_); }
+
+if ($main::cpp)
+	{
+	$align="ALIGN";
+	$under="";
+	$com_start='/*';
+	$com_end='*/';
+	}
+
+%lb=(	'eax',	'%al',
+	'ebx',	'%bl',
+	'ecx',	'%cl',
+	'edx',	'%dl',
+	'ax',	'%al',
+	'bx',	'%bl',
+	'cx',	'%cl',
+	'dx',	'%dl',
+	);
+
+%hb=(	'eax',	'%ah',
+	'ebx',	'%bh',
+	'ecx',	'%ch',
+	'edx',	'%dh',
+	'ax',	'%ah',
+	'bx',	'%bh',
+	'cx',	'%ch',
+	'dx',	'%dh',
+	);
+
+%regs=(	'eax',	'%eax',
+	'ebx',	'%ebx',
+	'ecx',	'%ecx',
+	'edx',	'%edx',
+	'esi',	'%esi',
+	'edi',	'%edi',
+	'ebp',	'%ebp',
+	'esp',	'%esp',
+	'mm0',  '%mm0',
+	'mm1',  '%mm1',
+	);
+
+%reg_val=(
+	'eax',	0x00,
+	'ebx',	0x03,
+	'ecx',	0x01,
+	'edx',	0x02,
+	'esi',	0x06,
+	'edi',	0x07,
+	'ebp',	0x05,
+	'esp',	0x04,
+	);
+
+sub main::LB
+	{
+	(defined($lb{$_[0]})) || die "$_[0] does not have a 'low byte'\n";
+	return($lb{$_[0]});
+	}
+
+sub main::HB
+	{
+	(defined($hb{$_[0]})) || die "$_[0] does not have a 'high byte'\n";
+	return($hb{$_[0]});
+	}
+
+sub main::DWP
+	{
+	local($addr,$reg1,$reg2,$idx)=@_;
+
+	$ret="";
+	$addr =~ s/(^|[+ \t])([A-Za-z_]+[A-Za-z0-9_]+)($|[+ \t])/$1$under$2$3/;
+	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+	$ret.=$addr if ($addr ne "") && ($addr ne 0);
+	if ($reg2 ne "")
+		{
+		if($idx ne "")
+		    { $ret.="($reg1,$reg2,$idx)"; }
+		else
+		    { $ret.="($reg1,$reg2)"; }
+	        }
+	else
+		{ $ret.="($reg1)" }
+	return($ret);
+	}
+
+sub main::BP
+	{
+	return(&main::DWP(@_));
+	}
+
+sub main::BC
+	{
+	return @_;
+	}
+
+sub main::DWC
+	{
+	return @_;
+	}
+
+#sub main::BP
+#	{
+#	local($addr,$reg1,$reg2,$idx)=@_;
+#
+#	$ret="";
+#
+#	$addr =~ s/(^|[+ \t])([A-Za-z_]+)($|[+ \t])/$1$under$2$3/;
+#	$reg1="$regs{$reg1}" if defined($regs{$reg1});
+#	$reg2="$regs{$reg2}" if defined($regs{$reg2});
+#	$ret.=$addr if ($addr ne "") && ($addr ne 0);
+#	if ($reg2 ne "")
+#		{ $ret.="($reg1,$reg2,$idx)"; }
+#	else
+#		{ $ret.="($reg1)" }
+#	return($ret);
+#	}
+
+sub main::mov	{ &out2("movl",@_); }
+sub main::movb	{ &out2("movb",@_); }
+sub main::and	{ &out2("andl",@_); }
+sub main::or	{ &out2("orl",@_); }
+sub main::shl	{ &out2("sall",@_); }
+sub main::shr	{ &out2("shrl",@_); }
+sub main::xor	{ &out2("xorl",@_); }
+sub main::xorb	{ &out2("xorb",@_); }
+sub main::add	{ &out2("addl",@_); }
+sub main::adc	{ &out2("adcl",@_); }
+sub main::sub	{ &out2("subl",@_); }
+sub main::rotl	{ &out2("roll",@_); }
+sub main::rotr	{ &out2("rorl",@_); }
+sub main::exch	{ &out2("xchg",@_); }
+sub main::cmp	{ &out2("cmpl",@_); }
+sub main::lea	{ &out2("leal",@_); }
+sub main::mul	{ &out1("mull",@_); }
+sub main::div	{ &out1("divl",@_); }
+sub main::jmp	{ &out1("jmp",@_); }
+sub main::jmp_ptr { &out1p("jmp",@_); }
+sub main::je	{ &out1("je",@_); }
+sub main::jle	{ &out1("jle",@_); }
+sub main::jne	{ &out1("jne",@_); }
+sub main::jnz	{ &out1("jnz",@_); }
+sub main::jz	{ &out1("jz",@_); }
+sub main::jge	{ &out1("jge",@_); }
+sub main::jl	{ &out1("jl",@_); }
+sub main::jb	{ &out1("jb",@_); }
+sub main::jc	{ &out1("jc",@_); }
+sub main::jnc	{ &out1("jnc",@_); }
+sub main::jno	{ &out1("jno",@_); }
+sub main::dec	{ &out1("decl",@_); }
+sub main::inc	{ &out1("incl",@_); }
+sub main::push	{ &out1("pushl",@_); $stack+=4; }
+sub main::pop	{ &out1("popl",@_); $stack-=4; }
+sub main::not	{ &out1("notl",@_); }
+sub main::call	{ &out1("call",$under.$_[0]); }
+sub main::ret	{ &out0("ret"); }
+sub main::nop	{ &out0("nop"); }
+
+# The bswapl instruction is new for the 486. Emulate if i386.
+sub main::bswap
+	{
+	if ($main::i386)
+		{
+		&main::comment("bswapl @_");
+		&main::exch(main::HB(@_),main::LB(@_));
+		&main::rotr(@_,16);
+		&main::exch(main::HB(@_),main::LB(@_));
+		}
+	else
+		{
+		&out1("bswapl",@_);
+		}
+	}
+
+sub out2
+	{
+	local($name,$p1,$p2)=@_;
+	local($l,$ll,$t);
+	local(%special)=(	"roll",0xD1C0,"rorl",0xD1C8,
+				"rcll",0xD1D0,"rcrl",0xD1D8,
+				"shll",0xD1E0,"shrl",0xD1E8,
+				"sarl",0xD1F8);
+	
+	if ((defined($special{$name})) && defined($regs{$p1}) && ($p2 == 1))
+		{
+		$op=$special{$name}|$reg_val{$p1};
+		$tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
+		$tmp2=sprintf(".byte %d\t",$op     &0xff);
+		push(@out,$tmp1);
+		push(@out,$tmp2);
+
+		$p2=&conv($p2);
+		$p1=&conv($p1);
+		&main::comment("$name $p2 $p1");
+		return;
+		}
+
+	push(@out,"\t$name\t");
+	$t=&conv($p2).",";
+	$l=length($t);
+	push(@out,$t);
+	$ll=4-($l+9)/8;
+	$tmp1=sprintf("\t" x $ll);
+	push(@out,$tmp1);
+	push(@out,&conv($p1)."\n");
+	}
+
+sub out1
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+	local(%special)=("bswapl",0x0FC8);
+
+	if ((defined($special{$name})) && defined($regs{$p1}))
+		{
+		$op=$special{$name}|$reg_val{$p1};
+		$tmp1=sprintf(".byte %d\n",($op>>8)&0xff);
+		$tmp2=sprintf(".byte %d\t",$op     &0xff);
+		push(@out,$tmp1);
+		push(@out,$tmp2);
+
+		$p2=&conv($p2);
+		$p1=&conv($p1);
+		&main::comment("$name $p2 $p1");
+		return;
+		}
+
+	push(@out,"\t$name\t".&conv($p1)."\n");
+	}
+
+sub out1p
+	{
+	local($name,$p1)=@_;
+	local($l,$t);
+
+	push(@out,"\t$name\t*".&conv($p1)."\n");
+	}
+
+sub out0
+	{
+	push(@out,"\t$_[0]\n");
+	}
+
+sub conv
+	{
+	local($p)=@_;
+
+#	$p =~ s/0x([0-9A-Fa-f]+)/0$1h/;
+
+	$p=$regs{$p} if (defined($regs{$p}));
+
+	$p =~ s/^(-{0,1}[0-9A-Fa-f]+)$/\$$1/;
+	$p =~ s/^(0x[0-9A-Fa-f]+)$/\$$1/;
+	return $p;
+	}
+
+sub main::file
+	{
+	local($file)=@_;
+
+	local($tmp)=<<"EOF";
+	.file	"$file.s"
+	.version	"01.01"
+gcc2_compiled.:
+EOF
+	push(@out,$tmp);
+	}
+
+sub main::function_begin
+	{
+	local($func)=@_;
+
+	&main::external_label($func);
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+.text
+	.align $align
+.globl $func
+EOF
+	push(@out,$tmp);
+	if ($main::cpp)
+		{ $tmp=push(@out,"\tTYPE($func,\@function)\n"); }
+	elsif ($main::gaswin)
+		{ $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
+	else	{ $tmp=push(@out,"\t.type\t$func,\@function\n"); }
+	push(@out,"$func:\n");
+	$tmp=<<"EOF";
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+
+EOF
+	push(@out,$tmp);
+	$stack=20;
+	}
+
+sub main::function_begin_B
+	{
+	local($func,$extra)=@_;
+
+	&main::external_label($func);
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+.text
+	.align $align
+.globl $func
+EOF
+	push(@out,$tmp);
+	if ($main::cpp)
+		{ push(@out,"\tTYPE($func,\@function)\n"); }
+	elsif ($main::gaswin)
+		{ $tmp=push(@out,"\t.def\t$func;\t.scl\t2;\t.type\t32;\t.endef\n"); }
+	else	{ push(@out,"\t.type	$func,\@function\n"); }
+	push(@out,"$func:\n");
+	$stack=4;
+	}
+
+sub main::function_end
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	local($tmp)=<<"EOF";
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.${func}_end:
+EOF
+	push(@out,$tmp);
+	if ($main::cpp)
+		{ push(@out,"\tSIZE($func,.${func}_end-$func)\n"); }
+	elsif ($main::gaswin)
+                { $tmp=push(@out,"\t.align 4\n"); }
+	else	{ push(@out,"\t.size\t$func,.${func}_end-$func\n"); }
+	push(@out,".ident	\"$func\"\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main::function_end_A
+	{
+	local($func)=@_;
+
+	local($tmp)=<<"EOF";
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+EOF
+	push(@out,$tmp);
+	}
+
+sub main::function_end_B
+	{
+	local($func)=@_;
+
+	$func=$under.$func;
+
+	push(@out,".L_${func}_end:\n");
+	if ($main::cpp)
+		{ push(@out,"\tSIZE($func,.L_${func}_end-$func)\n"); }
+        elsif ($main::gaswin)
+                { push(@out,"\t.align 4\n"); }
+	else	{ push(@out,"\t.size\t$func,.L_${func}_end-$func\n"); }
+	push(@out,".ident	\"desasm.pl\"\n");
+	$stack=0;
+	%label=();
+	}
+
+sub main::wparam
+	{
+	local($num)=@_;
+
+	return(&main::DWP($stack+$num*4,"esp","",0));
+	}
+
+sub main::stack_push
+	{
+	local($num)=@_;
+	$stack+=$num*4;
+	&main::sub("esp",$num*4);
+	}
+
+sub main::stack_pop
+	{
+	local($num)=@_;
+	$stack-=$num*4;
+	&main::add("esp",$num*4);
+	}
+
+sub main::swtmp
+	{
+	return(&main::DWP($_[0]*4,"esp","",0));
+	}
+
+# Should use swtmp, which is above esp.  Linix can trash the stack above esp
+#sub main::wtmp
+#	{
+#	local($num)=@_;
+#
+#	return(&main::DWP(-($num+1)*4,"esp","",0));
+#	}
+
+sub main::comment
+	{
+	foreach (@_)
+		{
+		if (/^\s*$/)
+			{ push(@out,"\n"); }
+		else
+			{ push(@out,"\t$com_start $_ $com_end\n"); }
+		}
+	}
+
+sub main::label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=".${label}${_[0]}";
+		$label++;
+		}
+	return($label{$_[0]});
+	}
+
+sub main::set_label
+	{
+	if (!defined($label{$_[0]}))
+		{
+		$label{$_[0]}=".${label}${_[0]}";
+		$label++;
+		}
+	push(@out,".align $align\n") if ($_[1] != 0);
+	push(@out,"$label{$_[0]}:\n");
+	}
+
+sub main::file_end
+	{
+	}
+
+sub main::data_word
+	{
+	push(@out,"\t.long $_[0]\n");
+	}
+
+##
+## Additional functions required for MMX and other ops
+##
+sub main::testb { &out2('testb', @_) }
+sub main::movzx { &out2('movzx', @_) }
+sub main::movd { &out2('movd', @_) }
+sub main::emms { &out0('emms', @_) }

