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