/*
	Fast password transform.
*/

#include	"fdes.h"

 
extern	unsb	E[];
extern	unsb	FP[];
extern	void	DoSelfMod(void);
extern	void  fsetkey(obpb1 *);
extern	void	xform(sbpb24 *,sbpb24);
extern	obpb1	LR[64];
extern	obpb1	L[32];
extern	obpb1	R[32];

extern	Fperm(unsb *);
extern	undoe(obpb1 *, obpb1 *);
extern	toBA64(sbpb24 *, obpb1 *);
ebpb24	sixbitTOtf(sbpb24 sb);
sbpb24	tfTOsixbit(ebpb24);


void setname(char *pw)
{
reg	int  i, j, c;
static	obpb1 block[66];

	for (i = 0 ; i < 66 ; i++)
		block[i] = 0;
#pragma warn -pia
	for (i = 0 ; (c = *pw) && i < 64 ; pw++)  {
#pragma warn +pia
		for (j = 0 ; j < 7 ; j++, i++)
			block[i] = (c >> (6 - j)) & 01;
		i++;		/* Skip parity bit. */
		}
	
	fsetkey(block);
	DoSelfMod();
}


sbpb24 getsaltval(char *salt)
{
reg		int  i, j, c;
sbpb24	saltvalue;

	saltvalue = 0;
	for (i = 0 ; i < 2 ; i++)  {
		c = *salt++;
		if (c > 'Z')
			c -= 6;
		if (c > '9')
			c -= 7;
		c -= '.';
		for (j = 0 ; j < 6 ; j++)
			saltvalue |= ((c >> j) & 01) << (6 * i + j);
		}
	saltvalue = tfTOsixbit(saltvalue);
	return saltvalue;
}


char *fcrypt(pw,salt)
char *pw;
char *salt;
{
reg		int  i, j, c;
static	obpb1 block[66];
static	char iobuf[16];
static	sbpb24 out96[4];
sbpb24	saltvalue;

	for (i = 0 ; i < 66 ; i++)
		block[i] = 0;
#pragma warn -pia
	for (i = 0 ; (c = *pw) && i < 64 ; pw++)  {
#pragma warn +pia
		for (j = 0 ; j < 7 ; j++, i++)
			block[i] = (c >> (6 - j)) & 01;
		i++;		/* Skip parity bit. */
		}
 
	fsetkey(block);
	DoSelfMod();

	for (i = 0 ; i < 66 ; i++)
		block[i] = 0;

	saltvalue = 0;
	for (i = 0 ; i < 2 ; i++)  {
		c = *salt++;
		iobuf[i] = c;
		if (c > 'Z')
			c -= 6;
		if (c > '9')
			c -= 7;
		c -= '.';
		for (j = 0 ; j < 6 ; j++)
			saltvalue |= ((c >> j) & 01) << (6 * i + j);
		}
	saltvalue = tfTOsixbit(saltvalue);

 	xform(out96, saltvalue);

	toBA64(out96, block);

	for (i = 0 ; i < 11 ; i++)  {
		c = 0;
		for (j = 0 ; j < 6 ; j++)  {
			c <<= 1;
			c |= block[6 * i + j];
			}
		c += '.';
		if (c > '9')
			c += 7;
		if (c > 'Z')
			c += 6;
		iobuf[i+2] = c;
	}
	iobuf[i+2] = 0;
	if (iobuf[1] == 0)
		iobuf[1] = iobuf[0];
	return(iobuf);
}



char *expand(sbpb24 *out96)
{
reg		int  i, j, c;
static	obpb1 block[66];
static	char iobuf[16];
sbpb24	saltvalue;

	toBA64(out96, block);
	
	for (i = 0 ; i < 11 ; i++)  {
		c = 0;
		for (j = 0 ; j < 6 ; j++)  {
			c <<= 1;
			c |= block[6 * i + j];
			}
		c += '.';
		if (c > '9')
			c += 7;
		if (c > 'Z')
			c += 6;
		iobuf[i+2] = c;
	}
	iobuf[i+2] = 0;
	iobuf[0]=iobuf[1]=' ';
	return(iobuf);
}



sbpb24 flatten(char *s,sbpb24 *out96)
{
obpb1 block[66];
obpb1	tmpE[48];
sbpb24 l;
int i,j,c;

	/* Inverse of final ascii mapping */
	for(i=0; i<11; i++){
		c = s[i+2];
		if(c>='a')
			c -= 6;
		if(c>='A')
			c -= 7;
		c -= '.';
		for(j=0;j<6;j++){
			block[6 * i + j] = (c & 0x20) ? 1 : 0;
			c <<= 1;
		}
	}

	for(i=0;i<64;i++)
		L[i] = 0;

	/* Inverse of Fperm */
	for(i=0; i<64; i++)
 		L[FP[i]] = block[i];

	for(i=0;i<48;i++)
		tmpE[i] = 0;

	for(i=0;i<32;i++)
		tmpE[1 + (i & 03) + 6 * (i >> 2)] = R[i];

	l = 0;

	for(i=0;i<24;i++){
		l <<= 1;
		l |= tmpE[47-i];
	}

	out96[3] = tfTOsixbit(l);
	out96[3] = ((out96[3] & 0x00ff00ff) << 2) | (out96[3] & 0xff00ff00);

	l = 0;

	for(i=0;i<24;i++){
		l <<= 1;
		l |= tmpE[23-i];
	}

	out96[2] = tfTOsixbit(l);
	out96[2] = ((out96[2] & 0x00ff00ff) << 2) | (out96[2] & 0xff00ff00);


	for(i=0;i<48;i++)
		tmpE[i] = 0;

	for(i=0;i<32;i++)
		tmpE[1 + (i & 03) + 6 * (i >> 2)] = L[i];

	l = 0;

	for(i=0;i<24;i++){
		l <<= 1;
		l |= tmpE[47-i];
	}

	out96[1] = tfTOsixbit(l);
	out96[1] = ((out96[1] & 0x00ff00ff) << 2) | (out96[1] & 0xff00ff00);

	l = 0;

	for(i=0;i<24;i++){
		l <<= 1;
		l |= tmpE[23-i];
	}

	out96[0] = tfTOsixbit(l);
	out96[0] = ((out96[0] & 0x00ff00ff) << 2) | (out96[0] & 0xff00ff00);

	l = getsaltval(s);
	l = ((l & 0x00ff00ff) <<2) | (l & 0xff00ff00);
	return(l);
}
