. 1
( 8)



>>

Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page




Source Code .............................................. 623
PART V ..................................................... 623
DES ........................................................ 623
LOKI91 ................................................... 623
IDEA ..................................................... 637
GOST ..................................................... 643
BLOWFISH ............................................. 647
3-Way ..................................................... 654
RC5 ........................................................ 659
A5 ........................................................... 662
SEAL ...................................................... 667
References ................................................. 675
Index ........................................................... 743
Information Security.................................. 758
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page




Afterword
by Matt Blaze
One of the most dangerous aspects of cryptology (and, by extension, of this book), is
that you can almost measure it. Knowledge of key lengths, factoring methods, and
cryptanalytic techniques makes it possible to estimate (in the absence of a real the-
ory of cipher design) the “work factor” required to break a particular cipher. It™s all
too tempting to misuse these estimates as if they were overall security metrics for
the systems in which they are used. The real world offers the attacker a richer menu
of options than mere cryptanalysis. Often more worrisome are protocol attacks,
Trojan horses, viruses, electromagnetic monitoring, physical compromise, black-
mail and intimidation of key holders, operating system bugs, application program
bugs, hardware bugs, user errors, physical eavesdropping, social engineering, and
dumpster diving, to name just a few.
High-quality ciphers and protocols are important tools, but by themselves make
poor substitutes for realistic, critical thinking about what is actually being pro-
tected and how various defenses might fail (attackers, after all, rarely restrict them-
selves to the clean, well-defined threat models of the academic world). Ross
Anderson gives examples of cryptographically strong systems (in the banking indus-
try) that fail when exposed to the threats of the real world [43,44]. Even when the
attacker has access only to ciphertext, seemingly minor breaches in other parts of
the system can leak enough information to render good cryptosystems useless. The
Allies in World War II broke the German Enigma traffic largely by carefully exploit-
ing operator errors [1587].
An NSA-employed acquaintance, when asked whether the government can crack
DES traffic, quipped that real systems are so insecure that they never need to bother.
Unfortunately, there are no easy recipes for making a system secure, no substitute
for careful design and critical, ongoing scrutiny. Good cryptosystems have the nice
property of making life much harder for the attacker than for the legitimate user;
this is not the case for almost every other aspect of computer and communication




Page 619
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page
Afterword


security. Consider the following (quite incomplete) “Top Ten Threats to Security in
Real Systems” list; all are easier to exploit than to prevent.

1. The sorry state of software. Everyone knows that nobody knows how to
write software. Modern systems are complex, with hundreds of thousands
of lines of code; any one of them has the chance to compromise security.
Fatal bugs may even be far-removed from the security portion of the soft-
ware.
2. Ineffective protection against denial-of-service attacks. Some crypto-
graphic protocols allow anonymity. It may be especially dangerous to
deploy anonymous protocols if they increase the opportunities for uniden-
tified vandals to disrupt service; anonymous systems therefore need to be
especially resistant to denial-of-service attacks. Robust networks can more
easily support anonymity; consider that hardly anyone worries very much
about the millions of anonymous entry points to more robust networks
like the telephone system or the postal service, where it™s relatively diffi-
cult (or expensive) for an individual to cause large-scale failures.
3. No place to store secrets. Cryptosystems protect large secrets with smaller
ones (keys). Unfortunately, modern computers aren™t especially good at pro-
tecting even the smallest secrets. Multi-user networked workstations can
be broken into and their memories compromised. Standalone, single-user
machines can be stolen or compromised through viruses that leak secrets
asynchronously. Remote servers, where there may be no user available to
enter a passphrase (but see threat #5), are an especially hard problem.
4. Poor random-number generation. Keys and session variables need good
sources of unpredictable bits. A running computer has a lot of entropy in it
but rarely provides applications with a convenient or reliable way to
exploit it. A number of techniques have been proposed for getting true ran-
dom numbers in software (taking advantage of unpredictability in things
like I/O interarrival timing, clock and timer skew, and even air turbulence
inside disk enclosures), but all these are very sensitive to slight changes in
the environments in which they are used.
5. Weak passphrases. Most cryptographic software addresses the key storage
and key generation problems by relying on user-generated passphrase
strings, which are presumed to be unpredictable enough to produce good
key material and are also easy enough to remember that they do not
require secure storage. While dictionary attacks are a well-known problem
with short passwords, much less is known about lines of attack against
user-selected passphrase-based keys. Shannon tells us that English text has
only just over 1 bit of entropy per character, which would seem to leave
most passphrases well within reach of brute-force search. Less is known,
however, about good techniques for enumerating passphrases in order to
exploit this. Until we have a better understanding of how to attack
passphrases, we really have no idea how weak or strong they are.




Page 620
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page




6. Mismatched trust. Almost all currently available cryptographic software
assumes that the user is in direct control over the systems on which it runs
and has a secure path to it. For example, the interfaces to programs like
PGP assume that their passphrase input always comes from the user over
a secure path like the local console. This is not always the case, of course;
consider the problem of reading your encrypted mail when logged in over a
network connection. What the system designer assumes is trusted may not
match the needs or expectations of the real users, especially when software
can be controlled remotely over insecure networks.
7. Poorly understood protocol and service interactions. As systems get bigger
and more complex, benign features frequently come back to haunt us, and
it™s hard to know even where to look when things fail. The Internet worm
was propagated via an obscure and innocent-looking feature in the send-
mail program; how many more features in how many more programs have
unexpected consequences just waiting to be discovered?
8. Unrealistic threat and risks assessment. Security experts tend to focus on
the threats they know how to model and prevent. Unfortunately, attackers
focus on what they know how to exploit, and the two are rarely exactly the
same. Too many “secure” systems are designed without considering what
the attacker is actually likely to do.
9. Interfaces that make security expensive and special. If security features are
to be used, they must be convenient and transparent enough that people
actually turn them on. It™s easy to design encryption mechanisms that
come only at the expense of performance or ease of use, and even easier to
design mechanisms that invite mistakes. Security should be harder to turn
off than on; unfortunately, few systems actually work this way.
10. Little broad-based demand for security. This is a well-known problem
among almost everyone who has tied his or her fortune to selling security
products and services. Until there is widespread demand for transparent
security, the tools and infrastructure needed to support it will be expensive
and inaccessible to many applications. This is partly a problem of under-
standing and exposing the threats and risks in real applications and partly
a problem of not designing systems that include security as a basic feature
rather than as a later add-on.

A more complete list and discussion of these kinds of threats could easily fill a
book of this size and barely scratch the surface. What makes them especially diffi-
cult and dangerous is that there are no magic techniques, beyond good engineering
and ongoing scrutiny, for avoiding them. The lesson for the aspiring cryptographer
is to respect the limits of the art.

Matt Blaze
New York, NY




Page 621
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page




PARTV




1. DES
2. LOKI91
3. IDEA
4. GOST
5. BLOWFISH
6. 3-Way
7. RC5
8. A5
9. SEAL


DES
/* MODE == encrypt */
#define EN0 0
I* MODE == decrypt *I
#define DE1 1

typedef struct 1
unsigned long ekL321;
unsigned long dk[321;
I des-ctx;

extern void deskeycunsigned char *, short);
hexkeyC81 MODE
/*
* Sets the internal key register according to the hexadecimal
* key contained in the 8 bytes of hexkey, according to the DES,
* for encryption or decryption according to MODE.
"I

extern void usekeycunsigned long *);
cookedkeyL321
/*




Page 622
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page
Source Code


* Loads the internal key register with the data in cookedkey.
*/

extern void cpkeycunsigned long "1;
/* cookedkey[321
* Copies the contents of the internal key register into the storage
* located at &cookedkey[Ol.
*I

extern void descunsigned char *, unsigned char *);
toL81
/* from[El
* Encrypts/Decrypts (according to the key currently loaded in the
* internal key register) one block of eight bytes at address 'from'
* into the block at address 'to'. They can be the same.
*/

static void scrunchcunsigned char *, unsigned long *);
static void unscrun(unsigned long *, unsigned char *I;
static void desfunccunsigned long *, unsigned long *);
static void cookey(unsigned long *);

static unsigned long KnL[321 = 1 OL 1;
static unsigned long KnR1321 = I OL 1;
static unsigned long Kn3[321 = 1 OL 1;
static unsigned char Df_Key[241 =1
0x01,0x23,0x45,0x67,Ox89,0xab,Oxcd,Oxef,
Oxfe,Oxdc,Oxba,0x98,Ox76,Ox54,Ox32,OxlO,
0x89,0xab,Oxcd,Oxef,OxOl,Ox23,Ox45,Ox67 I;

static unsigned short bytebit[El =1
0200, 0100, 040, 020, 010, 04, 02, 01 I;

static unsigned long bigbyteC241 = 1
OX˜OOOOOL, 0x400000L, 0x200000L, 0x100000L,
OxEOOOOL, 0x40000L, 0x20000L, 0x10000L,
OxEOOOL, 0x4000L, 0x1000L,
0x2000L,
OxEOOL, Ox4OOL, Ox2OOL, OxlOOL,
OxEOL, Ox4OL, Ox2OL, OxlOL,
OxEL, Ox4L, Ox2L, OxlL 1;

X3.92-1981). */
/* Use the key schedule specified in the Standard (ANSI

static unsigned char pc1[561 =1
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 I;
static unsigned char totrotC161 =1
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 I;

static unsigned char pc2[481 =1
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
22, 18, 15, 6, 26, 19, 12, 1,
11, 3, 25, 7,
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 1;




Page 623
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page




/* Thanks to James Gillogly & Phil Karn! */
void deskeyckey, edf)
unsigned char *key;
short edf;
1
register int i, j, 1, m, n;
unsigned char pclmL561, pcr[%l;
unsigned long kn[321;

for ( j = 0; j < 56; j++ ) (
1 = pcl[jl;
m = 1 & 07;
pclm[jl = (key[l >> 31 & bytebitCm1) ? 1 : 0;

for( i = 0; i < 16; i++ 1 I
if( edf == DE1 ) m = (15 i << 1;
else m = i << 1;
n=m+l;
kn[ml = kn[nl = OL;
for( j = 0; j < 28; j++ ) 1
1 = j + totrot[il;
if( 1 < 28 ) pcr[jl = pclm[ll;
else pcr[jl = pclm[l 281;

for( j = 28; j < 56; j++ 1 1
1 = j + totrot[il;
if( 1 < 56 1 pCr[jl = Pclm[ll;
else pcr[jl = pclmC1 281;

for( j = 0; j < 24; j++ ) 1
if( pcr[pc2[jll ) kn[ml I= bigbyte[jl;
if( pcr[pc2[j+2411 ) kn[nl I= bigbyte[jl;

I
cookey(
return;
I

static void cookey(raw1)
register unsigned long *rawl;
1
register unsigned long *cook, *rawO;
unsigned long dough[321;
register int i;

cook = dough;
for-( i = 0; i < 16; i++, rawl++ )1
raw0 = rawl++;
= (*raw0 & OxOOfcOOOOL) << 6;
*cook
*cook I= (*raw0 & OxOOOOOfcOL) << 10;
( *raw1 & OxOOfcOOOOL) >> 10;
:˜˜˜˜++I=
I= (*raw1 & OxOOOOOfcOL) >> 6;
*cook = (*raw0 & Ox0003fOOOL) << 12;
I= (*raw0 & Ox0000003fL) << 16;
*cook
*raw1 & Ox0003fOOOL) >> 4;
/= (*raw1 & Ox0000003fL);




Page 624
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page
Source Code


I
usekey(dough);
return;


void cpkey(into)
register unsigned long *into;
i
register unsigned long *from, *endp;

from = KnL, endp = &KnLC321;
while( from < endp 1 *into++ = *from++;
return;


void usekey(from)
register unsigned long *from;

register unsigned long *to, *endp;

to = KnL, endp = &KnL[321;
whiled to < endp 1 *to++ = *from++;
return;


void descinblock, outblock)
unsigned char *inblock, *outblock;
t
unsigned long workC21;

scrunch(inblock, work);
desfunc(work, KnL);
unscrun(work, outblock);
return;


static void scrunch(outof, into)
register unsigned char *outof;
register unsigned long *into;

= (*outof++ & OxffL) << 24;
*into
*into I= (*outof++ & OxffL) << 16;
*into I= (*outof++ & OxffL) << 8;
*into++ I= (*outof++ & OxffL);
= (*outof++ & OxffL) << 24;
*into
*into I= (*outof++ & OxffL) << 16;
*into I= (*outof++ & OxffL) << 8;
*into (= ("outof & OxffL);
return;


static void unscrun(outof, into)
register unsigned long *outof;
register unsigned char *into;
I




Page 625
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page




*into++ = (*outof >> 24) & OxffL;
*into++ = (*outof >> 16) & OxffL;
*into++ = (*outof >> 8) & OxffL;
*into++ = & OxffL;
*OUtOf++
*into++ = (*outof >> 24) & OxffL;
*into++ = (*outof >> 16) & OxffL;
*into++ = (*outof >> 8) & OxffL;
& OxffL;
*into = *OUtOf
return;


static unsigned long SP11641 = {
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L I;

static unsigned long SP2[641 = {
Ox8010802OL, Ox8OOO8OOOL, OxOOOO8OOOL, 0x00108020L,
OxOO1OOOOOL, OxOOOOOO2OL, 0x80100020L, Ox8000802OL,
Ox8OOOOO2OL, Ox8010802OL, 0x80108000L, Ox8OOOOOOOL,
Ox8OOO8OOOL, OxOO1OOOOOL, OxOOOOOO2OL, 0x80100020L,
OxOO1O8OOOL, OxOO1OOO2OL, Ox8000802OL, OxOOOOOOOOL,
Ox8OOOOOOOL, OxOOOO8OOOL, 0x00108020L, Ox8O1OOOOOL,
OxOO1OOO2OL, Ox8OOOOO2OL, OxOOOOOOOOL, OxOO1O8OOOL,
OxOOOO8O2OL, 0x80108000L, Ox8O1OOOOOL, OxOOOO8O2OL,
OxOOOOOOOOL, 0x00108020L, 0x80100020L, OxOO1OOOOOL,
Ox8000802OL, Ox8O1OOOOOL, 0x80108000L, OxOOOO8OOOL,
Ox8O1OOOOOL, Ox8OOO8OOOL, OxOOOOOO2OL, Ox8010802OL,
0x00108020L, OxOOOOOO2OL, OxOOOO8OOOL, Ox8OOOOOOOL,
OxOOOO8O2OL, 0x80108000L, OxOO1OOOOOL, Ox8OOOOO2OL,
OxOO1OOO2OL, Ox8000802OL, Ox8OOOOO2OL, OxOO1OOO2OL,
OxOO1O8OOOL, OxOOOOOOOOL, Ox8OOO8OOOL, OxOOOO8O2OL,
Ox8OOOOOOOL, 0x80100020L, Ox8010802OL, OxOO1O8OOOL 1;

static unsigned long SP3[641 = {
OxOOOOO2O8L, OxO80202OOL, OxOOOOOOOOL, OxO8020008L,
OxO8OOO2OOL, OxOOOOOOOOL, OxOOO20208L, OxO8OOO2OOL,
OxOOO2OOO8L, OxO8OOOOO8L, OxO8OOOOO8L, OxOOO2OOOOL,
OxO8020208L, OxOOO2OOO8L, OxO8O2OOOOL, OxOOOOO2O8L,
OxO8OOOOOOL, OxOOOOOOO8L, OxO80202OOL, OxOOOOO2OOL,
OxOOO2O2OOL, OxO8O2OOOOL, OxO8020008L, OxOOO20208L,




Page 626
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page
Source Code


OxO8000208L, OxOOO2O2OOL, OxOOO2OOOOL, OxO8000208L,
OxOOOOOOO8L, OxO8020208L, OxOOOOO2OOL, OxO8OOOOOOL,
OxO80202OOL, OxO8OOOOOOL, OxOOO2OOO8L, OxOOOOO2O8L,
OxOOO2OOOOL, OxO80202OOL, OxO8OOO2OOL, OxOOOOOOOOL,
OxOOOOO2OOL, OxOOO2OOO8L, OxO8020208L, OxO8OOO2OOL,
OxO8OOOOO8L, OxOOOOO2OOL, OxOOOOOOOOL, OxO8020008L,
OxO8000208L, OxOOO2OOOOL, OxO8OOOOOOL, OxO8020208L,
OxOOOOOOO8L, OxOOO20208L, OxOOO2O2OOL, OxO8OOOOO8L,
OxO8O2OOOOL, OxO8000208L, OxOOOOO2O8L, OxO8O2OOOOL,
OxOOO20208L, OxOOOOOOO8L, OxO8020008L, OxOOO2O2OOL I;

static unsigned long SP4[641 = I
0x00802001L, OxOOOO2O81L, OxOOOO2O81L, OxOOOOOO8OL,
OxOO80208OL, OxOO8OOO81L, OxOO8OOOO1L, OxOOOO2OO1L,
OxOOOOOOOOL, OxOO8O2OOOL, OxOO8O2OOOL, OxOO802081L,
OxOOOOOO81L, OxOOOOOOOOL, OxOO8OOO8OL, OxOO8OOOO1L,
OxOOOOOOO1L, OxOOOO2OOOL, OxOO8OOOOOL, 0x00802001L,
OxOOOOOO8OL, OxOO8OOOOOL, OxOOOO2OO1L, OxOOOO2O8OL,
OxOO8OOO81L, OxOOOOOOO1L, OxOOOO2O8OL, OxOO8OOO8OL,
OxOOOO2OOOL, OxOO80208OL, OxOO802081L, OxOOOOOO81L,
OxOO8OOO8OL, OxOO8OOOO1L, OxOO8O2OOOL, OxOO802081L,
OxOOOOOO81L, OxOOOOOOOOL, OxOOOOOOOOL, OxOO8O2OOOL,
OxOOOO2O8OL, OxOO8OOO8OL, OxOO8OOO81L, OxOOOOOOO1L,
0x00802001L, OxOOOO2O81L, OxOOOO2O81L, OxOOOOOO8OL,
OxOO802081L, OxOOOOOO81L, OxOOOOOOO1L, OxOOOO2OOOL,
OxOO8OOOO1L, OxOOOO2OO1L, OxOO80208OL, OxOO8OOO81L,
OxOOOO2OO1L, OxOOOO2O8OL, OxOO8OOOOOL, 0x00802001L,
OxOOOOOO8OL, OxOO8OOOOOL, OxOOOO2OOOL, OxOO80208OL I;

static unsigned long SP5[641 = 1
OxOOOOO1OOL, 0x02080100L, OxO2O8OOOOL, Ox42OOO1OOL,
OxOOO8OOOOL, OxOOOOO1OOL, Ox4OOOOOOOL, OxO2O8OOOOL,
0x40080100L, OxOOO8OOOOL, OxO2OOO1OOL, 0x40080100L,
Ox42OOO1OOL, Ox4208OOOOL, 0x00080100L, Ox4OOOOOOOL,
OxO2OOOOOOL, Ox4OO8OOOOL, Ox4OO8OOOOL, OxOOOOOOOOL,
Ox4OOOO1OOL, Ox4208OlOOL, Ox4208OlOOL, OxO2OOO1OOL,
Ox4208OOOOL, Ox4OOOO1OOL, OxOOOOOOOOL, Ox42OOOOOOL,
0x02080100L, OxO2OOOOOOL, Ox42OOOOOOL, OxOOO8O1OOL,
OxOOO8OOOOL, Ox42OOO1OOL, OxOOOOO1OOL, OxO2OOOOOOL,
Ox4OOOOOOOL, OxO2O8OOOOL, Ox42OOO1OOL, 0x40080100L,
OxO2OOO1OOL, Ox4OOOOOOOL, Ox4208OOOOL, 0x02080100L,
0x40080100L, OxOOOOO1OOL, OxO2OOOOOOL, Ox4208OOOOL,
Ox420801OOL, OxOOO8O1OOL, Ox42OOOOOOL, Ox420801OOL,
OxO2O8OOOOL, 0x00000000L, Ox4OO8OOOOL, Ox42OOOOOOL,
OxOOO8O1OOL, OxO2OOO1OOL, Ox4OOOO1OOL, OxOOO8OOOOL,
OxOOOOOOOOL, Ox4OO8OOOOL, 0x02080100L, Ox4OOOO1OOL I;

static unsigned long SP6[64] = (
Ox2OOOOO1OL, Ox2O4OOOOOL, OxOOOO4OOOL, Ox2040401OL,
Ox2O4OOOOOL, OxOOOOOO1OL, 0x20404010L, OxOO4OOOOOL,
Ox2OOO4OOOL, 0x00404010L, OxOO4OOOOOL, Ox2OOOOO1OL,
OxOO4OOO1OL, Ox2OOO4OOOL, 0x20000000L, OxOOOO4O1OL,
OxOOOOOOOOL, OxOO4OOO1OL, 0x20004010L, OxOOOO4OOOL,
OxOO4O4OOOL, 0x20004010L, OxOOOOOO1OL, 0x20400010L,




Page 627
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page

DES


0x20400010L, OxOOOOOOOOL, 0x00404010L, Ox20404OOOL,
OxOOOO4O1OL, OxOO4O4OOOL, Ox20404OOOL, Ox2OOOOOOOL,
Ox2OOO4OOOL, OxOOOOOO1OL, 0x20400010L, 0x00404000L,
Ox2040401OL, OxOO4OOOOOL, OxOOOO4O1OL, Ox2OOOOO1OL,
OxOO4OOOOOL, Ox2OOO4OOOL, Ox2OOOOOOOL, OxOOOO4O1OL,
Ox2OOOOO1OL, Ox2040401OL, OxOO4O4OOOL, Ox2O4OOOOOL,
0x00404010L, Ox20404OOOL, OxOOOOOOOOL, 0x20400010L,
OxOOOOOO1OL, OxOOOO4OOOL, Ox2O4OOOOOL, 0x00404010L,
OxOOOO4OOOL, OxOO4OOO1OL, 0x20004010L, OxOOOOOOOOL,
Ox20404OOOL, Ox2OOOOOOOL, OxOO4OOO1OL, 0x20004010L I;

static unsigned long SP7[641 = 1
OxOO2OOOOOL, OxO4200002L, OxO4000802L, OxOOOOOOOOL,
OxOOOOO8OOL, OxO4000802L, OxOO200802L, OxO42008OOL,
OxO4200802L, OxOO2OOOOOL, OxOOOOOOOOL, OxO4OOOOO2L,
OxOOOOOOO2L, OxO4OOOOOOL, OxO4200002L, OxOOOOO8O2L,
OxO4OOO8OOL, OxOO200802L, OxOO2OOOO2L, OxO4OOO8OOL,
OxO4OOOOO2L, OxO42OOOOOL, OxO42008OOL, OxOO2OOOO2L,
OxO42OOOOOL, OxOOOOO8OOL, OxOOOOO8O2L, OxO4200802L,
OxOO2OO8OOL, OxOOOOOOO2L, OxO4OOOOOOL, OxOO2OO8OOL,
OxO4OOOOOOL, OxOO2OO8OOL, OxOO2OOOOOL, OxO4000802L,
OxO4000802L, OxO4200002L, OxO4200002L, OxOOOOOOO2L,
OxOO2OOOO2L, OxO4OOOOOOL, 0x04000800L, OxOO2OOOOOL,
OxO42008OOL, OxOOOOO8O2L, OxOO200802L, OxO42008OOL,
OxOOOOO8O2L, OxO4OOOOO2L, OxO4200802L, OxO42OOOOOL,
OxOO2OO8OOL, OxOOOOOOOOL, OxOOOOOOO2L, OxO4200802L,
OxOOOOOOOOL, OxOO200802L, OxO42OOOOOL, OxOOOOO8OOL,
OxO4OOOOO2L, OxO4OOO8OOL, OxOOOOO8OOL, OxOO2OOOO2L I;

static unsigned long SP8[641 = I
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L I;

static void desfunc(block, keys)
register unsigned long *block, *keys;
f
register unsigned long fval, work, right, leftt;
register int round;

leftt = block[Ol;




Page 628
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page
Source Code


right = block[ll;
>> 4) h right) & OxOfOfOfOfL;
work = ((leftt
right /I= work;
leftt h= (work << 4);
work = ((leftt >> 16) A right) & OxOOOOffffL;
right h= work;
leftt n= (work << 16).
work = ((right >> 2) A leftt) & Ox33333333L;
leftt h= work*
right A= (work << 2);
>> 8) A leftt) & OxOOffOOffL;
work = ((right
leftt A= work.
right A= (work << 8);
right = ((right << 1) 1 ((right >> 31) & 1L)) & OxffffffffL;
h right) & OxaaaaaaaaL;
work = (leftt
leftt h= work.
A= work;
right
leftt = ((leftt << 1) 1 ((leftt >> 31) & 1L)) & OxffffffffL;

for( round = 0; round < 8; round++ 1i
= (right << 28) 1 (right >> 4);
work
work fi= *keys++;
fval = SP7[ work & Ox3fLl;
fval I= SP5CCwork >> 8) & Ox3fLl;
fval I= SP3CCwork >> 16) & Ox3fLl;
fval I= SPl[(work >> 24) & Ox3fLl;
= right A *keys++;
work
fval I= SPEC work & Ox3fLl;
fval I= SP6[(work >> 8) & Ox3fLl;
fval I= SP4[(work >> 16) & Ox3fLl;
fval )= SPZ[(work >> 24) & Ox3fLl;
leftt h= fval.
= (left; << 28) 1 (leftt >> 4);
work
work II= *keys++;
= SP7[ work
fval & Ox3fLl;
= SP5[(work >> 8) & Ox3fLl;
fval
= SP3[(work >> 16) & Ox3fLl;
fval
= SPl[(work >> 24) & Ox3fLl;
fval
= leftt h *keys++;
work
= SPEI: work
fval & Ox3fLl;
= SPGCCwork >> 8) & Ox3fLl;
fval
= SP4CCwork >> 16) & Ox3fLl;
fval
= SPP[(work >> 24) & Ox3fLl;
fval
right A= fval;


right = (right << 31) I (right >> 1);
work = (leftt h right) & OxaaaaaaaaL;
leftt '= work.
right h= work:
leftt = (leftt << 31) 1 (leftt >> 1);
work = ((leftt >> 8) h right) & OxOOffOOffL;
right A= work;
leftt h= (work << 8);




Page 629
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page
DES


work = ((leftt >> 2) h right) & Ox33333333L;
right h= work;
leftt A= (work << 2).
work = ((right >> 161 A leftt) & OxOOOOffffL;
leftt h= work.
right A= (work << 16);
work = ((right >> 4) A leftt) & OxOfOfOfOfL;
leftt A= work.
right A= (work << 4);
*block++ = right;
*block = leftt;
return:


/* Validation sets:
*
* Single-length key, single-length plaintext -
* Key : 0123 4567 89ab cdef
* Plain : 0123 4567 89ab cde7
* Cipher : c957 4425 6a5e d31d
*


void des-key(des-ctx *dc, unsigned char *key){
deskey(key,ENO);
cpkeycdc->ek);
deskey(key,DEl);
cpkeycdc->dk);


/* Encrypt several blocks in ECB mode. Caller is responsible for
short blocks. */
void des-enc(des-ctx *dc, unsigned char *data, int blocks)(
unsigned long workC21;
int i;
unsigned char *cp;

cp = data;
for(i=O;i<blocks;i++)[
scrunch(cp,work);
desfunc(work,dc->ek);
unscrun(work,cp);
cp+=8;



void des-dec(des-ctx *dc, unsigned char *data, int blocks){
unsigned long work[21;
int i;
unsigned char *cp;

cp = data;
for(i=O;i<blocks;i++)(
scrunch(cp,work);
desfunc(work,dc->dk);




Page 630
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page
Source Code


unscrun(work,cp);
cp+=8;
I


void main(void){
des-ctx dc;
int i;
unsigned long data[lOl;
char *cp,key[81 = l0x01,0x23,0x45,0x67,Ox89,Oxab,Oxcd,OxefI;
char xC81 = ˜0x01,0x23,0x45,0x67,Ox89,0xab,Oxcd,Oxe7l;

cp = x;

des-key(&dc,key);
des-enc(&dc,cp,l);
printf("Enc(0..7,0..7) = "I;
for(i=O;i<8;i++) printf("%02x ", ((unsigned int) cpCil)&OxOOff);
printf("\n");

des-dec(&dc,cp,l);

printf("Dec(above,0..7) = "I;
for(i=O;i<E;i++) printf("%OZx " ,((unsigned int)cp[il)&OxOOff);
printf("\n");

cp = (char *) data;
for(i=O;i<lO;i++)data[i]=i;

des_enc(&dc,cp,5); /* Enc 5 blocks. */
for(i=O;i<lO;i+=2) printf("Block %Old = %081x %081x.\n",
i/2,data[il,data[i+l]);

des-dec(&dc,cp,l);
des_dec(&dc,cp+8,4);
for(i=O;i<lO;i+=2) printf("Block %Old = %081x %081x.\n",
i/2,data[il,data[i+l]I;




LOKI91
#include <stdio.h>

#define LOKIBLK 8 /* No of bytes in a LOKI data-block */
#define ROUNDS 16 /* No of LOKI rounds */

typedef unsigned long Long; /* type specification for aligned LOKI blocks
*/

extern Long lokikeyC21; /* 64-bit key used by LOKI routines *I
extern char *loki-lib-ver; /* String with version no. & copyright "I

#ifdef -STDC- /* declare prototypes for library functions */
extern void enlokicchar *b);




Page 631
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page

LOKI91


extern void delokicchar *b);
extern void setlokikey(char key[LOKIBLKI);
/* else just declare library functions extern */
#else
extern void enloki0, deloki0, setlokikeyo;
#endif -STDC-

char P[321 = I
31, 23, 15, 7, 30, 22, 14, 6,
29, 21, 13, 5, 28, 20, 12, 4,
27, 19, 11, 3, 26, 18, 10, 2,
25, 17, 9, 1, 24, 16, 8, 0
I:

struct 1
typedef
/* irreducible polynomial used in this field */
short gen;
/* exponent used to generate this s function */
short exp;
I sfn-desc;

sfn-desc sfn[l =1
*/ 379,
( /* 101110111 */ 375, 311, 1 /* 101111011 311,
( /* 110000111 */ 391, 31), 1 /* 110001011 */ 395, 31t,
*/ 415,
1 /* 110001101 */ 397, 31t, 1 /* 110011111 311,
*/ 425,
1 /* 110100011 */ 419, 311, { /* 110101001 311,
*/ 445,
I /* 110110001 */ 433, 311, 1 /* 110111101 311,
{ /* 111000011 */ 451, 311, ( /* 111001111 */ 463, 311,
{ /* 111010111 */ 471, 311, ( /* 111011101 */ 477, 311,
( /* 111100111 */ 487, 311, ( /* 111110011 */ 499, 311,
1 00, 001 I;

typedef struct (
Long loki-subkeys[ROlJNDSl;
1 loki-ctx;

/* declare LOKI function f */
static Long f0;
/* declare LOKI S-box fn s */
static short so;

#define ROL12(b) b = ((b << 12) I (b >> 20));
#define ROL13(b) b = ((b << 13) I (b >> 19));

#ifdef LITTLE-ENDIAN
#define bswap(cb) 1 \
register char c; \
c = cb[Ol; cbCO1 = cb[31; cb[31 = c; \
c = cb[ll; cb[ll = cb[21; cb[21 = c; \
c = cb[41; cb[41 = cbC71; cb[71 = c; \
c = cb[51; cb[51 = cbC61; cb[61 = c; \

#endif

void
setlokikey(loki-ctx *c, char *key)
1
register i;
register Long KL, KR;




Page 632
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page

Source Code


#ifdef LITTLE-ENDIAN
bswapckey); I* swap bytes round if little-endian *I
#endif
KL = ((Long *)key)LOl;
KR = ((Long *)keyI[ll;

for (i=O; i<ROUNDS; i+=4) 1 I* Generate the 16 subkeys *I
c->loki-subkeys[il = KL;
ROL12 (KL);
c->loki-subkeys[i+ll = KL;
ROL13 (KL);
c->loki_subkeys[i+21 = KR;
ROL12 (KR);
c->loki_subkeys[i+31 = KR;
ROL13 (KR);


#ifdef LITTLE-ENDIAN
bswap(key); I* swap bytes back if little-endian *I
#endif


void
enloki (loki-ctx *c, char *b)

register i;
register Long L, R; I* left & right data halves *I

#ifdef LITTLE-ENDIAN
bswap(b); I* swap bytes round if little-endian *I
#endif

L = ((Long *)b)[Ol;
R = ((Long *)b)[ll;

for (i=O; i<ROUNDS; i+=2) 1 I* Encrypt with the 16 subkeys */
L '= f CR, c->loki-subkeys[i])
j);
R '= f CL, c->loki-subkeys[i+l


((Long *)b)[Ol = R; Y = swap(LR) *I
/*
*)b)[ll = L;
((Long

#ifdef LITTLE-ENDIAN
bswapcb); I* swap bytes round if little-endian *I
#endif
I

void
deloki(loki-ctx *c, char *b)
f
register i;
register Long L, R; I* left & right data halves *I

#ifdef LITTLE-ENDIAN




Page 633
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page
LOKI91


I* swap bytes round if little-endian *I
bswapcb);
#endif

I* LR = X XOR K *I
L = ((Long *)b)[Ol;
R = ((Long *)b)Cll;

for (i=ROUNDS; i>O; i-=2) { I* subkeys in reverse order *I
L h= f(R, c->loki-subkeys[i-11);
R h= f(L, c->loki-subkeys[i-21);


((Long *)b)[Ol = R; I* Y = LR XOR K "I
((Long *)b)[ll = L;


#define MASK12 OxOfff I* 12 bit mask for expansion E */

static Long
f(r, k)
register Long r; I* Data value R(i-1) *I
Long K(i) *I
I* Key
k;

Long I* 32 bit S-box output, & P output */
a, b, c;

a=r^k; I* A = R(i-1) XOR K(i) *I

I* want to use slow speed/small size version *I
b = ((Long)s((a & MASKlP)) ) I I* B = S(E(R(i-l))^K(i)) *I
((Long)s(((a >> 8) & MASK12)) << 8) I
((Long)s(((a >> 16) & MASK1211 << 16) I
((Long)s((((a >> 24) 1 (a << 8)) & MASK12)) << 24);

perm32(&c, &b, P); I* C = P(S( E(R(i-1)) XOR K(i))) */

return(c); I* f returns the result C *I


static short s(i)
register Long i; I* return S-box value for input i *I

register short r, c, v, t;
short exp80; I* exponentiation routine for GF(2^8) *I

r = ((i>>8) & Oxc) I (i & 0x3); I* row value-top 2 & bottom 2 *I
c = (i>>2) & Oxff; I* column value-middle 8 bits *I
t = Cc + ((r * 17) A Oxff)) & Oxff; I* base value for Sfn *I
v = exp8(t, sfn[rl.exp, sfn[r].gen); I* Sfn[r1 = t h exp mod gen *I
return(v);


#define MSB Ox8OOOOOOOL I* MSB of 32-bit word *I

perm32(out, in , perm)
Long *out; I* Output 32.bit block to be permuted "I




Page 634
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page

Source Code


*in;
Long */
I* Input 32-bit block after permutation
char permK321; I* Permutation array */

Long *I
mask = MSB; I* mask used to set bit in output
register int i, o, b; I* input bit no, output bit no, value *I
register char *p = perm; I* ptr to permutation array *I

*out = 0; I* clear output block *I
for (o=O; 0<32; of+) 1 I* For each output bit position o *I
i =(int)*p++; /* get input bit permuted to output o *I
b = (*in >> i) & 01; /* value of input bit i *I
if (b) I* If the input bit i is set *I
*out I= mask; I* OR in mask to output i *I
*I
mask >>= 1; I* Shift mask to next bit



#define SIZE 256 I* 256 elements in GF(2^8) *I

short mult8(a, b, gen)
short a, b; I* operands for multiply *I
short I* irreducible polynomial generating Galois Field *I
wn;

short product = 0; I* result of multiplication */

while(b != 0) 1 I* while multiplier is non-zero *I
if (b & 01)
/*
product II= a; add multiplicand if LSB of b set *I
a <<= 1; /* shift multiplicand one place *I
if (a >= SIZE)
a h= gen; /* and modulo reduce if needed *I
b >>= 1; /* shift multiplier one place *I
1
return(product);


short exp8(base, exponent, gen)
base;
short I* base of exponentiation */
short exponent; I* exponent */
short I* irreducible polynomial generating Galois Field *I
wn ;
1
short accum = base; I* superincreasing sequence of base */
short result = 1; I* result of exponentiation */

if (base == 0) I* if zero base specified then */
return(O); *I
I* the result is "0" if base = 0

while (exponent != 0) I I* repeat while exponent non-zero *I
if CC exponent & 0x0001) == 0x0001) I* multiply if exp 1 *I
result = mult8(result, accum, gen);
exponent >>= 1; I* shift exponent to next digit *I
accum = multE(accum, accum, gen); I* & square *I

return(resultI;




Page 635
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page
IDEA


*c, unsigned char *key){
void loki-key(loki-ctx
setlokikey(c,key);
1

void loki-enccloki-ctx *c, unsigned char *data, int blocks)(
unsigned char *cp;
int i;

cp = data;
for(i=O;i<blocks;i++)(
enloki(c,cp);
cp+=E;
1
1

void loki-dec(loki-ctx *c, unsigned char *data, int blocks){
unsigned char *cp;
int i;

cp = data;
for(i=O;i<blocks;i++)[
deloki(c,cp);
cp+=E;



void main(void){
loki-ctx lc;
unsigned long data[lO];
unsigned char *cp;
unsigned char key[] = 10,1,2,3,4,5,6,7);
int i;

for(i=O;i<lO;i++) data[i]=i;

loki-key(&lc,key);

cp = (char *)data;
loki_enc(&lc,cp,5);
for(i=O;i<lO;i+=2) printf("Block %Old = %081x %OElx\n",
i/2,data[il,data[i+ll);
loki-dec(&lc,cp,l);
loki_dec(&lc,cp+8,4);
for(i=O;i<lO;i+=2) printf("Block %Old = %081x %081x\n",
i/2,data[il,data[i+lI);




IDEA
typedef unsigned char boolean; I* values are TRUE or FALSE *I
typedef unsigned char byte; I* values are O-255 *I
typedef byte *byteptr; I* pointer to byte *I




Page 636
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page
Source Code


typedef char *string;/* pointer to ASCII character string *I
typedef unsigned short word16; I* values are O-65535 *I
typedef unsigned long word32; I* values are O-4294967295 *I

#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif I* if TRUE not already defined */

#ifndef min I* if min macro not already defined *I
#define min(a,b) ( (a)<(b) ? (a) : (b) )
#define max(a,b) ( (a)>(b) ? (a) : (b) )
#endif I* if min macro not already defined *I

#define IDEAKEYSIZE 16
#define IDEABLOCKSIZE 8

#define IDEAROUNDS 8
#define IDEAKEYLEN (G*IDEAROUNDS+4)

typedef structl
word16 ek[IDEAKEYLENl,dk[IDEAKEYLENl;
lidea-ctx;

I* End includes for 1DEA.C *I
#ifdef IDEA32 I* Use >16-bit temporaries *I
#define lowl6(xI c(x) & OxFFFF)
typedef unsigned int uintl6;/* at LEAST 16 bits, maybe more *I
#else
#define lowl6Cx) (x1 I* this is only ever applied to uintl6's *I
typedef word16 uint16;
#endif

#ifdef SMALL-CACHE
static uintl6
mulcregister uintl6 a, register uint16 b)
(
register word32 p;

p = (word32)a * b;
if (p) 1
b = lowl6Cp);
a = p>>16;
return (b a) + (b < a);
) else if (a) I
return l-b;
I else 1
return l-a;
I
1 I* mu1 *I
#endif I* SMALL-CACHE *I

static uintl6
mulInv(uintl6 XI




Page 637
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page

IDEA


uintl6 to, tl;
uint16 q, y;

if (x <= 1)
I* 0 and 1 are self-inverse *I
return x;
I* Since x >= 2, this fits into 16 bits *I
t1 = 0x10001L I x;
y = 0x10001L % x;
if (y == 1)
return lowl6(1-tl);
to = 1;
do I
q=xly;
x=x%y;
to += q * t1;
if (x == 1)
return to;
q=ylx;
y=y%x;
t1 += q * to;
I while (y != 1);
return lowl6(1-tl);
1 I* mukInv */

static void
ideaExpandKey(byte const *userkey, word16 *EK)

int i,j;

for Cj=O; j<8; j++) 1
EK[jl = (userkey[01<<8) + userkeyC11;
userkey += 2;

for (i=O; j < IDEAKEYLEN; j++) {
i++;
EK[i+71 = EK[i & 71 << 9 I EK[i+l & 71 >> 7;
EK += i & 8;
i &= 7;

t I* ideaExpandKey *I

static void
ideaInvertKey(wordl6 const *EK, word16 DKCIDEAKEYLENI)
1
int i;
uint16 tl, t2, t3;
word16 temp[IDEAKEYLENl;
word16 *p = temp + IDEAKEYLEN;

tl = mulInv(*EK++);
t2 = -*EK++;
t3 = -*EK++;
*--p = mulInv(*EK++);
*..p = t3;
*..p = t2;




Page 638
Prev. Chapter Home Previous Page
Next Page
Prev. page
Next Page

Source Code




for (i = 0; i < IDEAROUNDS-1; i++) [
tl = *EK++;
*--p = *EK++;
*.-p = t1;

tl = mulInv(*EK++);
t2 = -*EK++;
t3 = -*EK++;
*--p = mulInv(*EK++);
*-.p = t2;
*Lp = t3;
*..p = t1;
1
tl = *EK++;
*--p = *EK++;
*--p = t1;

tl = mulInv(*EK++);
t2 = -*EK++;
t3 = -*EK++;
*--p = mulInv(*EK++);
"LP = t3;
*..p = t2;
*-.p = t1;
I* Copy and destroy temp copy *I
memcpy(DK, temp, sizeof(temp));
for(i=O;i<IDEAKEYLEN;i++)temp[i]=O;
1 I* ideaInvertKey *I

#ifdef SMALL-CACHE
#define MUL(x,y) (x = mul(lowl6(x),y))
#else I* !SMALL-CACHE *I
Gifdef AVOID-JUMPS
#define MUL(x,y) (x = lowl6(x-1), t16 = lowl6((y)-l), \
t32 = (word32)x*t16 + x + t16 + 1, x = low16(t32), \

. 1
( 8)



>>