1 /* $NetBSD: salt.c,v 1.3 2014/04/24 13:45:34 pettai Exp $ */
2
3 /*
4 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include "krb5_locl.h"
37
38 /* coverity[+alloc : arg-*3] */
39 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_salttype_to_string(krb5_context context,krb5_enctype etype,krb5_salttype stype,char ** string)40 krb5_salttype_to_string (krb5_context context,
41 krb5_enctype etype,
42 krb5_salttype stype,
43 char **string)
44 {
45 struct _krb5_encryption_type *e;
46 struct salt_type *st;
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 e = _krb5_find_enctype (etype);
81 if (e == NULL) {
82 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
83 N_("encryption type %d not supported", ""),
84 etype);
85 return KRB5_PROG_ETYPE_NOSUPP;
86 }
87 for (st = e->keytype->string_to_key; st && st->type; st++) {
88 if (strcasecmp (st->name, string) == 0) {
89 *salttype = st->type;
90 return 0;
91 }
92 }
93 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
94 N_("salttype %s not supported", ""), string);
95 return HEIM_ERR_SALTTYPE_NOSUPP;
96 }
97
98 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_pw_salt(krb5_context context,krb5_const_principal principal,krb5_salt * salt)99 krb5_get_pw_salt(krb5_context context,
100 krb5_const_principal principal,
101 krb5_salt *salt)
102 {
103 size_t len;
104 size_t i;
105 krb5_error_code ret;
106 char *p;
107
108 salt->salttype = KRB5_PW_SALT;
109 len = strlen(principal->realm);
110 for (i = 0; i < principal->name.name_string.len; ++i)
111 len += strlen(principal->name.name_string.val[i]);
112 ret = krb5_data_alloc (&salt->saltvalue, len);
113 if (ret)
114 return ret;
115 p = salt->saltvalue.data;
116 memcpy (p, principal->realm, strlen(principal->realm));
117 p += strlen(principal->realm);
118 for (i = 0; i < principal->name.name_string.len; ++i) {
119 memcpy (p,
120 principal->name.name_string.val[i],
121 strlen(principal->name.name_string.val[i]));
122 p += strlen(principal->name.name_string.val[i]);
123 }
124 return 0;
125 }
126
127 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_free_salt(krb5_context context,krb5_salt salt)128 krb5_free_salt(krb5_context context,
129 krb5_salt salt)
130 {
131 krb5_data_free(&salt.saltvalue);
132 return 0;
133 }
134
135 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)136 krb5_string_to_key_data (krb5_context context,
137 krb5_enctype enctype,
138 krb5_data password,
139 krb5_principal principal,
140 krb5_keyblock *key)
141 {
142 krb5_error_code ret;
143 krb5_salt salt;
144
145 ret = krb5_get_pw_salt(context, principal, &salt);
146 if(ret)
147 return ret;
148 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
149 krb5_free_salt(context, salt);
150 return ret;
151 }
152
153 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)154 krb5_string_to_key (krb5_context context,
155 krb5_enctype enctype,
156 const char *password,
157 krb5_principal principal,
158 krb5_keyblock *key)
159 {
160 krb5_data pw;
161 pw.data = rk_UNCONST(password);
162 pw.length = strlen(password);
163 return krb5_string_to_key_data(context, enctype, pw, principal, key);
164 }
165
166 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)167 krb5_string_to_key_data_salt (krb5_context context,
168 krb5_enctype enctype,
169 krb5_data password,
170 krb5_salt salt,
171 krb5_keyblock *key)
172 {
173 krb5_data opaque;
174 krb5_data_zero(&opaque);
175 return krb5_string_to_key_data_salt_opaque(context, enctype, password,
176 salt, opaque, key);
177 }
178
179 /*
180 * Do a string -> key for encryption type `enctype' operation on
181 * `password' (with salt `salt' and the enctype specific data string
182 * `opaque'), returning the resulting key in `key'
183 */
184
185 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)186 krb5_string_to_key_data_salt_opaque (krb5_context context,
187 krb5_enctype enctype,
188 krb5_data password,
189 krb5_salt salt,
190 krb5_data opaque,
191 krb5_keyblock *key)
192 {
193 struct _krb5_encryption_type *et =_krb5_find_enctype(enctype);
194 struct salt_type *st;
195 if(et == NULL) {
196 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
197 N_("encryption type %d not supported", ""),
198 enctype);
199 return KRB5_PROG_ETYPE_NOSUPP;
200 }
201 for(st = et->keytype->string_to_key; st && st->type; st++)
202 if(st->type == salt.salttype)
203 return (*st->string_to_key)(context, enctype, password,
204 salt, opaque, key);
205 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
206 N_("salt type %d not supported", ""),
207 salt.salttype);
208 return HEIM_ERR_SALTTYPE_NOSUPP;
209 }
210
211 /*
212 * Do a string -> key for encryption type `enctype' operation on the
213 * string `password' (with salt `salt'), returning the resulting key
214 * in `key'
215 */
216
217 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)218 krb5_string_to_key_salt (krb5_context context,
219 krb5_enctype enctype,
220 const char *password,
221 krb5_salt salt,
222 krb5_keyblock *key)
223 {
224 krb5_data pw;
225 pw.data = rk_UNCONST(password);
226 pw.length = strlen(password);
227 return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
228 }
229
230 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)231 krb5_string_to_key_salt_opaque (krb5_context context,
232 krb5_enctype enctype,
233 const char *password,
234 krb5_salt salt,
235 krb5_data opaque,
236 krb5_keyblock *key)
237 {
238 krb5_data pw;
239 pw.data = rk_UNCONST(password);
240 pw.length = strlen(password);
241 return krb5_string_to_key_data_salt_opaque(context, enctype,
242 pw, salt, opaque, key);
243 }
244
245
246 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)247 krb5_string_to_key_derived(krb5_context context,
248 const void *str,
249 size_t len,
250 krb5_enctype etype,
251 krb5_keyblock *key)
252 {
253 struct _krb5_encryption_type *et = _krb5_find_enctype(etype);
254 krb5_error_code ret;
255 struct _krb5_key_data kd;
256 size_t keylen;
257 u_char *tmp;
258
259 if(et == NULL) {
260 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
261 N_("encryption type %d not supported", ""),
262 etype);
263 return KRB5_PROG_ETYPE_NOSUPP;
264 }
265 keylen = et->keytype->bits / 8;
266
267 ALLOC(kd.key, 1);
268 if(kd.key == NULL) {
269 krb5_set_error_message (context, ENOMEM,
270 N_("malloc: out of memory", ""));
271 return ENOMEM;
272 }
273 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
274 if(ret) {
275 free(kd.key);
276 return ret;
277 }
278 kd.key->keytype = etype;
279 tmp = malloc (keylen);
280 if(tmp == NULL) {
281 krb5_free_keyblock(context, kd.key);
282 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
283 return ENOMEM;
284 }
285 ret = _krb5_n_fold(str, len, tmp, keylen);
286 if (ret) {
287 free(tmp);
288 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
289 return ret;
290 }
291 kd.schedule = NULL;
292 _krb5_DES3_random_to_key(context, kd.key, tmp, keylen);
293 memset(tmp, 0, keylen);
294 free(tmp);
295 ret = _krb5_derive_key(context,
296 et,
297 &kd,
298 "kerberos", /* XXX well known constant */
299 strlen("kerberos"));
300 if (ret) {
301 _krb5_free_key_data(context, &kd, et);
302 return ret;
303 }
304 ret = krb5_copy_keyblock_contents(context, kd.key, key);
305 _krb5_free_key_data(context, &kd, et);
306 return ret;
307 }
308