// Copyright (c) 2003-2011 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__L15P_h__OOO # define OOO__L15P_h__OOO // ``ISO C89''/``ANSI C'' // # include // For: size_t typedef unsigned int LValueType; static const size_t L15P_DIGEST_LEN = 32; // Add a second layer of security (through indirection) to the output // mechanism of L15 (resulting in minimal additional performance-loss // and code-complexity). // # define L15P_OUTPUT_INDIR // ``ANSI C++'' // class L15P { private: LValueType x, y; const LValueType start_x; static const size_t stateSize = 256; LValueType state [ stateSize ]; LValueType MOD (const LValueType in) { return (in % stateSize); } void Swap (const LValueType pos1, const LValueType pos2) { const LValueType 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 LValueType * const key, const size_t keyLen) { # define L15P_SCHEDULE(xx, yy) \ \ for (size_t i = 0; i < stateSize; ++i) { \ Swap (i, MOD((yy) += (state [ i ] + (xx)))); \ } LValueType stateIndex = 0; L15P_SCHEDULE(keyLen, stateIndex); for (size_t keyIndex = 0; keyIndex < keyLen; ++keyIndex) { L15P_SCHEDULE(key [ keyIndex ], stateIndex); } } void Discard (const LValueType numCalls) { for (LValueType i = 0; i < numCalls; ++i) { (void) Output (); } } public: // For digital-fingerprint usage (where there is no initial "key"). L15P (void) : x (0), y (stateSize-1), start_x (x) { InitState (); } L15P (const LValueType * const key, const size_t keyLen) : x (0), y (stateSize-1), start_x (x) { InitState (); KSA (key, keyLen); Discard (Output ()); // Makes x/y unknown values. } ~L15P (void) { // Clear memory. InitState (); x = y = 0; } LValueType Output (void) { Swap (state [ MOD(x) ], MOD(y)); const LValueType z = (state [ MOD(x++) ] + state [ MOD(y--) ]); if (MOD(x) == start_x) { --y; } # ifdef L15P_OUTPUT_INDIR return state [ state [ MOD(z) ] ]; # else return state [ MOD(z) ]; # endif } // For semantically correct digital-fingerprint usage: void Update (const LValueType * const data, const size_t dataLen) { KSA (data, dataLen); } // For digital-fingerprint usage (produce fingerprint): void Final (LValueType * const digest) { for (size_t i = 0; i < L15P_DIGEST_LEN; ++i) { digest [ i ] = Output (); } } void Vector (const LValueType * const key, const size_t keyLen) { KSA (key, keyLen); } size_t QueryStateSize (void) const { return stateSize; } }; # endif // !OOO__L15P_h__OOO