//  KEY.C

#include <stdlib.h>
#include <memory.h>
#include <assert.h>

#include "me5.h"

//  'bytes' form a text key if and only if
//  all bytes (except for trailing zeros) are text or CR or LF
//  and there are at most three CR's.
/*-------------------------------------------------*/
int _stdcall key_is_text(unsigned char *bytes, int n)
{
int k, m=0;
unsigned char b;

for ( k=0; k<n; k++ )
    {
    b = bytes[k];
    m += ( b == RETURN );
    if ( ( b >= SPACE && b <= 0xA8 )
         || ( b == RETURN && ( k < n-1 ) && bytes[k+1] == LINEFEED )
         || ( b == RETURN && k == n-1 )
         || ( b == LINEFEED && ( k > 0 ) && bytes[k-1] == RETURN ) )
        continue;
    else
        break;
    }

if ( m > 3 )
    return ( false );

if ( b != 0 )
    return ( k == n  );
else
    {
    while ( ++k < n )
        {
        if ( bytes[k] != 0 )
            return ( false );
        }
    return ( true );
    }
}

//  This assumes RNGs seeded from encryption key at key[].
//  Priming key is set up at kt[].
//  This is called for each block, and produces a different
//  priming key for each block.
/*-------------------------*/
void define_priming_key(void)
{
unsigned int i;

#if DEVEL
assert ( MAX_KEYTEXT_SEGMENT_LENGTH - MIN_KEYTEXT_SEGMENT_LENGTH + 1 <= 256 ) ;
#endif

keylength = MIN_KEYTEXT_SEGMENT_LENGTH + pm()%(MAX_KEYTEXT_SEGMENT_LENGTH - MIN_KEYTEXT_SEGMENT_LENGTH + 1); 

for ( i=0; i<keylength; i++ )
    {
    kt[i] = key[i%MAX_KEY_LENGTH] + (i+1)*(block+1);

    if ( pm()%2 )
        kt[i] ^= (rnd()*(block+pm()))&0xFF;
    else
        kt[i] ^= (pm()*(block+rnd()))&0xFF;
    }
}

//  This takes the current keytext segment at kt[]
//  and forms a new keytext segment at kt[].
/*----------------------------------*/
void define_next_keytext_segment(void)
{
unsigned int i=0,j=0,k=0;
unsigned int k1, k2, k3, k4, k5, l;

//  Mix the plaintext segment (just encrypted or just decrypted)
//  with the just-used keytext segment, modified by the segment number.
while ( k < 2*keylength )
    {
    if ( k%2 )
        mh_scratch[k++] = kt[i++] + segment*segment;
    else
        mh_scratch[k++] = pt[j++] - segment;
    }
    //  2*MIN_KEYTEXT_SEGMENT_LENGTH <= 2*keylength <= 2*MAX_KEYTEXT_SEGMENT_LENGTH
    //  so these bytes are from 400 to 800 in number.

//  Get five random numbers in the range 0 through 63.
k1 = pm() & 0x3F;
do    
    {
    k2 = pm() & 0x3F;
    } while ( k2 == k1 );
do    
    {
    k3 = pm() & 0x3F;
    } while ( ( k3 == k2 ) || ( k3 == k1 ) );
do    
    {
    k4 = pm() & 0x3F;
    } while ( ( k4 == k3 ) || ( k4 == k2 ) || ( k4 == k1 ) );
do    
    {
    k5 = pm() & 0x3F;
    } while ( ( k5 == k4 ) || ( k5 == k3 ) || ( k5 == k2 ) || ( k5 == k1 ) );

l = k1 + k2 + k3 + k4 + k5;     //  10 <= l <= (63+62+61+60+59) = 305
//  Average l is 5*31 = 155.

MD5Init2(&mh_mdContext);
MD5Update2(&mh_mdContext,&mh_scratch[k1],l-k2);
MD5Final2(v,&mh_mdContext);

MD5Init2(&mh_mdContext);
MD5Update2(&mh_mdContext,&mh_scratch[k2],l-k3);
MD5Final2(&v[16],&mh_mdContext);

MD5Init2(&mh_mdContext);
MD5Update2(&mh_mdContext,&mh_scratch[k3],l-k4);
MD5Final2(&v[32],&mh_mdContext);

MD5Init2(&mh_mdContext);
MD5Update2(&mh_mdContext,&mh_scratch[k4],l-k5);
MD5Final2(&v[48],&mh_mdContext);

MD5Init2(&mh_mdContext);
MD5Update2(&mh_mdContext,&mh_scratch[k5],l-k1);
MD5Final2(&v[64],&mh_mdContext);

//  Rightmost possible part is byte 63 + (63+62+61+60) = byte 309.
//  Number of bytes in mh_scratch is 400 to 800, so part for digest always falls among them.
//  On average the part runs from byte 31 through byte 155 (120 or so bytes long).

keylength = MIN_KEYTEXT_SEGMENT_LENGTH + pm()%(MAX_KEYTEXT_SEGMENT_LENGTH - MIN_KEYTEXT_SEGMENT_LENGTH + 1); 

//  Form new keytext segment by selecting bytes at random from v[].
for ( k=0; k<keylength; k++ )
    kt[k] = v[rnd()%80];
}