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