HEIMDAL: move code from source4/heimdal* to third_party/heimdal*
[Samba.git] / third_party / heimdal / lib / krb5 / salt.c
blobfa926f3d6c604c59b555949a22f996943f4661d6
1 /*
2 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include "krb5_locl.h"
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)
43 struct _krb5_encryption_type *e;
44 struct salt_type *st;
46 *string = NULL;
47 e = _krb5_find_enctype (etype);
48 if (e == NULL) {
49 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
50 "encryption type %d not supported",
51 etype);
52 return KRB5_PROG_ETYPE_NOSUPP;
54 for (st = e->keytype->string_to_key; st && st->type; st++) {
55 if (st->type == stype) {
56 *string = strdup (st->name);
57 if (*string == NULL)
58 return krb5_enomem(context);
59 return 0;
62 krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
63 "salttype %d not supported", stype);
64 return HEIM_ERR_SALTTYPE_NOSUPP;
67 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
68 krb5_string_to_salttype (krb5_context context,
69 krb5_enctype etype,
70 const char *string,
71 krb5_salttype *salttype)
73 struct _krb5_encryption_type *e;
74 struct salt_type *st;
76 e = _krb5_find_enctype (etype);
77 if (e == NULL) {
78 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
79 N_("encryption type %d not supported", ""),
80 etype);
81 return KRB5_PROG_ETYPE_NOSUPP;
83 for (st = e->keytype->string_to_key; st && st->type; st++) {
84 if (strcasecmp (st->name, string) == 0) {
85 *salttype = st->type;
86 return 0;
89 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
90 N_("salttype %s not supported", ""), string);
91 return HEIM_ERR_SALTTYPE_NOSUPP;
95 * Like MIT's krb5_string_to_keysalts(), but simpler and with a context
96 * argument.
98 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
99 krb5_string_to_keysalts2(krb5_context context, const char *string,
100 size_t *nksaltp, krb5_key_salt_tuple **ksaltp)
102 /* deleted: tupleseps, ksaltseps, dups */
103 krb5_key_salt_tuple *tmp = NULL;
104 krb5_error_code ret = 0;
105 char *copy, *token, *stype_str;
106 char *lasts = NULL;
107 krb5_enctype etype;
108 krb5_salttype stype;
109 size_t i;
111 *ksaltp = NULL;
112 *nksaltp = 0;
113 if ((copy = strdup(string)) == NULL)
114 return krb5_enomem(context);
115 for (token = strtok_r(copy, ", \t", &lasts), ret = 0;
116 token != NULL;
117 token = strtok_r(NULL, ", \t", &lasts)) {
118 if ((stype_str = strchr(token, ':')) != NULL)
119 *(stype_str++) = '\0';
120 if ((ret = krb5_string_to_enctype(context, token, &etype)))
121 continue;
122 if (stype_str == NULL)
123 stype = KRB5_PW_SALT;
124 else if ((ret = krb5_string_to_salttype(context, etype, stype_str, &stype)))
125 continue;
126 for (i = 0; i < *nksaltp; i++) {
127 if ((*ksaltp)[i].ks_enctype == etype &&
128 (*ksaltp)[i].ks_salttype == stype)
129 goto skip;
131 tmp = realloc(*ksaltp, ((*nksaltp) + 1) * sizeof(**ksaltp));
132 if (tmp == NULL) {
133 ret = krb5_enomem(context);
134 break;
136 *ksaltp = tmp;
137 (*ksaltp)[*nksaltp].ks_enctype = etype;
138 (*ksaltp)[*nksaltp].ks_salttype = stype;
139 (*nksaltp)++;
140 skip:
141 (void)1;
143 free(copy);
144 if (ret == ENOMEM) {
145 free(*ksaltp);
146 *nksaltp = 0;
147 *ksaltp = NULL;
148 } else if (*nksaltp) {
149 return 0;
150 } else if (ret == 0) {
151 return KRB5_PROG_ETYPE_NOSUPP;
153 return ret;
157 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
158 krb5_get_pw_salt(krb5_context context,
159 krb5_const_principal principal,
160 krb5_salt *salt)
162 size_t len;
163 size_t i;
164 krb5_error_code ret;
165 char *p;
167 salt->salttype = KRB5_PW_SALT;
168 len = strlen(principal->realm);
169 for (i = 0; i < principal->name.name_string.len; ++i)
170 len += strlen(principal->name.name_string.val[i]);
171 ret = krb5_data_alloc (&salt->saltvalue, len);
172 if (ret)
173 return ret;
174 p = salt->saltvalue.data;
175 memcpy (p, principal->realm, strlen(principal->realm));
176 p += strlen(principal->realm);
177 for (i = 0; i < principal->name.name_string.len; ++i) {
178 memcpy (p,
179 principal->name.name_string.val[i],
180 strlen(principal->name.name_string.val[i]));
181 p += strlen(principal->name.name_string.val[i]);
183 return 0;
186 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
187 krb5_free_salt(krb5_context context,
188 krb5_salt salt)
190 krb5_data_free(&salt.saltvalue);
191 return 0;
194 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
195 krb5_string_to_key_data (krb5_context context,
196 krb5_enctype enctype,
197 krb5_data password,
198 krb5_const_principal principal,
199 krb5_keyblock *key)
201 krb5_error_code ret;
202 krb5_salt salt;
204 ret = krb5_get_pw_salt(context, principal, &salt);
205 if(ret)
206 return ret;
207 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
208 krb5_free_salt(context, salt);
209 return ret;
212 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
213 krb5_string_to_key (krb5_context context,
214 krb5_enctype enctype,
215 const char *password,
216 krb5_const_principal principal,
217 krb5_keyblock *key)
219 krb5_data pw;
220 pw.data = rk_UNCONST(password);
221 pw.length = strlen(password);
222 return krb5_string_to_key_data(context, enctype, pw, principal, key);
225 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
226 krb5_string_to_key_data_salt (krb5_context context,
227 krb5_enctype enctype,
228 krb5_data password,
229 krb5_salt salt,
230 krb5_keyblock *key)
232 krb5_data opaque;
233 krb5_data_zero(&opaque);
234 return krb5_string_to_key_data_salt_opaque(context, enctype, password,
235 salt, opaque, key);
239 * Do a string -> key for encryption type `enctype' operation on
240 * `password' (with salt `salt' and the enctype specific data string
241 * `opaque'), returning the resulting key in `key'
244 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
245 krb5_string_to_key_data_salt_opaque (krb5_context context,
246 krb5_enctype enctype,
247 krb5_data password,
248 krb5_salt salt,
249 krb5_data opaque,
250 krb5_keyblock *key)
252 struct _krb5_encryption_type *et =_krb5_find_enctype(enctype);
253 struct salt_type *st;
254 if(et == NULL) {
255 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
256 N_("encryption type %d not supported", ""),
257 enctype);
258 return KRB5_PROG_ETYPE_NOSUPP;
260 for(st = et->keytype->string_to_key; st && st->type; st++)
261 if(st->type == salt.salttype)
262 return (*st->string_to_key)(context, enctype, password,
263 salt, opaque, key);
264 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
265 N_("salt type %d not supported", ""),
266 salt.salttype);
267 return HEIM_ERR_SALTTYPE_NOSUPP;
271 * Do a string -> key for encryption type `enctype' operation on the
272 * string `password' (with salt `salt'), returning the resulting key
273 * in `key'
276 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
277 krb5_string_to_key_salt (krb5_context context,
278 krb5_enctype enctype,
279 const char *password,
280 krb5_salt salt,
281 krb5_keyblock *key)
283 krb5_data pw;
284 pw.data = rk_UNCONST(password);
285 pw.length = strlen(password);
286 return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
289 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
290 krb5_string_to_key_salt_opaque (krb5_context context,
291 krb5_enctype enctype,
292 const char *password,
293 krb5_salt salt,
294 krb5_data opaque,
295 krb5_keyblock *key)
297 krb5_data pw;
298 pw.data = rk_UNCONST(password);
299 pw.length = strlen(password);
300 return krb5_string_to_key_data_salt_opaque(context, enctype,
301 pw, salt, opaque, key);
305 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
306 krb5_string_to_key_derived(krb5_context context,
307 const void *str,
308 size_t len,
309 krb5_enctype etype,
310 krb5_keyblock *key)
312 struct _krb5_encryption_type *et = _krb5_find_enctype(etype);
313 krb5_error_code ret;
314 struct _krb5_key_data kd;
315 size_t keylen;
316 u_char *tmp;
318 if(et == NULL) {
319 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
320 N_("encryption type %d not supported", ""),
321 etype);
322 return KRB5_PROG_ETYPE_NOSUPP;
324 keylen = et->keytype->bits / 8;
326 ALLOC(kd.key, 1);
327 if (kd.key == NULL)
328 return krb5_enomem(context);
329 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
330 if(ret) {
331 free(kd.key);
332 return ret;
334 kd.key->keytype = etype;
335 tmp = malloc (keylen);
336 if(tmp == NULL) {
337 krb5_free_keyblock(context, kd.key);
338 return krb5_enomem(context);
340 ret = _krb5_n_fold(str, len, tmp, keylen);
341 if (ret) {
342 free(tmp);
343 krb5_enomem(context);
344 return ret;
346 kd.schedule = NULL;
347 _krb5_DES3_random_to_key(context, kd.key, tmp, keylen);
348 memset(tmp, 0, keylen);
349 free(tmp);
350 ret = _krb5_derive_key(context,
352 &kd,
353 "kerberos", /* XXX well known constant */
354 strlen("kerberos"));
355 if (ret) {
356 _krb5_free_key_data(context, &kd, et);
357 return ret;
359 ret = krb5_copy_keyblock_contents(context, kd.key, key);
360 _krb5_free_key_data(context, &kd, et);
361 return ret;