// diamond.cpp - modified by Wei Dai from: /* diamond2.c - Encryption designed to exceed DES in security. This file and the Diamond2 and Diamond2 Lite Block Ciphers described herein are hereby dedicated to the Public Domain by the author and inventor, Michael Paul Johnson. Feel free to use these for any purpose that is legally and morally right. The names "Diamond2 Block Cipher" and "Diamond2 Lite Block Cipher" should only be used to describe the algorithms described in this file, to avoid confusion. Disclaimers: the following comes with no warranty, expressed or implied. You, the user, must determine the suitability of this information to your own uses. You must also find out what legal requirements exist with respect to this data and programs using it, and comply with whatever valid requirements exist. */ #include "pch.h" #include "diamond.h" #include "crc.h" NAMESPACE_BEGIN(CryptoPP) class Diamond2SboxMaker { public: Diamond2SboxMaker(const byte *external_key, unsigned int key_size, unsigned int rounds, bool lite); void MakeSbox(byte *sbox, CipherDir direction); private: unsigned int keyrand(unsigned int max_value, const byte *prevSbox); void makeonebox(byte *s, unsigned int i, unsigned int j); CRC32 crc; const byte *const key; const unsigned keysize; unsigned keyindex; const unsigned numrounds; const unsigned roundsize; // Number of bytes in one round of substitution boxes const unsigned blocksize; }; Diamond2SboxMaker::Diamond2SboxMaker(const byte *external_key, unsigned int key_size, unsigned int rounds, bool lite) : key(external_key), keysize(key_size), keyindex(0), numrounds(rounds), roundsize(lite ? 2048 : 4096), blocksize(lite ? 8 : 16) { assert((rounds * blocksize) <= 255); } // Returns uniformly distributed pseudorandom value based on key[], sized keysize inline unsigned int Diamond2SboxMaker::keyrand(unsigned int max_value, const byte *prevSbox) { assert(max_value <= 255); if (!max_value) return 0; unsigned int mask, prandvalue, i; // Create a mask to get the minimum number of // bits to cover the range 0 to max_value. for (i=max_value, mask=0; i > 0; i = i >> 1) mask = (mask << 1) | 1; assert(i==0); do { if (prevSbox) crc.UpdateByte(prevSbox[key[keyindex++]]); else crc.UpdateByte(key[keyindex++]); if (keyindex >= keysize) { keyindex = 0; /* Recycle thru the key */ crc.UpdateByte(byte(keysize)); crc.UpdateByte(byte(keysize >> 8)); } prandvalue = crc.GetCrcByte(0) & mask; if ((++i>97) && (prandvalue > max_value)) /* Don't loop forever. */ prandvalue -= max_value; /* Introduce negligible bias. */ } while (prandvalue > max_value); /* Discard out of range values. */ return prandvalue; } void Diamond2SboxMaker::makeonebox(byte *s, unsigned int i, unsigned int j) { bool filled[256]; byte *sbox = s + (roundsize*i) + (256*j); byte *prevSbox = (i||j) ? sbox-256 : 0; unsigned m; for (m = 0; m < 256; m++) /* The filled array is used to make sure that */ filled[m] = false; /* each byte of the array is filled only once. */ for (int n = 255; n >= 0 ; n--) /* n counts the number of bytes left to fill */ { // pos is the position among the UNFILLED // components of the s array that the number n should be placed. unsigned pos = keyrand(n, prevSbox); unsigned p=0; while (filled[p]) p++; for (m=0; m= 0; round--) { ipermute(y); substitute(round, y, y); } if (xorBlock) xorbuf(outBlock, xorBlock, y, BLOCKSIZE); else memcpy(outBlock, y, BLOCKSIZE); } void Diamond2Lite::Base::UncheckedSetKey(CipherDir direction, const byte *userKey, unsigned int length, unsigned int rounds) { AssertValidKeyLength(length); numrounds = rounds; s.New(numrounds * ROUNDSIZE); Diamond2SboxMaker m(userKey, length, rounds, true); m.MakeSbox(s, direction); } inline void Diamond2Lite::Base::substitute(int round, byte *x, const byte *y) const { const byte *sbox = s + (ROUNDSIZE*round); x[0] = sbox[0*256+y[0]]; x[1] = sbox[1*256+y[1]]; x[2] = sbox[2*256+y[2]]; x[3] = sbox[3*256+y[3]]; x[4] = sbox[4*256+y[4]]; x[5] = sbox[5*256+y[5]]; x[6] = sbox[6*256+y[6]]; x[7] = sbox[7*256+y[7]]; } #ifdef DIAMOND_USE_PERMTABLE inline void Diamond2Lite::Base::permute(byte *a) { word32 temp = permtable[0][a[0]] | permtable[1][a[1]] | permtable[2][a[2]] | permtable[3][a[3]] | permtable[4][a[4]] | permtable[5][a[5]] | permtable[6][a[6]] | permtable[7][a[7]]; ((word32 *)a)[1] = permtable[0][a[4]] | permtable[1][a[5]] | permtable[2][a[6]] | permtable[3][a[7]] | permtable[4][a[0]] | permtable[5][a[1]] | permtable[6][a[2]] | permtable[7][a[3]]; ((word32 *)a)[0] = temp; } inline void Diamond2Lite::Base::ipermute(byte *a) { word32 temp = ipermtable[0][a[0]] | ipermtable[1][a[1]] | ipermtable[2][a[2]] | ipermtable[3][a[3]] | ipermtable[4][a[4]] | ipermtable[5][a[5]] | ipermtable[6][a[6]] | ipermtable[7][a[7]]; ((word32 *)a)[1] = ipermtable[0][a[4]] | ipermtable[1][a[5]] | ipermtable[2][a[6]] | ipermtable[3][a[7]] | ipermtable[4][a[0]] | ipermtable[5][a[1]] | ipermtable[6][a[2]] | ipermtable[7][a[3]]; ((word32 *)a)[0] = temp; } #else inline void Diamond2Lite::Base::permute(byte *a) { byte b[8]; b[0] = (a[0] & 1) + (a[1] & 2) + (a[2] & 4) + (a[3] & 8) + (a[4] & 0x10) + (a[5] & 0x20) + (a[6] & 0x40) + (a[7] & 0x80); b[1] = (a[1] & 1) + (a[2] & 2) + (a[3] & 4) + (a[4] & 8) + (a[5] & 0x10) + (a[6] & 0x20) + (a[7] & 0x40) + (a[0] & 0x80); b[2] = (a[2] & 1) + (a[3] & 2) + (a[4] & 4) + (a[5] & 8) + (a[6] & 0x10) + (a[7] & 0x20) + (a[0] & 0x40) + (a[1] & 0x80); b[3] = (a[3] & 1) + (a[4] & 2) + (a[5] & 4) + (a[6] & 8) + (a[7] & 0x10) + (a[0] & 0x20) + (a[1] & 0x40) + (a[2] & 0x80); b[4] = (a[4] & 1) + (a[5] & 2) + (a[6] & 4) + (a[7] & 8) + (a[0] & 0x10) + (a[1] & 0x20) + (a[2] & 0x40) + (a[3] & 0x80); b[5] = (a[5] & 1) + (a[6] & 2) + (a[7] & 4) + (a[0] & 8) + (a[1] & 0x10) + (a[2] & 0x20) + (a[3] & 0x40) + (a[4] & 0x80); b[6] = (a[6] & 1) + (a[7] & 2) + (a[0] & 4) + (a[1] & 8) + (a[2] & 0x10) + (a[3] & 0x20) + (a[4] & 0x40) + (a[5] & 0x80); b[7] = (a[7] & 1) + (a[0] & 2) + (a[1] & 4) + (a[2] & 8) + (a[3] & 0x10) + (a[4] & 0x20) + (a[5] & 0x40) + (a[6] & 0x80); memcpy(a, b, 8); } inline void Diamond2Lite::Base::ipermute(byte *b) { byte a[8]; a[0] = (b[0] & 1) + (b[7] & 2) + (b[6] & 4) + (b[5] & 8) + (b[4] & 0x10) + (b[3] & 0x20) + (b[2] & 0x40) + (b[1] & 0x80); a[1] = (b[1] & 1) + (b[0] & 2) + (b[7] & 4) + (b[6] & 8) + (b[5] & 0x10) + (b[4] & 0x20) + (b[3] & 0x40) + (b[2] & 0x80); a[2] = (b[2] & 1) + (b[1] & 2) + (b[0] & 4) + (b[7] & 8) + (b[6] & 0x10) + (b[5] & 0x20) + (b[4] & 0x40) + (b[3] & 0x80); a[3] = (b[3] & 1) + (b[2] & 2) + (b[1] & 4) + (b[0] & 8) + (b[7] & 0x10) + (b[6] & 0x20) + (b[5] & 0x40) + (b[4] & 0x80); a[4] = (b[4] & 1) + (b[3] & 2) + (b[2] & 4) + (b[1] & 8) + (b[0] & 0x10) + (b[7] & 0x20) + (b[6] & 0x40) + (b[5] & 0x80); a[5] = (b[5] & 1) + (b[4] & 2) + (b[3] & 4) + (b[2] & 8) + (b[1] & 0x10) + (b[0] & 0x20) + (b[7] & 0x40) + (b[6] & 0x80); a[6] = (b[6] & 1) + (b[5] & 2) + (b[4] & 4) + (b[3] & 8) + (b[2] & 0x10) + (b[1] & 0x20) + (b[0] & 0x40) + (b[7] & 0x80); a[7] = (b[7] & 1) + (b[6] & 2) + (b[5] & 4) + (b[4] & 8) + (b[3] & 0x10) + (b[2] & 0x20) + (b[1] & 0x40) + (b[0] & 0x80); memcpy(b, a, 8); } #endif // DIAMOND_USE_PERMTABLE void Diamond2Lite::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const { const byte *x = inBlock; byte y[8]; substitute(0, y, x); for (int round=1; round < numrounds; round++) { permute(y); substitute(round, y, y); } if (xorBlock) xorbuf(outBlock, xorBlock, y, BLOCKSIZE); else memcpy(outBlock, y, BLOCKSIZE); } void Diamond2Lite::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const { const byte *x = inBlock; byte y[8]; substitute(numrounds-1, y, x); for (int round=numrounds-2; round >= 0; round--) { ipermute(y); substitute(round, y, y); } if (xorBlock) xorbuf(outBlock, xorBlock, y, BLOCKSIZE); else memcpy(outBlock, y, BLOCKSIZE); } NAMESPACE_END