17c478bd9Sstevel@tonic-gate /*
20275604fSmp153739  * 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  *
107c478bd9Sstevel@tonic-gate  * 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.
24505d05c7Sgtb  *
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.
42505d05c7Sgtb  *
43505d05c7Sgtb  * All rights reserved.
44505d05c7Sgtb  *
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.
49505d05c7Sgtb  *
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.
60505d05c7Sgtb  *
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. */
857c478bd9Sstevel@tonic-gate   /* much of the work has already been done by the only caller
867c478bd9Sstevel@tonic-gate      which is mit_des_string_to_key; in particular, *keyblock is already
877c478bd9Sstevel@tonic-gate      set up. */
88505d05c7Sgtb 
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));
1270275604fSmp153739 
1280275604fSmp153739       /* Solaris Kerberos: Success */
1290275604fSmp153739       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       }
1467c478bd9Sstevel@tonic-gate 
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,
1567c478bd9Sstevel@tonic-gate 				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,
1687c478bd9Sstevel@tonic-gate 				key, i, &usekey, ikey);
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate       /* now fix up key parity again */
1717c478bd9Sstevel@tonic-gate       mit_des_fixup_key_parity(key);
1727c478bd9Sstevel@tonic-gate 
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    */
1947c478bd9Sstevel@tonic-gate 
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 };
2337c478bd9Sstevel@tonic-gate 
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 };
2477c478bd9Sstevel@tonic-gate 
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 };
2587c478bd9Sstevel@tonic-gate 
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 };
2657c478bd9Sstevel@tonic-gate 
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 };
2727c478bd9Sstevel@tonic-gate 
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 };
2837c478bd9Sstevel@tonic-gate 
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 };
2907c478bd9Sstevel@tonic-gate 
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 };
3047c478bd9Sstevel@tonic-gate 
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 };
3197c478bd9Sstevel@tonic-gate 
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,
3277c478bd9Sstevel@tonic-gate 	  0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
3287c478bd9Sstevel@tonic-gate 	  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},
3307c478bd9Sstevel@tonic-gate 
331505d05c7Sgtb 	{15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
3327c478bd9Sstevel@tonic-gate 	  3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
3337c478bd9Sstevel@tonic-gate 	  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},
3357c478bd9Sstevel@tonic-gate 
336505d05c7Sgtb 	{10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
3377c478bd9Sstevel@tonic-gate 	 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
3387c478bd9Sstevel@tonic-gate 	 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},
3407c478bd9Sstevel@tonic-gate 
341505d05c7Sgtb 	{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
3427c478bd9Sstevel@tonic-gate 	 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
3437c478bd9Sstevel@tonic-gate 	 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},
3457c478bd9Sstevel@tonic-gate 
346505d05c7Sgtb 	{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
3477c478bd9Sstevel@tonic-gate 	 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
3487c478bd9Sstevel@tonic-gate 	  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},
3507c478bd9Sstevel@tonic-gate 
351505d05c7Sgtb 	{12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
3527c478bd9Sstevel@tonic-gate 	 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
3537c478bd9Sstevel@tonic-gate 	  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},
3557c478bd9Sstevel@tonic-gate 
356505d05c7Sgtb 	{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
3577c478bd9Sstevel@tonic-gate 	 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
3587c478bd9Sstevel@tonic-gate 	  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},
3607c478bd9Sstevel@tonic-gate 
361505d05c7Sgtb 	{13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
3627c478bd9Sstevel@tonic-gate 	  1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
3637c478bd9Sstevel@tonic-gate 	  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 };
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 
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)
371505d05c7Sgtb {
372505d05c7Sgtb 	int i, j, c;
373505d05c7Sgtb 	int temp;
374505d05c7Sgtb 	char block[66];
375505d05c7Sgtb 	char E[48];
3767c478bd9Sstevel@tonic-gate 	/*
3777c478bd9Sstevel@tonic-gate 	 * The key schedule.
3787c478bd9Sstevel@tonic-gate 	 * Generated from the key.
3797c478bd9Sstevel@tonic-gate 	 */
380505d05c7Sgtb 	char KS[16][48];
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	for(i=0; i<66; i++)
3837c478bd9Sstevel@tonic-gate 		block[i] = 0;
384159d09a2SMark Phalan 	/* Solaris Kerberos */
385*940daf74SToomas 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 	}
3907c478bd9Sstevel@tonic-gate 
391505d05c7Sgtb 	krb5_afs_crypt_setkey(block, E, KS);
3927c478bd9Sstevel@tonic-gate 
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 		}
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	for(i=0; i<25; i++)
412505d05c7Sgtb 		krb5_afs_encrypt(block,E,KS);
4137c478bd9Sstevel@tonic-gate 
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  */
4347c478bd9Sstevel@tonic-gate 
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];
4437c478bd9Sstevel@tonic-gate 
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 	}
4817c478bd9Sstevel@tonic-gate 
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 }
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate /*
4927c478bd9Sstevel@tonic-gate  * The payoff: encrypt a block.
4937c478bd9Sstevel@tonic-gate  */
4947c478bd9Sstevel@tonic-gate 
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