17c478bd9Sstevel@tonic-gate /*
20275604fSmp * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate * lib/crypto/des/string2key.c
97c478bd9Sstevel@tonic-gate *
10*55fea89dSDan Cross * based on lib/crypto/des/string2key.c from MIT V5
117c478bd9Sstevel@tonic-gate * and on lib/des/afs_string_to_key.c from UMD.
127c478bd9Sstevel@tonic-gate * constructed by Mark Eichin, Cygnus Support, 1995.
13505d05c7Sgtb * made thread-safe by Ken Raeburn, MIT, 2001.
147c478bd9Sstevel@tonic-gate */
157c478bd9Sstevel@tonic-gate
16505d05c7Sgtb /*
17505d05c7Sgtb * Copyright 2001 by the Massachusetts Institute of Technology.
18505d05c7Sgtb * All Rights Reserved.
19505d05c7Sgtb *
20505d05c7Sgtb * Export of this software from the United States of America may
21505d05c7Sgtb * require a specific license from the United States Government.
22505d05c7Sgtb * It is the responsibility of any person or organization contemplating
23505d05c7Sgtb * export to obtain such a license before exporting.
24*55fea89dSDan Cross *
25505d05c7Sgtb * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
26505d05c7Sgtb * distribute this software and its documentation for any purpose and
27505d05c7Sgtb * without fee is hereby granted, provided that the above copyright
28505d05c7Sgtb * notice appear in all copies and that both that copyright notice and
29505d05c7Sgtb * this permission notice appear in supporting documentation, and that
30505d05c7Sgtb * the name of M.I.T. not be used in advertising or publicity pertaining
31505d05c7Sgtb * to distribution of the software without specific, written prior
32505d05c7Sgtb * permission. Furthermore if you modify this software you must label
33505d05c7Sgtb * your software as modified software and not distribute it in such a
34505d05c7Sgtb * fashion that it might be confused with the original M.I.T. software.
35505d05c7Sgtb * M.I.T. makes no representations about the suitability of
36505d05c7Sgtb * this software for any purpose. It is provided "as is" without express
37505d05c7Sgtb * or implied warranty.
38505d05c7Sgtb */
39505d05c7Sgtb
40505d05c7Sgtb /*
41505d05c7Sgtb * Copyright (C) 1998 by the FundsXpress, INC.
42*55fea89dSDan Cross *
43505d05c7Sgtb * All rights reserved.
44*55fea89dSDan Cross *
45505d05c7Sgtb * Export of this software from the United States of America may require
46505d05c7Sgtb * a specific license from the United States Government. It is the
47505d05c7Sgtb * responsibility of any person or organization contemplating export to
48505d05c7Sgtb * obtain such a license before exporting.
49*55fea89dSDan Cross *
50505d05c7Sgtb * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
51505d05c7Sgtb * distribute this software and its documentation for any purpose and
52505d05c7Sgtb * without fee is hereby granted, provided that the above copyright
53505d05c7Sgtb * notice appear in all copies and that both that copyright notice and
54505d05c7Sgtb * this permission notice appear in supporting documentation, and that
55505d05c7Sgtb * the name of FundsXpress. not be used in advertising or publicity pertaining
56505d05c7Sgtb * to distribution of the software without specific, written prior
57505d05c7Sgtb * permission. FundsXpress makes no representations about the suitability of
58505d05c7Sgtb * this software for any purpose. It is provided "as is" without express
59505d05c7Sgtb * or implied warranty.
60*55fea89dSDan Cross *
61505d05c7Sgtb * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
62505d05c7Sgtb * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
63505d05c7Sgtb * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
64505d05c7Sgtb */
65505d05c7Sgtb
66505d05c7Sgtb #include "k5-int.h"
67505d05c7Sgtb #include "des_int.h"
687c478bd9Sstevel@tonic-gate #include <ctype.h>
697c478bd9Sstevel@tonic-gate
70505d05c7Sgtb #define afs_crypt mit_afs_crypt
71505d05c7Sgtb char *afs_crypt (const char *, const char *, char *);
72505d05c7Sgtb
73505d05c7Sgtb #undef min
74505d05c7Sgtb #define min(a,b) ((a)>(b)?(b):(a))
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate /*ARGSUSED*/
777c478bd9Sstevel@tonic-gate krb5_error_code
mit_afs_string_to_key(krb5_context context,krb5_keyblock * keyblock,const krb5_data * data,const krb5_data * salt)78505d05c7Sgtb mit_afs_string_to_key (krb5_context context,
79505d05c7Sgtb krb5_keyblock *keyblock, const krb5_data *data,
80505d05c7Sgtb const krb5_data *salt)
817c478bd9Sstevel@tonic-gate {
82159d09a2SMark Phalan /* Solaris Kerberos */
837c478bd9Sstevel@tonic-gate krb5_error_code retval = KRB5_PROG_ETYPE_NOSUPP;
847c478bd9Sstevel@tonic-gate /* totally different approach from MIT string2key. */
85*55fea89dSDan Cross /* much of the work has already been done by the only caller
86*55fea89dSDan Cross which is mit_des_string_to_key; in particular, *keyblock is already
877c478bd9Sstevel@tonic-gate set up. */
88*55fea89dSDan Cross
897c478bd9Sstevel@tonic-gate char *realm = salt->data;
90505d05c7Sgtb unsigned int i, j;
917c478bd9Sstevel@tonic-gate krb5_octet *key = keyblock->contents;
92159d09a2SMark Phalan /* Solaris Kerberos */
937c478bd9Sstevel@tonic-gate krb5_keyblock usekey;
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate if (data->length <= 8) {
96505d05c7Sgtb /* One block only. Run afs_crypt and use the first eight
97505d05c7Sgtb returned bytes after the copy of the (fixed) salt.
98505d05c7Sgtb
99505d05c7Sgtb Since the returned bytes are alphanumeric, the output is
100505d05c7Sgtb limited to 2**48 possibilities; for each byte, only 64
101505d05c7Sgtb possible values can be used. */
102505d05c7Sgtb unsigned char password[9]; /* trailing nul for crypt() */
103505d05c7Sgtb char afs_crypt_buf[16];
104505d05c7Sgtb
105505d05c7Sgtb memset (password, 0, sizeof (password));
106505d05c7Sgtb memcpy (password, realm, min (salt->length, 8));
1077c478bd9Sstevel@tonic-gate for (i=0; i<8; i++)
1087c478bd9Sstevel@tonic-gate if (isupper(password[i]))
1097c478bd9Sstevel@tonic-gate password[i] = tolower(password[i]);
1107c478bd9Sstevel@tonic-gate for (i=0; i<data->length; i++)
1117c478bd9Sstevel@tonic-gate password[i] ^= data->data[i];
1127c478bd9Sstevel@tonic-gate for (i=0; i<8; i++)
1137c478bd9Sstevel@tonic-gate if (password[i] == '\0')
1147c478bd9Sstevel@tonic-gate password[i] = 'X';
1157c478bd9Sstevel@tonic-gate password[8] = '\0';
116505d05c7Sgtb /* Out-of-bounds salt characters are equivalent to a salt string
117505d05c7Sgtb of "p1". */
118505d05c7Sgtb strncpy((char *) key,
119505d05c7Sgtb (char *) afs_crypt((char *) password, "#~", afs_crypt_buf) + 2,
120505d05c7Sgtb 8);
1217c478bd9Sstevel@tonic-gate for (i=0; i<8; i++)
1227c478bd9Sstevel@tonic-gate key[i] <<= 1;
1237c478bd9Sstevel@tonic-gate /* now fix up key parity again */
1247c478bd9Sstevel@tonic-gate mit_des_fixup_key_parity(key);
1257c478bd9Sstevel@tonic-gate /* clean & free the input string */
1267c478bd9Sstevel@tonic-gate memset(password, 0, (size_t) sizeof(password));
1270275604fSmp
1280275604fSmp /* Solaris Kerberos: Success */
1290275604fSmp retval = 0;
1307c478bd9Sstevel@tonic-gate } else {
131505d05c7Sgtb /* Multiple blocks. Do a CBC checksum, twice, and use the
132505d05c7Sgtb result as the new key. */
1337c478bd9Sstevel@tonic-gate mit_des_cblock ikey, tkey;
134505d05c7Sgtb unsigned int pw_len = salt->length+data->length;
135505d05c7Sgtb unsigned char *password = malloc(pw_len+1);
1367c478bd9Sstevel@tonic-gate if (!password) return ENOMEM;
1377c478bd9Sstevel@tonic-gate
138505d05c7Sgtb /* Some bound checks from the original code are elided here as
1397c478bd9Sstevel@tonic-gate the malloc above makes sure we have enough storage. */
140505d05c7Sgtb memcpy (password, data->data, data->length);
141505d05c7Sgtb for (i=data->length, j = 0; j < salt->length; i++, j++) {
142505d05c7Sgtb password[i] = realm[j];
1437c478bd9Sstevel@tonic-gate if (isupper(password[i]))
1447c478bd9Sstevel@tonic-gate password[i] = tolower(password[i]);
1457c478bd9Sstevel@tonic-gate }
146*55fea89dSDan Cross
1477c478bd9Sstevel@tonic-gate memcpy (ikey, "kerberos", sizeof(ikey));
1487c478bd9Sstevel@tonic-gate memcpy (tkey, ikey, sizeof(tkey));
1497c478bd9Sstevel@tonic-gate mit_des_fixup_key_parity (tkey);
1507c478bd9Sstevel@tonic-gate
151159d09a2SMark Phalan /* Solaris Kerberos */
1522b825471Ssemery usekey.enctype = ENCTYPE_DES_CBC_CRC;
1537c478bd9Sstevel@tonic-gate usekey.contents = tkey;
1547c478bd9Sstevel@tonic-gate usekey.length = 8;
1557c478bd9Sstevel@tonic-gate retval = mit_des_cbc_cksum (context, (unsigned char *)password,
156505d05c7Sgtb tkey, i, &usekey, ikey);
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate memcpy (ikey, tkey, sizeof(ikey));
1597c478bd9Sstevel@tonic-gate mit_des_fixup_key_parity (tkey);
160159d09a2SMark Phalan /* Solaris Kerberos */
1612b825471Ssemery if (usekey.hKey != CK_INVALID_HANDLE) {
1622b825471Ssemery (void) C_DestroyObject(krb_ctx_hSession(context), usekey.hKey);
1632b825471Ssemery usekey.hKey = CK_INVALID_HANDLE;
1642b825471Ssemery }
1657c478bd9Sstevel@tonic-gate usekey.contents = tkey;
1667c478bd9Sstevel@tonic-gate usekey.length = 8;
1677c478bd9Sstevel@tonic-gate retval = mit_des_cbc_cksum (context, (unsigned char *) password,
168505d05c7Sgtb key, i, &usekey, ikey);
169505d05c7Sgtb
1707c478bd9Sstevel@tonic-gate /* now fix up key parity again */
1717c478bd9Sstevel@tonic-gate mit_des_fixup_key_parity(key);
172*55fea89dSDan Cross
173159d09a2SMark Phalan /* Solaris Kerberos */
1742b825471Ssemery if (usekey.hKey != CK_INVALID_HANDLE) {
1752b825471Ssemery (void) C_DestroyObject(krb_ctx_hSession(context), usekey.hKey);
1762b825471Ssemery usekey.hKey = CK_INVALID_HANDLE;
1772b825471Ssemery }
1787c478bd9Sstevel@tonic-gate /* clean & free the input string */
1797c478bd9Sstevel@tonic-gate memset(password, 0, (size_t) pw_len);
1807c478bd9Sstevel@tonic-gate krb5_xfree(password);
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate #if 0
1837c478bd9Sstevel@tonic-gate /* must free here because it was copied for this special case */
1847c478bd9Sstevel@tonic-gate krb5_xfree(salt->data);
1857c478bd9Sstevel@tonic-gate #endif
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate return retval;
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate /* Portions of this code:
1927c478bd9Sstevel@tonic-gate Copyright 1989 by the Massachusetts Institute of Technology
1937c478bd9Sstevel@tonic-gate */
194*55fea89dSDan Cross
1957c478bd9Sstevel@tonic-gate /*
1967c478bd9Sstevel@tonic-gate * Copyright (c) 1990 Regents of The University of Michigan.
1977c478bd9Sstevel@tonic-gate * All Rights Reserved.
1987c478bd9Sstevel@tonic-gate *
1997c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software
2007c478bd9Sstevel@tonic-gate * and its documentation for any purpose and without fee is hereby
2017c478bd9Sstevel@tonic-gate * granted, provided that the above copyright notice appears in all
2027c478bd9Sstevel@tonic-gate * copies and that both that copyright notice and this permission
2037c478bd9Sstevel@tonic-gate * notice appear in supporting documentation, and that the name of
2047c478bd9Sstevel@tonic-gate * The University of Michigan not be used in advertising or
2057c478bd9Sstevel@tonic-gate * publicity pertaining to distribution of the software without
2067c478bd9Sstevel@tonic-gate * specific, written prior permission. This software is supplied as
2077c478bd9Sstevel@tonic-gate * is without expressed or implied warranties of any kind.
2087c478bd9Sstevel@tonic-gate *
2097c478bd9Sstevel@tonic-gate * ITD Research Systems
2107c478bd9Sstevel@tonic-gate * University of Michigan
2117c478bd9Sstevel@tonic-gate * 535 W. William Street
2127c478bd9Sstevel@tonic-gate * Ann Arbor, Michigan
2137c478bd9Sstevel@tonic-gate * +1-313-936-2652
2147c478bd9Sstevel@tonic-gate * netatalk@terminator.cc.umich.edu
2157c478bd9Sstevel@tonic-gate */
2167c478bd9Sstevel@tonic-gate
217505d05c7Sgtb static void krb5_afs_crypt_setkey (char*, char*, char(*)[48]);
218505d05c7Sgtb static void krb5_afs_encrypt (char*,char*,char (*)[48]);
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate /*
2217c478bd9Sstevel@tonic-gate * Initial permutation,
2227c478bd9Sstevel@tonic-gate */
223505d05c7Sgtb static const char IP[] = {
2247c478bd9Sstevel@tonic-gate 58,50,42,34,26,18,10, 2,
2257c478bd9Sstevel@tonic-gate 60,52,44,36,28,20,12, 4,
2267c478bd9Sstevel@tonic-gate 62,54,46,38,30,22,14, 6,
2277c478bd9Sstevel@tonic-gate 64,56,48,40,32,24,16, 8,
2287c478bd9Sstevel@tonic-gate 57,49,41,33,25,17, 9, 1,
2297c478bd9Sstevel@tonic-gate 59,51,43,35,27,19,11, 3,
2307c478bd9Sstevel@tonic-gate 61,53,45,37,29,21,13, 5,
2317c478bd9Sstevel@tonic-gate 63,55,47,39,31,23,15, 7,
2327c478bd9Sstevel@tonic-gate };
233*55fea89dSDan Cross
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate * Final permutation, FP = IP^(-1)
2367c478bd9Sstevel@tonic-gate */
237505d05c7Sgtb static const char FP[] = {
2387c478bd9Sstevel@tonic-gate 40, 8,48,16,56,24,64,32,
2397c478bd9Sstevel@tonic-gate 39, 7,47,15,55,23,63,31,
2407c478bd9Sstevel@tonic-gate 38, 6,46,14,54,22,62,30,
2417c478bd9Sstevel@tonic-gate 37, 5,45,13,53,21,61,29,
2427c478bd9Sstevel@tonic-gate 36, 4,44,12,52,20,60,28,
2437c478bd9Sstevel@tonic-gate 35, 3,43,11,51,19,59,27,
2447c478bd9Sstevel@tonic-gate 34, 2,42,10,50,18,58,26,
2457c478bd9Sstevel@tonic-gate 33, 1,41, 9,49,17,57,25,
2467c478bd9Sstevel@tonic-gate };
247*55fea89dSDan Cross
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate * Permuted-choice 1 from the key bits to yield C and D.
2507c478bd9Sstevel@tonic-gate * Note that bits 8,16... are left out: They are intended for a parity check.
2517c478bd9Sstevel@tonic-gate */
252505d05c7Sgtb static const char PC1_C[] = {
2537c478bd9Sstevel@tonic-gate 57,49,41,33,25,17, 9,
2547c478bd9Sstevel@tonic-gate 1,58,50,42,34,26,18,
2557c478bd9Sstevel@tonic-gate 10, 2,59,51,43,35,27,
2567c478bd9Sstevel@tonic-gate 19,11, 3,60,52,44,36,
2577c478bd9Sstevel@tonic-gate };
258*55fea89dSDan Cross
259505d05c7Sgtb static const char PC1_D[] = {
2607c478bd9Sstevel@tonic-gate 63,55,47,39,31,23,15,
2617c478bd9Sstevel@tonic-gate 7,62,54,46,38,30,22,
2627c478bd9Sstevel@tonic-gate 14, 6,61,53,45,37,29,
2637c478bd9Sstevel@tonic-gate 21,13, 5,28,20,12, 4,
2647c478bd9Sstevel@tonic-gate };
265*55fea89dSDan Cross
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate * Sequence of shifts used for the key schedule.
2687c478bd9Sstevel@tonic-gate */
269505d05c7Sgtb static const char shifts[] = {
2707c478bd9Sstevel@tonic-gate 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
2717c478bd9Sstevel@tonic-gate };
272*55fea89dSDan Cross
2737c478bd9Sstevel@tonic-gate /*
2747c478bd9Sstevel@tonic-gate * Permuted-choice 2, to pick out the bits from
2757c478bd9Sstevel@tonic-gate * the CD array that generate the key schedule.
2767c478bd9Sstevel@tonic-gate */
277505d05c7Sgtb static const char PC2_C[] = {
2787c478bd9Sstevel@tonic-gate 14,17,11,24, 1, 5,
2797c478bd9Sstevel@tonic-gate 3,28,15, 6,21,10,
2807c478bd9Sstevel@tonic-gate 23,19,12, 4,26, 8,
2817c478bd9Sstevel@tonic-gate 16, 7,27,20,13, 2,
2827c478bd9Sstevel@tonic-gate };
283*55fea89dSDan Cross
284505d05c7Sgtb static const char PC2_D[] = {
2857c478bd9Sstevel@tonic-gate 41,52,31,37,47,55,
2867c478bd9Sstevel@tonic-gate 30,40,51,45,33,48,
2877c478bd9Sstevel@tonic-gate 44,49,39,56,34,53,
2887c478bd9Sstevel@tonic-gate 46,42,50,36,29,32,
2897c478bd9Sstevel@tonic-gate };
290*55fea89dSDan Cross
2917c478bd9Sstevel@tonic-gate /*
2927c478bd9Sstevel@tonic-gate * The E bit-selection table.
2937c478bd9Sstevel@tonic-gate */
294505d05c7Sgtb static const char e[] = {
2957c478bd9Sstevel@tonic-gate 32, 1, 2, 3, 4, 5,
2967c478bd9Sstevel@tonic-gate 4, 5, 6, 7, 8, 9,
2977c478bd9Sstevel@tonic-gate 8, 9,10,11,12,13,
2987c478bd9Sstevel@tonic-gate 12,13,14,15,16,17,
2997c478bd9Sstevel@tonic-gate 16,17,18,19,20,21,
3007c478bd9Sstevel@tonic-gate 20,21,22,23,24,25,
3017c478bd9Sstevel@tonic-gate 24,25,26,27,28,29,
3027c478bd9Sstevel@tonic-gate 28,29,30,31,32, 1,
3037c478bd9Sstevel@tonic-gate };
304*55fea89dSDan Cross
3057c478bd9Sstevel@tonic-gate /*
3067c478bd9Sstevel@tonic-gate * P is a permutation on the selected combination
3077c478bd9Sstevel@tonic-gate * of the current L and key.
3087c478bd9Sstevel@tonic-gate */
309505d05c7Sgtb static const char P[] = {
3107c478bd9Sstevel@tonic-gate 16, 7,20,21,
3117c478bd9Sstevel@tonic-gate 29,12,28,17,
3127c478bd9Sstevel@tonic-gate 1,15,23,26,
3137c478bd9Sstevel@tonic-gate 5,18,31,10,
3147c478bd9Sstevel@tonic-gate 2, 8,24,14,
3157c478bd9Sstevel@tonic-gate 32,27, 3, 9,
3167c478bd9Sstevel@tonic-gate 19,13,30, 6,
3177c478bd9Sstevel@tonic-gate 22,11, 4,25,
3187c478bd9Sstevel@tonic-gate };
319*55fea89dSDan Cross
3207c478bd9Sstevel@tonic-gate /*
3217c478bd9Sstevel@tonic-gate * The 8 selection functions.
3227c478bd9Sstevel@tonic-gate * For some reason, they give a 0-origin
3237c478bd9Sstevel@tonic-gate * index, unlike everything else.
3247c478bd9Sstevel@tonic-gate */
325505d05c7Sgtb static const char S[8][64] = {
326505d05c7Sgtb {14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
327505d05c7Sgtb 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
328505d05c7Sgtb 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
329505d05c7Sgtb 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13},
330*55fea89dSDan Cross
331505d05c7Sgtb {15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
332505d05c7Sgtb 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
333505d05c7Sgtb 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
334505d05c7Sgtb 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9},
335*55fea89dSDan Cross
336505d05c7Sgtb {10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
337505d05c7Sgtb 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
338505d05c7Sgtb 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
339505d05c7Sgtb 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12},
340*55fea89dSDan Cross
341505d05c7Sgtb { 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
342505d05c7Sgtb 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
343505d05c7Sgtb 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
344505d05c7Sgtb 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14},
345*55fea89dSDan Cross
346505d05c7Sgtb { 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
347505d05c7Sgtb 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
348505d05c7Sgtb 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
349505d05c7Sgtb 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3},
350*55fea89dSDan Cross
351505d05c7Sgtb {12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
352505d05c7Sgtb 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
353505d05c7Sgtb 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
354505d05c7Sgtb 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13},
355*55fea89dSDan Cross
356505d05c7Sgtb { 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
357505d05c7Sgtb 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
358505d05c7Sgtb 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
359505d05c7Sgtb 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12},
360*55fea89dSDan Cross
361505d05c7Sgtb {13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
362505d05c7Sgtb 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
363505d05c7Sgtb 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
364505d05c7Sgtb 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11},
3657c478bd9Sstevel@tonic-gate };
366*55fea89dSDan Cross
367*55fea89dSDan Cross
afs_crypt(const char * pw,const char * salt,char * iobuf)368505d05c7Sgtb char *afs_crypt(const char *pw, const char *salt,
369505d05c7Sgtb /* must be at least 16 bytes */
370505d05c7Sgtb char *iobuf)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate int i, j, c;
3737c478bd9Sstevel@tonic-gate int temp;
374505d05c7Sgtb char block[66];
375505d05c7Sgtb char E[48];
376505d05c7Sgtb /*
377505d05c7Sgtb * The key schedule.
378505d05c7Sgtb * Generated from the key.
379505d05c7Sgtb */
380505d05c7Sgtb char KS[16][48];
381*55fea89dSDan Cross
3827c478bd9Sstevel@tonic-gate for(i=0; i<66; i++)
3837c478bd9Sstevel@tonic-gate block[i] = 0;
384159d09a2SMark Phalan /* Solaris Kerberos */
385940daf74SToomas Soome for(i=0; ((c= *pw) != 0) && i<64; pw++){
3867c478bd9Sstevel@tonic-gate for(j=0; j<7; j++, i++)
3877c478bd9Sstevel@tonic-gate block[i] = (c>>(6-j)) & 01;
3887c478bd9Sstevel@tonic-gate i++;
3897c478bd9Sstevel@tonic-gate }
390*55fea89dSDan Cross
391505d05c7Sgtb krb5_afs_crypt_setkey(block, E, KS);
392505d05c7Sgtb
3937c478bd9Sstevel@tonic-gate for(i=0; i<66; i++)
3947c478bd9Sstevel@tonic-gate block[i] = 0;
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate for(i=0;i<2;i++){
3977c478bd9Sstevel@tonic-gate c = *salt++;
3987c478bd9Sstevel@tonic-gate iobuf[i] = c;
3997c478bd9Sstevel@tonic-gate if(c>'Z') c -= 6;
4007c478bd9Sstevel@tonic-gate if(c>'9') c -= 7;
4017c478bd9Sstevel@tonic-gate c -= '.';
4027c478bd9Sstevel@tonic-gate for(j=0;j<6;j++){
4037c478bd9Sstevel@tonic-gate if((c>>j) & 01){
4047c478bd9Sstevel@tonic-gate temp = E[6*i+j];
4057c478bd9Sstevel@tonic-gate E[6*i+j] = E[6*i+j+24];
4067c478bd9Sstevel@tonic-gate E[6*i+j+24] = temp;
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate }
410*55fea89dSDan Cross
4117c478bd9Sstevel@tonic-gate for(i=0; i<25; i++)
412505d05c7Sgtb krb5_afs_encrypt(block,E,KS);
413*55fea89dSDan Cross
4147c478bd9Sstevel@tonic-gate for(i=0; i<11; i++){
4157c478bd9Sstevel@tonic-gate c = 0;
4167c478bd9Sstevel@tonic-gate for(j=0; j<6; j++){
4177c478bd9Sstevel@tonic-gate c <<= 1;
4187c478bd9Sstevel@tonic-gate c |= block[6*i+j];
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate c += '.';
4217c478bd9Sstevel@tonic-gate if(c>'9') c += 7;
4227c478bd9Sstevel@tonic-gate if(c>'Z') c += 6;
4237c478bd9Sstevel@tonic-gate iobuf[i+2] = c;
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate iobuf[i+2] = 0;
4267c478bd9Sstevel@tonic-gate if(iobuf[1]==0)
4277c478bd9Sstevel@tonic-gate iobuf[1] = iobuf[0];
4287c478bd9Sstevel@tonic-gate return(iobuf);
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate /*
4327c478bd9Sstevel@tonic-gate * Set up the key schedule from the key.
4337c478bd9Sstevel@tonic-gate */
434*55fea89dSDan Cross
krb5_afs_crypt_setkey(char * key,char * E,char (* KS)[48])435505d05c7Sgtb static void krb5_afs_crypt_setkey(char *key, char *E, char (*KS)[48])
4367c478bd9Sstevel@tonic-gate {
437159d09a2SMark Phalan register int i, j, k;
4387c478bd9Sstevel@tonic-gate int t;
439505d05c7Sgtb /*
440505d05c7Sgtb * The C and D arrays used to calculate the key schedule.
441505d05c7Sgtb */
442505d05c7Sgtb char C[28], D[28];
443*55fea89dSDan Cross
4447c478bd9Sstevel@tonic-gate /*
4457c478bd9Sstevel@tonic-gate * First, generate C and D by permuting
4467c478bd9Sstevel@tonic-gate * the key. The low order bit of each
4477c478bd9Sstevel@tonic-gate * 8-bit char is not used, so C and D are only 28
4487c478bd9Sstevel@tonic-gate * bits apiece.
4497c478bd9Sstevel@tonic-gate */
4507c478bd9Sstevel@tonic-gate for (i=0; i<28; i++) {
4517c478bd9Sstevel@tonic-gate C[i] = key[PC1_C[i]-1];
4527c478bd9Sstevel@tonic-gate D[i] = key[PC1_D[i]-1];
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate /*
4557c478bd9Sstevel@tonic-gate * To generate Ki, rotate C and D according
4567c478bd9Sstevel@tonic-gate * to schedule and pick up a permutation
4577c478bd9Sstevel@tonic-gate * using PC2.
4587c478bd9Sstevel@tonic-gate */
4597c478bd9Sstevel@tonic-gate for (i=0; i<16; i++) {
4607c478bd9Sstevel@tonic-gate /*
4617c478bd9Sstevel@tonic-gate * rotate.
4627c478bd9Sstevel@tonic-gate */
4637c478bd9Sstevel@tonic-gate for (k=0; k<shifts[i]; k++) {
4647c478bd9Sstevel@tonic-gate t = C[0];
4657c478bd9Sstevel@tonic-gate for (j=0; j<28-1; j++)
4667c478bd9Sstevel@tonic-gate C[j] = C[j+1];
4677c478bd9Sstevel@tonic-gate C[27] = t;
4687c478bd9Sstevel@tonic-gate t = D[0];
4697c478bd9Sstevel@tonic-gate for (j=0; j<28-1; j++)
4707c478bd9Sstevel@tonic-gate D[j] = D[j+1];
4717c478bd9Sstevel@tonic-gate D[27] = t;
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate /*
4747c478bd9Sstevel@tonic-gate * get Ki. Note C and D are concatenated.
4757c478bd9Sstevel@tonic-gate */
4767c478bd9Sstevel@tonic-gate for (j=0; j<24; j++) {
4777c478bd9Sstevel@tonic-gate KS[i][j] = C[PC2_C[j]-1];
4787c478bd9Sstevel@tonic-gate KS[i][j+24] = D[PC2_D[j]-28-1];
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate }
481*55fea89dSDan Cross
482505d05c7Sgtb #if 0
4837c478bd9Sstevel@tonic-gate for(i=0;i<48;i++) {
4847c478bd9Sstevel@tonic-gate E[i] = e[i];
4857c478bd9Sstevel@tonic-gate }
486505d05c7Sgtb #else
487505d05c7Sgtb memcpy(E, e, 48);
488505d05c7Sgtb #endif
4897c478bd9Sstevel@tonic-gate }
490*55fea89dSDan Cross
4917c478bd9Sstevel@tonic-gate /*
4927c478bd9Sstevel@tonic-gate * The payoff: encrypt a block.
4937c478bd9Sstevel@tonic-gate */
494*55fea89dSDan Cross
krb5_afs_encrypt(char * block,char * E,char (* KS)[48])495505d05c7Sgtb static void krb5_afs_encrypt(char *block, char *E, char (*KS)[48])
4967c478bd9Sstevel@tonic-gate {
497505d05c7Sgtb const long edflag = 0;
4987c478bd9Sstevel@tonic-gate int i, ii;
4997c478bd9Sstevel@tonic-gate int t, j, k;
500505d05c7Sgtb char tempL[32];
501505d05c7Sgtb char f[32];
502505d05c7Sgtb /*
503505d05c7Sgtb * The current block, divided into 2 halves.
504505d05c7Sgtb */
505505d05c7Sgtb char L[64];
506505d05c7Sgtb char *const R = &L[32];
507505d05c7Sgtb /*
508505d05c7Sgtb * The combination of the key and the input, before selection.
509505d05c7Sgtb */
510505d05c7Sgtb char preS[48];
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate /*
5137c478bd9Sstevel@tonic-gate * First, permute the bits in the input
5147c478bd9Sstevel@tonic-gate */
5157c478bd9Sstevel@tonic-gate for (j=0; j<64; j++)
5167c478bd9Sstevel@tonic-gate L[j] = block[IP[j]-1];
5177c478bd9Sstevel@tonic-gate /*
5187c478bd9Sstevel@tonic-gate * Perform an encryption operation 16 times.
5197c478bd9Sstevel@tonic-gate */
5207c478bd9Sstevel@tonic-gate for (ii=0; ii<16; ii++) {
5217c478bd9Sstevel@tonic-gate /*
5227c478bd9Sstevel@tonic-gate * Set direction
5237c478bd9Sstevel@tonic-gate */
5247c478bd9Sstevel@tonic-gate if (edflag)
5257c478bd9Sstevel@tonic-gate i = 15-ii;
5267c478bd9Sstevel@tonic-gate else
5277c478bd9Sstevel@tonic-gate i = ii;
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate * Save the R array,
5307c478bd9Sstevel@tonic-gate * which will be the new L.
5317c478bd9Sstevel@tonic-gate */
532505d05c7Sgtb #if 0
5337c478bd9Sstevel@tonic-gate for (j=0; j<32; j++)
5347c478bd9Sstevel@tonic-gate tempL[j] = R[j];
535505d05c7Sgtb #else
536505d05c7Sgtb memcpy(tempL, R, 32);
537505d05c7Sgtb #endif
5387c478bd9Sstevel@tonic-gate /*
5397c478bd9Sstevel@tonic-gate * Expand R to 48 bits using the E selector;
5407c478bd9Sstevel@tonic-gate * exclusive-or with the current key bits.
5417c478bd9Sstevel@tonic-gate */
5427c478bd9Sstevel@tonic-gate for (j=0; j<48; j++)
5437c478bd9Sstevel@tonic-gate preS[j] = R[E[j]-1] ^ KS[i][j];
5447c478bd9Sstevel@tonic-gate /*
5457c478bd9Sstevel@tonic-gate * The pre-select bits are now considered
5467c478bd9Sstevel@tonic-gate * in 8 groups of 6 bits each.
5477c478bd9Sstevel@tonic-gate * The 8 selection functions map these
5487c478bd9Sstevel@tonic-gate * 6-bit quantities into 4-bit quantities
5497c478bd9Sstevel@tonic-gate * and the results permuted
5507c478bd9Sstevel@tonic-gate * to make an f(R, K).
5517c478bd9Sstevel@tonic-gate * The indexing into the selection functions
5527c478bd9Sstevel@tonic-gate * is peculiar; it could be simplified by
5537c478bd9Sstevel@tonic-gate * rewriting the tables.
5547c478bd9Sstevel@tonic-gate */
5557c478bd9Sstevel@tonic-gate for (j=0; j<8; j++) {
5567c478bd9Sstevel@tonic-gate t = 6*j;
5577c478bd9Sstevel@tonic-gate k = S[j][(preS[t+0]<<5)+
5587c478bd9Sstevel@tonic-gate (preS[t+1]<<3)+
5597c478bd9Sstevel@tonic-gate (preS[t+2]<<2)+
5607c478bd9Sstevel@tonic-gate (preS[t+3]<<1)+
5617c478bd9Sstevel@tonic-gate (preS[t+4]<<0)+
5627c478bd9Sstevel@tonic-gate (preS[t+5]<<4)];
5637c478bd9Sstevel@tonic-gate t = 4*j;
5647c478bd9Sstevel@tonic-gate f[t+0] = (k>>3)&01;
5657c478bd9Sstevel@tonic-gate f[t+1] = (k>>2)&01;
5667c478bd9Sstevel@tonic-gate f[t+2] = (k>>1)&01;
5677c478bd9Sstevel@tonic-gate f[t+3] = (k>>0)&01;
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate /*
5707c478bd9Sstevel@tonic-gate * The new R is L ^ f(R, K).
5717c478bd9Sstevel@tonic-gate * The f here has to be permuted first, though.
5727c478bd9Sstevel@tonic-gate */
5737c478bd9Sstevel@tonic-gate for (j=0; j<32; j++)
5747c478bd9Sstevel@tonic-gate R[j] = L[j] ^ f[P[j]-1];
5757c478bd9Sstevel@tonic-gate /*
5767c478bd9Sstevel@tonic-gate * Finally, the new L (the original R)
5777c478bd9Sstevel@tonic-gate * is copied back.
5787c478bd9Sstevel@tonic-gate */
579505d05c7Sgtb #if 0
5807c478bd9Sstevel@tonic-gate for (j=0; j<32; j++)
5817c478bd9Sstevel@tonic-gate L[j] = tempL[j];
582505d05c7Sgtb #else
583505d05c7Sgtb memcpy(L, tempL, 32);
584505d05c7Sgtb #endif
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate /*
5877c478bd9Sstevel@tonic-gate * The output L and R are reversed.
5887c478bd9Sstevel@tonic-gate */
5897c478bd9Sstevel@tonic-gate for (j=0; j<32; j++) {
5907c478bd9Sstevel@tonic-gate t = L[j];
5917c478bd9Sstevel@tonic-gate L[j] = R[j];
5927c478bd9Sstevel@tonic-gate R[j] = t;
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate /*
5957c478bd9Sstevel@tonic-gate * The final output
5967c478bd9Sstevel@tonic-gate * gets the inverse permutation of the very original.
5977c478bd9Sstevel@tonic-gate */
5987c478bd9Sstevel@tonic-gate for (j=0; j<64; j++)
5997c478bd9Sstevel@tonic-gate block[j] = L[FP[j]-1];
6007c478bd9Sstevel@tonic-gate }
601