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