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