xref: /csrg-svn/lib/libc/gen/crypt.c (revision 22083)
1*22083Smckusick #ifndef lint
2*22083Smckusick static char sccsid[] = "@(#)crypt.c	5.1 (Berkeley) 06/05/85";
3*22083Smckusick #endif not lint
4*22083Smckusick 
51958Swnj /*
61958Swnj  * This program implements the
71958Swnj  * Proposed Federal Information Processing
81958Swnj  *  Data Encryption Standard.
91958Swnj  * See Federal Register, March 17, 1975 (40FR12134)
101958Swnj  */
111958Swnj 
121958Swnj /*
131958Swnj  * Initial permutation,
141958Swnj  */
151958Swnj static	char	IP[] = {
161958Swnj 	58,50,42,34,26,18,10, 2,
171958Swnj 	60,52,44,36,28,20,12, 4,
181958Swnj 	62,54,46,38,30,22,14, 6,
191958Swnj 	64,56,48,40,32,24,16, 8,
201958Swnj 	57,49,41,33,25,17, 9, 1,
211958Swnj 	59,51,43,35,27,19,11, 3,
221958Swnj 	61,53,45,37,29,21,13, 5,
231958Swnj 	63,55,47,39,31,23,15, 7,
241958Swnj };
251958Swnj 
261958Swnj /*
271958Swnj  * Final permutation, FP = IP^(-1)
281958Swnj  */
291958Swnj static	char	FP[] = {
301958Swnj 	40, 8,48,16,56,24,64,32,
311958Swnj 	39, 7,47,15,55,23,63,31,
321958Swnj 	38, 6,46,14,54,22,62,30,
331958Swnj 	37, 5,45,13,53,21,61,29,
341958Swnj 	36, 4,44,12,52,20,60,28,
351958Swnj 	35, 3,43,11,51,19,59,27,
361958Swnj 	34, 2,42,10,50,18,58,26,
371958Swnj 	33, 1,41, 9,49,17,57,25,
381958Swnj };
391958Swnj 
401958Swnj /*
411958Swnj  * Permuted-choice 1 from the key bits
421958Swnj  * to yield C and D.
431958Swnj  * Note that bits 8,16... are left out:
441958Swnj  * They are intended for a parity check.
451958Swnj  */
461958Swnj static	char	PC1_C[] = {
471958Swnj 	57,49,41,33,25,17, 9,
481958Swnj 	 1,58,50,42,34,26,18,
491958Swnj 	10, 2,59,51,43,35,27,
501958Swnj 	19,11, 3,60,52,44,36,
511958Swnj };
521958Swnj 
531958Swnj static	char	PC1_D[] = {
541958Swnj 	63,55,47,39,31,23,15,
551958Swnj 	 7,62,54,46,38,30,22,
561958Swnj 	14, 6,61,53,45,37,29,
571958Swnj 	21,13, 5,28,20,12, 4,
581958Swnj };
591958Swnj 
601958Swnj /*
611958Swnj  * Sequence of shifts used for the key schedule.
621958Swnj */
631958Swnj static	char	shifts[] = {
641958Swnj 	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
651958Swnj };
661958Swnj 
671958Swnj /*
681958Swnj  * Permuted-choice 2, to pick out the bits from
691958Swnj  * the CD array that generate the key schedule.
701958Swnj  */
711958Swnj static	char	PC2_C[] = {
721958Swnj 	14,17,11,24, 1, 5,
731958Swnj 	 3,28,15, 6,21,10,
741958Swnj 	23,19,12, 4,26, 8,
751958Swnj 	16, 7,27,20,13, 2,
761958Swnj };
771958Swnj 
781958Swnj static	char	PC2_D[] = {
791958Swnj 	41,52,31,37,47,55,
801958Swnj 	30,40,51,45,33,48,
811958Swnj 	44,49,39,56,34,53,
821958Swnj 	46,42,50,36,29,32,
831958Swnj };
841958Swnj 
851958Swnj /*
861958Swnj  * The C and D arrays used to calculate the key schedule.
871958Swnj  */
881958Swnj 
891958Swnj static	char	C[28];
901958Swnj static	char	D[28];
911958Swnj /*
921958Swnj  * The key schedule.
931958Swnj  * Generated from the key.
941958Swnj  */
951958Swnj static	char	KS[16][48];
961958Swnj 
971958Swnj /*
9817337Sralph  * The E bit-selection table.
9917337Sralph  */
10017337Sralph static	char	E[48];
10117337Sralph static	char	e[] = {
10217337Sralph 	32, 1, 2, 3, 4, 5,
10317337Sralph 	 4, 5, 6, 7, 8, 9,
10417337Sralph 	 8, 9,10,11,12,13,
10517337Sralph 	12,13,14,15,16,17,
10617337Sralph 	16,17,18,19,20,21,
10717337Sralph 	20,21,22,23,24,25,
10817337Sralph 	24,25,26,27,28,29,
10917337Sralph 	28,29,30,31,32, 1,
11017337Sralph };
11117337Sralph 
11217337Sralph /*
1131958Swnj  * Set up the key schedule from the key.
1141958Swnj  */
1151958Swnj 
1161958Swnj setkey(key)
1171958Swnj char *key;
1181958Swnj {
1191958Swnj 	register i, j, k;
1201958Swnj 	int t;
1211958Swnj 
1221958Swnj 	/*
1231958Swnj 	 * First, generate C and D by permuting
1241958Swnj 	 * the key.  The low order bit of each
1251958Swnj 	 * 8-bit char is not used, so C and D are only 28
1261958Swnj 	 * bits apiece.
1271958Swnj 	 */
1281958Swnj 	for (i=0; i<28; i++) {
1291958Swnj 		C[i] = key[PC1_C[i]-1];
1301958Swnj 		D[i] = key[PC1_D[i]-1];
1311958Swnj 	}
1321958Swnj 	/*
1331958Swnj 	 * To generate Ki, rotate C and D according
1341958Swnj 	 * to schedule and pick up a permutation
1351958Swnj 	 * using PC2.
1361958Swnj 	 */
1371958Swnj 	for (i=0; i<16; i++) {
1381958Swnj 		/*
1391958Swnj 		 * rotate.
1401958Swnj 		 */
1411958Swnj 		for (k=0; k<shifts[i]; k++) {
1421958Swnj 			t = C[0];
1431958Swnj 			for (j=0; j<28-1; j++)
1441958Swnj 				C[j] = C[j+1];
1451958Swnj 			C[27] = t;
1461958Swnj 			t = D[0];
1471958Swnj 			for (j=0; j<28-1; j++)
1481958Swnj 				D[j] = D[j+1];
1491958Swnj 			D[27] = t;
1501958Swnj 		}
1511958Swnj 		/*
1521958Swnj 		 * get Ki. Note C and D are concatenated.
1531958Swnj 		 */
1541958Swnj 		for (j=0; j<24; j++) {
1551958Swnj 			KS[i][j] = C[PC2_C[j]-1];
1561958Swnj 			KS[i][j+24] = D[PC2_D[j]-28-1];
1571958Swnj 		}
1581958Swnj 	}
15917337Sralph 
16017337Sralph 	for(i=0;i<48;i++)
16117337Sralph 		E[i] = e[i];
1621958Swnj }
1631958Swnj 
1641958Swnj /*
1651958Swnj  * The 8 selection functions.
1661958Swnj  * For some reason, they give a 0-origin
1671958Swnj  * index, unlike everything else.
1681958Swnj  */
1691958Swnj static	char	S[8][64] = {
1701958Swnj 	14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
1711958Swnj 	 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
1721958Swnj 	 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
1731958Swnj 	15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
1741958Swnj 
1751958Swnj 	15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
1761958Swnj 	 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
1771958Swnj 	 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
1781958Swnj 	13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
1791958Swnj 
1801958Swnj 	10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
1811958Swnj 	13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
1821958Swnj 	13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
1831958Swnj 	 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
1841958Swnj 
1851958Swnj 	 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
1861958Swnj 	13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
1871958Swnj 	10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
1881958Swnj 	 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
1891958Swnj 
1901958Swnj 	 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
1911958Swnj 	14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
1921958Swnj 	 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
1931958Swnj 	11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
1941958Swnj 
1951958Swnj 	12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
1961958Swnj 	10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
1971958Swnj 	 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
1981958Swnj 	 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
1991958Swnj 
2001958Swnj 	 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
2011958Swnj 	13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
2021958Swnj 	 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
2031958Swnj 	 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
2041958Swnj 
2051958Swnj 	13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
2061958Swnj 	 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
2071958Swnj 	 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
2081958Swnj 	 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
2091958Swnj };
2101958Swnj 
2111958Swnj /*
2121958Swnj  * P is a permutation on the selected combination
2131958Swnj  * of the current L and key.
2141958Swnj  */
2151958Swnj static	char	P[] = {
2161958Swnj 	16, 7,20,21,
2171958Swnj 	29,12,28,17,
2181958Swnj 	 1,15,23,26,
2191958Swnj 	 5,18,31,10,
2201958Swnj 	 2, 8,24,14,
2211958Swnj 	32,27, 3, 9,
2221958Swnj 	19,13,30, 6,
2231958Swnj 	22,11, 4,25,
2241958Swnj };
2251958Swnj 
2261958Swnj /*
2271958Swnj  * The current block, divided into 2 halves.
2281958Swnj  */
2291958Swnj static	char	L[32], R[32];
2301958Swnj static	char	tempL[32];
2311958Swnj static	char	f[32];
2321958Swnj 
2331958Swnj /*
2341958Swnj  * The combination of the key and the input, before selection.
2351958Swnj  */
2361958Swnj static	char	preS[48];
2371958Swnj 
2381958Swnj /*
2391958Swnj  * The payoff: encrypt a block.
2401958Swnj  */
2411958Swnj 
2421958Swnj encrypt(block, edflag)
2431958Swnj char *block;
2441958Swnj {
2451958Swnj 	int i, ii;
2461958Swnj 	register t, j, k;
2471958Swnj 
2481958Swnj 	/*
2491958Swnj 	 * First, permute the bits in the input
2501958Swnj 	 */
2511958Swnj 	for (j=0; j<64; j++)
2521958Swnj 		L[j] = block[IP[j]-1];
2531958Swnj 	/*
2541958Swnj 	 * Perform an encryption operation 16 times.
2551958Swnj 	 */
2561958Swnj 	for (ii=0; ii<16; ii++) {
2571958Swnj 		/*
2581958Swnj 		 * Set direction
2591958Swnj 		 */
2601958Swnj 		if (edflag)
2611958Swnj 			i = 15-ii;
2621958Swnj 		else
2631958Swnj 			i = ii;
2641958Swnj 		/*
2651958Swnj 		 * Save the R array,
2661958Swnj 		 * which will be the new L.
2671958Swnj 		 */
2681958Swnj 		for (j=0; j<32; j++)
2691958Swnj 			tempL[j] = R[j];
2701958Swnj 		/*
2711958Swnj 		 * Expand R to 48 bits using the E selector;
2721958Swnj 		 * exclusive-or with the current key bits.
2731958Swnj 		 */
2741958Swnj 		for (j=0; j<48; j++)
2751958Swnj 			preS[j] = R[E[j]-1] ^ KS[i][j];
2761958Swnj 		/*
2771958Swnj 		 * The pre-select bits are now considered
2781958Swnj 		 * in 8 groups of 6 bits each.
2791958Swnj 		 * The 8 selection functions map these
2801958Swnj 		 * 6-bit quantities into 4-bit quantities
2811958Swnj 		 * and the results permuted
2821958Swnj 		 * to make an f(R, K).
2831958Swnj 		 * The indexing into the selection functions
2841958Swnj 		 * is peculiar; it could be simplified by
2851958Swnj 		 * rewriting the tables.
2861958Swnj 		 */
2871958Swnj 		for (j=0; j<8; j++) {
2881958Swnj 			t = 6*j;
2891958Swnj 			k = S[j][(preS[t+0]<<5)+
2901958Swnj 				(preS[t+1]<<3)+
2911958Swnj 				(preS[t+2]<<2)+
2921958Swnj 				(preS[t+3]<<1)+
2931958Swnj 				(preS[t+4]<<0)+
2941958Swnj 				(preS[t+5]<<4)];
2951958Swnj 			t = 4*j;
2961958Swnj 			f[t+0] = (k>>3)&01;
2971958Swnj 			f[t+1] = (k>>2)&01;
2981958Swnj 			f[t+2] = (k>>1)&01;
2991958Swnj 			f[t+3] = (k>>0)&01;
3001958Swnj 		}
3011958Swnj 		/*
3021958Swnj 		 * The new R is L ^ f(R, K).
3031958Swnj 		 * The f here has to be permuted first, though.
3041958Swnj 		 */
3051958Swnj 		for (j=0; j<32; j++)
3061958Swnj 			R[j] = L[j] ^ f[P[j]-1];
3071958Swnj 		/*
3081958Swnj 		 * Finally, the new L (the original R)
3091958Swnj 		 * is copied back.
3101958Swnj 		 */
3111958Swnj 		for (j=0; j<32; j++)
3121958Swnj 			L[j] = tempL[j];
3131958Swnj 	}
3141958Swnj 	/*
3151958Swnj 	 * The output L and R are reversed.
3161958Swnj 	 */
3171958Swnj 	for (j=0; j<32; j++) {
3181958Swnj 		t = L[j];
3191958Swnj 		L[j] = R[j];
3201958Swnj 		R[j] = t;
3211958Swnj 	}
3221958Swnj 	/*
3231958Swnj 	 * The final output
3241958Swnj 	 * gets the inverse permutation of the very original.
3251958Swnj 	 */
3261958Swnj 	for (j=0; j<64; j++)
3271958Swnj 		block[j] = L[FP[j]-1];
3281958Swnj }
3291958Swnj 
3301958Swnj char *
3311958Swnj crypt(pw,salt)
3321958Swnj char *pw;
3331958Swnj char *salt;
3341958Swnj {
3351958Swnj 	register i, j, c;
3361958Swnj 	int temp;
3371958Swnj 	static char block[66], iobuf[16];
33817337Sralph 
3391958Swnj 	for(i=0; i<66; i++)
3401958Swnj 		block[i] = 0;
3411958Swnj 	for(i=0; (c= *pw) && i<64; pw++){
3421958Swnj 		for(j=0; j<7; j++, i++)
3431958Swnj 			block[i] = (c>>(6-j)) & 01;
3441958Swnj 		i++;
3451958Swnj 	}
3461958Swnj 
3471958Swnj 	setkey(block);
3481958Swnj 
3491958Swnj 	for(i=0; i<66; i++)
3501958Swnj 		block[i] = 0;
3511958Swnj 
3521958Swnj 	for(i=0;i<2;i++){
3531958Swnj 		c = *salt++;
3541958Swnj 		iobuf[i] = c;
3551958Swnj 		if(c>'Z') c -= 6;
3561958Swnj 		if(c>'9') c -= 7;
3571958Swnj 		c -= '.';
3581958Swnj 		for(j=0;j<6;j++){
3591958Swnj 			if((c>>j) & 01){
3601958Swnj 				temp = E[6*i+j];
3611958Swnj 				E[6*i+j] = E[6*i+j+24];
3621958Swnj 				E[6*i+j+24] = temp;
3631958Swnj 				}
3641958Swnj 			}
3651958Swnj 		}
3661958Swnj 
3671958Swnj 	for(i=0; i<25; i++)
3681958Swnj 		encrypt(block,0);
3691958Swnj 
3701958Swnj 	for(i=0; i<11; i++){
3711958Swnj 		c = 0;
3721958Swnj 		for(j=0; j<6; j++){
3731958Swnj 			c <<= 1;
3741958Swnj 			c |= block[6*i+j];
3751958Swnj 			}
3761958Swnj 		c += '.';
3771958Swnj 		if(c>'9') c += 7;
3781958Swnj 		if(c>'Z') c += 6;
3791958Swnj 		iobuf[i+2] = c;
3801958Swnj 	}
3811958Swnj 	iobuf[i+2] = 0;
3821958Swnj 	if(iobuf[1]==0)
3831958Swnj 		iobuf[1] = iobuf[0];
3841958Swnj 	return(iobuf);
3851958Swnj }
386