 93518bfab4
			
		
	
	93518bfab4
	
	
	
		
			
			lib roken includes support for memset_s() but it was not applied to the Heimdal source tree. Change-Id: I8362ec97a9be50205bb2d398e65b629b88ce1acd
		
			
				
	
	
		
			223 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
 | |
|  * (Royal Institute of Technology, Stockholm, Sweden).
 | |
|  * All rights reserved.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  *
 | |
|  * 1. Redistributions of source code must retain the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer.
 | |
|  *
 | |
|  * 2. Redistributions in binary form must reproduce the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer in the
 | |
|  *    documentation and/or other materials provided with the distribution.
 | |
|  *
 | |
|  * 3. Neither the name of the Institute nor the names of its contributors
 | |
|  *    may be used to endorse or promote products derived from this software
 | |
|  *    without specific prior written permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 | |
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | |
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | |
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 | |
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | |
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | |
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | |
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | |
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | |
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | |
|  * SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #include "krb5_locl.h"
 | |
| 
 | |
| #ifdef HEIM_WEAK_CRYPTO
 | |
| 
 | |
| #ifdef ENABLE_AFS_STRING_TO_KEY
 | |
| 
 | |
| /* This defines the Andrew string_to_key function.  It accepts a password
 | |
|  * string as input and converts it via a one-way encryption algorithm to a DES
 | |
|  * encryption key.  It is compatible with the original Andrew authentication
 | |
|  * service password database.
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * Short passwords, i.e 8 characters or less.
 | |
|  */
 | |
| static void
 | |
| krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
 | |
| 				 krb5_data cell,
 | |
| 				 DES_cblock *key)
 | |
| {
 | |
|     char  password[8+1];	/* crypt is limited to 8 chars anyway */
 | |
|     size_t   i;
 | |
| 
 | |
|     for(i = 0; i < 8; i++) {
 | |
| 	char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
 | |
| 	    ((i < cell.length) ?
 | |
| 	     tolower(((unsigned char*)cell.data)[i]) : 0);
 | |
| 	password[i] = c ? c : 'X';
 | |
|     }
 | |
|     password[8] = '\0';
 | |
| 
 | |
|     memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
 | |
| 
 | |
|     /* parity is inserted into the LSB so left shift each byte up one
 | |
|        bit. This allows ascii characters with a zero MSB to retain as
 | |
|        much significance as possible. */
 | |
|     for (i = 0; i < sizeof(DES_cblock); i++)
 | |
| 	((unsigned char*)key)[i] <<= 1;
 | |
|     DES_set_odd_parity (key);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Long passwords, i.e 9 characters or more.
 | |
|  */
 | |
| static void
 | |
| krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
 | |
| 				      krb5_data cell,
 | |
| 				      DES_cblock *key)
 | |
| {
 | |
|     DES_key_schedule schedule;
 | |
|     DES_cblock temp_key;
 | |
|     DES_cblock ivec;
 | |
|     char password[512];
 | |
|     size_t passlen;
 | |
| 
 | |
|     memcpy(password, pw.data, min(pw.length, sizeof(password)));
 | |
|     if(pw.length < sizeof(password)) {
 | |
| 	int len = min(cell.length, sizeof(password) - pw.length);
 | |
| 	size_t i;
 | |
| 
 | |
| 	memcpy(password + pw.length, cell.data, len);
 | |
| 	for (i = pw.length; i < pw.length + len; ++i)
 | |
| 	    password[i] = tolower((unsigned char)password[i]);
 | |
|     }
 | |
|     passlen = min(sizeof(password), pw.length + cell.length);
 | |
|     memcpy(&ivec, "kerberos", 8);
 | |
|     memcpy(&temp_key, "kerberos", 8);
 | |
|     DES_set_odd_parity (&temp_key);
 | |
|     DES_set_key_unchecked (&temp_key, &schedule);
 | |
|     DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
 | |
| 
 | |
|     memcpy(&temp_key, &ivec, 8);
 | |
|     DES_set_odd_parity (&temp_key);
 | |
|     DES_set_key_unchecked (&temp_key, &schedule);
 | |
|     DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
 | |
|     memset(&schedule, 0, sizeof(schedule));
 | |
|     memset(&temp_key, 0, sizeof(temp_key));
 | |
|     memset(&ivec, 0, sizeof(ivec));
 | |
|     memset_s(password, sizeof(password), 0, sizeof(password));
 | |
| 
 | |
|     DES_set_odd_parity (key);
 | |
| }
 | |
| 
 | |
| static krb5_error_code
 | |
| DES_AFS3_string_to_key(krb5_context context,
 | |
| 		       krb5_enctype enctype,
 | |
| 		       krb5_data password,
 | |
| 		       krb5_salt salt,
 | |
| 		       krb5_data opaque,
 | |
| 		       krb5_keyblock *key)
 | |
| {
 | |
|     DES_cblock tmp;
 | |
|     if(password.length > 8)
 | |
| 	krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
 | |
|     else
 | |
| 	krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
 | |
|     key->keytype = enctype;
 | |
|     krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
 | |
|     memset(&key, 0, sizeof(key));
 | |
|     return 0;
 | |
| }
 | |
| #endif /* ENABLE_AFS_STRING_TO_KEY */
 | |
| 
 | |
| static void
 | |
| DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
 | |
| {
 | |
|     DES_key_schedule schedule;
 | |
|     size_t i;
 | |
|     int reverse = 0;
 | |
|     unsigned char *p;
 | |
| 
 | |
|     unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
 | |
| 			     0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
 | |
|     memset(key, 0, 8);
 | |
| 
 | |
|     p = (unsigned char*)key;
 | |
|     for (i = 0; i < length; i++) {
 | |
| 	unsigned char tmp = data[i];
 | |
| 	if (!reverse)
 | |
| 	    *p++ ^= (tmp << 1);
 | |
| 	else
 | |
| 	    *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
 | |
| 	if((i % 8) == 7)
 | |
| 	    reverse = !reverse;
 | |
|     }
 | |
|     DES_set_odd_parity(key);
 | |
|     if(DES_is_weak_key(key))
 | |
| 	(*key)[7] ^= 0xF0;
 | |
|     DES_set_key_unchecked(key, &schedule);
 | |
|     DES_cbc_cksum((void*)data, key, length, &schedule, key);
 | |
|     memset(&schedule, 0, sizeof(schedule));
 | |
|     DES_set_odd_parity(key);
 | |
|     if(DES_is_weak_key(key))
 | |
| 	(*key)[7] ^= 0xF0;
 | |
| }
 | |
| 
 | |
| static krb5_error_code
 | |
| krb5_DES_string_to_key(krb5_context context,
 | |
| 		       krb5_enctype enctype,
 | |
| 		       krb5_data password,
 | |
| 		       krb5_salt salt,
 | |
| 		       krb5_data opaque,
 | |
| 		       krb5_keyblock *key)
 | |
| {
 | |
|     unsigned char *s;
 | |
|     size_t len;
 | |
|     DES_cblock tmp;
 | |
| 
 | |
| #ifdef ENABLE_AFS_STRING_TO_KEY
 | |
|     if (opaque.length == 1) {
 | |
| 	unsigned long v;
 | |
| 	_krb5_get_int(opaque.data, &v, 1);
 | |
| 	if (v == 1)
 | |
| 	    return DES_AFS3_string_to_key(context, enctype, password,
 | |
| 					  salt, opaque, key);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     len = password.length + salt.saltvalue.length;
 | |
|     s = malloc(len);
 | |
|     if (len > 0 && s == NULL)
 | |
| 	return krb5_enomem(context);
 | |
|     memcpy(s, password.data, password.length);
 | |
|     memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
 | |
|     DES_string_to_key_int(s, len, &tmp);
 | |
|     key->keytype = enctype;
 | |
|     krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
 | |
|     memset(&tmp, 0, sizeof(tmp));
 | |
|     memset(s, 0, len);
 | |
|     free(s);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| struct salt_type _krb5_des_salt[] = {
 | |
|     {
 | |
| 	KRB5_PW_SALT,
 | |
| 	"pw-salt",
 | |
| 	krb5_DES_string_to_key
 | |
|     },
 | |
| #ifdef ENABLE_AFS_STRING_TO_KEY
 | |
|     {
 | |
| 	KRB5_AFS3_SALT,
 | |
| 	"afs3-salt",
 | |
| 	DES_AFS3_string_to_key
 | |
|     },
 | |
| #endif
 | |
|     { 0, NULL, NULL }
 | |
| };
 | |
| #endif
 |