summaryrefslogtreecommitdiff
path: root/kerberosIV/krb/str2key.c
blob: f9dbd50a08e64f93fe6fb87f6ec4f453a11d65eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * This software may now be redistributed outside the US.
 *
 * $Source: /cvs/OpenBSD/src/kerberosIV/krb/Attic/str2key.c,v $
 *
 * $Locker:  $
 */

/*
 * This defines the Andrew string_to_key function.  It accepts a password
 * string as input and converts its via a one-way encryption algorithm to a DES
 * encryption key.  It is compatible with the original Andrew authentication
 * service password database.
 */

#include "krb_locl.h"

/*
EXPORT void afs_string_to_key(char *passwd, char *cell, des_cblock *key);
*/

static void
mklower(s)
	char *s;
{
    for (; *s; s++)
        if ('A' <= *s && *s <= 'Z')
            *s = *s - 'A' + 'a';
}

/*
 * Short passwords, i.e 8 characters or less.
 */
static void
afs_cmu_StringToKey (str, cell, key)
	char *str;
	char *cell;
	des_cblock *key;
{
    char  password[8+1];	/* crypt is limited to 8 chars anyway */
    int   i;
    int   passlen;

    bzero (key, sizeof(key));
    bzero(password, sizeof(password));

    strncpy (password, cell, 8);
    passlen = strlen (str);
    if (passlen > 8) passlen = 8;

    for (i=0; i<passlen; i++)
        password[i] = str[i] ^ cell[i];	/* make sure cell is zero padded */

    for (i=0; i<8; i++)
        if (password[i] == '\0') password[i] = 'X';

    /* crypt only considers the first 8 characters of password but for some
       reason returns eleven characters of result (plus the two salt chars). */
    strncpy((void *)key, (char *)crypt(password, "#~") + 2, sizeof(des_cblock));

    /* parity is inserted into the LSB so leftshift each byte up one bit.  This
       allows ascii characters with a zero MSB to retain as much significance
       as possible. */
    {   char *keybytes = (char *)key;
        unsigned int temp;

        for (i = 0; i < 8; i++) {
            temp = (unsigned int) keybytes[i];
            keybytes[i] = (unsigned char) (temp << 1);
        }
    }
    des_fixup_key_parity (key);
}

#undef  BUFSIZ
#define	BUFSIZ		512

/*
 * Long passwords, i.e 9 characters or more.
*/
static void
afs_transarc_StringToKey (str, cell, key)
	char *str;
	char *cell;
	des_cblock *key;
{
    des_key_schedule schedule;
    des_cblock temp_key;
    des_cblock ivec;
    char password[BUFSIZ];
    int  passlen;

    strncpy (password, str, sizeof(password)-1);
    password[sizeof(password)-1] = '\0';
    if ((passlen = strlen (password)) < sizeof(password)-1)
        strncat (password, cell, sizeof(password)-passlen);
    if ((passlen = strlen(password)) > sizeof(password))
	passlen = sizeof(password);

    bcopy ("kerberos", &ivec, 8);
    bcopy ("kerberos", &temp_key, 8);
    des_fixup_key_parity (&temp_key);
    des_key_sched (&temp_key, schedule);
    des_cbc_cksum ((des_cblock *)password, &ivec, passlen, schedule, &ivec);

    bcopy (&ivec, &temp_key, 8);
    des_fixup_key_parity (&temp_key);
    des_key_sched (&temp_key, schedule);
    des_cbc_cksum ((des_cblock *)password, key, passlen, schedule, &ivec);

    des_fixup_key_parity (key);
}

#undef  REALM_SZ
#define	REALM_SZ	41

void
afs_string_to_key(str, cell, key)
	char *str;
	char *cell;
	des_cblock *key;
{
    char  realm[REALM_SZ];
    (void)strcpy(realm, cell);
    (void)mklower(realm);

    if (strlen(str) > 8)
        afs_transarc_StringToKey (str, realm, key);
    else
        afs_cmu_StringToKey (str, realm, key);
}