static STATUS gcn_decrypt( char *key, char *pbuff, char *passwd ) { CI_KS ksch; char kbuff[ CRYPT_SIZE + 1 ]; i4 len; /* ** Validate input. */ if ( key == NULL || passwd == NULL ) return( FAIL ); if ( pbuff == NULL || *pbuff == EOS ) { *passwd = EOS; return( OK ); } /* ** Adjust key to CRYPT_SIZE by padding/truncation. */ for( len = 0; len < CRYPT_SIZE; len++ ) kbuff[len] = *key ? *key++ : ' '; kbuff[ CRYPT_SIZE ] = EOS; CIsetkey( kbuff, ksch ); /* ** Password is passed as text, convert back to encoded ** binary. Encoded password should be of correct size. ** Decrypt password. */ CItobin( pbuff, &len, (u_char *)passwd ); if ( len % CRYPT_SIZE ) return( FAIL ); CIdecode( passwd, len, ksch, passwd ); /* ** Cleanup password by removing trailing ** spaces and the end marker. */ passwd[ len ] = EOS; len = STtrmwhite( passwd ); if ( passwd[ --len ] != GCN_PASSWD_END ) return( FAIL ); passwd[ len ] = EOS; return( OK ); }
void gcd_decode( char *key, u_i1 *mask, u_i1 *data, u_i2 length, char *buff ) { CI_KS ks; u_i1 kbuff[ CRYPT_SIZE ]; char *ptr; u_i2 i, j; /* ** The key schedule is built from a single CRYPT_SIZE ** byte array. We use the input key to build the byte ** array, truncating or duplicating as necessary. ** The key is also combined with an optional mask. */ for( i = 0, ptr = key; i < CRYPT_SIZE; i++ ) { if ( ! *ptr ) ptr = key; kbuff[ i ] = *ptr++ ^ (mask ? mask[ i ] : 0); } CIsetkey( (PTR)kbuff, ks ); CIdecode( (PTR)data, length, ks, (PTR)buff ); /* ** The encoded data must be padded to a multiple of ** CRYPT_SIZE bytes. Random data is used for the pad, ** so for strings the null terminator is included in ** the data. A random value is added to each block ** so that a given key/data pair does not encode the ** same way twice. */ for( i = 0, ptr = buff; i < length; i += CRYPT_SIZE ) for( j = 1; j < CRYPT_SIZE; j++ ) if ( ! (*ptr++ = buff[ i + j ]) ) /* stop at EOS */ break; return; }
static STATUS gcn_decode( char *key, u_i1 *mask, char *ipb, char *opb ) { CI_KS ksch; char kbuff[ CRYPT_SIZE + 1 ]; char *ptr; i4 len; /* ** Validate input. */ if ( key == NULL || opb == NULL ) return( FAIL ); if ( ipb == NULL || *ipb == EOS ) { *opb = EOS; return( OK ); } if ( mask == NULL ) mask = zeros; /* ** Adjust key to CRYPT_SIZE by duplication/truncation. */ for( ptr = key, len = 0; len < CRYPT_SIZE; len++ ) { if ( ! *ptr ) ptr = key; kbuff[ len ] = *ptr++ ^ mask[ len ]; } CIsetkey( kbuff, ksch ); /* ** Password is passed as text, convert back to encoded ** binary. Encoded password should be of correct size. ** Decrypt password. ** ** Decode password will be smaller than input. The ** decoded password also needs to be deformatted, which ** can be done in place, so decode directly into output ** buffer. */ CItobin( ipb, &len, (u_char *)opb ); if ( len % CRYPT_SIZE ) return( FAIL ); CIdecode( (PTR)opb, len, ksch, (PTR)opb ); /* ** Remove padding and delimiter from last encryption block. */ while( len && (u_char)opb[ --len ] != CRYPT_DELIM ); opb[ len ] = EOS; /* ** Extract original password by skipping random salt at ** start of each encryption block. */ for( ptr = opb, len = 0; opb[ len ]; len++ ) if ( len % CRYPT_SIZE ) *ptr++ = opb[ len ]; *ptr = EOS; return( OK ); }