· 6 years ago · Apr 10, 2020, 05:44 PM
1/* Includes: Standard include files */
2#include <stdio.h>
3#include <string.h>
4
5#define DIR_ENCRYPT 0 /* Are we encrypting? */
6#define DIR_DECRYPT 1 /* Are we decrypting? */
7#define MODE_CBC 2 /* Are we ciphering in CBC mode? */
8#define S_TRUE 1
9#define S_FALSE 0
10
11/* Error Codes */
12#define BAD_KEY_DIR -1 /* Key direction is invalid, e.g.,
13 unknown value */
14#define BAD_KEY_MAT -2 /* Key material not of correct
15 length */
16#define BAD_KEY_INSTANCE -3 /* Key passed is not valid */
17#define BAD_CIPHER_MODE -4 /* Params struct passed to
18 cipherInit invalid */
19#define BAD_CIPHER_STATE -5 /* Cipher in wrong state (e.g., not
20 initialized) */
21#define BAD_CIPHER_INPUT -6 /* Cipher input not BLOCK_SIZE multiple */
22
23/* Algorithm Specific Defines */
24#define MAX_KEY_SIZE 64 /* # of ASCII char's needed to
25 represent a key */
26#define MAX_IV_SIZE 16 /* # bytes needed to represent an IV */
27
28/* Number of bytes in a data-block. */
29#define BLOCK_SIZE 16
30
31/* Number of rounds for the algorithm. */
32#define ROUNDS 16
33
34/* Number of subkeys used by the algorithm. */
35#define NUM_SUBKEYS 3*ROUNDS
36
37/* Typedefs: */
38
39typedef unsigned char BYTE; /* unsigned byte */
40
41typedef struct ULONG64 {
42 unsigned long l,r;
43} ULONG64; /* 64bit unsigned int */
44
45/* The structure for key information */
46typedef struct keyInstance {
47 BYTE direction; /* Key used for encrypting or decrypting? */
48 int keyLen; /* Length of the key */
49 unsigned char keyMaterial[MAX_KEY_SIZE+1]; /* Raw key data in ASCII,
50 e.g., user input or KAT values */
51 /* The following parameters are algorithm dependent */
52 ULONG64 SK[NUM_SUBKEYS]; /* LOKI97 subkeys for this key */
53 } keyInstance;
54
55/* The structure for cipher information */
56typedef struct cipherInstance {
57 BYTE mode; /* MODE_CBC*/
58 BYTE IV[MAX_IV_SIZE]; /* A possible Initialization Vector for
59 ciphering */
60 /* Add any algorithm specific parameters needed here */
61 ULONG64 IVL, IVR; /* IV packed into 64-bit L & R halves */
62 int blockSize; /* Sample: Handles non-128 bit block sizes
63 (if available) */
64 } cipherInstance;
65
66/* Function protoypes */
67int makeKey(keyInstance *key, BYTE direction, int keyLen,
68 unsigned char *keyMaterial);
69
70int cipherInit(cipherInstance *cipher, BYTE mode, unsigned char *IV);
71
72int blockEncrypt(cipherInstance *cipher, keyInstance *key, BYTE *input,
73 int inputLen, BYTE *outBuffer);
74
75int blockDecrypt(cipherInstance *cipher, keyInstance *key, BYTE *input,
76 int inputLen, BYTE *outBuffer);
77
78int self_test();
79
80/* include standard AES C header file */
81
82/* Global defines and variables */
83
84#define NAME "LOKI97"
85#define L_DEBUG 0
86
87/*
88 * Debug diagnostics. Valid values of symbolic constant L_DEBUG: <p>
89 *
90 * Values are:<dl compact>
91 * <dt> 1 <dd> engine calls,
92 * <dt> 2 <dd> enc/dec round values,
93 * <dt> 3 <dd> subkeys,
94 * <dt> 4 <dd> func f calls,
95 * <dt> 5 <dd> func f internals,
96 * <dt> 6 <dd> static init. </dl>
97 */
98#define debuglevel L_DEBUG
99
100/* LOKI97 algorithm specific constants and tables */
101/* ........................................................................... */
102
103/* Generator polynomial for S-box S1, in GF(2<sup>13</sup>). */
104#define S1_GEN 0x2911
105
106/* Size of S-box S1, for 13-bit inputs. */
107#define S1_SIZE 0x2000
108
109/* Table of pre-computed S-box S1 values. */
110static BYTE S1[S1_SIZE];
111
112/* Generator polynomial for S-box S2, in GF(2<sup>11</sup>). */
113#define S2_GEN 0xAA7
114
115/* Size of S-box S2, for 11-bit inputs. */
116#define S2_SIZE 0x800
117
118/* Table of pre-computed S-box S2 values. */
119static BYTE S2[S2_SIZE];
120
121/* Constant value for Delta which is used in the key schedule */
122static ULONG64 DELTA = {0x9E3779B9L, 0x7F4A7C15L};
123
124/*
125 * Table specifying the pre-computed permutation P.
126 * nb. precompute permutations for lowest 8 bits only,
127 * value of P is a 64-bit wide (long) mask of the permuted input value.
128 */
129static ULONG64 P[0x100];
130
131/* Flag specifying whether once-off init of S1, S2 and P has been done */
132static int init_done = S_FALSE;
133
134/* prototypes for local utility functions */
135static int enECB(cipherInstance *cipher, keyInstance *key, BYTE *input,
136 int inputLen, BYTE *outBuffer);
137static int enCBC(cipherInstance *cipher, keyInstance *key, BYTE *input,
138 int inputLen, BYTE *outBuffer);
139static int enCFB1(cipherInstance *cipher, keyInstance *key, BYTE *input,
140 int inputLen, BYTE *outBuffer);
141static int deECB(cipherInstance *cipher, keyInstance *key, BYTE *input,
142 int inputLen, BYTE *outBuffer);
143static int deCBC(cipherInstance *cipher, keyInstance *key, BYTE *input,
144 int inputLen, BYTE *outBuffer);
145static int deCFB1(cipherInstance *cipher, keyInstance *key, BYTE *input,
146 int inputLen, BYTE *outBuffer);
147static ULONG64 f (ULONG64 A, ULONG64 B) ;
148static ULONG64 add64(ULONG64 a, ULONG64 b) ;
149static ULONG64 sub64(ULONG64 a, ULONG64 b) ;
150static int exp3 (int b, int g, int n) ;
151static int mult (int a, int b, int g, int n) ;
152static ULONG64 byteToULONG64(BYTE *inp) ;
153static BYTE *ULONG64ToBYTE(BYTE *buf, ULONG64 I) ;
154static BYTE *charToBYTE(BYTE *buf, unsigned char *hex, int len) ;
155/* static ULONG64 charToULONG64(unsigned char *hex) ; */
156static int fromHex (unsigned char ch) ;
157void puthex(BYTE *out, int len, FILE *f);
158
159/* Initialise cipher, precompute S-boxes and permutation table */
160/* ......................................................................... */
161
162int cipherInit(cipherInstance *cipher, BYTE mode, unsigned char *IV)
163{
164 int S1_MASK = S1_SIZE - 1; /* mask to select S1 input bits */
165 int S2_MASK = S2_SIZE - 1; /* mask to select S2 input bits */
166
167 int i, j, k; /* index into S-box, P bit , out bit */
168 int b; /* S-box fn input */
169 long pval; /* perm P mask for given input value */
170 BYTE *input; /* pointer into byte array for IV */
171
172 if (debuglevel) fprintf(stderr,"%s: cipherInit(mode=%d, IV=%s)\n", NAME, mode, IV);
173
174 if (!init_done) {
175
176 /* precompute S-box tables for S1 and S2 */
177 if (debuglevel > 5) fprintf(stderr,"%s: Static init of S1, S2 & P \n", NAME);
178 for (i = 0; i < S1_SIZE; i++) { /* for all S1 inputs */
179 b = i ^ S1_MASK; /* compute input value */
180 S1[i] = exp3(b, S1_GEN, S1_SIZE); /* compute fn value */
181 if (debuglevel > 5) fprintf(stderr,"%s: S1[%04x] = %02x\n", NAME, i, S1[i]);
182 }
183 for (i = 0; i < S2_SIZE; i++) { /* for all S2 inputs */
184 b = i ^ S2_MASK; /* compute input value */
185 S2[i] = exp3(b, S2_GEN, S2_SIZE); /* compute fn value */
186 if (debuglevel > 5) fprintf(stderr,"%s: S2[%04x] = %02x\n", NAME, i, S2[i]);
187 }
188
189 /* initialising expanded permutation P table (for lowest BYTE only) */
190 /* Permutation P maps input bits [63..0] to outputs bits: */
191 /* [56, 48, 40, 32, 24, 16, 8, 0, */
192 /* 57, 49, 41, 33, 25, 17, 9, 1, */
193 /* 58, 50, 42, 34, 26, 18, 10, 2, */
194 /* 59, 51, 43, 35, 27, 19, 11, 3, */
195 /* 60, 52, 44, 36, 28, 20, 12, 4, */
196 /* 61, 53, 45, 37, 29, 21, 13, 5, */
197 /* 62, 54, 46, 38, 30, 22, 14, 6, */
198 /* 63, 55, 47, 39, 31, 23, 15, 7] <- this row only used in table */
199 /* since it is so regular, we can construct it on the fly */
200 for (i = 0; i < 0x100; i++) { /* loop over all 8-bit inputs */
201 /* for each input bit permute to specified output position */
202 pval = 0L;
203 for (j = 0, k = 7; j < 4; j++, k += 8) /* do right half of P */
204 pval |= (long)((i >> j) & 0x1) << k;
205 P[i].r = pval;
206 pval = 0L;
207 for (j = 4, k = 7; j < 8; j++, k += 8) /* do left half of P */
208 pval |= (long)((i >> j) & 0x1) << k;
209 P[i].l = pval;
210 if (debuglevel > 5) fprintf(stderr,"%s: P[%02x] = %08lx%08lx\n", NAME, i, P[i].l, P[i].r);
211 }
212
213 /* and remember that init has been done */
214 init_done = S_TRUE;
215 }
216
217 /* now fill out cipherInstance structure */
218 cipher->mode = mode; /* copy mode over */
219 if (IV != NULL) { /* IV specified */
220 charToBYTE(cipher->IV,IV,sizeof(cipher->IV)); /* convert IV */
221 /* pack IV into IVL and IVR */
222 input = cipher->IV;
223 cipher->IVL = byteToULONG64(input); input += 8;
224 cipher->IVR = byteToULONG64(input); input += 8;
225 } else { /* no IV, so set to 0 */
226 memset(cipher->IV,0,sizeof(cipher->IV));
227 cipher->IVL.l = cipher->IVL.r = cipher->IVR.l = cipher->IVR.r = 0L;
228 }
229 cipher->blockSize = BLOCK_SIZE*8; /* BLOCK_SIZE in bits */
230
231 /* decide correct return value */
232 if (mode == MODE_CBC)
233 return S_TRUE;
234 else
235 return BAD_CIPHER_MODE;
236
237}
238
239/*
240 * Returns residue of base b to power 3 mod g in GF(2^n).
241 *
242 * @param b Base of exponentiation, the exponent being always 3.
243 * @param g Irreducible polynomial generating Galois Field (GF(2^n)).
244 * @param n Size of the galois field.
245 * @return (b ** 3) mod g.
246 */
247static int exp3 (int b, int g, int n) {
248 int r = b; /* r = b */
249 if (b == 0)
250 return 0;
251 b = mult(r, b, g, n); /* r = b ** 2 */
252 r = mult(r, b, g, n); /* r = b ** 3 */
253 return r;
254}
255
256/*
257 * Returns the product of two binary numbers a and b, using the
258 * generator g as the modulus: p = (a * b) mod g. g Generates a
259 * suitable Galois Field in GF(2^n).
260 *
261 * @param a First multiplicand.
262 * @param b Second multiplicand.
263 * @param g Irreducible polynomial generating Galois Field.
264 * @param n Size of the galois field.
265 * @return (a * b) mod g.
266 */
267static int mult (int a, int b, int g, int n) {
268 int p = 0;
269 while (b != 0) {
270 if ((b & 0x01) != 0)
271 p ^= a;
272 a <<= 1;
273 if (a >= n)
274 a ^= g;
275 b >>= 1;
276 }
277 return p;
278}
279
280/* Basic NIST API methods for LOKI97 */
281/* ......................................................................... */
282
283/* Expand a user-supplied key material into a LOKI97 session key. */
284int makeKey(keyInstance *key, BYTE direction, int keyLen, unsigned char *keyMaterial)
285{
286 ULONG64 k4, k3, k2, k1; /* key schedule 128-bit entities */
287 ULONG64 deltan = DELTA; /* multiples of delta */
288 ULONG64 t1, t2; /* temps used for doing 64-bit adds */
289 ULONG64 f_out; /* fn f output value for debug */
290 int i = 0; /* index into key input */
291 unsigned long long tmp;
292
293 /* do some basic sanity checks on the keyMaterial */
294 if ((key == NULL) || (keyMaterial == NULL)) return BAD_KEY_INSTANCE;
295 if (!(direction == DIR_ENCRYPT || direction == DIR_DECRYPT))
296 return BAD_KEY_DIR;
297 if (!(keyLen == 128 || keyLen == 192 || keyLen == 256))
298 return BAD_KEY_MAT;
299
300 /* fill out the keyInstance structure with input params */
301 key->direction = direction;
302 key->keyLen = keyLen;
303
304 strncpy(key->keyMaterial, keyMaterial, MAX_KEY_SIZE);
305
306 /* convert ascii hex text into into 64-bit entities: k4, k3, k2, k1 */
307 /* k4 = charToULONG64(keyMaterial); keyMaterial += 16; */
308 /* k3 = charToULONG64(keyMaterial); keyMaterial += 16; */
309
310 tmp = 0;
311 for (i = 0; i < 8; i++) {
312 tmp = (tmp << 8);
313 tmp |= keyMaterial[i];
314 }
315
316 k4.l = tmp >> 32;
317 k4.r = tmp;
318
319 tmp = 0;
320 for (i = 8; i < 16; i++) {
321 tmp = (tmp << 8);
322 tmp |= keyMaterial[i];
323 }
324
325 k3.l = tmp >> 32;
326 k3.r = tmp;
327
328 if (keyLen == 128) { /* 128-bit key - call fn f twice to gen 256 bits */
329 k2 = f(k3, k4);
330 k1 = f(k4, k3);
331 } else { /* 192 or 256-bit key - pack k2 from key data */
332 tmp = 0;
333 for (i = 16; i < 24; i++) {
334 tmp = (tmp << 8);
335 tmp |= keyMaterial[i];
336 }
337
338 /* k2 = charToULONG64(keyMaterial); keyMaterial += 16; */
339 k2.l = tmp >> 32;
340 k2.r = tmp;
341
342 if (keyLen == 192) /* 192-bit key - call fn f once to gen 256 bits */
343 k1 = f(k4, k3);
344 else { /* 256-bit key - pack k1 from key data */
345 tmp = 0;
346 for (i = 24; i < 32; i++) {
347 tmp = (tmp << 8);
348 tmp |= keyMaterial[i];
349 }
350
351 /* k1 = charToULONG64(keyMaterial); keyMaterial += 16; */
352 k1.l = tmp >> 32;
353 k1.r = tmp;
354 }
355 }
356
357 if (debuglevel) fprintf(stderr,"%s: makeKey(k4.l=%08lx k4.r=%08lx k3.l=%08lx k3.r=%08lx k2.l=%08lx k2.r=%08lx k1.l=%08lx k1.r=%08lx,%s)\n", NAME, k4.l, k4.r, k3.l, k3.r, k2.l, k2.r, k1.l, k1.r, direction?"Dec":"Enc");
358
359 /* iterate over all LOKI97 rounds to generate the required subkeys */
360 for (i = 0; i < NUM_SUBKEYS; i++) {
361 t1 = add64(k1,k3); /* compute f(k1+k3+n.delta,k2) */
362 t2 = add64(t1,deltan);
363 f_out = f(t2, k2);
364 key->SK[i].l = k4.l ^ f_out.l; /* compute next subkey using fn f */
365 key->SK[i].r = k4.r ^ f_out.r;
366 k4 = k3; /* exchange the other words around */
367 k3 = k2;
368 k2 = k1;
369 k1 = key->SK[i];
370 deltan = add64(deltan,DELTA); /* next multiple of delta */
371 if (debuglevel > 2) fprintf(stderr,"%s: SK[%02d]=%08lx%08lx\t", NAME, i, key->SK[i].l, key->SK[i].r);
372 if (debuglevel > 2) fprintf(stderr,"f=%08lx%08lx,\tdeltan=%08lx%08lx\n", f_out.l, f_out.r, deltan.l, deltan.r);
373 }
374
375 return S_TRUE;
376}
377
378/* ....................................................................... */
379/*
380 * blockEncrypt(cipher,key,input,inputLen,outBuffer) -
381 * encrypt blocks of plaintext from input to outBuffer using cipher & key.
382 */
383int blockEncrypt(cipherInstance *cipher, keyInstance *key, BYTE *input,
384 int inputLen, BYTE *outBuffer)
385{
386 /* do some basic sanity checks on params */
387 if (!init_done) return BAD_CIPHER_STATE;
388 if (cipher == NULL) return BAD_CIPHER_STATE;
389 if (key == NULL) return BAD_KEY_INSTANCE;
390 if (key->direction != DIR_ENCRYPT) return BAD_KEY_DIR;
391
392 /* now call appropriate mode encrypt routine */
393 if (cipher->mode == MODE_CBC)
394 return enCBC(cipher, key, input, inputLen, outBuffer);
395 else
396 return BAD_CIPHER_MODE;
397}
398
399/*
400 * encrypt blocks in ECB mode
401 */
402static int enECB(cipherInstance *cipher, keyInstance *key, BYTE *input,
403 int inputLen, BYTE *outBuffer)
404{
405 int i,j,k; /* assorted loop counters */
406 int blocks = inputLen / (BLOCK_SIZE*8); /* compute # input blocks */
407 ULONG64 L, R; /* left and right data blocks */
408 ULONG64 nR, f_out;
409
410 /* do some basic sanity checks on params */
411 if (inputLen % (BLOCK_SIZE*8) != 0) return BAD_CIPHER_INPUT;
412
413 /* now loop over all blocks of input */
414 for (j = 0; j < blocks; j++) {
415
416 /* pack input block into L and R */
417 L = byteToULONG64(input); input += 8;
418 R = byteToULONG64(input); input += 8;
419
420 if (debuglevel) fprintf(stderr,"%s: enECB(%08lx%08lx%08lx%08lx) ", NAME, L.l, L.r, R.l, R.r);
421 if (debuglevel > 1) fprintf(stderr,"\n");
422
423 /* compute all rounds for this 1 block */
424 k = 0;
425 for (i = 0; i < ROUNDS; i++) {
426 nR = add64(R, key->SK[k++]); /* nR = R+SK(k) */
427 f_out = f(nR, key->SK[k++]); /* f = f(nR,SK(k+1)) */
428 nR = add64(nR, key->SK[k++]); /* nR = nR+SK(k+2) */
429 R.l = L.l ^ f_out.l; R.r = L.r ^ f_out.r; /* R = L XOR f */
430 L = nR; /* L = nR */
431 if (debuglevel > 1) fprintf(stderr," L[%02d]=%08lx%08lx; R[%02d]=%08lx%08lx; f(SK(%02d))=%08lx%08lx\n", i+1, L.l, L.r, i+1, R.l, R.r, k-2, f_out.l, f_out.r);
432 }
433
434 if (debuglevel > 0) fprintf(stderr,"= %08lx%08lx%08lx%08lx\n", R.l, R.r, L.l, L.r);
435
436 /* unpack resulting L & R into output - undoing last swap */
437 ULONG64ToBYTE(outBuffer, R); outBuffer += 8;
438 ULONG64ToBYTE(outBuffer, L); outBuffer += 8;
439 }
440 return S_TRUE;
441}
442
443/*
444 * encrypt blocks in CBC mode
445 */
446static int enCBC(cipherInstance *cipher, keyInstance *key, BYTE *input,
447 int inputLen, BYTE *outBuffer)
448{
449 int i,j,k; /* assorted loop counters */
450 int blocks = inputLen / (BLOCK_SIZE*8); /* compute # input blocks */
451 ULONG64 L, R; /* left and right data blocks */
452 ULONG64 nR, f_out;
453
454 /* do some basic sanity checks on params */
455 if (inputLen % (BLOCK_SIZE*8) != 0) return BAD_CIPHER_INPUT;
456
457 /* now loop over all blocks of input */
458 for (j = 0; j < blocks; j++) {
459
460 /* pack input block into L and R */
461 L = byteToULONG64(input); input += 8;
462 R = byteToULONG64(input); input += 8;
463
464 /* XOR with IV value */
465 L.l ^= cipher->IVL.l; L.r ^= cipher->IVL.r;
466 R.l ^= cipher->IVR.l; R.r ^= cipher->IVR.r;
467
468 if (debuglevel) fprintf(stderr,"%s: enCBC(%08lx%08lx%08lx%08lx) ", NAME, L.l, L.r, R.l, R.r);
469 if (debuglevel > 1) fprintf(stderr,"\n");
470
471 /* compute all rounds for this 1 block */
472 k = 0;
473 for (i = 0; i < ROUNDS; i++) {
474 nR = add64(R, key->SK[k++]); /* nR = R+SK(k) */
475 f_out = f(nR, key->SK[k++]); /* f = f(nR,SK(k+1)) */
476 nR = add64(nR, key->SK[k++]); /* nR = nR+SK(k+2) */
477 R.l = L.l ^ f_out.l; R.r = L.r ^ f_out.r; /* R = L XOR f */
478 L = nR; /* L = nR */
479 if (debuglevel > 1) fprintf(stderr," L[%02d]=%08lx%08lx; R[%02d]=%08lx%08lx; f(SK(%02d))=%08lx%08lx\n", i+1, L.l, L.r, i+1, R.l, R.r, k-2, f_out.l, f_out.r);
480 }
481
482 /* save new IV value (nb. undo last swap, as per output transform */
483 cipher->IVL = R; cipher->IVR = L;
484
485 if (debuglevel > 0) fprintf(stderr,"= %08lx%08lx%08lx%08lx\n", R.l, R.r, L.l, L.r);
486
487 /* unpack resulting L & R into output - undoing last swap */
488 ULONG64ToBYTE(outBuffer, R); outBuffer += 8;
489 ULONG64ToBYTE(outBuffer, L); outBuffer += 8;
490 }
491 return S_TRUE;
492}
493
494/*
495 * encrypt blocks in CFB1 mode
496 */
497static int enCFB1(cipherInstance *cipher, keyInstance *key, BYTE *input,
498 int inputLen, BYTE *outBuffer)
499{
500 int i,j,k; /* assorted loop counters */
501 int b; /* bit number being processed in byte */
502 BYTE msgbit, keybit; /* current message and stream key bits */
503 ULONG64 L, R; /* left and right data blocks */
504 ULONG64 nR, f_out;
505
506 /* get CFB1 input buffer from IV */
507 L = cipher->IVL; R = cipher->IVR;
508
509 /* get ready to process first byte */
510 b = 7; /* start with top bit in byte */
511 *outBuffer = 0; /* and zero byte in outBuffer */
512
513 /* now loop over all bits of input */
514 for (j = 0; j < inputLen; j++) {
515 msgbit = (*input >> b) & 01; /* get next msg bit */
516
517 if (debuglevel) fprintf(stderr,"%s: enCFB1(%01x,%08lx%08lx%08lx%08lx) ", NAME, msgbit, L.l, L.r, R.l, R.r);
518 if (debuglevel > 1) fprintf(stderr,"\n");
519
520 /* compute all rounds to encrypt current CFB1 buffer */
521 k = 0;
522 for (i = 0; i < ROUNDS; i++) {
523 nR = add64(R, key->SK[k++]); /* nR = R+SK(k) */
524 f_out = f(nR, key->SK[k++]); /* f = f(nR,SK(k+1)) */
525 nR = add64(nR, key->SK[k++]); /* nR = nR+SK(k+2) */
526 R.l = L.l ^ f_out.l; R.r = L.r ^ f_out.r; /* R = L XOR f */
527 L = nR; /* L = nR */
528 if (debuglevel > 1) fprintf(stderr," L[%02d]=%08lx%08lx; R[%02d]=%08lx%08lx; f(SK(%02d))=%08lx%08lx\n", i+1, L.l, L.r, i+1, R.l, R.r, k-2, f_out.l, f_out.r);
529 }
530 /* undo last swap */
531 L = R; R = nR;
532
533 /* now process msgbit by getting stream key bit, XOR in and or to out */
534 keybit = L.l >> 31;
535 msgbit ^= keybit;
536 *outBuffer |= (msgbit << b);
537
538 if (debuglevel > 0) fprintf(stderr,"= %01x,%08lx%08lx%08lx%08lx\n", msgbit, L.l, L.r, R.l, R.r);
539
540 /* and update the CFB1 shift register (input buffer L,R) */
541 L.l = (L.l << 1) | (L.r >> 31); L.r = (L.r << 1) | (R.l >> 31);
542 R.l = (R.l << 1) | (R.r >> 31); R.r = (R.r << 1) | msgbit;
543
544 /* and update bit position counter */
545 b--;
546 /* and move to next input/output byte if necessary */
547 if (b<0) { b = 7; input++; outBuffer++; *outBuffer = 0; }
548 }
549
550 /* save new IV value */
551 cipher->IVL = L; cipher->IVR = R;
552 return S_TRUE;
553}
554
555
556/* ....................................................................... */
557/*
558 * blockDecrypt(cipher,key,input,inputLen,outBuffer) -
559 * decrypt blocks of plaintext from input to outBuffer using cipher & key.
560 */
561int blockDecrypt(cipherInstance *cipher, keyInstance *key, BYTE *input,
562 int inputLen, BYTE *outBuffer)
563{
564 /* do some basic sanity checks on params */
565 if (!init_done) return BAD_CIPHER_STATE;
566 if (cipher == NULL) return BAD_CIPHER_STATE;
567 if (key == NULL) return BAD_KEY_INSTANCE;
568 if (key->direction != DIR_DECRYPT) return BAD_KEY_DIR;
569
570 /* now call appropriate mode decrypt routine */
571 if (cipher->mode == MODE_CBC)
572 return deCBC(cipher, key, input, inputLen, outBuffer);
573 else
574 return BAD_CIPHER_MODE;
575}
576
577/*
578 * decrypt blocks in ECB mode
579 */
580static int deECB(cipherInstance *cipher, keyInstance *key, BYTE *input,
581 int inputLen, BYTE *outBuffer)
582{
583 int i,j,k; /* assorted loop counters */
584 int blocks = inputLen / (BLOCK_SIZE*8); /* compute # input blocks */
585 ULONG64 L, R; /* left and right data blocks */
586 ULONG64 nR, f_out;
587
588 /* do some basic sanity checks on params */
589 if (inputLen % (BLOCK_SIZE*8) != 0) return BAD_CIPHER_INPUT;
590
591 /* now loop over all blocks of input */
592 for (j = 0; j < blocks; j++) {
593
594 /* pack input block into L and R */
595 L = byteToULONG64(input); input += 8;
596 R = byteToULONG64(input); input += 8;
597
598 if (debuglevel) fprintf(stderr,"%s: deECB(%08lx%08lx%08lx%08lx) ", NAME, L.l, L.r, R.l, R.r);
599 if (debuglevel > 1) fprintf(stderr,"\n");
600
601 /* compute all rounds for this 1 block */
602 k = NUM_SUBKEYS - 1;
603 for (i = 0; i < ROUNDS; i++) {
604 nR = sub64(R, key->SK[k--]); /* nR = R+SK(k) */
605 f_out = f(nR, key->SK[k--]); /* f = f(nR,SK(k+1)) */
606 nR = sub64(nR, key->SK[k--]); /* nR = nR+SK(k+2) */
607 R.l = L.l ^ f_out.l; R.r = L.r ^ f_out.r; /* R = L XOR f */
608 L = nR; /* L = nR */
609 if (debuglevel > 1) fprintf(stderr," L[%02d]=%08lx%08lx; R[%02d]=%08lx%08lx; f(SK(%02d))=%08lx%08lx\n", i+1, L.l, L.r, i+1, R.l, R.r, k+2, f_out.l, f_out.r);
610 }
611
612 if (debuglevel > 0) fprintf(stderr,"= %08lx%08lx%08lx%08lx\n", R.l, R.r, L.l, L.r);
613
614 /* unpack resulting L & R into output - undoing last swap */
615 ULONG64ToBYTE(outBuffer, R); outBuffer += 8;
616 ULONG64ToBYTE(outBuffer, L); outBuffer += 8;
617 }
618 return S_TRUE;
619}
620
621/*
622 * Dncrypt blocks in CBC mode
623 */
624static int deCBC(cipherInstance *cipher, keyInstance *key, BYTE *input,
625 int inputLen, BYTE *outBuffer)
626{
627 int i,j,k; /* assorted loop counters */
628 int blocks = inputLen / (BLOCK_SIZE*8); /* compute # input blocks */
629 ULONG64 L, R; /* left and right data blocks */
630 ULONG64 newIVL, newIVR; /* next IV L & R halves */
631 ULONG64 nR, f_out;
632
633 /* do some basic sanity checks on params */
634 if (inputLen % (BLOCK_SIZE*8) != 0) return BAD_CIPHER_INPUT;
635
636 /* now loop over all blocks of input */
637 for (j = 0; j < blocks; j++) {
638
639 /* pack input block into L and R */
640 L = byteToULONG64(input); input += 8;
641 R = byteToULONG64(input); input += 8;
642
643 /* save new IV value */
644 newIVL = L; newIVR = R;
645
646 if (debuglevel) fprintf(stderr,"%s: deCBC(%08lx%08lx%08lx%08lx) ", NAME, L.l, L.r, R.l, R.r);
647 if (debuglevel > 1) fprintf(stderr,"\n");
648
649 /* compute all rounds for this 1 block */
650 k = NUM_SUBKEYS - 1;
651 for (i = 0; i < ROUNDS; i++) {
652 nR = sub64(R, key->SK[k--]); /* nR = R+SK(k) */
653 f_out = f(nR, key->SK[k--]); /* f = f(nR,SK(k+1)) */
654 nR = sub64(nR, key->SK[k--]); /* nR = nR+SK(k+2) */
655 R.l = L.l ^ f_out.l; R.r = L.r ^ f_out.r; /* R = L XOR f */
656 L = nR; /* L = nR */
657 if (debuglevel > 1) fprintf(stderr," L[%02d]=%08lx%08lx; R[%02d]=%08lx%08lx; f(SK(%02d))=%08lx%08lx\n", i+1, L.l, L.r, i+1, R.l, R.r, k+2, f_out.l, f_out.r);
658 }
659
660 /* XOR with IV value (undoing last swap) */
661 R.l ^= cipher->IVL.l; R.r ^= cipher->IVL.r;
662 L.l ^= cipher->IVR.l; L.r ^= cipher->IVR.r;
663
664 /* save IV value */
665 cipher->IVL = newIVL; cipher->IVR = newIVR;
666
667 if (debuglevel > 0) fprintf(stderr,"= %08lx%08lx%08lx%08lx\n", R.l, R.r, L.l, L.r);
668
669 /* unpack resulting L & R into output - undoing last swap */
670 ULONG64ToBYTE(outBuffer, R); outBuffer += 8;
671 ULONG64ToBYTE(outBuffer, L); outBuffer += 8;
672 }
673 return S_TRUE;
674}
675
676/*
677 * decrypt blocks in CFB1 mode
678 */
679static int deCFB1(cipherInstance *cipher, keyInstance *key, BYTE *input,
680 int inputLen, BYTE *outBuffer)
681{
682 int i,j,k; /* assorted loop counters */
683 int b; /* bit number being processed in byte */
684 BYTE msgbit, prev, keybit; /* current & prev message and stream key bits */
685 ULONG64 L, R; /* left and right data blocks */
686 ULONG64 nR, f_out;
687
688 /* get CFB1 input buffer from IV */
689 L = cipher->IVL; R = cipher->IVR;
690
691 /* get ready to process first byte */
692 b = 7; /* start with top bit in byte */
693 *outBuffer = 0; /* and zero byte in outBuffer */
694
695 /* now loop over all bits of input */
696 for (j = 0; j < inputLen; j++) {
697 msgbit = (*input >> b) & 01; /* get next msg bit */
698 prev = msgbit; /* and save for shift register update */
699
700 if (debuglevel) fprintf(stderr,"%s: deCFB1(%01x,%08lx%08lx%08lx%08lx) ", NAME, msgbit, L.l, L.r, R.l, R.r);
701 if (debuglevel > 1) fprintf(stderr,"\n");
702
703 /* compute all rounds to encrypt current CFB1 buffer */
704 k = 0;
705 for (i = 0; i < ROUNDS; i++) {
706 nR = add64(R, key->SK[k++]); /* nR = R+SK(k) */
707 f_out = f(nR, key->SK[k++]); /* f = f(nR,SK(k+1)) */
708 nR = add64(nR, key->SK[k++]); /* nR = nR+SK(k+2) */
709 R.l = L.l ^ f_out.l; R.r = L.r ^ f_out.r; /* R = L XOR f */
710 L = nR; /* L = nR */
711 if (debuglevel > 1) fprintf(stderr," L[%02d]=%08lx%08lx; R[%02d]=%08lx%08lx; f(SK(%02d))=%08lx%08lx\n", i+1, L.l, L.r, i+1, R.l, R.r, k-2, f_out.l, f_out.r);
712 }
713 /* undo last swap */
714 L = R; R = nR;
715
716 /* now process msgbit by getting stream key bit, XOR in and or to out */
717 keybit = L.l >> 31;
718 msgbit ^= keybit;
719 *outBuffer |= (msgbit << b);
720
721 if (debuglevel > 0) fprintf(stderr,"= %01x,%08lx%08lx%08lx%08lx\n", msgbit, L.l, L.r, R.l, R.r);
722
723 /* and update the CFB1 shift register (input buffer L,R) */
724 L.l = (L.l << 1) | (L.r >> 31); L.r = (L.r << 1) | (R.l >> 31);
725 R.l = (R.l << 1) | (R.r >> 31); R.r = (R.r << 1) | prev;
726
727 /* and update bit position counter */
728 b--;
729 /* and move to next input/output byte if necessary */
730 if (b<0) { b = 7; input++; outBuffer++; *outBuffer = 0; }
731 }
732
733 /* save new IV value */
734 cipher->IVL = L; cipher->IVR = R;
735 return S_TRUE;
736}
737
738/* LOKI97 methods */
739/* ......................................................................... */
740
741/*
742 * f(A,B) = Sb(P(Sa(E(KP(A,hi(B))))),lo(B)) - complex non-linear round function
743 */
744static ULONG64 f(ULONG64 A, ULONG64 B)
745{
746
747 ULONG64 d, e, f; /* intermediate values in f computation */
748 register int s; /* s-box output value */
749
750 /* Intermediate values in the computation are: */
751 /* d = KP(A,Br) */
752 /* e = P(Sa(d)) */
753 /* f = Sb(e,Bl) */
754
755 /* Compute d = KP(A,B), where KP is a keyed permutation used to */
756 /* exchange corresponding bits in 32-bit words [Al,Ar] */
757 /* based on the lower half of B (swap if B bit is 1) */
758 /* KP(A,B) = ((Al & ~Br)|(Ar & Br)) | ((Ar & ~Br)|(Al & Br)) */
759
760 d.l = ((A.l & ~B.r) | (A.r & B.r));
761 d.r = ((A.r & ~B.r) | (A.l & B.r));
762
763 /* Compute e = P(Sa(d)) */
764 /* mask out each group of 12 bits for E */
765 /* then compute first S-box column [S1,S2,S1,S2,S2,S1,S2,S1] */
766 /* permuting output through P (with extra shift to build full P) */
767
768 s = S1[(d.l>>24 | d.r<<8) & 0x1FFF]; e.l = P[s].l>>7; e.r = P[s].r>>7;
769 s = S2[(d.l>>16) & 0x7FF]; e.l |= P[s].l>>6; e.r |= P[s].r>>6;
770 s = S1[(d.l>> 8) & 0x1FFF]; e.l |= P[s].l>>5; e.r |= P[s].r>>5;
771 s = S2[ d.l & 0x7FF]; e.l |= P[s].l>>4; e.r |= P[s].r>>4;
772 s = S2[(d.r>>24 | d.l<<8) & 0x7FF]; e.l |= P[s].l>>3; e.r |= P[s].r>>3;
773 s = S1[(d.r>>16) & 0x1FFF]; e.l |= P[s].l>>2; e.r |= P[s].r>>2;
774 s = S2[(d.r>> 8) & 0x7FF]; e.l |= P[s].l>>1; e.r |= P[s].r>>1;
775 s = S1[ d.r & 0x1FFF]; e.l |= P[s].l; e.r |= P[s].r;
776
777 /* Compute f = Sb(e,B) */
778 /* where the second S-box column is [S2,S2,S1,S1,S2,S2,S1,S1] */
779 /* for each S, lower bits come from e, upper from upper half of B */
780
781 f.l = S2[(((e.l>>24) & 0xFF) | ((B.l>>21) & 0x700))] << 24 |
782 S2[(((e.l>>16) & 0xFF) | ((B.l>>18) & 0x700))] << 16 |
783 S1[(((e.l>> 8) & 0xFF) | ((B.l>>13) & 0x1F00))] << 8 |
784 S1[(((e.l ) & 0xFF) | ((B.l>> 8) & 0x1F00))];
785 f.r = S2[(((e.r>>24) & 0xFF) | ((B.l>> 5) & 0x700))] << 24 |
786 S2[(((e.r>>16) & 0xFF) | ((B.l>> 2) & 0x700))] << 16 |
787 S1[(((e.r>> 8) & 0xFF) | ((B.l<< 3) & 0x1F00))] << 8 |
788 S1[(( e.r & 0xFF) | ((B.l<< 8) & 0x1F00))];
789
790 if (debuglevel > 3) fprintf(stderr,"%s: f(%08lx%08lx,%08lx%08lx) = %08lx%08lx\n", NAME, A.l, A.r, B.l, B.r, f.l, f.r);
791 if (debuglevel > 4) fprintf(stderr,"%s: d=%08lx%08lx; e=%08lx%08lx\n", NAME, d.l, d.r, e.l, e.r);
792
793 return f;
794}
795
796/* utility methods */
797/* ......................................................................... */
798
799/* add64(a,b) - fudge 64-bit addition of ULONG64's a and b */
800/* thanks to Markku-Juhani Saarinen <mjos@ssh.fi> for the nice tips */
801static ULONG64 add64(ULONG64 a, ULONG64 b)
802{
803 ULONG64 sum; /* sum = a + b */
804
805 sum.r = a.r + b.r; /* add lower half */
806 sum.l = a.l + b.l; /* add upper half without carry */
807 if (sum.r < b.r) sum.l++; /* add carry if needed */
808
809 return sum; /* return resulting sum */
810}
811
812/* sub64(a,b) - fudge 64-bit subtraction of ULONG64's a and b */
813/* thanks to Markku-Juhani Saarinen <mjos@ssh.fi> for the nice tips */
814static ULONG64 sub64(ULONG64 a, ULONG64 b)
815{
816 ULONG64 diff; /* diff = a + b */
817
818 diff.r = a.r - b.r; /* sub lower 32-bits */
819 diff.l = a.l - b.l; /* sub upper 32-bits */
820 if (diff.r > a.r) diff.l--; /* sub borrow if needed */
821
822 return diff; /* return resulting diff */
823}
824
825/* Returns a ULONG64 I constructed from a byte array. */
826static ULONG64 byteToULONG64(BYTE *inp)
827{
828 ULONG64 I;
829 I.l = (*inp++ << 24);
830 I.l |= (*inp++ << 16);
831 I.l |= (*inp++ << 8);
832 I.l |= *inp++;
833 I.r = (*inp++ << 24);
834 I.r |= (*inp++ << 16);
835 I.r |= (*inp++ << 8);
836 I.r |= *inp++;
837 return I;
838}
839
840/* Returns a byte array buf constructed by unpacking ULONG64 I. */
841static BYTE *ULONG64ToBYTE(BYTE *buf, ULONG64 I)
842{
843 BYTE *sav = buf;
844 *buf++ = (I.l >> 24);
845 *buf++ = (I.l >> 16);
846 *buf++ = (I.l >> 8);
847 *buf++ = I.l;
848 *buf++ = (I.r >> 24);
849 *buf++ = (I.r >> 16);
850 *buf++ = (I.r >> 8);
851 *buf++ = I.r;
852 return sav;
853}
854
855/* Returns a BYTE array from a string of hexadecimal digits. */
856static BYTE *charToBYTE(BYTE *buf, unsigned char *hex, int len)
857{
858 int i = 0, j = 0;
859 while (j < len) {
860 buf[j++] = (BYTE)((fromHex(hex[i++])<<4) | fromHex(hex[i++]));
861 }
862 return buf;
863}
864
865/* Returns a ULONG64 I constructed from a string of hexadecimal digits. */
866/*static ULONG64 charToULONG64(unsigned char *hex)
867{
868 ULONG64 I;
869 I.l = fromHex(*hex++) << 28;
870 I.l |= fromHex(*hex++) << 24;
871 I.l |= fromHex(*hex++) << 20;
872 I.l |= fromHex(*hex++) << 16;
873 I.l |= fromHex(*hex++) << 12;
874 I.l |= fromHex(*hex++) << 8;
875 I.l |= fromHex(*hex++) << 4;
876 I.l |= fromHex(*hex++);
877 I.r = fromHex(*hex++) << 28;
878 I.r |= fromHex(*hex++) << 24;
879 I.r |= fromHex(*hex++) << 20;
880 I.r |= fromHex(*hex++) << 16;
881 I.r |= fromHex(*hex++) << 12;
882 I.r |= fromHex(*hex++) << 8;
883 I.r |= fromHex(*hex++) << 4;
884 I.r |= fromHex(*hex++);
885 return I;
886} */
887
888/* Returns number from 0 to 15 corresponding to hex digit ch */
889static int fromHex (unsigned char ch)
890{
891 if (ch >= '0' && ch <= '9')
892 return ch - '0';
893 else if (ch >= 'A' && ch <= 'F')
894 return ch - 'A' + 10;
895 else if (ch >= 'a' && ch <= 'f')
896 return ch - 'a' + 10;
897 else
898 return 0;
899}
900
901/* puthex(out, len, f) - display a len byte value out in hex to file f */
902void puthex(BYTE *out, int len, FILE *f)
903{
904 int i;
905 for(i=0;i<len;i++){
906 fprintf(f, "%02x",*out++ & 0xff);
907 }
908 fputc(' ', f);
909}
910
911/* ......................................................................... */
912/*
913 * self_test() - Encryption/decryption test using the standard single triple
914 * returns true or error code
915 */
916int self_test()
917{
918 int enok = S_TRUE, deok = S_TRUE;
919 //unsigned char *hexkey = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F";
920 unsigned char hexkey[32] = {
921 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
922 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
923 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
924 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1F
925 };
926
927 unsigned char *hexcipher = "75080e359f10fe640144b35c57128dad";
928
929 //unsigned char *hexIV = "00000000000000000000000000000000";
930 /*unsigned char hexIV[16] = {
931 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
932 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
933 }; */
934
935 BYTE plain[BLOCK_SIZE] =
936 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
937 BYTE etemp[BLOCK_SIZE], dtemp[BLOCK_SIZE], cipher[BLOCK_SIZE];
938 keyInstance enc_key, dec_key; /* AES keyInstances */
939 cipherInstance loki97_cipher; /* AES cipherInstance */
940 int st;
941
942 /* construct desired cipher block */
943 charToBYTE(cipher,hexcipher,sizeof(cipher));
944
945 /* Init LOKI97 cipher in ECB mode */
946 st = cipherInit(&loki97_cipher, MODE_CBC, ""); if (st != S_TRUE) return st;
947
948 /* test encrypt */
949 st = makeKey(&enc_key, DIR_ENCRYPT, 256, hexkey); if (st != S_TRUE) return st;
950 st = makeKey(&dec_key, DIR_DECRYPT, 256, hexkey); if (st != S_TRUE) return st;
951 fprintf(stderr,"Plaintext is: ");
952 puthex(plain,16,stderr); fprintf(stderr,"\n");
953
954 st = blockEncrypt(&loki97_cipher, &enc_key, plain, sizeof(plain)*8, etemp);
955 if (st != S_TRUE) return st;
956 if (memcmp(etemp, cipher, sizeof(etemp)) != 0) enok = S_FALSE;
957 fprintf(stderr,"Test encrypt: "); puthex(etemp,16,stderr);
958 fprintf(stderr," %s\n", (enok?"GOOD" : "FAILED"));
959
960 /* test decrypt */
961 st = blockDecrypt(&loki97_cipher, &dec_key, etemp, sizeof(etemp)*8, dtemp);
962 if (st != S_TRUE) return st;
963 if (memcmp(dtemp, plain, sizeof(dtemp)) != 0) deok = S_FALSE;
964 fprintf(stderr,"Test decrypt: "); puthex(dtemp,16,stderr);
965 fprintf(stderr," %s\n", (deok?"GOOD" : "FAILED"));
966
967 return (enok && deok); /* return S_TRUE only if both en & decrypt ok */
968}
969
970int main(void)
971{
972 int st;
973
974 printf("LOKI97 Self_test\n");
975 st = self_test();
976 printf("LOKI97 self_test returned %s (%d)\n", (st ? "OK" : "BAD"), st);
977 return 0;
978}