#!/bin/sh
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	Makefile
#	README
#	log.single89
#	log.single91
#	loki.h
#	loki.i
#	loki89.c
#	loki91.c
#	lokibench.c
#	lokicert.c
#	single89
#	single91
#	triples89
#	triples91
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
X#
X#	Makefile - for LOKI routines
X#
X#	major targets are:
X#		make all	- compile binaries in this directory
X#		make clean	- remove all object files
X#		make clobber	- remove all files except original source
X#
X#	Copyright 1988 Lawrence Brown and CITRAD
X#
X#	Compiler Defines:
X#	-----------------
X#	    if this program is compiled on a little-endian machine (eg Vax)
X#		define '-DLITTLE_ENDIAN' in CFLAGS
X#		in order to enable the byte swapping  routines, 
X#		which will incur a time penalty
X#
X#	    if a detailed trace of LOKI function f is required for debugging
X#		define '-DTRACE=1', '-DTRACE=2' or '-DTRACE=3' in CFLAGS
X#               for increasingly detailed diagnostics from the loki64 routines.
X
XCFLAGS=-O
X
XPROGS = bench89 bench91 cert89 cert91
XOBJS  = lokibench.o lokicert.o loki89.o loki91.o
X
Xall: ${PROGS}
X
Xcert89: lokicert.o loki89.o
X	${CC} ${CFLAGS} lokicert.o loki89.o -o cert89
X
Xcert91: lokicert.o loki91.o
X	${CC} ${CFLAGS} lokicert.o loki91.o -o cert91
X
Xbench89: lokibench.o loki89.o
X	${CC} ${CFLAGS} lokibench.o loki89.o -o bench89
X
Xbench91: lokibench.o loki91.o
X	${CC} ${CFLAGS} lokibench.o loki91.o -o bench91
X
X${OBJS}:	loki.h
X
Xclean:
X	-rm ${OBJS} a.out core
X
Xclobber:	clean
X	-rm ${PROGS}
X
X.c.o: 
X	${CC} ${CFLAGS} -c $*.c
X
X
END-of-Makefile
echo ", sum on Makefile gives 32240 3"
echo x - README
sed 's/^X//' >README << 'END-of-README'
XThis directory contains the Unix source for the original LOKI89 and for
XLOKI91, the upgraded version of LOKI.
XThe files it contains are -
X
X	README		- This file
X	loki.h		- Interface specification include file for LOKI89 & 91
X	loki.i		- LOKI S & P box definition file for LOKI89 & 91
X	loki89.c	- Source code for LOKI89
X	loki91.c	- Source code for LOKI91
X	lokicert.c	- Certification program
X	triples89	- LOKI89 certification triplets
X	triples91	- LOKI91 certification triplets
X	single89, single91 - single LOKI89 & LOKI91 certification triplets
X	log.single89, log.single91 - logs of the certification runs on
X			single89 & single91 with TRACE=2 defined
X
XTo compile the certification program for LOKI89 & 91 use
X(note comments in each re DEFINE targets for various options and
Xarchitectures):
X
X	cc loki89.c lokicert.c -o cert89
X	cc loki91.c lokicert.c -o cert91
X
XTo run the certification use
X
X	cert89 < triples89
X	cert91 < triples91
X
XLOKI91 differs from LOKI89 in that the key schedule uses 13 bit
Xrotations instead of 12, and the S-boxes are generated by a slightly
Xdifferent function. In LOKI89 the base for Galois Field exponentiation
Xwas
X	b = col ^ row
X
XIn LOKI91 it is
X
X	b = (col + ((row * 17) ^ 0xff)) & 0xff
X
XOtherwise the algorithms are identical. The E-boxes and permutation
Xfunctions are unchanged.
X
XLawrie Brown & Matthew Kwan
END-of-README
echo ", sum on README gives 46059 3"
echo x - log.single89
sed 's/^X//' >log.single89 << 'END-of-log.single89'
X  keyinit(5b5a5767, 6a56676e)
X  enloki(675a6967, 5e5a6b5a)
X  f(340c0c34, 5b5a5767) = P.S(6f565b53) = P(e11a0f7d) = 8995736b
X  f(b5954d6b, 6a56676e) = P.S(dfc32a05) = P(e98c7f93) = daa3e63b
X  f(eeafea0f, a57675b5) = P.S(4bd99fba) = P(99a044ff) = d3599319
X  f(66ccde72, 6676e6a5) = P.S(00ba38d7) = P(a5e2d8d7) = f7c32959
X  f(196cc356, 675b5a57) = P.S(7e379901) = P(387a99b7) = 34dfe153
X  f(52133f21, 6e6a5667) = P.S(3c796946) = P(2b0753fe) = 139395fe
X  f(0aff56a8, b5a57675) = P.S(bf5a20dd) = P(2cc4b838) = 64b3bc00
X  f(36a08321, a56676e6) = P.S(93c6f5c7) = P(ead11b65) = cd96a1a7
X  f(c769f70f, 57675b5a) = P.S(900eac55) = P(830107eb) = 911012bf
X  f(a7b0919e, 676e6a56) = P.S(c0defbc8) = P(824e3573) = 853346d3
X  f(425ab1dc, 75b5a576) = P.S(37ef14aa) = P(b705ac86) = b0a82f9c
X  f(1718be02, e6a56676) = P.S(f1bdd874) = P(c8f8f5fb) = ff77d213
X  f(bd2d63cf, 5a57675b) = P.S(e77a0494) = P(49325f07) = 0a46a37b
X  f(1d5e1d79, 56676e6a) = P.S(4b397313) = P(5ad61743) = 4d0e86f3
X  f(f023e53c, 7675b5a5) = P.S(86565099) = P(7c93853a) = 689d9a56
X  f(75c3872f, 76e6a566) = P.S(03252249) = P(8559ca28) = a614782c
X  enloki returns 3c61fa7e, 2e99d048
X  deloki(3c61fa7e, 2e99d048)
X  f(75c3872f, 76e6a566) = P.S(03252249) = P(8559ca28) = a614782c
X  f(f023e53c, 7675b5a5) = P.S(86565099) = P(7c93853a) = 689d9a56
X  f(1d5e1d79, 56676e6a) = P.S(4b397313) = P(5ad61743) = 4d0e86f3
X  f(bd2d63cf, 5a57675b) = P.S(e77a0494) = P(49325f07) = 0a46a37b
X  f(1718be02, e6a56676) = P.S(f1bdd874) = P(c8f8f5fb) = ff77d213
X  f(425ab1dc, 75b5a576) = P.S(37ef14aa) = P(b705ac86) = b0a82f9c
X  f(a7b0919e, 676e6a56) = P.S(c0defbc8) = P(824e3573) = 853346d3
X  f(c769f70f, 57675b5a) = P.S(900eac55) = P(830107eb) = 911012bf
X  f(36a08321, a56676e6) = P.S(93c6f5c7) = P(ead11b65) = cd96a1a7
X  f(0aff56a8, b5a57675) = P.S(bf5a20dd) = P(2cc4b838) = 64b3bc00
X  f(52133f21, 6e6a5667) = P.S(3c796946) = P(2b0753fe) = 139395fe
X  f(196cc356, 675b5a57) = P.S(7e379901) = P(387a99b7) = 34dfe153
X  f(66ccde72, 6676e6a5) = P.S(00ba38d7) = P(a5e2d8d7) = f7c32959
X  f(eeafea0f, a57675b5) = P.S(4bd99fba) = P(99a044ff) = d3599319
X  f(b5954d6b, 6a56676e) = P.S(dfc32a05) = P(e98c7f93) = daa3e63b
X  f(340c0c34, 5b5a5767) = P.S(6f565b53) = P(e11a0f7d) = 8995736b
X  deloki returns 675a6967, 5e5a6b5a
XTest  1,  K: 5b5a57676a56676e  P: 675a69675e5a6b5a  C: 3c61fa7e2e99d048 OK
Xlokicert: 0 failures in 1 tests
END-of-log.single89
echo ", sum on log.single89 gives 12230 5"
echo x - log.single91
sed 's/^X//' >log.single91 << 'END-of-log.single91'
X  keyinit(3849674c, 2602319e)
X  enloki(126898d5, 5e911500)
X  f(5e911500, 3849674c) = P.S(66d8724c) = P(f87162a9) = 9efc9025
X  f(8c9408f0, 9674c384) = P.S(1ae0cb74) = P(33922c03) = 40ac22d9
X  f(1e3d37d9, 2602319e) = P.S(383f0647) = P(09581c84) = 1406e308
X  f(9892ebf8, 2319e260) = P.S(bb8b0998) = P(bb39254c) = 81ecd38e
X  f(9fd1e457, 987092ce) = P.S(07a17699) = P(f3060821) = 889824c9
X  f(100acf31, 092ce987) = P.S(192626b6) = P(c965744b) = 8f62961d
X  f(10b3724a, 3c4c0463) = P.S(2cff7629) = P(9f55c124) = a61c8d8e
X  f(b61642bf, c04633c4) = P.S(7650717b) = P(964f0840) = 85086cc4
X  f(95bb1e8e, 9d30e125) = P.S(088bffab) = P(ad7e306f) = 85f6dd59
X  f(33e09fe6, 0e1259d3) = P.S(3df2c635) = P(d5950b95) = d80d2d2f
X  f(4db633a1, c6789808) = P.S(8bceaba9) = P(c7fcaaf0) = fd756ca8
X  f(ce95f34e, 89808c67) = P.S(47157f29) = P(a20c6292) = 92a144b0
X  f(df177711, 4b3a61c2) = P.S(942d16d3) = P(4ddad7ce) = 7f06db7a
X  f(b1932834, a61c24b3) = P.S(178f0c87) = P(137d6e14) = 066d67ac
X  f(d97a10bd, 118cf130) = P.S(c8f6e18d) = P(0d92618c) = 5224994a
X  f(e3b7b17e, cf130118) = P.S(2ca4b066) = P(0d171eea) = 1116be7c
X  enloki returns c86caec1, e3b7b17e
X  deloki(c86caec1, e3b7b17e)
X  f(e3b7b17e, cf130118) = P.S(2ca4b066) = P(0d171eea) = 1116be7c
X  f(d97a10bd, 118cf130) = P.S(c8f6e18d) = P(0d92618c) = 5224994a
X  f(b1932834, a61c24b3) = P.S(178f0c87) = P(137d6e14) = 066d67ac
X  f(df177711, 4b3a61c2) = P.S(942d16d3) = P(4ddad7ce) = 7f06db7a
X  f(ce95f34e, 89808c67) = P.S(47157f29) = P(a20c6292) = 92a144b0
X  f(4db633a1, c6789808) = P.S(8bceaba9) = P(c7fcaaf0) = fd756ca8
X  f(33e09fe6, 0e1259d3) = P.S(3df2c635) = P(d5950b95) = d80d2d2f
X  f(95bb1e8e, 9d30e125) = P.S(088bffab) = P(ad7e306f) = 85f6dd59
X  f(b61642bf, c04633c4) = P.S(7650717b) = P(964f0840) = 85086cc4
X  f(10b3724a, 3c4c0463) = P.S(2cff7629) = P(9f55c124) = a61c8d8e
X  f(100acf31, 092ce987) = P.S(192626b6) = P(c965744b) = 8f62961d
X  f(9fd1e457, 987092ce) = P.S(07a17699) = P(f3060821) = 889824c9
X  f(9892ebf8, 2319e260) = P.S(bb8b0998) = P(bb39254c) = 81ecd38e
X  f(1e3d37d9, 2602319e) = P.S(383f0647) = P(09581c84) = 1406e308
X  f(8c9408f0, 9674c384) = P.S(1ae0cb74) = P(33922c03) = 40ac22d9
X  f(5e911500, 3849674c) = P.S(66d8724c) = P(f87162a9) = 9efc9025
X  deloki returns 126898d5, 5e911500
XTest  1,  K: 3849674c2602319e  P: 126898d55e911500  C: c86caec1e3b7b17e OK
Xlokicert: 0 failures in 1 tests
END-of-log.single91
echo ", sum on log.single91 gives 10773 5"
echo x - loki.h
sed 's/^X//' >loki.h << 'END-of-loki.h'
X/*
X *  loki.h - specifies the interface to the LOKI encryption routines.
X *      This library proviloki routines to expand a key, encrypt and
X *      decrypt 64-bit data blocks.  The LOKI Data Encryption Algorithm
X *      is a block cipher which ensures that its output is a complex
X *      function of its input and the key.
X *
X *  Authors:	Lawrie Brown <Lawrie.Brown@adfa.oz.au>	Aug 1989
X *		Matthew Kwan <mkwan@cs.adfa.oz.au>	Sep 1991
X *
X *      Computer Science, UC UNSW, Australian Defence Force Academy,
X *          Canberra, ACT 2600, Australia.
X *
X *  Version:
X *      v1.0 - of loki64.o is current 7/89 lpb
X *	v2.0 - of loki64.c is current 9/91 mkwan
X *	v3.0 - now have loki89.c & loki91.c 10/92 lpb
X *
X *  Copyright 1989 by Lawrie Brown and UNSW. All rights reserved.
X *      This program may not be sold or used as inducement to buy a
X *      product without the written permission of the author.
X *
X *  Description:
X *  The routines provided by the library are:
X *
X *  lokikey(key)	    - expands a key into subkey, for use in 
X *    char  key[8];             encryption and decryption operations.
X *
X *  enloki(b)		    - main LOKI encryption routine, this routine 
X *    char  b[8];               encrypts one 64-bit block b with subkey
X *
X *  deloki(b)		    - main LOKI decryption routine, this routine 
X *    char  b[8];               decrypts one 64-bit block b with subkey
X *
X *  The 64-bit data & key blocks used in the algorithm are specified as eight
X *      unsigned chars. For the purposes of implementing the LOKI algorithm,
X *      these MUST be word aligned with bits are numbered as follows:
X *        [63..56] [55..48] 		...		[7..0]
X *      in  b[0]     b[1]  b[2]  b[3]  b[4]  b[5]  b[6]  b[7]
X */
X
X#define LOKIBLK	8		/* No of bytes in a LOKI data-block          */
X#define ROUNDS	16		/* No of LOKI rounds             	     */
X
Xtypedef unsigned long	Long;   /* type specification for aligned LOKI blocks */
X
Xextern Long	lokikey[2];	/* 64-bit key used by LOKI routines          */
Xextern char	*loki_lib_ver;	/* String with version no. & copyright       */
X
X#ifdef __STDC__			/* declare prototypes for library functions  */
Xextern void enloki(char b[LOKIBLK]);
Xextern void deloki(char b[LOKIBLK]);
Xextern void setlokikey(char key[LOKIBLK]);
X#else				/* else just declare library functions extern */
Xextern void enloki(), deloki(), setlokikey();
X#endif __STDC__
END-of-loki.h
echo ", sum on loki.h gives 56491 5"
echo x - loki.i
sed 's/^X//' >loki.i << 'END-of-loki.i'
X/*
X *	loki.i - contains the fixed permutation and substitution tables 
X *			for a 64 bit LOKI89 & LOKI91 implementations.
X *
X *  Modifications:
X *	v1.0	original tables                       	Aug 1989 lpb
X *	v2.0	add various speed/size versions		Apr 1990 lpb
X *	v2.1	install into RCS system for production control 5/90 lpb
X *	v3.0	LOKI89 & LOKI91 now supported		10/92 lpb
X *
X *  Author:	Lawrence Brown <lpb@csadfa.oz>		Aug 1989
X *		Computer Science, UC UNSW, ADFA, Canberra, ACT 2600, Australia.
X *
X *  Copyright 1989 by Lawrence Brown and UNSW. All rights reserved.
X *      This program may not be sold or used as inducement to buy a
X *      product without the written permission of the author.
X */
X
X/* 32-bit permutation function P */
X/*   specifies which input bit is permuted to output bits */
X/*   31 30 29 ... 2 1 0 respectively (ie in MSB to LSB order) */
Xchar P[32] = {
X	31, 23, 15, 7, 30, 22, 14, 6,
X	29, 21, 13, 5, 28, 20, 12, 4,
X	27, 19, 11, 3, 26, 18, 10, 2,
X	25, 17, 9, 1, 24, 16, 8, 0
X	};
X
X/*
X *	sfn_desc - a desriptor table specifying which irreducible polynomial
X *		and exponent is to be used for each of the 16 S functions in
X *		the Loki S-box
X */
Xtypedef	struct {
X	short	gen;		/* irreducible polynomial used in this field */
X	short	exp;		/* exponent used to generate this s function */
X	} sfn_desc;
X
X/*
X *	sfn - the table specifying the irreducible polys & exponents used
X *		in the Loki S-boxes for the Loki algorithm
X */
Xsfn_desc sfn[] = {
X	{ /* 101110111 */ 375, 31},
X	{ /* 101111011 */ 379, 31},
X	{ /* 110000111 */ 391, 31},
X	{ /* 110001011 */ 395, 31},
X	{ /* 110001101 */ 397, 31},
X	{ /* 110011111 */ 415, 31},
X	{ /* 110100011 */ 419, 31},
X	{ /* 110101001 */ 425, 31},
X	{ /* 110110001 */ 433, 31},
X	{ /* 110111101 */ 445, 31},
X	{ /* 111000011 */ 451, 31},
X	{ /* 111001111 */ 463, 31},
X	{ /* 111010111 */ 471, 31},
X	{ /* 111011101 */ 477, 31},
X	{ /* 111100111 */ 487, 31},
X	{ /* 111110011 */ 499, 31},
X	{ 00, 00}
X	};
END-of-loki.i
echo ", sum on loki.i gives 4691 4"
echo x - loki89.c
sed 's/^X//' >loki89.c << 'END-of-loki89.c'
X/*
X *	loki89.c - library routines for a 64 bit LOKI89 implementation
X *
X *  Author:	Lawrence Brown <lpb@csadfa.oz>		Aug 1989
X *		Computer Science, UC UNSW, ADFA, Canberra, ACT 2600, Australia.
X *
X *  Modifications:
X *		v1.0 - original set of code (based on des64.c v4.0) 9/89 lpb
X *		v2.0 - include conditionals for various speed/sizes 4/90 lpb
X *		v2.1 - use RCS system for production control	5/90 lpb
X *		v3.0 - support both LOKI89 & LOKI91 versions   10/92 lpb
X *
X *  Copyright 1989 by Lawrence Brown and UNSW. All rights reserved.
X *      This program may not be sold or used as inducement to buy a
X *      product without the written permission of the author.
X *
X *	nb: if this program is compiled on a little-endian machine (eg Vax)
X *		#define LITTLE_ENDIAN
X *		in order to enable the byte swapping  routines 
X *
X *	    if a detailed trace of LOKI89 function f is required for debugging
X *		#define TRACE=n		n=1 print blocks, n=2 print fn f also
X *                                      n=3 print individual S-box calcs also
X *
X *	    these routines assume that the 8-byte char arrays used to pass
X *		the 64-bit blocks fall on a word boundary, so that the blocks
X *		may be read as longwords for efficiency reasons. If this is
X *		not true, the load & save of the parameters will need changing.
X */
X#include <stdio.h>
X#include "loki.h"	/* include Interface Specification header file       */
X#include "loki.i"	/* include LOKI89 Permutation, Subs & Key tables*/
X
X/*
X *	string specifying version and copyright message
X */
Xchar	*loki_lib_ver = "LOKI89 library v3.0, Copyright (C) 1990 Lawrence Brown & UNSW";
X
Xstatic Long	f();	/* declare LOKI89 function f		     */
Xstatic short	s();	/* declare LOKI89 s-box routine (for small ver) */
X
X/*
X *	lokikey - the 64-bit key for the LOKI89 library routines
X */
XLong	lokikey[2] = {0, 0};
X
X
X/*
X *	ROL12(b) - macro to rotate 32-bit block b left  by 12 bits
X *	ROR12(b) - macro to rotate 32-bit block b right by 12 bits
X */
X#define ROL12(b) b = ((b << 12) | (b >> 20));
X#define ROR12(b) b = ((b >> 12) | (b << 20));
X
X/*
X *      bswap(b) - exchanged bytes in each longword of a 64-bit data block
X *                      on little-endian machines where byte order is reversed
X */
X#ifdef  LITTLE_ENDIAN
X#define bswap(cb) {                             \
X        register char   c;                      \
X        c = cb[0]; cb[0] = cb[3]; cb[3] = c;    \
X        c = cb[1]; cb[1] = cb[2]; cb[2] = c;    \
X        c = cb[4]; cb[4] = cb[7]; cb[7] = c;    \
X        c = cb[5]; cb[5] = cb[6]; cb[6] = c;    \
X}
X#endif
X
X/*
X *	setlokikey(key) - save 64-bit key for use in encryptions & decryptions
X */
X
Xvoid
Xsetlokikey(key)
Xchar	key[LOKIBLK];		/* Key to use, stored as an array of Longs    */
X{
X#ifdef LITTLE_ENDIAN
X	bswap(key);			/* swap bytes round if little-endian */
X#endif
X
X	lokikey[0] = ((Long *)key)[0];
X	lokikey[1] = ((Long *)key)[1];
X
X#if	TRACE >= 1
X	fprintf(stderr,"  keyinit(%08lx, %08lx)\n", lokikey[0], lokikey[1]);
X#endif
X
X#ifdef LITTLE_ENDIAN
X	bswap(key);			/* swap bytes back if little-endian */
X#endif
X}
X
X
X/*
X *	enloki(b) - main LOKI89 encryption routine, this routine encrypts one 
X *		64-bit block b using the LOKI89 algorithm with lokikey
X *
X *		The encryption operation involves XOR'ing the input block with
X *		the key, applying a LOKI89 round sixteen times
X *		(which ensures the output is a complex function of the input,
X *		and the key), and finally XOR'ing the input block with the key
X *
X *		Each round performs the following calculation using a 48-bit
X *		subkeys:
X *			L(i) = R(i-1)
X *			R(i) = L(i-1) XOR f(R(i-1), K(i))
X *
X *		To save swapping, alternate calls to f use L & R respectively
X *
X *		nb: The 64-bit block is passed as two longwords. For the
X *			purposes of the LOKI89 algorithm, the bits are numbered:
X *			    [63 62 .. 33 32] [31 30 ... 1 0]
X *			The L (left) half is b[0], the R (right) half is b[1]
X *
X */
Xvoid
Xenloki(b)
Xchar	b[LOKIBLK];
X{
X	register Long	L, R;			/* left & right data halves  */
X	register Long	KL, KR;			/* left & right key  halves  */
X
X#ifdef LITTLE_ENDIAN
X	bswap(b);			/* swap bytes round if little-endian */
X#endif
X
X#if	TRACE >= 1
X	fprintf(stderr,"  enloki(%08lx, %08lx)\n", ((Long *)b)[0], ((Long *)b)[1]);
X#endif
X
X	KL = lokikey[0];			/* load keys in register vars */
X	KR = lokikey[1];
X
X	L = ((Long *)b)[0] ^ KL;		/* LR = X XOR K */
X	R = ((Long *)b)[1] ^ KR;
X
X	/* Perform the 16 rounds using sub-keys in usual order               */
X	L ^= f(R, KL);	ROL12(KL);		
X	R ^= f(L, KR);	ROL12(KR);
X	L ^= f(R, KL);	ROL12(KL);		
X	R ^= f(L, KR);	ROL12(KR);
X	L ^= f(R, KL);	ROL12(KL);		
X	R ^= f(L, KR);	ROL12(KR);
X	L ^= f(R, KL);	ROL12(KL);		
X	R ^= f(L, KR);	ROL12(KR);
X	L ^= f(R, KL);	ROL12(KL);		
X	R ^= f(L, KR);	ROL12(KR);
X	L ^= f(R, KL);	ROL12(KL);		
X	R ^= f(L, KR);	ROL12(KR);
X	L ^= f(R, KL);	ROL12(KL);		
X	R ^= f(L, KR);	ROL12(KR);
X	L ^= f(R, KL);	ROL12(KL);		
X	R ^= f(L, KR);	ROL12(KR);
X
X	((Long *)b)[0] = R ^ KR;		/* Y = swap(LR) XOR K */
X	((Long *)b)[1] = L ^ KL;
X
X#if	TRACE >= 1
X	fprintf(stderr,"  enloki returns %08lx, %08lx\n", ((Long *)b)[0], ((Long *)b)[1]);
X#endif
X
X#ifdef LITTLE_ENDIAN
X	bswap(b);			/* swap bytes round if little-endian */
X#endif
X}
X
X
X/*
X *	deloki(b) - main LOKI89 decryption routine, this routine decrypts one 
X *		64-bit block b using the LOKI89 algorithm with lokikey
X *
X *		Decryption uses the same algorithm as encryption, except that
X *		the subkeys are used in reverse order.
X */
Xvoid
Xdeloki(b)
Xchar	b[LOKIBLK];
X{
X	register Long	L, R;			/* left & right data halves  */
X	register Long	KL, KR;			/* left & right key  halves  */
X
X#ifdef LITTLE_ENDIAN
X	bswap(b);			/* swap bytes round if little-endian */
X#endif
X
X#if	TRACE >= 1
X	fprintf(stderr,"  deloki(%08lx, %08lx)\n", ((Long *)b)[0], ((Long *)b)[1]);
X#endif
X
X	KL = lokikey[0];			/* load keys in register vars */
X	KR = lokikey[1];
X
X	L = ((Long *)b)[0] ^ KR;		/* LR = X XOR K */
X	R = ((Long *)b)[1] ^ KL;
X
X	/* Perform the 16 rounds using sub-keys in usual order               */
X	ROR12(KR);	L ^= f(R, KR);
X	ROR12(KL);	R ^= f(L, KL);
X	ROR12(KR);	L ^= f(R, KR);
X	ROR12(KL);	R ^= f(L, KL);
X	ROR12(KR);	L ^= f(R, KR);
X	ROR12(KL);	R ^= f(L, KL);
X	ROR12(KR);	L ^= f(R, KR);
X	ROR12(KL);	R ^= f(L, KL);
X	ROR12(KR);	L ^= f(R, KR);
X	ROR12(KL);	R ^= f(L, KL);
X	ROR12(KR);	L ^= f(R, KR);
X	ROR12(KL);	R ^= f(L, KL);
X	ROR12(KR);	L ^= f(R, KR);
X	ROR12(KL);	R ^= f(L, KL);
X	ROR12(KR);	L ^= f(R, KR);
X	ROR12(KL);	R ^= f(L, KL);
X
X	((Long *)b)[0] = R ^ KL;		/* Y = LR XOR K */
X	((Long *)b)[1] = L ^ KR;
X
X#if	TRACE >= 1
X	fprintf(stderr,"  deloki returns %08lx, %08lx\n", ((Long *)b)[0], ((Long *)b)[1]);
X#endif
X
X#ifdef LITTLE_ENDIAN
X	bswap(b);			/* swap bytes round if little-endian */
X#endif
X}
X
X
X/*
X *	f(r, k) - is the complex non-linear LOKI89 function, whose output
X *		is a complex function of both input data and sub-key.
X *		The input data R(i-1) is:
X *			added modulo 2 to the key K(i)
X *			expanded to 48-bits via expansion fn E
X *			substituted into the S-boxes
X *			permuted by P.
X *		ie the calculation is:
X *			A = E(R(i-1) XOR K(i))		(a 48-bit value)
X *			B = S(A)			(a 32-bit value)
X *			f = P(B)			(a 32-bit value)
X *
X *	nb: the 12-bit S-box input value [x x x x 11 10 9 ... 3 2 1 0]
X *	    is interpreted as:
X *		bits [11 10 1 0] select 1 of 16 rows within each box,
X *		bits [9 8 ... 3 2] then select a column within that row
X */
X
X#define MASK12	0x0fff			/* 12 bit mask for expansion E */
X
Xstatic Long
Xf(r, k)
Xregister Long	r;	/* Data value R(i-1) */
XLong		k;	/* Key     K(i)   */
X{
X	Long	a, b, c;		/* 32 bit S-box output, & P output */
X
X	a = r ^ k;			/* A = R(i-1) XOR K(i) */
X
X	/* want to use slow speed/small size version */
X	b = ((Long)s((a         & MASK12))      ) | /* B = S(E(R(i-1))^K(i)) */
X	    ((Long)s(((a >>  8) & MASK12)) <<  8) |
X	    ((Long)s(((a >> 16) & MASK12)) << 16) |
X	    ((Long)s((((a >> 24) | (a << 8)) & MASK12)) << 24);
X
X	perm32(&c, &b, P);		/* C = P(S( E(R(i-1)) XOR K(i))) */
X
X#if	TRACE >= 2	/* If Tracing, dump A, K(i), and f(R(i-1),K(i)) */
X	fprintf(stderr,"  f(%08lx, %08lx) = P.S(%08lx) = P(%08lx) = %08lx\n",
X		r, k, a, b, c);
X#endif
X
X	return(c);			/* f returns the result C */
X}
X
X
X/*
X *	s(i) - return S-box value for input i
X */
Xstatic short s(i)
Xregister Long i;	/* return S-box value for input i */
X{
X	register short	r, c, v, t;
X	short	exp8();		/* exponentiation routine for GF(2^8) */
X	
X	r = ((i>>8) & 0xc) | (i & 0x3);		/* row value */
X	c = (i>>2) & 0xff;			/* column value */
X	t = c ^ r;				/* base value for Sfn */
X	v = exp8(t, sfn[r].exp, sfn[r].gen);	/* Sfn[r] = t ^ exp mod gen */
X#if TRACE >= 3
X	fprintf(stderr, "   s(%lx=[%d,%d]) = %x sup %d mod %d = %x\n",
X			i, r, c, t, sfn[r].exp, sfn[r].gen, v);
X#endif
X	return(v);
X}
X
X/*
X *	perm32(out, in, perm) is the general permutation of a 32-bit input
X *		block to a 32-bit output block, under the control of a 
X *		permutation array perm. Each element of perm specifies which
X *		input bit is to be permuted to the output bit with the same
X *		index as the array element.
X *
X *	nb: to set bits in the output word, as mask with a single 1 in it is
X *		used. On each step, the 1 is shifted into the next location
X */
X
X#define	MSB	0x80000000L		/* MSB of 32-bit word */
X
Xperm32(out, in , perm)
XLong	*out;		/* Output 32-bit block to be permuted                */
XLong	*in;		/* Input  32-bit block after permutation             */
Xchar	perm[32]; 	/* Permutation array                                 */
X{
X	Long	mask = MSB;		/* mask used to set bit in output    */
X	register int	i, o, b;	/* input bit no, output bit no, value */
X	register char	*p = perm;	/* ptr to permutation array  */
X
X	*out = 0;			/* clear output block */
X	for (o=0; o<32; o++) {		/* For each output bit position o */	
X		i =(int)*p++;		/* get input bit permuted to output o */
X		b = (*in >> i) & 01;	/* value of input bit i */
X		if (b)			/* If the input bit i is set */
X			*out |= mask;		/*  OR in mask to output i */
X		mask >>= 1;			/* Shift mask to next bit    */
X	}
X}
X
X/*
X *	mult8(a, b, gen) - returns the product of two binary
X *		strings a and b using the generator gen as the modulus
X *			mult = a * b mod gen
X *		gen generates a suitable Galois field in GF(2^8)
X */
X
X#define SIZE 256		/* 256 elements in GF(2^8) */
X
Xshort mult8(a, b, gen)
Xshort	a, b;		/* operands for multiply */
Xshort	gen;		/* irreducible polynomial generating Galois Field */
X{
X	short	product = 0;		/* result of multiplication */
X
X	while(b != 0) {			/* while multiplier is non-zero */
X		if (b & 01)
X			product ^= a;	/*   add multiplicand if LSB of b set */
X		a <<= 1;		/*   shift multiplicand one place */
X		if (a >= SIZE)
X			a ^= gen;	/*   and modulo reduce if needed */
X		b >>= 1;		/*   shift multiplier one place  */
X	}
X	return(product);
X}
X
X/*
X *	exp8(base, exponent, gen) - returns the result of
X *		exponentiation given the base, exponent, generator of GF,
X *			exp = base ^ exp mod gen
X */
X
Xshort exp8(base, exponent, gen)
Xshort	base;		/* base of exponentiation 	*/
Xshort	exponent;	/* exponent			*/
Xshort	gen;		/* irreducible polynomial generating Galois Field */
X{
X	short	accum = base;	/* superincreasing sequence of base */
X	short	result = 1;	/* result of exponentiation	    */
X
X	if (base == 0)		/* if zero base specified then      */
X		return(0);	/* the result is "0" if base = 0    */
X
X	while (exponent != 0) {	/* repeat while exponent non-zero */
X		if (( exponent & 0x0001) == 0x0001)	/* multiply if exp 1 */
X			result = mult8(result, accum, gen);
X		exponent >>= 1;		/* shift exponent to next digit */
X		accum = mult8(accum, accum, gen);	/* & square  */
X	}
X	return(result);
X}
END-of-loki89.c
echo ", sum on loki89.c gives 55267 23"
echo x - loki91.c
sed 's/^X//' >loki91.c << 'END-of-loki91.c'
X/*
X *	loki91.c - library routines for a 64 bit LOKI91 implementation
X *
X * Designed by  Matthew Kwan <mkwan@crypto.cs.adfa.oz.au> and
X *		Lawrence Brown <lpb@cs.adfa.oz.au>
X
X *  Modifications:
X *		v2.0 - original set of code by mkwan 9/91
X *		v3.0 - support both LOKI89 & LOKI91 versions   10/92 lpb
X *
X *  Copyright 1991 by Lawrence Brown and UNSW. All rights reserved.
X *      This program may not be sold or used as inducement to buy a
X *      product without the written permission of the author.
X *
X *	nb: if this program is compiled on a little-endian machine (eg Vax)
X *		#define LITTLE_ENDIAN
X *		in order to enable the byte swapping  routines 
X *
X *	    if a detailed trace of LOKI91 function f is required for debugging
X *		#define TRACE=n		n=1 print blocks, n=2 print fn f also
X *                                      n=3 print individual S-box calcs also
X *
X *	    these routines assume that the 8-byte char arrays used to pass
X *		the 64-bit blocks fall on a word boundary, so that the blocks
X *		may be read as longwords for efficiency reasons. If this is
X *		not true, the load & save of the parameters will need changing.
X */
X
X
X#include <stdio.h>
X#include "loki.h"	/* include Interface Specification header file */
X#include "loki.i"	/* include Interface Specification header file */
X
X/*
X *	string specifying version and copyright message
X */
Xchar	*loki_lib_ver = "LOKI91 library v3.0, Copyright (C) 1991 Lawrence Brown & UNSW";
X
XLong	loki_subkeys[ROUNDS];		/* subkeys at the 16 rounds */
Xstatic Long	f();			/* declare LOKI function f */
Xstatic short	s();			/* declare LOKI S-box fn s */
X
X
X/*
X *	ROL12(b) - macro to rotate 32-bit block b left by 12 bits
X *	ROL13(b) - macro to rotate 32-bit block b left by 13 bits
X */
X
X#define ROL12(b) b = ((b << 12) | (b >> 20));
X#define ROL13(b) b = ((b << 13) | (b >> 19));
X
X/*
X *      bswap(b) - exchanged bytes in each longword of a 64-bit data block
X *                      on little-endian machines where byte order is reversed
X */
X#ifdef  LITTLE_ENDIAN
X#define bswap(cb) {                             \
X        register char   c;                      \
X        c = cb[0]; cb[0] = cb[3]; cb[3] = c;    \
X        c = cb[1]; cb[1] = cb[2]; cb[2] = c;    \
X        c = cb[4]; cb[4] = cb[7]; cb[7] = c;    \
X        c = cb[5]; cb[5] = cb[6]; cb[6] = c;    \
X}
X#endif
X
X/*
X *	setlokikey(key) - save 64-bit key for use in encryptions & decryptions
X *			  and compute sub-keys using the key schedule 
X */
X
Xvoid
Xsetlokikey(key)
Xchar	key[LOKIBLK];		/* Key to use, stored as an array of Longs    */
X{
X	register	i;
X	register Long	KL, KR;
X
X#ifdef LITTLE_ENDIAN
X	bswap(key);			/* swap bytes round if little-endian */
X#endif
X
X#if	TRACE >= 1
X	fprintf(stderr,"  keyinit(%08lx, %08lx)\n", ((Long *)key)[0], ((Long *)key)[1]);
X#endif
X
X	KL = ((Long *)key)[0];
X	KR = ((Long *)key)[1];
X
X	for (i=0; i<ROUNDS; i+=4) {	/* Generate the 16 subkeys */
X	    loki_subkeys[i] = KL;
X	    ROL12 (KL);
X	    loki_subkeys[i+1] = KL;
X	    ROL13 (KL);
X	    loki_subkeys[i+2] = KR;
X	    ROL12 (KR);
X	    loki_subkeys[i+3] = KR;
X	    ROL13 (KR);
X	}
X
X#ifdef LITTLE_ENDIAN
X	bswap(key);			/* swap bytes back if little-endian */
X#endif
X}
X
X
X/*
X *	enloki(b) - main LOKI91 encryption routine, this routine encrypts one 
X *		64-bit block b using the LOKI91 algorithm with loki_subkeys
X *
X *		nb: The 64-bit block is passed as two longwords. For the
X *			purposes of the LOKI89 algorithm, the bits are numbered:
X *			    [63 62 .. 33 32] [31 30 ... 1 0]
X *			The L (left) half is b[0], the R (right) half is b[1]
X *
X */
X
Xvoid
Xenloki (b)
Xchar	b[LOKIBLK];
X{
X	register	i;
X	register Long	L, R;		/* left & right data halves  */
X
X#ifdef LITTLE_ENDIAN
X	bswap(b);			/* swap bytes round if little-endian */
X#endif
X
X#if	TRACE >= 1
X	fprintf(stderr,"  enloki(%08lx, %08lx)\n", ((Long *)b)[0], ((Long *)b)[1]);
X#endif
X
X	L = ((Long *)b)[0];
X	R = ((Long *)b)[1];
X
X	for (i=0; i<ROUNDS; i+=2) {	/* Encrypt with the 16 subkeys */
X	    L ^= f (R, loki_subkeys[i]);
X	    R ^= f (L, loki_subkeys[i+1]);
X	}
X
X	((Long *)b)[0] = R;		/* Y = swap(LR) */
X	((Long *)b)[1] = L;
X
X#if	TRACE >= 1
X	fprintf(stderr,"  enloki returns %08lx, %08lx\n", ((Long *)b)[0], ((Long *)b)[1]);
X#endif
X
X#ifdef LITTLE_ENDIAN
X	bswap(b);			/* swap bytes round if little-endian */
X#endif
X}
X
X
X/*
X *	deloki(b) - main LOKI91 decryption routine, this routine decrypts one 
X *		64-bit block b using the LOKI91 algorithm with loki_subkeys
X *
X *		Decryption uses the same algorithm as encryption, except that
X *		the subkeys are used in reverse order.
X */
Xvoid
Xdeloki(b)
Xchar	b[LOKIBLK];
X{
X	register	i;
X	register Long	L, R;			/* left & right data halves  */
X
X#ifdef LITTLE_ENDIAN
X	bswap(b);			/* swap bytes round if little-endian */
X#endif
X
X#if	TRACE >= 1
X	fprintf(stderr,"  deloki(%08lx, %08lx)\n", ((Long *)b)[0], ((Long *)b)[1]);
X#endif
X
X	L = ((Long *)b)[0];			/* LR = X XOR K */
X	R = ((Long *)b)[1];
X
X	for (i=ROUNDS; i>0; i-=2) {		/* subkeys in reverse order */
X	    L ^= f(R, loki_subkeys[i-1]);
X	    R ^= f(L, loki_subkeys[i-2]);
X	}
X
X	((Long *)b)[0] = R;			/* Y = LR XOR K */
X	((Long *)b)[1] = L;
X
X#if	TRACE >= 1
X	fprintf(stderr,"  deloki returns %08lx, %08lx\n", ((Long *)b)[0], ((Long *)b)[1]);
X#endif
X
X#ifdef LITTLE_ENDIAN
X	bswap(b);			/* swap bytes round if little-endian */
X#endif
X}
X
X
X/*
X *	f(r, k) - is the complex non-linear LOKI function, whose output
X *		is a complex function of both input data and sub-key.
X *
X *	The data is XORed with the subkey, then expanded into 4 x 12-bit
X *	values, which are fed into the S-boxes. The 4 x 8-bit outputs
X *	from the S-boxes are permuted together to form the 32-bit value
X *	which is returned.
X *
X *	In this implementation the outputs from the S-boxes have been
X *	pre-permuted and stored in lookup tables.
X */
X
X#define MASK12	0x0fff			/* 12 bit mask for expansion E */
X
Xstatic Long
Xf(r, k)
Xregister Long	r;	/* Data value R(i-1) */
XLong		k;	/* Key     K(i)   */
X{
X	Long	a, b, c;		/* 32 bit S-box output, & P output */
X
X	a = r ^ k;			/* A = R(i-1) XOR K(i) */
X
X	/* want to use slow speed/small size version */
X	b = ((Long)s((a         & MASK12))      ) | /* B = S(E(R(i-1))^K(i)) */
X	    ((Long)s(((a >>  8) & MASK12)) <<  8) |
X	    ((Long)s(((a >> 16) & MASK12)) << 16) |
X	    ((Long)s((((a >> 24) | (a << 8)) & MASK12)) << 24);
X
X	perm32(&c, &b, P);		/* C = P(S( E(R(i-1)) XOR K(i))) */
X
X#if	TRACE >= 2	/* If Tracing, dump A, K(i), and f(R(i-1),K(i)) */
X	fprintf(stderr,"  f(%08lx, %08lx) = P.S(%08lx) = P(%08lx) = %08lx\n",
X		r, k, a, b, c);
X#endif
X
X	return(c);			/* f returns the result C */
X}
X
X
X/*
X *	s(i) - return S-box value for input i
X */
Xstatic short s(i)
Xregister Long i;	/* return S-box value for input i */
X{
X	register short	r, c, v, t;
X	short	exp8();		/* exponentiation routine for GF(2^8) */
X	
X	r = ((i>>8) & 0xc) | (i & 0x3);		/* row value-top 2 & bottom 2 */
X	c = (i>>2) & 0xff;			/* column value-middle 8 bits */
X	t = (c + ((r * 17) ^ 0xff)) & 0xff;	/* base value for Sfn */
X	v = exp8(t, sfn[r].exp, sfn[r].gen);	/* Sfn[r] = t ^ exp mod gen */
X#if TRACE >= 3
X	fprintf(stderr, "   s(%lx=[%d,%d]) = %x sup %d mod %d = %x\n",
X			i, r, c, t, sfn[r].exp, sfn[r].gen, v);
X#endif
X	return(v);
X}
X
X/*
X *	perm32(out, in, perm) is the general permutation of a 32-bit input
X *		block to a 32-bit output block, under the control of a 
X *		permutation array perm. Each element of perm specifies which
X *		input bit is to be permuted to the output bit with the same
X *		index as the array element.
X *
X *	nb: to set bits in the output word, as mask with a single 1 in it is
X *		used. On each step, the 1 is shifted into the next location
X */
X
X#define	MSB	0x80000000L		/* MSB of 32-bit word */
X
Xperm32(out, in , perm)
XLong	*out;		/* Output 32-bit block to be permuted                */
XLong	*in;		/* Input  32-bit block after permutation             */
Xchar	perm[32]; 	/* Permutation array                                 */
X{
X	Long	mask = MSB;		/* mask used to set bit in output    */
X	register int	i, o, b;	/* input bit no, output bit no, value */
X	register char	*p = perm;	/* ptr to permutation array  */
X
X	*out = 0;			/* clear output block */
X	for (o=0; o<32; o++) {		/* For each output bit position o */	
X		i =(int)*p++;		/* get input bit permuted to output o */
X		b = (*in >> i) & 01;	/* value of input bit i */
X		if (b)			/* If the input bit i is set */
X			*out |= mask;		/*  OR in mask to output i */
X		mask >>= 1;			/* Shift mask to next bit    */
X	}
X}
X
X
X/*
X *	mult8(a, b, gen) - returns the product of two binary
X *		strings a and b using the generator gen as the modulus
X *			mult = a * b mod gen
X *		gen generates a suitable Galois field in GF(2^8)
X */
X
X#define SIZE 256		/* 256 elements in GF(2^8) */
X
Xshort mult8(a, b, gen)
Xshort	a, b;		/* operands for multiply */
Xshort	gen;		/* irreducible polynomial generating Galois Field */
X{
X	short	product = 0;		/* result of multiplication */
X
X	while(b != 0) {			/* while multiplier is non-zero */
X		if (b & 01)
X			product ^= a;	/*   add multiplicand if LSB of b set */
X		a <<= 1;		/*   shift multiplicand one place */
X		if (a >= SIZE)
X			a ^= gen;	/*   and modulo reduce if needed */
X		b >>= 1;		/*   shift multiplier one place  */
X	}
X	return(product);
X}
X
X/*
X *	exp8(base, exponent, gen) - returns the result of
X *		exponentiation given the base, exponent, generator of GF,
X *			exp = base ^ exp mod gen
X */
X
Xshort exp8(base, exponent, gen)
Xshort	base;		/* base of exponentiation 	*/
Xshort	exponent;	/* exponent			*/
Xshort	gen;		/* irreducible polynomial generating Galois Field */
X{
X	short	accum = base;	/* superincreasing sequence of base */
X	short	result = 1;	/* result of exponentiation	    */
X
X	if (base == 0)		/* if zero base specified then      */
X		return(0);	/* the result is "0" if base = 0    */
X
X	while (exponent != 0) {	/* repeat while exponent non-zero */
X		if (( exponent & 0x0001) == 0x0001)	/* multiply if exp 1 */
X			result = mult8(result, accum, gen);
X		exponent >>= 1;		/* shift exponent to next digit */
X		accum = mult8(accum, accum, gen);	/* & square  */
X	}
X	return(result);
X}
END-of-loki91.c
echo ", sum on loki91.c gives 25105 20"
echo x - lokibench.c
sed 's/^X//' >lokibench.c << 'END-of-lokibench.c'
X/*
X *	lokibench.c - run LOKI in a loop consuming CPU time for lokibenching
X *
X *	Usage:	lokibench [-e|-d] [-k key] [-w work_value]  num_iterations
X *		Flags:
X *		    -e		lokibench encryption (default)
X *		    -d		lokibench decryption
X *		    -k key	specifies key as 16 hex digits
X *		    -w work	specifies work value as 16 hex digits
X *
X *  Author:	Lawrence Brown <lpb@csadfa.oz>	Apr 1990
X *		Computer Science, UC UNSW, ADFA, Canberra, ACT 2600, Australia.
X *
X *		Based on PD program by Phil Karn, KA9Q <karn@flash.bellcore.com>
X *
X *  Copyright 1990 by Lawrence Brown and ITRACE. All rights reserved.
X *      This program may not be sold or used as inducement to buy a
X *      product without the written permission of the author.
X */
X#include "loki.h"
X#include <stdio.h>
X
Xchar	key[8]  = {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},	/* 64-bit key */
X	work[8] = {0,0,0,0,0,0,0,0};		/* 64-bit value to encrypt   */
Xchar	*Name;					/* Name of this program      */
Xchar	*usage = "lokibench [-e|-d] [-k key] [-w work_value]  num_iterations";
Xlong	count = 100;				/* number of iterations      */
Xint	encrypting = 1;				/* test encrypt fn flag      */
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	long	i;		/* loop counter                              */
X	int	errflag = 0;	/* Error detected in command line flags ?    */
X	int	c;		/* current flag found                        */
X	extern char	*optarg;	/* current getopt argument pointer   */
X	extern int	optind;	/* next arg in list after getopt     */
X	extern long	atol();
X
X	Name = argv[0];		/* save name of program for error messages   */
X				/* scan command line flags                   */
X
X	while ((c = getopt(argc, argv, "edk:w:")) != EOF) {
X		switch (c) {
X		  case 'e':	encrypting = 1;		break;
X		  case 'd':	encrypting = 0;		break;
X		  case 'k':	get8(key, optarg);	break;
X		  case 'w':	get8(work, optarg);	break;
X		  default:	errflag++;		break;
X		}
X	}
X	if (errflag) {		/* error in flags                            */
X		fprintf(stderr, "%s\n", usage);
X		exit(1);
X	}
X	if (optind < argc)
X		count = atol(argv[optind++]);	/* extract iteration count   */
X
X	printf("Setting key: "); put8(key); printf(", "); fflush(stdout);
X	setlokikey(key);	/* initialize LOKI key                        */
X
X	printf("%s ", (encrypting ? "encrypting" : "decrypting"));
X	put8(work); printf(" %ld times ... ",count); fflush(stdout);
X
X	if (encrypting)		/* perform required number of loops          */
X	    for(i = 0;i < count; i++)
X		enloki(work);
X	else
X	    for(i = 0;i < count; i++)
X	    	deloki(work);
X	printf("done\n");
X	exit(0);
X}
X
X
Xget8(cp, inp)
Xchar *cp, *inp;
X{
X	int i,t[8];
X
X	sscanf(inp, "%2x%2x%2x%2x%2x%2x%2x%2x",
X		&t[0],&t[1],&t[2],&t[3],&t[4],&t[5],&t[6],&t[7]);
X	for(i=0;i<8;i++){
X		*cp++ = t[i];
X	}
X}
X
Xput8(cp)
Xchar *cp;
X{
X	int i;
X
X	for(i=0;i<8;i++){
X		printf("%02X",*cp++ & 0xff);
X	}
X}
END-of-lokibench.c
echo ", sum on lokibench.c gives 13303 6"
echo x - lokicert.c
sed 's/^X//' >lokicert.c << 'END-of-lokicert.c'
X/*
X *	lokicert.c - invoke the LOKI library with data from a certification
X *		database, to validate its correct operation.
X *
X *  Author: Lawrence Brown <lpb@cs.adfa.oz.au>      Dec 1987
X *      Computer Science, UC UNSW, Australian Defence Force Academy,
X *          Canberra, ACT 2600, Australia.
X *
X *	Based on PD program by Phil Karn, KA9Q <karn@flash.bellcore.com>
X *
X *  Copyright 1989 by Lawrence Brown and UNSW. All rights reserved.
X *      This program may not be sold or used as inducement to buy a
X *      product without the written permission of the author.
X */
X
X
X#include "loki.h"
X#include <stdio.h>
X
X#ifndef lint
Xstatic char rcsid[]  = "$Header: lokicert.c,v 2.1 90/07/18 10:51:41 lpb Exp $";
X#endif
X
Xchar	*Name = "";		/* name this program was called by */
Xchar	*usage = "lokicert [testfile]";
XFILE	*filein = stdin;	/* input file to be processed                */
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	char	ikey[20], iplain[20], ianswer[20];
X	Long	key[2],plain[2],cipher[2],answer[2];
X	int	test = 0,			/* current test number*/
X		fail = 0,			/* failure indicator  */
X		failcnt = 0;			/* count of failures  */
X	char	buf[256];			/* input buffer, hex block */
X
X	/* parse input args if any */
X	Name = argv[0];
X	if (argc > 1) {			/* get input file name */
X        	if ((filein = fopen(argv[1], "r")) == NULL) {
X                	fprintf(stderr,"%s: unable to open input file %s\n",
X				Name, argv[1]);
X			perror(Name);
X			exit(1);
X		}
X	}
X
X	while ( fgets(buf, sizeof(buf), filein) != NULL) { /* read next line  */
X		if (buf[0] == '#')
X			continue;	/* skip comment lines                 */
X		test++;
X	    	sscanf(buf, "%s %s %s", ikey, iplain, ianswer);
X		get8(ikey, (char *)key);
X		get8(iplain, (char *)plain);
X		get8(ianswer, (char *)answer);
X
X		printf("Test %2d, ", test);
X		printf(" K: "); put8((char *)key);
X		printf(" P: "); put8((char *)plain);
X		printf(" C: "); put8((char *)answer);
X
X		setlokikey((char *)key);
X
X		cipher[0] = plain[0]; cipher[1] = plain[1];
X		enloki((char *)cipher);
X
X		fail = 0;
X		if ((cipher[0] != answer[0]) || (cipher[1] != answer[1])) {
X			printf("Encrypt failed, got: "); 
X			put8((char *)cipher);
X			fail++;
X		} 
X
X		deloki((char *)cipher);
X
X		if ((cipher[0] != plain[0]) || (cipher[1] != plain[1])) {
X			printf("Decrypt failed, got: "); 
X			put8((char *)cipher);
X			fail++;
X		}
X
X		if (!fail)
X			printf("OK");
X		else
X			failcnt++;
X		printf("\n");
X		fflush(stdout);
X	}
X	printf("lokicert: %d failures in %d tests\n", failcnt, test);
X	exit(failcnt);				/* exit with status set */
X}
X
Xget8(inp, cp)
Xchar *inp, *cp;
X{
X	int i,t[8];
X
X	sscanf(inp, "%2x%2x%2x%2x%2x%2x%2x%2x",
X		&t[0], &t[1], &t[2], &t[3], &t[4], &t[5], &t[6], &t[7]);
X	for(i=0;i<8;i++){
X		cp[i] = t[i];
X	}
X}
X
Xput8(cp)
Xchar *cp;
X{
X	int i;
X
X	for(i=0;i<8;i++){
X		printf("%02x",*cp++ & 0xff);
X	}
X	putchar(' ');
X}
END-of-lokicert.c
echo ", sum on lokicert.c gives 12914 6"
echo x - single89
sed 's/^X//' >single89 << 'END-of-single89'
X#	Single LOKI89 Certification triplet
X#		data is saved as (key, plaintext, ciphertext) triplets
X#
X5b5a57676a56676e 675a69675e5a6b5a 3c61fa7e2e99d048 
END-of-single89
echo ", sum on single89 gives 11819 1"
echo x - single91
sed 's/^X//' >single91 << 'END-of-single91'
X#	Single LOKI91 Certification triplet
X#		data is saved as (key, plaintext, ciphertext) triplets
X#
X3849674c2602319e 126898d55e911500 c86caec1e3b7b17e 
END-of-single91
echo ", sum on single91 gives 11689 1"
echo x - triples89
sed 's/^X//' >triples89 << 'END-of-triples89'
X#
X#       LOKI89 Validation Data Suite Triples
X#       data is saved as (key, plaintext, ciphertext) triplets
X#
X0000000000000000 0000000000000000 0000000000000000 
X0000000000000000 355550b2150e2451 8e2a251b94704c69 
X0000000000000000 35a7bae825c0d73b 8ca64de9c1b123a7 
X0000000000000000 8ca64de9c1b123a7 35a7bae825c0d73b 
X0000000000000000 8e2a251b94704c69 355550b2150e2451 
X0000000000000000 ffffffffffffffff 61f38c55061e3161 
X0101010101010101 0123456789abcdef f60b54c240d7ed14 
X0101010101010101 617b3a0ce8f07100 38ae088ae853f7fb 
X0101010101010101 9b38f6ce85aab9c3 617b3a0ce8f07100 
X0113b970fd34f2ce 059b5e0851cf143a 88c37b8c809c6dcd 
X0113b970fd34f2ce 7514cdb961b6760d 86a560f10ec6d85b 
X0113b970fd34f2ce 86a560f10ec6d85b 23e9b229fdea123f 
X0123456789abcdef 0000000000000000 d853533a6c1beb30 
X0123456789abcdef 1111111111111111 c4d29774e5d5247c 
X0123456789abcdef 17668dfc7292532d cc9feed345a9f7a1 
X0123456789abcdef 23c086665917b8e1 17668dfc7292532d 
X0123456789abcdef d5d44ff720683d0d 13d2967efa3aa3c2 
X0123456789abcdef fce30226576320bd d5d44ff720683d0d 
X0131d9619dc1376e 5cd54ca83def57da c251a566d109cfc2 
X0131d9619dc1376e 65e160aed7b773a9 7a389d10354bd271 
X0131d9619dc1376e 7a389d10354bd271 94c33356f2ee1adf 
X0170f175468fb5e6 0756d8e0774761d2 49a480651f03b452 
X0170f175468fb5e6 0cd3da020021dc09 afec86ec719000ad 
X0170f175468fb5e6 914c1806fccbce33 0cd3da020021dc09 
X018310dc409b26d6 1d9d5c5018f728c2 87bd17440173768b 
X018310dc409b26d6 5a0bf934fd6009f8 5f4c038ed12b2e41 
X018310dc409b26d6 5f4c038ed12b2e41 773740aa56ef058e 
X025816164629b007 480d39006ee762f2 719ebffea9a16c35 
X025816164629b007 a1f9915541020b56 16f949d4011073b5 
X025816164629b007 ec92e65da168b46f a1f9915541020b56 
X04689104c2fd3b2f 26955f6835af609a 8139b3c65393ea37 
X04689104c2fd3b2f 5265227fe08a28ec 5c513c9c4886c088 
X04689104c2fd3b2f 5c513c9c4886c088 bfd4c8c383533bdb 
X04b915ba43feb5b6 42fd443059577fa2 e7244bf3b0e5715d 
X04b915ba43feb5b6 a483ea7ccf2e0e5a af37fb421f8c4095 
X04b915ba43feb5b6 af37fb421f8c4095 762bd5f9b296f82e 
X07a1133e4a0b2686 0248d43806f67172 dd02c943fb4537a3 
X07a1133e4a0b2686 624f2e2dfa008142 868ebb51cab4599a 
X07a1133e4a0b2686 868ebb51cab4599a 235c5997034a503d 
X07a7137045da2a16 28e686668c3bd6d9 dfd64a815caf1a0f 
X07a7137045da2a16 3bdd119049372802 3de59f157f8b6bf9 
X07a7137045da2a16 dfd64a815caf1a0f 00b3f10e6f1063ed 
X1111111111111111 0123456789abcdef b0c9897c2765e214 
X1111111111111111 1111111111111111 f0a12c83c4529223 
X1111111111111111 24900548c21a3567 f40379ab9e0ec533 
X1111111111111111 8a5ae1f81ab8f2dd a273d7cb7d390531 
X1111111111111111 a273d7cb7d390531 8a5ae1f81ab8f2dd 
X1111111111111111 f40379ab9e0ec533 24900548c21a3567 
X1c587f1c13924fef 305532286d6f295a 8b62933a45dcf71f 
X1c587f1c13924fef 63fac0d034d9f793 b061dff8054771a8 
X1c587f1c13924fef f63de067f58c38ed 63fac0d034d9f793 
X1f08260d1ac2465e 2c0a241eb9f05999 ef1bf03e5dfa575a 
X1f08260d1ac2465e 6b056e18759f5cca c07261a9596039c3 
X1f08260d1ac2465e ef1bf03e5dfa575a b8705cc3a19ae567 
X1f1f1f1f0e0e0e0e 0123456789abcdef 16be5183d694e578 
X1f1f1f1f0e0e0e0e 322f206b2d39d65d db958605f8c8c606 
X1f1f1f1f0e0e0e0e db958605f8c8c606 1c37794afacf9e4e 
X3000000000000000 1000000000000001 85884d224ec9e63d 
X3000000000000000 958e6e627a05557b 389b4e8dc846c4aa 
X3000000000000000 d3c4539579b96231 958e6e627a05557b 
X37d06bb516cb7546 0a2aeeae3ff4ab77 45127fb1f43c5304 
X37d06bb516cb7546 164d5e404f275232 70f6cf2136677443 
X37d06bb516cb7546 19acae3136c0bc7c 0a2aeeae3ff4ab77 
X3849674c2602319e 126898d55e911500 7178876e01f19b2a 
X3849674c2602319e 51454b582ddf440a 57df30a9420a50ee 
X3849674c2602319e 7178876e01f19b2a 9ca72dbcd502b0ba 
X43297fad38e373fe 4c974f1caa59f5d4 ea676b2cb7db2b7a 
X43297fad38e373fe 762514b829bf486a 1d3eba477e45f553 
X43297fad38e373fe ea676b2cb7db2b7a 547018835947a9b3 
X49793ebc79b3258f 437540c8698f3cfa 7ce143bcd1108178 
X49793ebc79b3258f 6fbf1cafcffd0556 315e66ab98b26ded 
X49793ebc79b3258f a0cb2871752053f0 6fbf1cafcffd0556 
X49e95d6d4ca229bf 00b0024eaac70ae3 5a6b612cc26cce4a 
X49e95d6d4ca229bf 02fe55778117f12a 85028e1e6b858ec4 
X49e95d6d4ca229bf 5a6b612cc26cce4a 1b1789391a840fea 
X4fb05e1515ab73a7 072d43a077075292 cfeeb0bdeb67fef4 
X4fb05e1515ab73a7 2f22e49bab7ca1ac 237c628bb6892693 
X4fb05e1515ab73a7 ad87789bc00718c2 2f22e49bab7ca1ac 
X584023641aba6176 004bd6ef09176062 fcdebb14f3b2babb 
X584023641aba6176 88bf0db6d70dee56 d09730ee2f16f0d1 
X584023641aba6176 c7d2845ea6d01c70 88bf0db6d70dee56 
X5b5a57676a56676e 974affbf86022d1f 429941c32d5126e8 
X7ca110454a1a6e57 01a1d6d039776742 098c16c1e1f4a681 
X7ca110454a1a6e57 690f5b0d9a26939b c10935a58a249fbb 
X7ca110454a1a6e57 ecd1c2f929f33ced 690f5b0d9a26939b 
Xe0fee0fef1fef1fe 0123456789abcdef e29d11faf2d133ce 
Xe0fee0fef1fef1fe b7687facf9b1a656 edbfd1c66c29ccc7 
Xe0fee0fef1fef1fe edbfd1c66c29ccc7 c0f43c83cce0e0df 
Xfedcba9876543210 0123456789abcdef cfee5c8eb79153d9 
Xfedcba9876543210 2a2bb008df97c2f2 63f983b15c642726 
Xfedcba9876543210 7f46aa73f7fcde02 2a2bb008df97c2f2 
Xfedcba9876543210 c44c1b3668a0f2cf ed39d950fa74bcc4 
Xfedcba9876543210 ed39d950fa74bcc4 7420eb3d2a7aa178 
Xfedcba9876543210 ffffffffffffffff fce524b60ec5b3fc 
Xffffffffffffffff 0000000000000000 0000000000000000 
Xffffffffffffffff 16b15028f06a5ab8 caaaaf4deaf1dbae 
Xffffffffffffffff 3c7188775253884d 7359b2163e4edc58 
Xffffffffffffffff 7359b2163e4edc58 3c7188775253884d 
Xffffffffffffffff caaaaf4deaf1dbae 16b15028f06a5ab8 
Xffffffffffffffff ffffffffffffffff 61f38c55061e3161 
END-of-triples89
echo ", sum on triples89 gives 19790 11"
echo x - triples91
sed 's/^X//' >triples91 << 'END-of-triples91'
X#
X#       LOKI91 Validation Data Suite Triples
X#       data is saved as (key, plaintext, ciphertext) triplets
X#
X# List of weak and semi-weak keys
X#
X#  Weak Keys
X#
X0000000000000000 0000000000000000 bd84a2085ef609c7 
X0000000000000000 bd84a2085ef609c7 0000000000000000 
Xffffffffffffffff 0000000000000000 5c77e002d1991c4d 
Xffffffffffffffff 5c77e002d1991c4d 0000000000000000 
X55555555aaaaaaaa 0000000000000000 71fd6dc44bf4e881 
X55555555aaaaaaaa 71fd6dc44bf4e881 0000000000000000 
Xaaaaaaaa55555555 0000000000000000 65b38fdc551b2576 
Xaaaaaaaa55555555 65b38fdc551b2576 0000000000000000 
X#
X# Semi-Weak Keys
X#
X0000000055555555 0000000000000000 85d84cad08342044 
X0000000055555555 8621ccb894705f8f 0000000000000000 
Xaaaaaaaa00000000 0000000000000000 8621ccb894705f8f 
Xaaaaaaaa00000000 85d84cad08342044 0000000000000000 
X#
X00000000aaaaaaaa 0000000000000000 971fe23b8904399b 
X00000000aaaaaaaa e10c4efc9d4c9b52 0000000000000000 
X5555555500000000 0000000000000000 e10c4efc9d4c9b52 
X5555555500000000 971fe23b8904399b 0000000000000000 
X#
X00000000ffffffff 0000000000000000 ca30a526e3bf6fe9 
X00000000ffffffff 9cc24ace4d477f39 0000000000000000 
Xffffffff00000000 0000000000000000 9cc24ace4d477f39 
Xffffffff00000000 ca30a526e3bf6fe9 0000000000000000 
X#
X5555555555555555 0000000000000000 bc85de5e486d7ddb 
X5555555555555555 504d4c4fea439b63 0000000000000000 
Xaaaaaaaaaaaaaaaa 0000000000000000 504d4c4fea439b63 
Xaaaaaaaaaaaaaaaa bc85de5e486d7ddb 0000000000000000 
X#
X55555555ffffffff 0000000000000000 0bef28021cd23fcb 
X55555555ffffffff baa5521bd8ff9f75 0000000000000000 
Xffffffffaaaaaaaa 0000000000000000 baa5521bd8ff9f75 
Xffffffffaaaaaaaa 0bef28021cd23fcb 0000000000000000 
X#
Xaaaaaaaaffffffff 0000000000000000 a78c6f84509c4d9a 
Xaaaaaaaaffffffff 05dac4a04d83c0ab 0000000000000000 
Xffffffff55555555 0000000000000000 05dac4a04d83c0ab 
Xffffffff55555555 a78c6f84509c4d9a 0000000000000000 
X#
X# Inversion of all the key and plaintext bits results
X#  in the inversion of all the ciphertext bits
X#
X0123456789abcdef 0000000000000000 d26de3321aaa29f6 
X0123456789abcdef fcf597b7da5a3a3d 0000000000000000 
Xfedcba9876543210 ffffffffffffffff 2d921ccde555d609 
Xfedcba9876543210 030a684825a5c5c2 ffffffffffffffff 
X#
X# Other assorted values
X#
X0000000000000000 0000000000000000 bd84a2085ef609c7 
X0000000000000000 bd84a2085ef609c7 0000000000000000 
X0000000000000000 355550b2150e2451 3644dd20d5ba5d10 
X0000000000000000 3644dd20d5ba5d10 355550b2150e2451 
X0000000000000000 35a7bae825c0d73b 826ff28db7edf0a3 
X0000000000000000 826ff28db7edf0a3 35a7bae825c0d73b 
X0000000000000000 8ca64de9c1b123a7 fb3038a35a93646b 
X0000000000000000 fb3038a35a93646b 8ca64de9c1b123a7 
X0000000000000000 8e2a251b94704c69 4829a2faf34973e8 
X0000000000000000 4829a2faf34973e8 8e2a251b94704c69 
X0000000000000000 ffffffffffffffff a3881ffd2e66e3b2 
X0000000000000000 a3881ffd2e66e3b2 ffffffffffffffff 
X0101010101010101 0123456789abcdef 7935b683eada00f4 
X0101010101010101 ec5960c9d3bf1e1e 0123456789abcdef 
X0101010101010101 617b3a0ce8f07100 a6090c5f651d84ff 
X0101010101010101 8eeb7798a291b0b3 617b3a0ce8f07100 
X0101010101010101 9b38f6ce85aab9c3 2165fc9b5a4430d4 
X0101010101010101 2143badadbd4f539 9b38f6ce85aab9c3 
X0113b970fd34f2ce 059b5e0851cf143a f1f6daa4368d32c0 
X0113b970fd34f2ce 313b8c589bcf2955 059b5e0851cf143a 
X0113b970fd34f2ce 7514cdb961b6760d a2f3f0e425f6cd30 
X0113b970fd34f2ce 31b8050defd959ce 7514cdb961b6760d 
X0113b970fd34f2ce 86a560f10ec6d85b a27506525cf66e5c 
X0113b970fd34f2ce 6566f294daf82c26 86a560f10ec6d85b 
X0123456789abcdef 0000000000000000 d26de3321aaa29f6 
X0123456789abcdef fcf597b7da5a3a3d 0000000000000000 
X0123456789abcdef 1111111111111111 e1dd3b59134f32ab 
X0123456789abcdef c7c0ea4a6a9d3360 1111111111111111 
X0123456789abcdef 17668dfc7292532d 7aab3b9a42feceb2 
X0123456789abcdef 0a9462fa8fee7f4a 17668dfc7292532d 
X0123456789abcdef 23c086665917b8e1 9fbc1a193dcee02d 
X0123456789abcdef 1cb728f0c1b26f75 23c086665917b8e1 
X0123456789abcdef d5d44ff720683d0d 621f20a1884677f3 
X0123456789abcdef c8c9a1ace8cf89dc d5d44ff720683d0d 
X0123456789abcdef fce30226576320bd 5da683da7e9fd159 
X0123456789abcdef 5edf1c8466ce6cca fce30226576320bd 
X0131d9619dc1376e 5cd54ca83def57da 018781deb9ea97cc 
X0131d9619dc1376e bd1084a4b6d1ab38 5cd54ca83def57da 
X0131d9619dc1376e 65e160aed7b773a9 57e3c651e72c6d99 
X0131d9619dc1376e aeab88168e9c0e3e 65e160aed7b773a9 
X0131d9619dc1376e 7a389d10354bd271 5520951007ac3123 
X0131d9619dc1376e 78eaddbfcb1ca8f2 7a389d10354bd271 
X0170f175468fb5e6 0756d8e0774761d2 ab786040f925d13e 
X0170f175468fb5e6 b7c1284ca7043dcb 0756d8e0774761d2 
X0170f175468fb5e6 0cd3da020021dc09 77ce52c63517b689 
X0170f175468fb5e6 802191063dd8ff06 0cd3da020021dc09 
X0170f175468fb5e6 914c1806fccbce33 dd546f5263780633 
X0170f175468fb5e6 5356fadab9832b2c 914c1806fccbce33 
X018310dc409b26d6 1d9d5c5018f728c2 80d1106e854f7296 
X018310dc409b26d6 0eb06d867b7034b3 1d9d5c5018f728c2 
X018310dc409b26d6 5a0bf934fd6009f8 f67c664125809846 
X018310dc409b26d6 9c1edf390e47f09a 5a0bf934fd6009f8 
X018310dc409b26d6 5f4c038ed12b2e41 20a61c3bc186b0b2 
X018310dc409b26d6 e93ae52452b20098 5f4c038ed12b2e41 
X025816164629b007 480d39006ee762f2 8197cc96e066f971 
X025816164629b007 8e67efe514fa5985 480d39006ee762f2 
X025816164629b007 a1f9915541020b56 0e1b15aa45daad23 
X025816164629b007 7b1bd88c59347ee4 a1f9915541020b56 
X025816164629b007 ec92e65da168b46f fd5d36553cc7cdad 
X025816164629b007 10f09ce8ec84f207 ec92e65da168b46f 
X04689104c2fd3b2f 26955f6835af609a 082133fd6bfa1e88 
X04689104c2fd3b2f 36153da8e8e4a67a 26955f6835af609a 
X04689104c2fd3b2f 5265227fe08a28ec 1b03084901b20c14 
X04689104c2fd3b2f f2e7e1a4678d10a7 5265227fe08a28ec 
X04689104c2fd3b2f 5c513c9c4886c088 db8e496a8aa4eae8 
X04689104c2fd3b2f 49a2827db6293c72 5c513c9c4886c088 
X04b915ba43feb5b6 42fd443059577fa2 b794c8fec41d93fd 
X04b915ba43feb5b6 688762c5782c8d46 42fd443059577fa2 
X04b915ba43feb5b6 a483ea7ccf2e0e5a 1319804d5e6477fb 
X04b915ba43feb5b6 a4407673e0289704 a483ea7ccf2e0e5a 
X04b915ba43feb5b6 af37fb421f8c4095 5e1fbeca6d3dd240 
X04b915ba43feb5b6 76f8a9d3d646b45a af37fb421f8c4095 
X07a1133e4a0b2686 0248d43806f67172 bdc50f07265f98bb 
X07a1133e4a0b2686 5352ea74d4f98d17 0248d43806f67172 
X07a1133e4a0b2686 624f2e2dfa008142 43966fba71697d9e 
X07a1133e4a0b2686 94e8f64562868d44 624f2e2dfa008142 
X07a1133e4a0b2686 868ebb51cab4599a 2bc4d7ac9f09e2cf 
X07a1133e4a0b2686 38df7d98c5841cb1 868ebb51cab4599a 
X07a7137045da2a16 28e686668c3bd6d9 5ddb3c7fc1c8ce22 
X07a7137045da2a16 a725d943d567693c 28e686668c3bd6d9 
X07a7137045da2a16 3bdd119049372802 3f0db5539d36d6ff 
X07a7137045da2a16 e617587ef5ec4992 3bdd119049372802 
X07a7137045da2a16 dfd64a815caf1a0f a4af3b0773dad9be 
X07a7137045da2a16 3000a06acca1e95c dfd64a815caf1a0f 
X1111111111111111 0123456789abcdef 75f0c8bc2bafd309 
X1111111111111111 46b19d48d8569e55 0123456789abcdef 
X1111111111111111 1111111111111111 cc8a79bccae0bb7e 
X1111111111111111 d96e387165e701bc 1111111111111111 
X1111111111111111 24900548c21a3567 93f5dbd7f154b9ba 
X1111111111111111 66b41b7d36c436de 24900548c21a3567 
X1111111111111111 8a5ae1f81ab8f2dd 20f677bebabe1775 
X1111111111111111 d96faf34f9f90454 8a5ae1f81ab8f2dd 
X1111111111111111 a273d7cb7d390531 70ab8b1bc85a3535 
X1111111111111111 44260ee8c8eeb426 a273d7cb7d390531 
X1111111111111111 f40379ab9e0ec533 06f8080ae1393c2f 
X1111111111111111 9ae34de86300215f f40379ab9e0ec533 
X1c587f1c13924fef 305532286d6f295a 2fc181b0cb6b30b7 
X1c587f1c13924fef e9eef1eb68e8c676 305532286d6f295a 
X1c587f1c13924fef 63fac0d034d9f793 e3f0d7afe60812b2 
X1c587f1c13924fef 7409d13ab01f25f6 63fac0d034d9f793 
X1c587f1c13924fef f63de067f58c38ed 3f4913280d2793fc 
X1c587f1c13924fef 0109eccd8a9c40dd f63de067f58c38ed 
X1f08260d1ac2465e 2c0a241eb9f05999 e86f92ac2ec186f3 
X1f08260d1ac2465e 2dbafaaf1eb7b072 2c0a241eb9f05999 
X1f08260d1ac2465e 6b056e18759f5cca 02dd8970249255f1 
X1f08260d1ac2465e 377f235592b45ca9 6b056e18759f5cca 
X1f08260d1ac2465e ef1bf03e5dfa575a 98e1e5771c4a9455 
X1f08260d1ac2465e f489970bb6e8a94e ef1bf03e5dfa575a 
X1f1f1f1f0e0e0e0e 0123456789abcdef 1998d96b0bb0add6 
X1f1f1f1f0e0e0e0e 7454d8d7c56be016 0123456789abcdef 
X1f1f1f1f0e0e0e0e 322f206b2d39d65d 0b636eb981e987c0 
X1f1f1f1f0e0e0e0e 0b926c6049361bff 322f206b2d39d65d 
X1f1f1f1f0e0e0e0e db958605f8c8c606 5a153aea62bdd0cb 
X1f1f1f1f0e0e0e0e 2c7bf241aa0b2c97 db958605f8c8c606 
X3000000000000000 1000000000000001 12f2d0471de69a16 
X3000000000000000 b0ef21ad8b82dd0a 1000000000000001 
X3000000000000000 958e6e627a05557b 4be1b16ef2c9524a 
X3000000000000000 437b3ac6a2a027c8 958e6e627a05557b 
X3000000000000000 d3c4539579b96231 bbfcaf9cc8cd9e46 
X3000000000000000 7b8b6b2e19e13c69 d3c4539579b96231 
X37d06bb516cb7546 0a2aeeae3ff4ab77 32a65f25341d17f0 
X37d06bb516cb7546 90d6dcee0f2f8d62 0a2aeeae3ff4ab77 
X37d06bb516cb7546 164d5e404f275232 782a69ec6256c642 
X37d06bb516cb7546 1dabf24c62f0fd89 164d5e404f275232 
X37d06bb516cb7546 19acae3136c0bc7c 9cd87a6a8ea4c562 
X37d06bb516cb7546 f8bf4d34438681a2 19acae3136c0bc7c 
X3849674c2602319e 126898d55e911500 c86caec1e3b7b17e 
X3849674c2602319e d8d28161851ed6d6 126898d55e911500 
X3849674c2602319e 51454b582ddf440a 8904c12a608bac74 
X3849674c2602319e 562de7a88b1f4877 51454b582ddf440a 
X3849674c2602319e 7178876e01f19b2a ba940cd1789e92fd 
X3849674c2602319e 295ece9867b10e95 7178876e01f19b2a 
X43297fad38e373fe 4c974f1caa59f5d4 71a64728851d6e14 
X43297fad38e373fe f386803c5a434216 4c974f1caa59f5d4 
X43297fad38e373fe 762514b829bf486a 6684fb847e1283c0 
X43297fad38e373fe bf8e6fbf6c48ec44 762514b829bf486a 
X43297fad38e373fe ea676b2cb7db2b7a 5a2d250d39eb8fc1 
X43297fad38e373fe 6d42d3b3b5a9abcc ea676b2cb7db2b7a 
X49793ebc79b3258f 437540c8698f3cfa 0b46e6cd65118775 
X49793ebc79b3258f b9d425d544c1ce71 437540c8698f3cfa 
X49793ebc79b3258f 6fbf1cafcffd0556 50bfa6e233cef0af 
X49793ebc79b3258f 000c45276715001d 6fbf1cafcffd0556 
X49793ebc79b3258f a0cb2871752053f0 af27090a887c7e3e 
X49793ebc79b3258f 51fc08afec3c8f1a a0cb2871752053f0 
X49e95d6d4ca229bf 00b0024eaac70ae3 6f2421dc83df9ba2 
X49e95d6d4ca229bf 82537ce99e3476de 00b0024eaac70ae3 
X49e95d6d4ca229bf 02fe55778117f12a bd6bb416626be321 
X49e95d6d4ca229bf 417b8cdd1c64b3e7 02fe55778117f12a 
X49e95d6d4ca229bf 5a6b612cc26cce4a 73cb63595026b590 
X49e95d6d4ca229bf a90f566d8f4e3e41 5a6b612cc26cce4a 
X4fb05e1515ab73a7 072d43a077075292 ac6174b535bcad69 
X4fb05e1515ab73a7 2d139d3801a19346 072d43a077075292 
X4fb05e1515ab73a7 2f22e49bab7ca1ac 86019dd993c46cbe 
X4fb05e1515ab73a7 44fef33e6971a69b 2f22e49bab7ca1ac 
X4fb05e1515ab73a7 ad87789bc00718c2 733b12f600953a98 
X4fb05e1515ab73a7 8341990d8ba44544 ad87789bc00718c2 
X584023641aba6176 004bd6ef09176062 6ceca0e2d5351cd1 
X584023641aba6176 9c6aedffd92b1cca 004bd6ef09176062 
X584023641aba6176 88bf0db6d70dee56 b3a4719eca678ecc 
X584023641aba6176 bb39bb8bdf9db594 88bf0db6d70dee56 
X584023641aba6176 c7d2845ea6d01c70 2932e00da18db422 
X584023641aba6176 2217a63228e547c1 c7d2845ea6d01c70 
X5b5a57676a56676e 974affbf86022d1f 6b6413098aaa7f2b 
X5b5a57676a56676e daabfab98dea5e78 974affbf86022d1f 
X7ca110454a1a6e57 01a1d6d039776742 0200c0b643578183 
X7ca110454a1a6e57 1405433e91265b1b 01a1d6d039776742 
X7ca110454a1a6e57 690f5b0d9a26939b d6173b3a2f754508 
X7ca110454a1a6e57 9f7c523c7bfe7586 690f5b0d9a26939b 
X7ca110454a1a6e57 ecd1c2f929f33ced a5d38784ef7973ee 
X7ca110454a1a6e57 c6642999c37b99b3 ecd1c2f929f33ced 
Xe0fee0fef1fef1fe 0123456789abcdef e09ca157c6dfe236 
Xe0fee0fef1fef1fe 20bc4d004e45c048 0123456789abcdef 
Xe0fee0fef1fef1fe b7687facf9b1a656 eb2c523be4dedd8a 
Xe0fee0fef1fef1fe c21c42ef608f5ae6 b7687facf9b1a656 
Xe0fee0fef1fef1fe edbfd1c66c29ccc7 d7a84a5234f98995 
Xe0fee0fef1fef1fe cb3f0e23d4ad3760 edbfd1c66c29ccc7 
Xfedcba9876543210 0123456789abcdef 480f0eac8d4c6cbc 
Xfedcba9876543210 25d00012f501adaf 0123456789abcdef 
Xfedcba9876543210 2a2bb008df97c2f2 9de0df5e77b9880c 
Xfedcba9876543210 37365e5317307623 2a2bb008df97c2f2 
Xfedcba9876543210 7f46aa73f7fcde02 f6b3c639d4588687 
Xfedcba9876543210 286334c90fc54d99 7f46aa73f7fcde02 
Xfedcba9876543210 c44c1b3668a0f2cf f1fbe0db72af2072 
Xfedcba9876543210 4da710ea766dddb4 c44c1b3668a0f2cf 
Xfedcba9876543210 ed39d950fa74bcc4 1529a5409e492728 
Xfedcba9876543210 ba2fcbdf566d6b40 ed39d950fa74bcc4 
Xfedcba9876543210 ffffffffffffffff 2d921ccde555d609 
Xfedcba9876543210 030a684825a5c5c2 ffffffffffffffff 
Xffffffffffffffff 0000000000000000 5c77e002d1991c4d 
Xffffffffffffffff 5c77e002d1991c4d 0000000000000000 
Xffffffffffffffff 16b15028f06a5ab8 c594d15528f44560 
Xffffffffffffffff c594d15528f44560 16b15028f06a5ab8 
Xffffffffffffffff 3c7188775253884d ac490aef39a87b61 
Xffffffffffffffff ac490aef39a87b61 3c7188775253884d 
Xffffffffffffffff 7359b2163e4edc58 04cfc75ca56c9b94 
Xffffffffffffffff 04cfc75ca56c9b94 7359b2163e4edc58 
Xffffffffffffffff caaaaf4deaf1dbae c9bb22df2a45a2ef 
Xffffffffffffffff c9bb22df2a45a2ef caaaaf4deaf1dbae 
Xffffffffffffffff ffffffffffffffff 427b5df7a109f638 
Xffffffffffffffff 427b5df7a109f638 ffffffffffffffff 
END-of-triples91
echo ", sum on triples91 gives 36876 25"
exit

