css-auth.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:8k
- /*
- * Copyright (C) 1999
- * Derek Fawcus <derek@spider.com>
- * Mark Roberts <maroberts@dial.pipex.com>
- * This code may be used under the terms of Version 2 of the GPL,
- * read the file COPYING for details.
- *
- */
- #include <stdio.h>
- #include "css.h"
- #include "css-auth.h"
- typedef unsigned long u32;
- /*
- * We use two LFSR's (seeded from some of the input data bytes) to
- * generate two streams of pseudo-random bits. These two bit streams
- * are then combined by simply adding with carry to generate a final
- * sequence of pseudo-random bits which is stored in the buffer that
- * 'output' points to the end of - len is the size of this buffer.
- *
- * The first LFSR is of degree 25, and has a polynomial of:
- * x^13 + x^5 + x^4 + x^1 + 1
- *
- * The second LSFR is of degree 17, and has a (primitive) polynomial of:
- * x^15 + x^1 + 1
- *
- * I don't know if these polynomials are primitive modulo 2, and thus
- * represent maximal-period LFSR's.
- *
- *
- * Note that we take the output of each LFSR from the new shifted in
- * bit, not the old shifted out bit. Thus for ease of use the LFSR's
- * are implemented in bit reversed order.
- *
- */
- static void generate_bits(byte *output, int len, byte *s)
- {
- u32 lfsr0, lfsr1;
- int val;
- byte o_lfsr0, o_lfsr1;
- /* In order to ensure that the LFSR works we need to ensure that the
- * initial values are non-zero. Thus when we initialise them from
- * the seed, we ensure that a bit is set.
- */
- lfsr0 = (s[0] << 17) | (s[1] << 9) | ((s[2] & ~7) << 1) | 8 | (s[2] & 7);
- /*
- reverse lfsr0/1 to simplify calculation in loop
- */
- lfsr0 = (reverse[lfsr0&0xff]<<17) | (reverse[(lfsr0>>8)&0xff] << 9)
- | (reverse[(lfsr0>>16)&0xff]<<1) |(lfsr0>>24);
- lfsr1 = (reverse[s[4]] << 9) | 0x100 | ( reverse[ s[3]] );
- ++output;
- val = 0;
- do {
- /*
- reversed verion of
- o_lfsr0 = (lfsr0 >> 17) ^ (lfsr0 >> 14) ^ (lfsr0 >> 13) ^ (lfsr0 >> 5);
- lfsr0 = (lfsr0 << 8) ^ o_lfsr0
-
- o_lfsr1 = lfsr1 & 7;
- o_lfsr1 = (o_lfsr1 << 5) ^ (o_lfsr1 << 2) ^ (o_lfsr1 >> 1);
- o_lfsr1 ^= (lfsr1 >> 9) ^ (lfsr1 >> 12) ^ (lfsr1 >> 15);
- lfsr1 = (lfsr1 << 8) ^ o_lfsr1
- */
- o_lfsr0 = (lfsr0 >> 12) ^ (lfsr0 >> 4) ^ (lfsr0 >> 3) ^ lfsr0;
- o_lfsr1 = ((lfsr1 >> 14) & 7) ^ lfsr1;
- o_lfsr1 ^= (o_lfsr1 << 3) ^ (o_lfsr1 << 6);
- lfsr1 = (lfsr1 >> 8) ^ (o_lfsr1 << 9);
- lfsr0 = (lfsr0 >> 8) ^ (o_lfsr0 << 17);
- o_lfsr0 = ~o_lfsr0;
- o_lfsr1 = ~o_lfsr1;
- val += o_lfsr0 + o_lfsr1;
-
- *--output = val & 0xFF;
- val >>= 8;
- #if (CSSDEBUG & 2)
- fprintf(stderr, "lfsr0=%08x lfsr1=%08xn", lfsr0, lfsr1);
- #endif
- } while (--len > 0);
- }
- /*-----------------------------------------------------------------------*
- If this was C++, these would be inline functions
- *-----------------------------------------------------------------------*/
- #define MANGLE1(bs,ip,op)
- in = ip; out = op; bp = bs;
- for (i = 5, term = 0; --i >= 0; term = in[i]) {
- index = bp[i] ^ in[i];
- index = CSSmangle1[index] ^ cse;
- out[i] = CSSmangle2[index] ^ term;
- }
- #define MANGLE2( bs, ip, op)
- in = ip; out = op; bp = bs;
- for (i = 5, term = 0; --i >= 0; term = in[i]) {
- index = bp[i] ^ in[i];
- index = CSSmangle1[index] ^ cse;
- index = CSSmangle2[index] ^ term;
- out[i] = CSSmangle0[index];
- }
- /*
- * This encryption engine implements one of 32 variations
- * one the same theme depending upon the choice in the
- * varient parameter (0 - 31).
- *
- * The algorithm itself manipulates a 40 bit input into
- * a 40 bit output.
- * The parameter 'input' is 80 bits. It consists of
- * the 40 bit input value that is to be encrypted followed
- * by a 40 bit seed value for the pseudo random number
- * generators.
- */
- static void engine(int varient, const byte *input, byte *output)
- {
- byte cse, term, index;
- byte temp1[5], temp2[5];
- byte bits[30];
- const byte *in;
- byte *out;
- byte *bp;
- int i;
- /* Feed the secret into the input values such that
- * we alter the seed to the LFSR's used above, then
- * generate the bits to play with.
- */
- for (i = 5; --i >= 0; )
- temp1[i] = input[5 + i] ^ CSSsecret[i];
- generate_bits(&bits[29], sizeof bits, &temp1[0]);
- #if (CSSDEBUG & 1)
- fprintf(stderr, "nBits: ");
- print_tab( &bits[0], 30);
- #endif
- /* This term is used throughout the following to
- * select one of 32 different variations on the
- * algorithm.
- */
- cse = CSSvarients[varient];
- /* Now the actual blocks doing the encryption. Each
- * of these works on 40 bits at a time and are quite
- * similar.
- */
- MANGLE1( &bits[25], input, &temp1[0]);
- out[4] ^= out[0];
- #if (CSSDEBUG & 1)
- fprintf(stderr"nRound 1: ");
- print_tab( &out[0], 5);
- #endif
- MANGLE1( &bits[20], &temp1[0], &temp2[0]);
- out[4] ^= out[0];
- #if (CSSDEBUG & 1)
- fprintf(stderr, "nRound 2: ");
- print_tab( &out[0], 5);
- #endif
- MANGLE2( &bits[15], temp2, temp1);
- out[4] ^= out[0];
- #if (CSSDEBUG & 1)
- fprintf( stderr, "nRound 3: ");
- print_tab( &out[0], 5);
- #endif
- MANGLE2( &bits[10], temp1, temp2);
- out[4] ^= out[0];
- #if (CSSDEBUG & 1)
- fprintf(stderr, "nRound 4: ");
- print_tab( &out[0], 5);
- #endif
- MANGLE1( &bits[5], temp2, temp1);
- out[4] ^= out[0];
- #if (CSSDEBUG & 1)
- fprintf(stderr, "nRound 5: ");
- print_tab( &out[0], 5);
- #endif
- MANGLE1( &bits[0], temp1, output);
- #if (CSSDEBUG & 1)
- fprintf(stderr, "nRound 6: ");
- print_tab( &out[0], 5);
- #endif
- }
- /*
- * These routines do some reordering of the supplied data before
- * calling engine() to do the main work.
- *
- * The reordering seems similar to that done by the initial stages of
- * the DES algorithm, in that it looks like it's just been done to
- * try and make software decoding slower. I'm not sure that it
- * actually adds anything to the security.
- *
- * The nature of the shuffling is that the bits of the supplied
- * parameter 'varient' are reorganised (and some inverted), and
- * the bytes of the parameter 'challenge' are reorganised.
- *
- * The reorganisation in each routine is different, and the first
- * (CryptKey1) does not bother of play with the 'varient' parameter.
- *
- * Since this code is only run once per disk change, I've made the
- * code table driven in order to improve readability.
- *
- * Since these routines are so similar to each other, one could even
- * abstract them all to one routine supplied a parameter determining
- * the nature of the reordering it has to do.
- */
- void CryptKey1(int varient, byte const *challenge, struct block *key)
- {
- static byte perm_challenge[] = {1,3,0,7,5, 2,9,6,4,8};
- byte scratch[10];
- int i;
- for (i = 9; i >= 0; --i)
- scratch[i] = challenge[perm_challenge[i]];
- engine(varient, scratch, &key->b[0]);
- }
- /* This shuffles the bits in varient to make perm_varient such that
- * 4 -> !3
- * 3 -> 4
- * varient bits: 2 -> 0 perm_varient bits
- * 1 -> 2
- * 0 -> !1
- */
- void CryptKey2(int varient, byte const *challenge, struct block *key)
- {
- static byte perm_challenge[] = {6,1,9,3,8, 5,7,4,0,2};
- static byte perm_varient[] = {
- 0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d,
- 0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d,
- 0x02, 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05,
- 0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15};
- byte scratch[10];
- int i;
- for (i = 9; i >= 0; --i)
- scratch[i] = challenge[perm_challenge[i]];
- engine(perm_varient[varient], scratch, &key->b[0]);
- }
- /* This shuffles the bits in varient to make perm_varient such that
- * 4 -> 0
- * 3 -> !1
- * varient bits: 2 -> !4 perm_varient bits
- * 1 -> 2
- * 0 -> 3
- */
- void CryptBusKey(int varient, byte const *challenge, struct block *key)
- {
- static byte perm_challenge[] = {4,0,3,5,7, 2,8,6,1,9};
- static byte perm_varient[] = {
- 0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e,
- 0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c,
- 0x13, 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f,
- 0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d};
- byte scratch[10];
- int i;
- for (i = 9; i >= 0; --i)
- scratch[i] = challenge[perm_challenge[i]];
- engine(perm_varient[varient], scratch, &key->b[0]);
- }