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 36 /* coverity[+alloc : arg-*3] */ 37 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 38 krb5_salttype_to_string (krb5_context context, 39 krb5_enctype etype, 40 krb5_salttype stype, 41 char **string) 42 { 43 struct _krb5_encryption_type *e; 44 struct salt_type *st; 45 46 (void) fbsd_ossl_provider_load(); 47 48 e = _krb5_find_enctype (etype); 49 if (e == NULL) { 50 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 51 "encryption type %d not supported", 52 etype); 53 return KRB5_PROG_ETYPE_NOSUPP; 54 } 55 for (st = e->keytype->string_to_key; st && st->type; st++) { 56 if (st->type == stype) { 57 *string = strdup (st->name); 58 if (*string == NULL) { 59 krb5_set_error_message (context, ENOMEM, 60 N_("malloc: out of memory", "")); 61 return ENOMEM; 62 } 63 return 0; 64 } 65 } 66 krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP, 67 "salttype %d not supported", stype); 68 return HEIM_ERR_SALTTYPE_NOSUPP; 69 } 70 71 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 72 krb5_string_to_salttype (krb5_context context, 73 krb5_enctype etype, 74 const char *string, 75 krb5_salttype *salttype) 76 { 77 struct _krb5_encryption_type *e; 78 struct salt_type *st; 79 80 (void) fbsd_ossl_provider_load(); 81 82 e = _krb5_find_enctype (etype); 83 if (e == NULL) { 84 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 85 N_("encryption type %d not supported", ""), 86 etype); 87 return KRB5_PROG_ETYPE_NOSUPP; 88 } 89 for (st = e->keytype->string_to_key; st && st->type; st++) { 90 if (strcasecmp (st->name, string) == 0) { 91 *salttype = st->type; 92 return 0; 93 } 94 } 95 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP, 96 N_("salttype %s not supported", ""), string); 97 return HEIM_ERR_SALTTYPE_NOSUPP; 98 } 99 100 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 101 krb5_get_pw_salt(krb5_context context, 102 krb5_const_principal principal, 103 krb5_salt *salt) 104 { 105 size_t len; 106 size_t i; 107 krb5_error_code ret; 108 char *p; 109 110 salt->salttype = KRB5_PW_SALT; 111 len = strlen(principal->realm); 112 for (i = 0; i < principal->name.name_string.len; ++i) 113 len += strlen(principal->name.name_string.val[i]); 114 ret = krb5_data_alloc (&salt->saltvalue, len); 115 if (ret) 116 return ret; 117 p = salt->saltvalue.data; 118 memcpy (p, principal->realm, strlen(principal->realm)); 119 p += strlen(principal->realm); 120 for (i = 0; i < principal->name.name_string.len; ++i) { 121 memcpy (p, 122 principal->name.name_string.val[i], 123 strlen(principal->name.name_string.val[i])); 124 p += strlen(principal->name.name_string.val[i]); 125 } 126 return 0; 127 } 128 129 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 130 krb5_free_salt(krb5_context context, 131 krb5_salt salt) 132 { 133 krb5_data_free(&salt.saltvalue); 134 return 0; 135 } 136 137 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 138 krb5_string_to_key_data (krb5_context context, 139 krb5_enctype enctype, 140 krb5_data password, 141 krb5_principal principal, 142 krb5_keyblock *key) 143 { 144 krb5_error_code ret; 145 krb5_salt salt; 146 147 ret = krb5_get_pw_salt(context, principal, &salt); 148 if(ret) 149 return ret; 150 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key); 151 krb5_free_salt(context, salt); 152 return ret; 153 } 154 155 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 156 krb5_string_to_key (krb5_context context, 157 krb5_enctype enctype, 158 const char *password, 159 krb5_principal principal, 160 krb5_keyblock *key) 161 { 162 krb5_data pw; 163 pw.data = rk_UNCONST(password); 164 pw.length = strlen(password); 165 return krb5_string_to_key_data(context, enctype, pw, principal, key); 166 } 167 168 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 169 krb5_string_to_key_data_salt (krb5_context context, 170 krb5_enctype enctype, 171 krb5_data password, 172 krb5_salt salt, 173 krb5_keyblock *key) 174 { 175 krb5_data opaque; 176 krb5_data_zero(&opaque); 177 return krb5_string_to_key_data_salt_opaque(context, enctype, password, 178 salt, opaque, key); 179 } 180 181 /* 182 * Do a string -> key for encryption type `enctype' operation on 183 * `password' (with salt `salt' and the enctype specific data string 184 * `opaque'), returning the resulting key in `key' 185 */ 186 187 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 188 krb5_string_to_key_data_salt_opaque (krb5_context context, 189 krb5_enctype enctype, 190 krb5_data password, 191 krb5_salt salt, 192 krb5_data opaque, 193 krb5_keyblock *key) 194 { 195 struct _krb5_encryption_type *et =_krb5_find_enctype(enctype); 196 struct salt_type *st; 197 if(et == NULL) { 198 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 199 N_("encryption type %d not supported", ""), 200 enctype); 201 return KRB5_PROG_ETYPE_NOSUPP; 202 } 203 (void) fbsd_ossl_provider_load(); 204 for(st = et->keytype->string_to_key; st && st->type; st++) 205 if(st->type == salt.salttype) 206 return (*st->string_to_key)(context, enctype, password, 207 salt, opaque, key); 208 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP, 209 N_("salt type %d not supported", ""), 210 salt.salttype); 211 return HEIM_ERR_SALTTYPE_NOSUPP; 212 } 213 214 /* 215 * Do a string -> key for encryption type `enctype' operation on the 216 * string `password' (with salt `salt'), returning the resulting key 217 * in `key' 218 */ 219 220 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 221 krb5_string_to_key_salt (krb5_context context, 222 krb5_enctype enctype, 223 const char *password, 224 krb5_salt salt, 225 krb5_keyblock *key) 226 { 227 krb5_data pw; 228 pw.data = rk_UNCONST(password); 229 pw.length = strlen(password); 230 return krb5_string_to_key_data_salt(context, enctype, pw, salt, key); 231 } 232 233 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 234 krb5_string_to_key_salt_opaque (krb5_context context, 235 krb5_enctype enctype, 236 const char *password, 237 krb5_salt salt, 238 krb5_data opaque, 239 krb5_keyblock *key) 240 { 241 krb5_data pw; 242 pw.data = rk_UNCONST(password); 243 pw.length = strlen(password); 244 return krb5_string_to_key_data_salt_opaque(context, enctype, 245 pw, salt, opaque, key); 246 } 247 248 249 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 250 krb5_string_to_key_derived(krb5_context context, 251 const void *str, 252 size_t len, 253 krb5_enctype etype, 254 krb5_keyblock *key) 255 { 256 struct _krb5_encryption_type *et = _krb5_find_enctype(etype); 257 krb5_error_code ret; 258 struct _krb5_key_data kd; 259 size_t keylen; 260 u_char *tmp; 261 262 if(et == NULL) { 263 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 264 N_("encryption type %d not supported", ""), 265 etype); 266 return KRB5_PROG_ETYPE_NOSUPP; 267 } 268 keylen = et->keytype->bits / 8; 269 270 ALLOC(kd.key, 1); 271 if(kd.key == NULL) { 272 krb5_set_error_message (context, ENOMEM, 273 N_("malloc: out of memory", "")); 274 return ENOMEM; 275 } 276 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); 277 if(ret) { 278 free(kd.key); 279 return ret; 280 } 281 kd.key->keytype = etype; 282 tmp = malloc (keylen); 283 if(tmp == NULL) { 284 krb5_free_keyblock(context, kd.key); 285 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); 286 return ENOMEM; 287 } 288 ret = _krb5_n_fold(str, len, tmp, keylen); 289 if (ret) { 290 free(tmp); 291 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); 292 return ret; 293 } 294 kd.schedule = NULL; 295 _krb5_DES3_random_to_key(context, kd.key, tmp, keylen); 296 memset(tmp, 0, keylen); 297 free(tmp); 298 ret = _krb5_derive_key(context, 299 et, 300 &kd, 301 "kerberos", /* XXX well known constant */ 302 strlen("kerberos")); 303 if (ret) { 304 _krb5_free_key_data(context, &kd, et); 305 return ret; 306 } 307 ret = krb5_copy_keyblock_contents(context, kd.key, key); 308 _krb5_free_key_data(context, &kd, et); 309 return ret; 310 } 311