// // Copyright (c) 2003-2006 Robin J Carey. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions, and the following disclaimer, // without modification, immediately at the beginning of the file. // 2. The name of the author may not be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. // // # ifndef OOO__L15_h__OOO # define OOO__L15_h__OOO // ``ISO C89''/``ANSI C'' // # include // For: size_t // IMPORTANT NOTE: LByteType must be exactly 8-bits in size or this software // will not function correctly. The "unsigned char" type should really be // replaced with "uint8_t" from /``ISO C99''. // typedef unsigned char LByteType; // If you have use this instead: // // # include // typedef uint8_t LByteType; // static const size_t L15_DIGEST_BYTELEN = 32; // ``ANSI C++'' // class L15 { private: LByteType x, y, z; const LByteType start_x; static const size_t stateSize = 256; LByteType state [ stateSize ]; void Swap (const LByteType pos1, const LByteType pos2) { const LByteType save1 = state [ pos1 ]; state [ pos1 ] = state [ pos2 ]; state [ pos2 ] = save1; } void InitState (void) { for (size_t i = 0; i < stateSize; ++i) { state [ i ] = i; } } void KSA (const LByteType * const key, const size_t keyLen) { # define L_SCHEDULE(xx, yy) \ \ for (size_t i = 0; i < stateSize; ++i) { \ Swap (i, ((yy) += (state [ i ] + (xx)))); \ } LByteType stateIndex = 0; L_SCHEDULE(keyLen, stateIndex); for (size_t keyIndex = 0; keyIndex < keyLen; ++keyIndex) { L_SCHEDULE(key [ keyIndex ], stateIndex); } } void Discard (const LByteType numCalls) { for (LByteType i = 0; i < numCalls; ++i) { (void) Byte (); } } public: // For digital-fingerprint usage (where there is no initial "key"). L15 (void) : x (0), y (0), start_x (x) { InitState (); } L15 (const LByteType * const key, const size_t keyLen) : x (0), y (0), start_x (x) { InitState (); KSA (key, keyLen); Discard (Byte ()); // Makes x/y unknown values. } ~L15 (void) { // Clear memory. InitState (); x = y = z = 0; } LByteType Byte (void) { Swap (state [ x ], y); z = (state [ x++ ] + state [ y-- ]); if (x == start_x) { --y; } return state [ z ]; } // For semantically correct digital-fingerprint usage: void Update (const LByteType * const data, const size_t dataLen) { KSA (data, dataLen); } // For digital-fingerprint usage: void Final (LByteType * const digest) { for (size_t i = 0; i < L15_DIGEST_BYTELEN; ++i) { digest [ i ] = Byte (); } } void Vector (const LByteType * const key, const size_t keyLen) { KSA (key, keyLen); } size_t QueryStateSize (void) const { return stateSize; } }; # endif // !OOO__L15_h__OOO