Module Information
Public.Crypto.CRC
Viewing contents of Public_Crypto_CRC-0.1/module.pmod.in
// -*- Pike -*-
// Copyright (c) 2009-2010, Marc Dirix, The Netherlands.
//
//
// This script is open source software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2, or (at your option) any
// later version.
//
#pike __REAL_VERSION__
//! CRC used in USB Token and Start-Of-Frame packets
CrcAlgorithm CRC5_USB()
{
return CrcAlgorithm( 5, ({ 5, 2, 0 }), 0x1F , 1, 0, 0x1F );
}
//! Used in ATM HEC and SMBus.
CrcAlgorithm CRC8_SMBUS()
{
return CrcAlgorithm( 8, ({ 8, 2, 1, 0 }), 0 , 0, 0, 0 );
}
//! Used in Controller Area Network Frames
CrcAlgorithm CRC15()
{
return CrcAlgorithm( 15, ({ 15, 14, 10, 8, 7, 4, 3, 0 }), 0 , 0, 0, 0 );
}
//! CRC16 IBM Standard
CrcAlgorithm CRC16()
{
return CrcAlgorithm( 16, ({ 16, 15, 2, 0 }), 0 , 1, 0, 0 );
}
//! CRC16 xmodem or zmodem. Also used for PlugWise.
CrcAlgorithm CRC16X()
{
return CrcAlgorithm( 16, 0x11021, 0, 0, 0 , 0);
}
//! Used in USB data packets
CrcAlgorithm CRC16_USB()
{
return CrcAlgorithm( 16, ({ 16, 15, 2, 0 }), 0xFFFF , 1, 0, 0xFFFF );
}
//! CRC16 CCITT
//! @param seed
//! A integer starting value. If not set, seed=0xFFFF
CrcAlgorithm CRC_CCITT(int | void seed)
{
int z = seed | 0xFFFF;
return CrcAlgorithm( 16, ({ 16, 12, 5, 0 }), z , 0, 0, 0x0000 );
}
//! This is the algorithm used in X.25 and for the HDLC 2-byte FCS.
CrcAlgorithm CRC_HDLC()
{
return CrcAlgorithm( 16, ({ 16, 12, 5, 0 }), 0xFFFF , 1, 0, 0xFFFF );
}
//! Used in RFC-2440 and MIL STD 188-184
CrcAlgorithm CRC24()
{
return CrcAlgorithm( 24, ({ 24, 23, 18, 17, 14, 11, 10, 7, 6, 5, 4, 3, 1, 0}), 0xB704CE , 0, 0, 0 );
}
//! 32 Bit CRC algorithm.
CrcAlgorithm CRC32()
{
return CrcAlgorithm( 32, ({ 32, 26, 23, 22, 16, 12, 11, 10, 8, 7, 5, 4, 2, 1, 0 }), 0xFFFFFFFF , 1, 0, 0xFFFFFFFF );
}
//! Used iSCSI (RFC-3385); usually credited to Guy Castagnoli
CrcAlgorithm CRC32C()
{
return CrcAlgorithm( 16, ({ 32, 28, 27, 26, 25, 23, 22, 20, 19, 18, 14, 13, 11, 10, 9, 8, 6, 0 }), 0xFFFFFFFF , 1, 0, 0xFFFFFFFF );
}
//! ISO 3309
CrcAlgorithm CRC64()
{
return CrcAlgorithm( 64, ({ 64, 4, 3, 1, 0 }), 0 , 1, 0, 0 );
}
//! A 256 bit CRC.
CrcAlgorithm CRC256()
{
return CrcAlgorithm( 256,
0x82E2443E6320383A20B8A2A0A1EA91A3CCA99A30C5205038349C82AAA3A8FD2,
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
1, 0, 0 );
}
//! Inverts an integer.
//! @param value
//! The integer to be inverted.
//! @param width
//! The bit-length of the integer.
int reflect(int value, int width)
{
int ret=0;
for(int i=0; i> i) & 1) << (width -1 -i));
return ret;
}
//! The main CRC class.
class CrcAlgorithm
{
array polynomial=({});
int seed=0;
int width;
int lsbfirst=0;
int lsbfirstdata=0;
int xormask=0;
//! Creates a CRC object.
//! @param width
//! The length of the polynomial.
//! @param polynomial
//! The polynomial, either an array or integer.
//! @param seed
//! The starting value of the algoritm
//! @param lsbfirst
//! Calculate the CRC from msb to lsb (zero) or lsb to msb (non zero).
//! @param lsbfirstdata
//! Calculate the data words from msb to lsb (zero) or lsb to msb (non zero).
//! If lsbfirstdata is zero, lsbfirstdata behaviour follows lsbfirst.
//! @param xormask
//! The output mask for the final computed CRC.
void create(int width, int|array polynomial, int seed, int lsbfirst, int lsbfirstdata,int xormask)
{
int polymask;
this->width=width;
this->seed=seed;
this->lsbfirst=lsbfirst;
this->lsbfirstdata=lsbfirstdata;
this->xormask=xormask;
if (arrayp(polynomial))
this->polynomial=polynomial;
else
{
polymask=polynomial;
if(lsbfirst)
polymask=reflect(polymask,width);
this->polynomial = ({width});
for( int i=(width-1); i>=0 ; --i)
{
if ( (polymask >> i) & 1)
{
this->polynomial +=({i});
}
}
}
}
//! Calculate and returns CRC over a string.
//! @param s
//! The string over which the CRC has to be calculated.
int calcstring( string s )
{
object a = CrcRegister( this );
a->takestring(s);
return a->getfinalvalue();
}
}
//! This Class holds the intermediate state of the CRC algorithm
class CrcRegister()
{
CrcAlgorithm alg;
int bitmask;
int polymask;
int lsbfirstdata=0;
int inbitmask;
int outbitmask;
int value;
//! Create the object.
//! @param alg
//! The CRC object.
void create( CrcAlgorithm alg )
{
this->alg = alg;
bitmask = (1 << alg->width) -1;
int word = 0;
foreach(alg->polynomial,int n)
word |= 1 << n;
polymask = word & bitmask;
if(alg->lsbfirst)
{
polymask = reflect(polymask,alg->width);
inbitmask = 1 << (alg->width -1 );
outbitmask = 1;
}
else
{
this->inbitmask = 1;
this->outbitmask = 1 << ( alg->width -1 );
}
this->lsbfirstdata = alg->lsbfirstdata | alg->lsbfirst;
this->value = alg->seed;
}
//! Add's one bit to the CRC calculation.
void takebit( int bit )
{
int outbit;
if ( bit > 1 || bit < 0 )
werror( "Values other then 0 or 1 are not allowed for bits\n");
outbit = ((this->value & this->outbitmask) !=0 );
if ( alg->lsbfirst )
value >>= 1;
else
value <<= 1;
value &= bitmask;
if ( outbit ^ bit )
value ^= polymask;
}
//! Add one word (int) to the CRC calculation.
//! @param word
//! The added word (int)
//! @param width
//! The bitlength of the word value.
//! If none given a bitlength of 8 is assumed.
void takeword( int word, int|void width )
{
int len = 8;
if ( width > 0 )
len = width;
if ( this->lsbfirstdata )
for ( int i = 0; i < len; i++ )
this->takebit( (word >> i) & 1 );
else
for ( int i = (len-1) ; i >= 0 ; i-- )
this->takebit( (word >> i) & 1 );
}
//! Add a string to the CRC computation.
//! @param s
//! The string to be added.
void takestring( string s )
{
int len = String.width(s);
foreach( s/"", string s)
takeword( s[0] , len);
}
//! Get the current intermediate state of the CRC algoritm.
int getvalue()
{
return value;
}
//! Returns the computed CRC value with xormask applied.
int getfinalvalue()
{
return value ^ alg->xormask;
}
}
|
|