1/* 2 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "krb5_locl.h" 35#include <CommonCrypto/CommonCryptor.h> 36#ifndef __APPLE_TARGET_EMBEDDED__ 37#include <CommonCrypto/CommonCryptor.h> 38#include <CommonCrypto/CommonCryptorSPI.h> 39#endif 40 41#ifdef HEIM_KRB5_DES 42 43#ifdef ENABLE_AFS_STRING_TO_KEY 44 45/* This defines the Andrew string_to_key function. It accepts a password 46 * string as input and converts it via a one-way encryption algorithm to a DES 47 * encryption key. It is compatible with the original Andrew authentication 48 * service password database. 49 */ 50 51/* 52 * Short passwords, i.e 8 characters or less. 53 */ 54static void 55krb5_DES_AFS3_CMU_string_to_key (krb5_data pw, 56 krb5_data cell, 57 DES_cblock *key) 58{ 59 char password[8+1]; /* crypt is limited to 8 chars anyway */ 60 size_t i; 61 62 for(i = 0; i < 8; i++) { 63 char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^ 64 ((i < cell.length) ? 65 tolower(((unsigned char*)cell.data)[i]) : 0); 66 password[i] = c ? c : 'X'; 67 } 68 password[8] = '\0'; 69 70 memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock)); 71 72 /* parity is inserted into the LSB so left shift each byte up one 73 bit. This allows ascii characters with a zero MSB to retain as 74 much significance as possible. */ 75 for (i = 0; i < sizeof(DES_cblock); i++) 76 ((unsigned char*)key)[i] <<= 1; 77 CCDesSetOddParity(key, sizeof(*key)); 78} 79 80/* 81 * Long passwords, i.e 9 characters or more. 82 */ 83static void 84krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw, 85 krb5_data cell, 86 DES_cblock *key) 87{ 88 DES_key_schedule schedule; 89 DES_cblock temp_key; 90 DES_cblock ivec; 91 char password[512]; 92 size_t passlen; 93 94 memcpy(password, pw.data, min(pw.length, sizeof(password))); 95 if(pw.length < sizeof(password)) { 96 size_t len = min(cell.length, sizeof(password) - pw.length); 97 size_t i; 98 99 memcpy(password + pw.length, cell.data, len); 100 for (i = pw.length; i < pw.length + len; ++i) 101 password[i] = tolower((unsigned char)password[i]); 102 } 103 passlen = min(sizeof(password), pw.length + cell.length); 104 memcpy(&ivec, "kerberos", 8); 105 memcpy(&temp_key, "kerberos", 8); 106 CCDesCBCCksum(password, &ivec, passlen, temp_key, sizeof(temp_key), &ivec); 107 108 memcpy(&temp_key, &ivec, 8); 109 CCDesCBCCksum(password, &key, passlen, temp_key, sizeof(temp_key), &ivec); 110 memset(&schedule, 0, sizeof(schedule)); 111 memset(&temp_key, 0, sizeof(temp_key)); 112 memset(&ivec, 0, sizeof(ivec)); 113 memset(password, 0, sizeof(password)); 114 115 CCDesSetOddParity(key, sizeof(*key)); 116} 117 118static krb5_error_code 119DES_AFS3_string_to_key(krb5_context context, 120 krb5_enctype enctype, 121 krb5_data password, 122 krb5_salt salt, 123 krb5_data opaque, 124 krb5_keyblock *key) 125{ 126 DES_cblock tmp; 127 if(password.length > 8) 128 krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp); 129 else 130 krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp); 131 key->keytype = enctype; 132 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); 133 memset(&key, 0, sizeof(key)); 134 return 0; 135} 136#endif /* ENABLE_AFS_STRING_TO_KEY */ 137 138static void 139DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key) 140{ 141 DES_key_schedule schedule; 142 size_t i; 143 int reverse = 0; 144 unsigned char *p; 145 146 unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 147 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; 148 memset(key, 0, 8); 149 150 p = (unsigned char*)key; 151 for (i = 0; i < length; i++) { 152 unsigned char tmp = data[i]; 153 if (!reverse) 154 *p++ ^= (tmp << 1); 155 else 156 *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4]; 157 if((i % 8) == 7) 158 reverse = !reverse; 159 } 160 CCDesSetOddParity(key, sizeof(*key)); 161 if(CCDesIsWeakKey(key, sizeof(*key))) 162 (*key)[7] ^= 0xF0; 163#ifndef __APPLE_PRIVATE__ 164 DES_set_key_unchecked(key, &schedule); 165 DES_cbc_cksum((void*)data, key, length, &schedule, key); 166#else 167 CCDesCBCCksum(data, key, length, key, sizeof(*key), key); 168#endif 169 memset(&schedule, 0, sizeof(schedule)); 170 CCDesSetOddParity(key, sizeof(*key)); 171 if(CCDesIsWeakKey(key, sizeof(*key))) 172 (*key)[7] ^= 0xF0; 173} 174 175static krb5_error_code 176krb5_DES_string_to_key(krb5_context context, 177 krb5_enctype enctype, 178 krb5_data password, 179 krb5_salt salt, 180 krb5_data opaque, 181 krb5_keyblock *key) 182{ 183 unsigned char *s; 184 size_t len; 185 DES_cblock tmp; 186 187#ifdef ENABLE_AFS_STRING_TO_KEY 188 if (opaque.length == 1) { 189 unsigned long v; 190 _krb5_get_int(opaque.data, &v, 1); 191 if (v == 1) 192 return DES_AFS3_string_to_key(context, enctype, password, 193 salt, opaque, key); 194 } 195#endif 196 197 len = password.length + salt.saltvalue.length; 198 s = malloc(len); 199 if(len > 0 && s == NULL) { 200 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 201 return ENOMEM; 202 } 203 memcpy(s, password.data, password.length); 204 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); 205 DES_string_to_key_int(s, len, &tmp); 206 key->keytype = enctype; 207 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); 208 memset(&tmp, 0, sizeof(tmp)); 209 memset(s, 0, len); 210 free(s); 211 return 0; 212} 213 214struct salt_type _krb5_des_salt[] = { 215 { 216 KRB5_PW_SALT, 217 "pw-salt", 218 krb5_DES_string_to_key 219 }, 220#ifdef ENABLE_AFS_STRING_TO_KEY 221 { 222 KRB5_AFS3_SALT, 223 "afs3-salt", 224 DES_AFS3_string_to_key 225 }, 226#endif 227 { 0 } 228}; 229 230#endif /* HEIM_KRB5_DES */ 231