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
krb5_salttype_to_string(krb5_context context,krb5_enctype etype,krb5_salttype stype,char ** string)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
krb5_string_to_salttype(krb5_context context,krb5_enctype etype,const char * string,krb5_salttype * salttype)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
krb5_get_pw_salt(krb5_context context,krb5_const_principal principal,krb5_salt * salt)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
krb5_free_salt(krb5_context context,krb5_salt salt)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
krb5_string_to_key_data(krb5_context context,krb5_enctype enctype,krb5_data password,krb5_principal principal,krb5_keyblock * key)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
krb5_string_to_key(krb5_context context,krb5_enctype enctype,const char * password,krb5_principal principal,krb5_keyblock * key)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
krb5_string_to_key_data_salt(krb5_context context,krb5_enctype enctype,krb5_data password,krb5_salt salt,krb5_keyblock * key)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
krb5_string_to_key_data_salt_opaque(krb5_context context,krb5_enctype enctype,krb5_data password,krb5_salt salt,krb5_data opaque,krb5_keyblock * key)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
krb5_string_to_key_salt(krb5_context context,krb5_enctype enctype,const char * password,krb5_salt salt,krb5_keyblock * key)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
krb5_string_to_key_salt_opaque(krb5_context context,krb5_enctype enctype,const char * password,krb5_salt salt,krb5_data opaque,krb5_keyblock * key)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
krb5_string_to_key_derived(krb5_context context,const void * str,size_t len,krb5_enctype etype,krb5_keyblock * key)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