10Sstevel@tonic-gate /*
25826Smp153739  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate 
70Sstevel@tonic-gate /*
80Sstevel@tonic-gate  * lib/crypto/des/string2key.c
90Sstevel@tonic-gate  *
10781Sgtb  * based on lib/crypto/des/string2key.c from MIT V5
110Sstevel@tonic-gate  * and on lib/des/afs_string_to_key.c from UMD.
120Sstevel@tonic-gate  * constructed by Mark Eichin, Cygnus Support, 1995.
13781Sgtb  * made thread-safe by Ken Raeburn, MIT, 2001.
14781Sgtb  */
15781Sgtb 
16781Sgtb /*
17781Sgtb  * Copyright 2001 by the Massachusetts Institute of Technology.
18781Sgtb  * All Rights Reserved.
19781Sgtb  *
20781Sgtb  * Export of this software from the United States of America may
21781Sgtb  *   require a specific license from the United States Government.
22781Sgtb  *   It is the responsibility of any person or organization contemplating
23781Sgtb  *   export to obtain such a license before exporting.
24781Sgtb  *
25781Sgtb  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
26781Sgtb  * distribute this software and its documentation for any purpose and
27781Sgtb  * without fee is hereby granted, provided that the above copyright
28781Sgtb  * notice appear in all copies and that both that copyright notice and
29781Sgtb  * this permission notice appear in supporting documentation, and that
30781Sgtb  * the name of M.I.T. not be used in advertising or publicity pertaining
31781Sgtb  * to distribution of the software without specific, written prior
32781Sgtb  * permission.  Furthermore if you modify this software you must label
33781Sgtb  * your software as modified software and not distribute it in such a
34781Sgtb  * fashion that it might be confused with the original M.I.T. software.
35781Sgtb  * M.I.T. makes no representations about the suitability of
36781Sgtb  * this software for any purpose.  It is provided "as is" without express
37781Sgtb  * or implied warranty.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
40781Sgtb /*
41781Sgtb  * Copyright (C) 1998 by the FundsXpress, INC.
42781Sgtb  *
43781Sgtb  * All rights reserved.
44781Sgtb  *
45781Sgtb  * Export of this software from the United States of America may require
46781Sgtb  * a specific license from the United States Government.  It is the
47781Sgtb  * responsibility of any person or organization contemplating export to
48781Sgtb  * obtain such a license before exporting.
49781Sgtb  *
50781Sgtb  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
51781Sgtb  * distribute this software and its documentation for any purpose and
52781Sgtb  * without fee is hereby granted, provided that the above copyright
53781Sgtb  * notice appear in all copies and that both that copyright notice and
54781Sgtb  * this permission notice appear in supporting documentation, and that
55781Sgtb  * the name of FundsXpress. not be used in advertising or publicity pertaining
56781Sgtb  * to distribution of the software without specific, written prior
57781Sgtb  * permission.  FundsXpress makes no representations about the suitability of
58781Sgtb  * this software for any purpose.  It is provided "as is" without express
59781Sgtb  * or implied warranty.
60781Sgtb  *
61781Sgtb  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
62781Sgtb  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
63781Sgtb  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
64781Sgtb  */
65781Sgtb 
66781Sgtb #include "k5-int.h"
67781Sgtb #include "des_int.h"
680Sstevel@tonic-gate #include <ctype.h>
690Sstevel@tonic-gate 
70781Sgtb #define afs_crypt mit_afs_crypt
71781Sgtb char *afs_crypt (const char *, const char *, char *);
72781Sgtb 
73781Sgtb #undef min
74781Sgtb #define min(a,b) ((a)>(b)?(b):(a))
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*ARGSUSED*/
770Sstevel@tonic-gate krb5_error_code
mit_afs_string_to_key(krb5_context context,krb5_keyblock * keyblock,const krb5_data * data,const krb5_data * salt)78781Sgtb mit_afs_string_to_key (krb5_context context,
79781Sgtb 		    krb5_keyblock *keyblock, const krb5_data *data,
80781Sgtb 		    const krb5_data *salt)
810Sstevel@tonic-gate {
82*7934SMark.Phalan@Sun.COM     /* Solaris Kerberos */
830Sstevel@tonic-gate     krb5_error_code retval = KRB5_PROG_ETYPE_NOSUPP;
840Sstevel@tonic-gate /* EXPORT DELETE START */
850Sstevel@tonic-gate   /* totally different approach from MIT string2key. */
86781Sgtb   /* much of the work has already been done by the only caller
87781Sgtb      which is mit_des_string_to_key; in particular, *keyblock is already
880Sstevel@tonic-gate      set up. */
89781Sgtb 
900Sstevel@tonic-gate     char *realm = salt->data;
91781Sgtb     unsigned int i, j;
920Sstevel@tonic-gate     krb5_octet *key = keyblock->contents;
93*7934SMark.Phalan@Sun.COM     /* Solaris Kerberos */
940Sstevel@tonic-gate     krb5_keyblock usekey;
950Sstevel@tonic-gate 
960Sstevel@tonic-gate     if (data->length <= 8) {
97781Sgtb       /* One block only.  Run afs_crypt and use the first eight
98781Sgtb 	 returned bytes after the copy of the (fixed) salt.
99781Sgtb 
100781Sgtb 	 Since the returned bytes are alphanumeric, the output is
101781Sgtb 	 limited to 2**48 possibilities; for each byte, only 64
102781Sgtb 	 possible values can be used.  */
103781Sgtb       unsigned char password[9]; /* trailing nul for crypt() */
104781Sgtb       char afs_crypt_buf[16];
105781Sgtb 
106781Sgtb       memset (password, 0, sizeof (password));
107781Sgtb       memcpy (password, realm, min (salt->length, 8));
1080Sstevel@tonic-gate       for (i=0; i<8; i++)
1090Sstevel@tonic-gate 	if (isupper(password[i]))
1100Sstevel@tonic-gate 	  password[i] = tolower(password[i]);
1110Sstevel@tonic-gate       for (i=0; i<data->length; i++)
1120Sstevel@tonic-gate 	password[i] ^= data->data[i];
1130Sstevel@tonic-gate       for (i=0; i<8; i++)
1140Sstevel@tonic-gate 	if (password[i] == '\0')
1150Sstevel@tonic-gate 	  password[i] = 'X';
1160Sstevel@tonic-gate       password[8] = '\0';
117781Sgtb       /* Out-of-bounds salt characters are equivalent to a salt string
118781Sgtb 	 of "p1".  */
119781Sgtb       strncpy((char *) key,
120781Sgtb 	      (char *) afs_crypt((char *) password, "#~", afs_crypt_buf) + 2,
121781Sgtb 	      8);
1220Sstevel@tonic-gate       for (i=0; i<8; i++)
1230Sstevel@tonic-gate 	key[i] <<= 1;
1240Sstevel@tonic-gate       /* now fix up key parity again */
1250Sstevel@tonic-gate       mit_des_fixup_key_parity(key);
1260Sstevel@tonic-gate       /* clean & free the input string */
1270Sstevel@tonic-gate       memset(password, 0, (size_t) sizeof(password));
1285826Smp153739 
1295826Smp153739       /* Solaris Kerberos: Success */
1305826Smp153739       retval = 0;
1310Sstevel@tonic-gate     } else {
132781Sgtb       /* Multiple blocks.  Do a CBC checksum, twice, and use the
133781Sgtb 	 result as the new key.  */
1340Sstevel@tonic-gate       mit_des_cblock ikey, tkey;
135781Sgtb       unsigned int pw_len = salt->length+data->length;
136781Sgtb       unsigned char *password = malloc(pw_len+1);
1370Sstevel@tonic-gate       if (!password) return ENOMEM;
1380Sstevel@tonic-gate 
139781Sgtb       /* Some bound checks from the original code are elided here as
1400Sstevel@tonic-gate 	 the malloc above makes sure we have enough storage. */
141781Sgtb       memcpy (password, data->data, data->length);
142781Sgtb       for (i=data->length, j = 0; j < salt->length; i++, j++) {
143781Sgtb 	password[i] = realm[j];
1440Sstevel@tonic-gate 	if (isupper(password[i]))
1450Sstevel@tonic-gate 	  password[i] = tolower(password[i]);
1460Sstevel@tonic-gate       }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate       memcpy (ikey, "kerberos", sizeof(ikey));
1490Sstevel@tonic-gate       memcpy (tkey, ikey, sizeof(tkey));
1500Sstevel@tonic-gate       mit_des_fixup_key_parity (tkey);
1510Sstevel@tonic-gate 
152*7934SMark.Phalan@Sun.COM     /* Solaris Kerberos */
153421Ssemery       usekey.enctype = ENCTYPE_DES_CBC_CRC;
1540Sstevel@tonic-gate       usekey.contents = tkey;
1550Sstevel@tonic-gate       usekey.length = 8;
1560Sstevel@tonic-gate       retval = mit_des_cbc_cksum (context, (unsigned char *)password,
157781Sgtb 				tkey, i, &usekey, ikey);
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate       memcpy (ikey, tkey, sizeof(ikey));
1600Sstevel@tonic-gate       mit_des_fixup_key_parity (tkey);
161*7934SMark.Phalan@Sun.COM       /* Solaris Kerberos */
162421Ssemery       if (usekey.hKey != CK_INVALID_HANDLE) {
163421Ssemery          (void) C_DestroyObject(krb_ctx_hSession(context), usekey.hKey);
164421Ssemery          usekey.hKey = CK_INVALID_HANDLE;
165421Ssemery       }
1660Sstevel@tonic-gate       usekey.contents = tkey;
1670Sstevel@tonic-gate       usekey.length = 8;
168781Sgtb       retval = mit_des_cbc_cksum (context, (unsigned char *) password,
169781Sgtb 				key, i, &usekey, ikey);
170421Ssemery 
1710Sstevel@tonic-gate       /* now fix up key parity again */
1720Sstevel@tonic-gate       mit_des_fixup_key_parity(key);
173781Sgtb 
174*7934SMark.Phalan@Sun.COM       /* Solaris Kerberos */
175421Ssemery       if (usekey.hKey != CK_INVALID_HANDLE) {
176421Ssemery          (void) C_DestroyObject(krb_ctx_hSession(context), usekey.hKey);
177421Ssemery          usekey.hKey = CK_INVALID_HANDLE;
178421Ssemery       }
1790Sstevel@tonic-gate       /* clean & free the input string */
1800Sstevel@tonic-gate       memset(password, 0, (size_t) pw_len);
1810Sstevel@tonic-gate       krb5_xfree(password);
1820Sstevel@tonic-gate     }
1830Sstevel@tonic-gate #if 0
1840Sstevel@tonic-gate     /* must free here because it was copied for this special case */
1850Sstevel@tonic-gate     krb5_xfree(salt->data);
1860Sstevel@tonic-gate #endif
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate /* EXPORT DELETE END */
1890Sstevel@tonic-gate     return retval;
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate /* Portions of this code:
1940Sstevel@tonic-gate    Copyright 1989 by the Massachusetts Institute of Technology
1950Sstevel@tonic-gate    */
196781Sgtb 
1970Sstevel@tonic-gate /*
1980Sstevel@tonic-gate  * Copyright (c) 1990 Regents of The University of Michigan.
1990Sstevel@tonic-gate  * All Rights Reserved.
2000Sstevel@tonic-gate  *
2010Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software
2020Sstevel@tonic-gate  * and its documentation for any purpose and without fee is hereby
2030Sstevel@tonic-gate  * granted, provided that the above copyright notice appears in all
2040Sstevel@tonic-gate  * copies and that both that copyright notice and this permission
2050Sstevel@tonic-gate  * notice appear in supporting documentation, and that the name of
2060Sstevel@tonic-gate  * The University of Michigan not be used in advertising or
2070Sstevel@tonic-gate  * publicity pertaining to distribution of the software without
2080Sstevel@tonic-gate  * specific, written prior permission. This software is supplied as
2090Sstevel@tonic-gate  * is without expressed or implied warranties of any kind.
2100Sstevel@tonic-gate  *
2110Sstevel@tonic-gate  *	ITD Research Systems
2120Sstevel@tonic-gate  *	University of Michigan
2130Sstevel@tonic-gate  *	535 W. William Street
2140Sstevel@tonic-gate  *	Ann Arbor, Michigan
2150Sstevel@tonic-gate  *	+1-313-936-2652
2160Sstevel@tonic-gate  *	netatalk@terminator.cc.umich.edu
2170Sstevel@tonic-gate  */
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate /* EXPORT DELETE START */
220781Sgtb 
221781Sgtb static void krb5_afs_crypt_setkey (char*, char*, char(*)[48]);
222781Sgtb static void krb5_afs_encrypt (char*,char*,char (*)[48]);
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate /*
2250Sstevel@tonic-gate  * Initial permutation,
2260Sstevel@tonic-gate  */
227781Sgtb static const char	IP[] = {
2280Sstevel@tonic-gate 	58,50,42,34,26,18,10, 2,
2290Sstevel@tonic-gate 	60,52,44,36,28,20,12, 4,
2300Sstevel@tonic-gate 	62,54,46,38,30,22,14, 6,
2310Sstevel@tonic-gate 	64,56,48,40,32,24,16, 8,
2320Sstevel@tonic-gate 	57,49,41,33,25,17, 9, 1,
2330Sstevel@tonic-gate 	59,51,43,35,27,19,11, 3,
2340Sstevel@tonic-gate 	61,53,45,37,29,21,13, 5,
2350Sstevel@tonic-gate 	63,55,47,39,31,23,15, 7,
2360Sstevel@tonic-gate };
237781Sgtb 
2380Sstevel@tonic-gate /*
2390Sstevel@tonic-gate  * Final permutation, FP = IP^(-1)
2400Sstevel@tonic-gate  */
241781Sgtb static const char	FP[] = {
2420Sstevel@tonic-gate 	40, 8,48,16,56,24,64,32,
2430Sstevel@tonic-gate 	39, 7,47,15,55,23,63,31,
2440Sstevel@tonic-gate 	38, 6,46,14,54,22,62,30,
2450Sstevel@tonic-gate 	37, 5,45,13,53,21,61,29,
2460Sstevel@tonic-gate 	36, 4,44,12,52,20,60,28,
2470Sstevel@tonic-gate 	35, 3,43,11,51,19,59,27,
2480Sstevel@tonic-gate 	34, 2,42,10,50,18,58,26,
2490Sstevel@tonic-gate 	33, 1,41, 9,49,17,57,25,
2500Sstevel@tonic-gate };
251781Sgtb 
2520Sstevel@tonic-gate /*
2530Sstevel@tonic-gate  * Permuted-choice 1 from the key bits to yield C and D.
2540Sstevel@tonic-gate  * Note that bits 8,16... are left out: They are intended for a parity check.
2550Sstevel@tonic-gate  */
256781Sgtb static const char	PC1_C[] = {
2570Sstevel@tonic-gate 	57,49,41,33,25,17, 9,
2580Sstevel@tonic-gate 	 1,58,50,42,34,26,18,
2590Sstevel@tonic-gate 	10, 2,59,51,43,35,27,
2600Sstevel@tonic-gate 	19,11, 3,60,52,44,36,
2610Sstevel@tonic-gate };
262781Sgtb 
263781Sgtb static const char	PC1_D[] = {
2640Sstevel@tonic-gate 	63,55,47,39,31,23,15,
2650Sstevel@tonic-gate 	 7,62,54,46,38,30,22,
2660Sstevel@tonic-gate 	14, 6,61,53,45,37,29,
2670Sstevel@tonic-gate 	21,13, 5,28,20,12, 4,
2680Sstevel@tonic-gate };
269781Sgtb 
2700Sstevel@tonic-gate /*
2710Sstevel@tonic-gate  * Sequence of shifts used for the key schedule.
2720Sstevel@tonic-gate  */
273781Sgtb static const char	shifts[] = {
2740Sstevel@tonic-gate 	1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
2750Sstevel@tonic-gate };
276781Sgtb 
2770Sstevel@tonic-gate /*
2780Sstevel@tonic-gate  * Permuted-choice 2, to pick out the bits from
2790Sstevel@tonic-gate  * the CD array that generate the key schedule.
2800Sstevel@tonic-gate  */
281781Sgtb static const char	PC2_C[] = {
2820Sstevel@tonic-gate 	14,17,11,24, 1, 5,
2830Sstevel@tonic-gate 	 3,28,15, 6,21,10,
2840Sstevel@tonic-gate 	23,19,12, 4,26, 8,
2850Sstevel@tonic-gate 	16, 7,27,20,13, 2,
2860Sstevel@tonic-gate };
287781Sgtb 
288781Sgtb static const char	PC2_D[] = {
2890Sstevel@tonic-gate 	41,52,31,37,47,55,
2900Sstevel@tonic-gate 	30,40,51,45,33,48,
2910Sstevel@tonic-gate 	44,49,39,56,34,53,
2920Sstevel@tonic-gate 	46,42,50,36,29,32,
2930Sstevel@tonic-gate };
294781Sgtb 
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate  * The E bit-selection table.
2970Sstevel@tonic-gate  */
298781Sgtb static const char	e[] = {
2990Sstevel@tonic-gate 	32, 1, 2, 3, 4, 5,
3000Sstevel@tonic-gate 	 4, 5, 6, 7, 8, 9,
3010Sstevel@tonic-gate 	 8, 9,10,11,12,13,
3020Sstevel@tonic-gate 	12,13,14,15,16,17,
3030Sstevel@tonic-gate 	16,17,18,19,20,21,
3040Sstevel@tonic-gate 	20,21,22,23,24,25,
3050Sstevel@tonic-gate 	24,25,26,27,28,29,
3060Sstevel@tonic-gate 	28,29,30,31,32, 1,
3070Sstevel@tonic-gate };
308781Sgtb 
3090Sstevel@tonic-gate /*
3100Sstevel@tonic-gate  * P is a permutation on the selected combination
3110Sstevel@tonic-gate  * of the current L and key.
3120Sstevel@tonic-gate  */
313781Sgtb static const char	P[] = {
3140Sstevel@tonic-gate 	16, 7,20,21,
3150Sstevel@tonic-gate 	29,12,28,17,
3160Sstevel@tonic-gate 	 1,15,23,26,
3170Sstevel@tonic-gate 	 5,18,31,10,
3180Sstevel@tonic-gate 	 2, 8,24,14,
3190Sstevel@tonic-gate 	32,27, 3, 9,
3200Sstevel@tonic-gate 	19,13,30, 6,
3210Sstevel@tonic-gate 	22,11, 4,25,
3220Sstevel@tonic-gate };
323781Sgtb 
3240Sstevel@tonic-gate /*
3250Sstevel@tonic-gate  * The 8 selection functions.
3260Sstevel@tonic-gate  * For some reason, they give a 0-origin
3270Sstevel@tonic-gate  * index, unlike everything else.
3280Sstevel@tonic-gate  */
329781Sgtb static const char	S[8][64] = {
330781Sgtb 	{14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
331781Sgtb 	  0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
332781Sgtb 	  4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
333781Sgtb 	 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13},
334781Sgtb 
335781Sgtb 	{15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
336781Sgtb 	  3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
337781Sgtb 	  0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
338781Sgtb 	 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9},
339781Sgtb 
340781Sgtb 	{10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
341781Sgtb 	 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
342781Sgtb 	 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
343781Sgtb 	  1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12},
344781Sgtb 
345781Sgtb 	{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
346781Sgtb 	 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
347781Sgtb 	 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
348781Sgtb 	  3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14},
349781Sgtb 
350781Sgtb 	{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
351781Sgtb 	 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
352781Sgtb 	  4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
353781Sgtb 	 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3},
354781Sgtb 
355781Sgtb 	{12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
356781Sgtb 	 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
357781Sgtb 	  9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
358781Sgtb 	  4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13},
359781Sgtb 
360781Sgtb 	{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
361781Sgtb 	 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
362781Sgtb 	  1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
363781Sgtb 	  6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12},
364781Sgtb 
365781Sgtb 	{13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
366781Sgtb 	  1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
367781Sgtb 	  7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
368781Sgtb 	  2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11},
3690Sstevel@tonic-gate };
370781Sgtb 
371781Sgtb 
afs_crypt(const char * pw,const char * salt,char * iobuf)372781Sgtb char *afs_crypt(const char *pw, const char *salt,
373781Sgtb 		/* must be at least 16 bytes */
374781Sgtb 		char *iobuf)
3750Sstevel@tonic-gate {
3760Sstevel@tonic-gate 	int i, j, c;
3770Sstevel@tonic-gate 	int temp;
378781Sgtb 	char block[66];
379781Sgtb 	char E[48];
380781Sgtb 	/*
381781Sgtb 	 * The key schedule.
382781Sgtb 	 * Generated from the key.
383781Sgtb 	 */
384781Sgtb 	char KS[16][48];
385781Sgtb 
3860Sstevel@tonic-gate 	for(i=0; i<66; i++)
3870Sstevel@tonic-gate 		block[i] = 0;
388*7934SMark.Phalan@Sun.COM 	/* Solaris Kerberos */
3890Sstevel@tonic-gate 	for(i=0; ((c= *pw) != NULL) && i<64; pw++){
3900Sstevel@tonic-gate 		for(j=0; j<7; j++, i++)
3910Sstevel@tonic-gate 			block[i] = (c>>(6-j)) & 01;
3920Sstevel@tonic-gate 		i++;
3930Sstevel@tonic-gate 	}
3940Sstevel@tonic-gate 
395781Sgtb 	krb5_afs_crypt_setkey(block, E, KS);
396781Sgtb 
3970Sstevel@tonic-gate 	for(i=0; i<66; i++)
3980Sstevel@tonic-gate 		block[i] = 0;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	for(i=0;i<2;i++){
4010Sstevel@tonic-gate 		c = *salt++;
4020Sstevel@tonic-gate 		iobuf[i] = c;
4030Sstevel@tonic-gate 		if(c>'Z') c -= 6;
4040Sstevel@tonic-gate 		if(c>'9') c -= 7;
4050Sstevel@tonic-gate 		c -= '.';
4060Sstevel@tonic-gate 		for(j=0;j<6;j++){
4070Sstevel@tonic-gate 			if((c>>j) & 01){
4080Sstevel@tonic-gate 				temp = E[6*i+j];
4090Sstevel@tonic-gate 				E[6*i+j] = E[6*i+j+24];
4100Sstevel@tonic-gate 				E[6*i+j+24] = temp;
4110Sstevel@tonic-gate 				}
4120Sstevel@tonic-gate 			}
4130Sstevel@tonic-gate 		}
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	for(i=0; i<25; i++)
416781Sgtb 		krb5_afs_encrypt(block,E,KS);
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	for(i=0; i<11; i++){
4190Sstevel@tonic-gate 		c = 0;
4200Sstevel@tonic-gate 		for(j=0; j<6; j++){
4210Sstevel@tonic-gate 			c <<= 1;
4220Sstevel@tonic-gate 			c |= block[6*i+j];
4230Sstevel@tonic-gate 			}
4240Sstevel@tonic-gate 		c += '.';
4250Sstevel@tonic-gate 		if(c>'9') c += 7;
4260Sstevel@tonic-gate 		if(c>'Z') c += 6;
4270Sstevel@tonic-gate 		iobuf[i+2] = c;
4280Sstevel@tonic-gate 	}
4290Sstevel@tonic-gate 	iobuf[i+2] = 0;
4300Sstevel@tonic-gate 	if(iobuf[1]==0)
4310Sstevel@tonic-gate 		iobuf[1] = iobuf[0];
4320Sstevel@tonic-gate 	return(iobuf);
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate /*
4360Sstevel@tonic-gate  * Set up the key schedule from the key.
4370Sstevel@tonic-gate  */
438781Sgtb 
krb5_afs_crypt_setkey(char * key,char * E,char (* KS)[48])439781Sgtb static void krb5_afs_crypt_setkey(char *key, char *E, char (*KS)[48])
4400Sstevel@tonic-gate {
441*7934SMark.Phalan@Sun.COM 	register int i, j, k;
4420Sstevel@tonic-gate 	int t;
443781Sgtb 	/*
444781Sgtb 	 * The C and D arrays used to calculate the key schedule.
445781Sgtb 	 */
446781Sgtb 	char C[28], D[28];
447781Sgtb 
4480Sstevel@tonic-gate 	/*
4490Sstevel@tonic-gate 	 * First, generate C and D by permuting
4500Sstevel@tonic-gate 	 * the key.  The low order bit of each
4510Sstevel@tonic-gate 	 * 8-bit char is not used, so C and D are only 28
4520Sstevel@tonic-gate 	 * bits apiece.
4530Sstevel@tonic-gate 	 */
4540Sstevel@tonic-gate 	for (i=0; i<28; i++) {
4550Sstevel@tonic-gate 		C[i] = key[PC1_C[i]-1];
4560Sstevel@tonic-gate 		D[i] = key[PC1_D[i]-1];
4570Sstevel@tonic-gate 	}
4580Sstevel@tonic-gate 	/*
4590Sstevel@tonic-gate 	 * To generate Ki, rotate C and D according
4600Sstevel@tonic-gate 	 * to schedule and pick up a permutation
4610Sstevel@tonic-gate 	 * using PC2.
4620Sstevel@tonic-gate 	 */
4630Sstevel@tonic-gate 	for (i=0; i<16; i++) {
4640Sstevel@tonic-gate 		/*
4650Sstevel@tonic-gate 		 * rotate.
4660Sstevel@tonic-gate 		 */
4670Sstevel@tonic-gate 		for (k=0; k<shifts[i]; k++) {
4680Sstevel@tonic-gate 			t = C[0];
4690Sstevel@tonic-gate 			for (j=0; j<28-1; j++)
4700Sstevel@tonic-gate 				C[j] = C[j+1];
4710Sstevel@tonic-gate 			C[27] = t;
4720Sstevel@tonic-gate 			t = D[0];
4730Sstevel@tonic-gate 			for (j=0; j<28-1; j++)
4740Sstevel@tonic-gate 				D[j] = D[j+1];
4750Sstevel@tonic-gate 			D[27] = t;
4760Sstevel@tonic-gate 		}
4770Sstevel@tonic-gate 		/*
4780Sstevel@tonic-gate 		 * get Ki. Note C and D are concatenated.
4790Sstevel@tonic-gate 		 */
4800Sstevel@tonic-gate 		for (j=0; j<24; j++) {
4810Sstevel@tonic-gate 			KS[i][j] = C[PC2_C[j]-1];
4820Sstevel@tonic-gate 			KS[i][j+24] = D[PC2_D[j]-28-1];
4830Sstevel@tonic-gate 		}
4840Sstevel@tonic-gate 	}
485781Sgtb 
486781Sgtb #if 0
4870Sstevel@tonic-gate 	for(i=0;i<48;i++) {
4880Sstevel@tonic-gate 		E[i] = e[i];
4890Sstevel@tonic-gate 	}
490781Sgtb #else
491781Sgtb 	memcpy(E, e, 48);
492781Sgtb #endif
4930Sstevel@tonic-gate }
494781Sgtb 
4950Sstevel@tonic-gate /*
4960Sstevel@tonic-gate  * The payoff: encrypt a block.
4970Sstevel@tonic-gate  */
498781Sgtb 
krb5_afs_encrypt(char * block,char * E,char (* KS)[48])499781Sgtb static void krb5_afs_encrypt(char *block, char *E, char (*KS)[48])
5000Sstevel@tonic-gate {
501781Sgtb 	const long edflag = 0;
5020Sstevel@tonic-gate 	int i, ii;
5030Sstevel@tonic-gate 	int t, j, k;
504781Sgtb 	char tempL[32];
505781Sgtb 	char f[32];
506781Sgtb 	/*
507781Sgtb 	 * The current block, divided into 2 halves.
508781Sgtb 	 */
509781Sgtb 	char L[64];
510781Sgtb 	char *const R = &L[32];
511781Sgtb 	/*
512781Sgtb 	 * The combination of the key and the input, before selection.
513781Sgtb 	 */
514781Sgtb 	char preS[48];
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 	/*
5170Sstevel@tonic-gate 	 * First, permute the bits in the input
5180Sstevel@tonic-gate 	 */
5190Sstevel@tonic-gate 	for (j=0; j<64; j++)
5200Sstevel@tonic-gate 		L[j] = block[IP[j]-1];
5210Sstevel@tonic-gate 	/*
5220Sstevel@tonic-gate 	 * Perform an encryption operation 16 times.
5230Sstevel@tonic-gate 	 */
5240Sstevel@tonic-gate 	for (ii=0; ii<16; ii++) {
5250Sstevel@tonic-gate 		/*
5260Sstevel@tonic-gate 		 * Set direction
5270Sstevel@tonic-gate 		 */
5280Sstevel@tonic-gate 		if (edflag)
5290Sstevel@tonic-gate 			i = 15-ii;
5300Sstevel@tonic-gate 		else
5310Sstevel@tonic-gate 			i = ii;
5320Sstevel@tonic-gate 		/*
5330Sstevel@tonic-gate 		 * Save the R array,
5340Sstevel@tonic-gate 		 * which will be the new L.
5350Sstevel@tonic-gate 		 */
536781Sgtb #if 0
5370Sstevel@tonic-gate 		for (j=0; j<32; j++)
5380Sstevel@tonic-gate 			tempL[j] = R[j];
539781Sgtb #else
540781Sgtb 		memcpy(tempL, R, 32);
541781Sgtb #endif
5420Sstevel@tonic-gate 		/*
5430Sstevel@tonic-gate 		 * Expand R to 48 bits using the E selector;
5440Sstevel@tonic-gate 		 * exclusive-or with the current key bits.
5450Sstevel@tonic-gate 		 */
5460Sstevel@tonic-gate 		for (j=0; j<48; j++)
5470Sstevel@tonic-gate 			preS[j] = R[E[j]-1] ^ KS[i][j];
5480Sstevel@tonic-gate 		/*
5490Sstevel@tonic-gate 		 * The pre-select bits are now considered
5500Sstevel@tonic-gate 		 * in 8 groups of 6 bits each.
5510Sstevel@tonic-gate 		 * The 8 selection functions map these
5520Sstevel@tonic-gate 		 * 6-bit quantities into 4-bit quantities
5530Sstevel@tonic-gate 		 * and the results permuted
5540Sstevel@tonic-gate 		 * to make an f(R, K).
5550Sstevel@tonic-gate 		 * The indexing into the selection functions
5560Sstevel@tonic-gate 		 * is peculiar; it could be simplified by
5570Sstevel@tonic-gate 		 * rewriting the tables.
5580Sstevel@tonic-gate 		 */
5590Sstevel@tonic-gate 		for (j=0; j<8; j++) {
5600Sstevel@tonic-gate 			t = 6*j;
5610Sstevel@tonic-gate 			k = S[j][(preS[t+0]<<5)+
5620Sstevel@tonic-gate 				(preS[t+1]<<3)+
5630Sstevel@tonic-gate 				(preS[t+2]<<2)+
5640Sstevel@tonic-gate 				(preS[t+3]<<1)+
5650Sstevel@tonic-gate 				(preS[t+4]<<0)+
5660Sstevel@tonic-gate 				(preS[t+5]<<4)];
5670Sstevel@tonic-gate 			t = 4*j;
5680Sstevel@tonic-gate 				f[t+0] = (k>>3)&01;
5690Sstevel@tonic-gate 				f[t+1] = (k>>2)&01;
5700Sstevel@tonic-gate 				f[t+2] = (k>>1)&01;
5710Sstevel@tonic-gate 				f[t+3] = (k>>0)&01;
5720Sstevel@tonic-gate 		}
5730Sstevel@tonic-gate 		/*
5740Sstevel@tonic-gate 		 * The new R is L ^ f(R, K).
5750Sstevel@tonic-gate 		 * The f here has to be permuted first, though.
5760Sstevel@tonic-gate 		 */
5770Sstevel@tonic-gate 		for (j=0; j<32; j++)
5780Sstevel@tonic-gate 			R[j] = L[j] ^ f[P[j]-1];
5790Sstevel@tonic-gate 		/*
5800Sstevel@tonic-gate 		 * Finally, the new L (the original R)
5810Sstevel@tonic-gate 		 * is copied back.
5820Sstevel@tonic-gate 		 */
583781Sgtb #if 0
5840Sstevel@tonic-gate 		for (j=0; j<32; j++)
5850Sstevel@tonic-gate 			L[j] = tempL[j];
586781Sgtb #else
587781Sgtb 		memcpy(L, tempL, 32);
588781Sgtb #endif
5890Sstevel@tonic-gate 	}
5900Sstevel@tonic-gate 	/*
5910Sstevel@tonic-gate 	 * The output L and R are reversed.
5920Sstevel@tonic-gate 	 */
5930Sstevel@tonic-gate 	for (j=0; j<32; j++) {
5940Sstevel@tonic-gate 		t = L[j];
5950Sstevel@tonic-gate 		L[j] = R[j];
5960Sstevel@tonic-gate 		R[j] = t;
5970Sstevel@tonic-gate 	}
5980Sstevel@tonic-gate 	/*
5990Sstevel@tonic-gate 	 * The final output
6000Sstevel@tonic-gate 	 * gets the inverse permutation of the very original.
6010Sstevel@tonic-gate 	 */
6020Sstevel@tonic-gate 	for (j=0; j<64; j++)
6030Sstevel@tonic-gate 		block[j] = L[FP[j]-1];
6040Sstevel@tonic-gate }
6050Sstevel@tonic-gate /* EXPORT DELETE END */
606