1226031Sstas/*
2226031Sstas * Copyright (c) 1997 - 2008 Kungliga Tekniska H��gskolan
3226031Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4226031Sstas * All rights reserved.
5226031Sstas *
6226031Sstas * Redistribution and use in source and binary forms, with or without
7226031Sstas * modification, are permitted provided that the following conditions
8226031Sstas * are met:
9226031Sstas *
10226031Sstas * 1. Redistributions of source code must retain the above copyright
11226031Sstas *    notice, this list of conditions and the following disclaimer.
12226031Sstas *
13226031Sstas * 2. Redistributions in binary form must reproduce the above copyright
14226031Sstas *    notice, this list of conditions and the following disclaimer in the
15226031Sstas *    documentation and/or other materials provided with the distribution.
16226031Sstas *
17226031Sstas * 3. Neither the name of the Institute nor the names of its contributors
18226031Sstas *    may be used to endorse or promote products derived from this software
19226031Sstas *    without specific prior written permission.
20226031Sstas *
21226031Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24226031Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31226031Sstas * SUCH DAMAGE.
32226031Sstas */
33226031Sstas
34226031Sstas#include "krb5_locl.h"
35226031Sstas
36226031Sstas#ifdef HEIM_WEAK_CRYPTO
37226031Sstas
38226031Sstas#ifdef ENABLE_AFS_STRING_TO_KEY
39226031Sstas
40226031Sstas/* This defines the Andrew string_to_key function.  It accepts a password
41226031Sstas * string as input and converts it via a one-way encryption algorithm to a DES
42226031Sstas * encryption key.  It is compatible with the original Andrew authentication
43226031Sstas * service password database.
44226031Sstas */
45226031Sstas
46226031Sstas/*
47226031Sstas * Short passwords, i.e 8 characters or less.
48226031Sstas */
49226031Sstasstatic void
50226031Sstaskrb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
51226031Sstas				 krb5_data cell,
52226031Sstas				 DES_cblock *key)
53226031Sstas{
54226031Sstas    char  password[8+1];	/* crypt is limited to 8 chars anyway */
55226031Sstas    size_t   i;
56226031Sstas
57226031Sstas    for(i = 0; i < 8; i++) {
58226031Sstas	char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
59226031Sstas	    ((i < cell.length) ?
60226031Sstas	     tolower(((unsigned char*)cell.data)[i]) : 0);
61226031Sstas	password[i] = c ? c : 'X';
62226031Sstas    }
63226031Sstas    password[8] = '\0';
64226031Sstas
65226031Sstas    memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
66226031Sstas
67226031Sstas    /* parity is inserted into the LSB so left shift each byte up one
68226031Sstas       bit. This allows ascii characters with a zero MSB to retain as
69226031Sstas       much significance as possible. */
70226031Sstas    for (i = 0; i < sizeof(DES_cblock); i++)
71226031Sstas	((unsigned char*)key)[i] <<= 1;
72226031Sstas    DES_set_odd_parity (key);
73226031Sstas}
74226031Sstas
75226031Sstas/*
76226031Sstas * Long passwords, i.e 9 characters or more.
77226031Sstas */
78226031Sstasstatic void
79226031Sstaskrb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
80226031Sstas				      krb5_data cell,
81226031Sstas				      DES_cblock *key)
82226031Sstas{
83226031Sstas    DES_key_schedule schedule;
84226031Sstas    DES_cblock temp_key;
85226031Sstas    DES_cblock ivec;
86226031Sstas    char password[512];
87226031Sstas    size_t passlen;
88226031Sstas
89226031Sstas    memcpy(password, pw.data, min(pw.length, sizeof(password)));
90226031Sstas    if(pw.length < sizeof(password)) {
91226031Sstas	int len = min(cell.length, sizeof(password) - pw.length);
92226031Sstas	size_t i;
93226031Sstas
94226031Sstas	memcpy(password + pw.length, cell.data, len);
95226031Sstas	for (i = pw.length; i < pw.length + len; ++i)
96226031Sstas	    password[i] = tolower((unsigned char)password[i]);
97226031Sstas    }
98226031Sstas    passlen = min(sizeof(password), pw.length + cell.length);
99226031Sstas    memcpy(&ivec, "kerberos", 8);
100226031Sstas    memcpy(&temp_key, "kerberos", 8);
101226031Sstas    DES_set_odd_parity (&temp_key);
102226031Sstas    DES_set_key_unchecked (&temp_key, &schedule);
103226031Sstas    DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
104226031Sstas
105226031Sstas    memcpy(&temp_key, &ivec, 8);
106226031Sstas    DES_set_odd_parity (&temp_key);
107226031Sstas    DES_set_key_unchecked (&temp_key, &schedule);
108226031Sstas    DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
109226031Sstas    memset(&schedule, 0, sizeof(schedule));
110226031Sstas    memset(&temp_key, 0, sizeof(temp_key));
111226031Sstas    memset(&ivec, 0, sizeof(ivec));
112226031Sstas    memset(password, 0, sizeof(password));
113226031Sstas
114226031Sstas    DES_set_odd_parity (key);
115226031Sstas}
116226031Sstas
117226031Sstasstatic krb5_error_code
118226031SstasDES_AFS3_string_to_key(krb5_context context,
119226031Sstas		       krb5_enctype enctype,
120226031Sstas		       krb5_data password,
121226031Sstas		       krb5_salt salt,
122226031Sstas		       krb5_data opaque,
123226031Sstas		       krb5_keyblock *key)
124226031Sstas{
125226031Sstas    DES_cblock tmp;
126226031Sstas    if(password.length > 8)
127226031Sstas	krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
128226031Sstas    else
129226031Sstas	krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
130226031Sstas    key->keytype = enctype;
131226031Sstas    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
132226031Sstas    memset(&key, 0, sizeof(key));
133226031Sstas    return 0;
134226031Sstas}
135226031Sstas#endif /* ENABLE_AFS_STRING_TO_KEY */
136226031Sstas
137226031Sstasstatic void
138226031SstasDES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
139226031Sstas{
140226031Sstas    DES_key_schedule schedule;
141226031Sstas    size_t i;
142226031Sstas    int reverse = 0;
143226031Sstas    unsigned char *p;
144226031Sstas
145226031Sstas    unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
146226031Sstas			     0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
147226031Sstas    memset(key, 0, 8);
148226031Sstas
149226031Sstas    p = (unsigned char*)key;
150226031Sstas    for (i = 0; i < length; i++) {
151226031Sstas	unsigned char tmp = data[i];
152226031Sstas	if (!reverse)
153226031Sstas	    *p++ ^= (tmp << 1);
154226031Sstas	else
155226031Sstas	    *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
156226031Sstas	if((i % 8) == 7)
157226031Sstas	    reverse = !reverse;
158226031Sstas    }
159226031Sstas    DES_set_odd_parity(key);
160226031Sstas    if(DES_is_weak_key(key))
161226031Sstas	(*key)[7] ^= 0xF0;
162226031Sstas    DES_set_key_unchecked(key, &schedule);
163226031Sstas    DES_cbc_cksum((void*)data, key, length, &schedule, key);
164226031Sstas    memset(&schedule, 0, sizeof(schedule));
165226031Sstas    DES_set_odd_parity(key);
166226031Sstas    if(DES_is_weak_key(key))
167226031Sstas	(*key)[7] ^= 0xF0;
168226031Sstas}
169226031Sstas
170226031Sstasstatic krb5_error_code
171226031Sstaskrb5_DES_string_to_key(krb5_context context,
172226031Sstas		       krb5_enctype enctype,
173226031Sstas		       krb5_data password,
174226031Sstas		       krb5_salt salt,
175226031Sstas		       krb5_data opaque,
176226031Sstas		       krb5_keyblock *key)
177226031Sstas{
178226031Sstas    unsigned char *s;
179226031Sstas    size_t len;
180226031Sstas    DES_cblock tmp;
181226031Sstas
182226031Sstas#ifdef ENABLE_AFS_STRING_TO_KEY
183226031Sstas    if (opaque.length == 1) {
184226031Sstas	unsigned long v;
185226031Sstas	_krb5_get_int(opaque.data, &v, 1);
186226031Sstas	if (v == 1)
187226031Sstas	    return DES_AFS3_string_to_key(context, enctype, password,
188226031Sstas					  salt, opaque, key);
189226031Sstas    }
190226031Sstas#endif
191226031Sstas
192226031Sstas    len = password.length + salt.saltvalue.length;
193226031Sstas    s = malloc(len);
194226031Sstas    if(len > 0 && s == NULL) {
195226031Sstas	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
196226031Sstas	return ENOMEM;
197226031Sstas    }
198226031Sstas    memcpy(s, password.data, password.length);
199226031Sstas    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
200226031Sstas    DES_string_to_key_int(s, len, &tmp);
201226031Sstas    key->keytype = enctype;
202226031Sstas    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
203226031Sstas    memset(&tmp, 0, sizeof(tmp));
204226031Sstas    memset(s, 0, len);
205226031Sstas    free(s);
206226031Sstas    return 0;
207226031Sstas}
208226031Sstas
209226031Sstasstruct salt_type _krb5_des_salt[] = {
210226031Sstas    {
211226031Sstas	KRB5_PW_SALT,
212226031Sstas	"pw-salt",
213226031Sstas	krb5_DES_string_to_key
214226031Sstas    },
215226031Sstas#ifdef ENABLE_AFS_STRING_TO_KEY
216226031Sstas    {
217226031Sstas	KRB5_AFS3_SALT,
218226031Sstas	"afs3-salt",
219226031Sstas	DES_AFS3_string_to_key
220226031Sstas    },
221226031Sstas#endif
222226031Sstas    { 0 }
223226031Sstas};
224226031Sstas#endif
225