xref: /freebsd/crypto/heimdal/lib/kadm5/set_keys.c (revision b528cefc6b8f9670b31a865051741d946cb37085)
1b528cefcSMark Murray /*
2b528cefcSMark Murray  * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H�gskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include "kadm5_locl.h"
35b528cefcSMark Murray 
36b528cefcSMark Murray RCSID("$Id: set_keys.c,v 1.18 1999/12/04 23:11:01 assar Exp $");
37b528cefcSMark Murray 
38b528cefcSMark Murray /*
39b528cefcSMark Murray  * free all the memory used by (len, keys)
40b528cefcSMark Murray  */
41b528cefcSMark Murray 
42b528cefcSMark Murray static void
43b528cefcSMark Murray free_keys (kadm5_server_context *context,
44b528cefcSMark Murray 	   int len, Key *keys)
45b528cefcSMark Murray {
46b528cefcSMark Murray     int i;
47b528cefcSMark Murray 
48b528cefcSMark Murray     for (i = 0; i < len; ++i) {
49b528cefcSMark Murray 	free (keys[i].mkvno);
50b528cefcSMark Murray 	keys[i].mkvno = NULL;
51b528cefcSMark Murray 	if (keys[i].salt != NULL) {
52b528cefcSMark Murray 	    free_Salt(keys[i].salt);
53b528cefcSMark Murray 	    free(keys[i].salt);
54b528cefcSMark Murray 	    keys[i].salt = NULL;
55b528cefcSMark Murray 	}
56b528cefcSMark Murray 	krb5_free_keyblock_contents(context->context, &keys[i].key);
57b528cefcSMark Murray     }
58b528cefcSMark Murray     free (keys);
59b528cefcSMark Murray }
60b528cefcSMark Murray 
61b528cefcSMark Murray /*
62b528cefcSMark Murray  * null-ify `len', `keys'
63b528cefcSMark Murray  */
64b528cefcSMark Murray 
65b528cefcSMark Murray static void
66b528cefcSMark Murray init_keys (Key *keys, int len)
67b528cefcSMark Murray {
68b528cefcSMark Murray     int i;
69b528cefcSMark Murray 
70b528cefcSMark Murray     for (i = 0; i < len; ++i) {
71b528cefcSMark Murray 	keys[i].mkvno               = NULL;
72b528cefcSMark Murray 	keys[i].salt                = NULL;
73b528cefcSMark Murray 	keys[i].key.keyvalue.length = 0;
74b528cefcSMark Murray 	keys[i].key.keyvalue.data   = NULL;
75b528cefcSMark Murray     }
76b528cefcSMark Murray }
77b528cefcSMark Murray 
78b528cefcSMark Murray /*
79b528cefcSMark Murray  * the known and used DES enctypes
80b528cefcSMark Murray  */
81b528cefcSMark Murray 
82b528cefcSMark Murray static krb5_enctype des_types[] = { ETYPE_DES_CBC_CRC,
83b528cefcSMark Murray 				    ETYPE_DES_CBC_MD4,
84b528cefcSMark Murray 				    ETYPE_DES_CBC_MD5 };
85b528cefcSMark Murray 
86b528cefcSMark Murray static unsigned n_des_types = 3;
87b528cefcSMark Murray 
88b528cefcSMark Murray /*
89b528cefcSMark Murray  * Set the keys of `ent' to the string-to-key of `password'
90b528cefcSMark Murray  */
91b528cefcSMark Murray 
92b528cefcSMark Murray kadm5_ret_t
93b528cefcSMark Murray _kadm5_set_keys(kadm5_server_context *context,
94b528cefcSMark Murray 		hdb_entry *ent,
95b528cefcSMark Murray 		const char *password)
96b528cefcSMark Murray {
97b528cefcSMark Murray     kadm5_ret_t ret = 0;
98b528cefcSMark Murray     int i;
99b528cefcSMark Murray     unsigned len;
100b528cefcSMark Murray     Key *keys;
101b528cefcSMark Murray     krb5_salt salt;
102b528cefcSMark Murray     krb5_boolean v4_salt = FALSE;
103b528cefcSMark Murray 
104b528cefcSMark Murray     len  = n_des_types + 1;
105b528cefcSMark Murray     keys = malloc (len * sizeof(*keys));
106b528cefcSMark Murray     if (keys == NULL)
107b528cefcSMark Murray 	return ENOMEM;
108b528cefcSMark Murray 
109b528cefcSMark Murray     init_keys (keys, len);
110b528cefcSMark Murray 
111b528cefcSMark Murray     salt.salttype         = KRB5_PW_SALT;
112b528cefcSMark Murray     salt.saltvalue.length = 0;
113b528cefcSMark Murray     salt.saltvalue.data   = NULL;
114b528cefcSMark Murray 
115b528cefcSMark Murray     if (krb5_config_get_bool (context->context,
116b528cefcSMark Murray 			      NULL, "kadmin", "use_v4_salt", NULL)) {
117b528cefcSMark Murray 	v4_salt = TRUE;
118b528cefcSMark Murray     } else {
119b528cefcSMark Murray 	ret = krb5_get_pw_salt (context->context, ent->principal, &salt);
120b528cefcSMark Murray 	if (ret)
121b528cefcSMark Murray 	    goto out;
122b528cefcSMark Murray     }
123b528cefcSMark Murray 
124b528cefcSMark Murray     for (i = 0; i < n_des_types; ++i) {
125b528cefcSMark Murray 	ret = krb5_string_to_key_salt (context->context,
126b528cefcSMark Murray 				       des_types[i],
127b528cefcSMark Murray 				       password,
128b528cefcSMark Murray 				       salt,
129b528cefcSMark Murray 				       &keys[i].key);
130b528cefcSMark Murray 	if (ret)
131b528cefcSMark Murray 	    goto out;
132b528cefcSMark Murray 	if (v4_salt) {
133b528cefcSMark Murray 	    keys[i].salt = malloc (sizeof(*keys[i].salt));
134b528cefcSMark Murray 	    if (keys[i].salt == NULL) {
135b528cefcSMark Murray 		ret = ENOMEM;
136b528cefcSMark Murray 		goto out;
137b528cefcSMark Murray 	    }
138b528cefcSMark Murray 	    keys[i].salt->type = salt.salttype;
139b528cefcSMark Murray 	    ret = copy_octet_string (&salt.saltvalue, &keys[i].salt->salt);
140b528cefcSMark Murray 	    if (ret)
141b528cefcSMark Murray 		goto out;
142b528cefcSMark Murray 	}
143b528cefcSMark Murray     }
144b528cefcSMark Murray 
145b528cefcSMark Murray     ret = krb5_string_to_key (context->context,
146b528cefcSMark Murray 			      ETYPE_DES3_CBC_SHA1,
147b528cefcSMark Murray 			      password,
148b528cefcSMark Murray 			      ent->principal,
149b528cefcSMark Murray 			      &keys[n_des_types].key);
150b528cefcSMark Murray     if (ret)
151b528cefcSMark Murray 	goto out;
152b528cefcSMark Murray 
153b528cefcSMark Murray     free_keys (context, ent->keys.len, ent->keys.val);
154b528cefcSMark Murray     ent->keys.len = len;
155b528cefcSMark Murray     ent->keys.val = keys;
156b528cefcSMark Murray     ent->kvno++;
157b528cefcSMark Murray     return ret;
158b528cefcSMark Murray out:
159b528cefcSMark Murray     krb5_data_free (&salt.saltvalue);
160b528cefcSMark Murray     free_keys (context, len, keys);
161b528cefcSMark Murray     return ret;
162b528cefcSMark Murray }
163b528cefcSMark Murray 
164b528cefcSMark Murray /*
165b528cefcSMark Murray  * Set the keys of `ent' to (`n_key_data', `key_data')
166b528cefcSMark Murray  */
167b528cefcSMark Murray 
168b528cefcSMark Murray kadm5_ret_t
169b528cefcSMark Murray _kadm5_set_keys2(hdb_entry *ent,
170b528cefcSMark Murray 		 int16_t n_key_data,
171b528cefcSMark Murray 		 krb5_key_data *key_data)
172b528cefcSMark Murray {
173b528cefcSMark Murray     krb5_error_code ret;
174b528cefcSMark Murray     int i;
175b528cefcSMark Murray 
176b528cefcSMark Murray     ent->keys.len = n_key_data;
177b528cefcSMark Murray     ent->keys.val = malloc(ent->keys.len * sizeof(*ent->keys.val));
178b528cefcSMark Murray     if(ent->keys.val == NULL)
179b528cefcSMark Murray 	return ENOMEM;
180b528cefcSMark Murray     for(i = 0; i < n_key_data; i++) {
181b528cefcSMark Murray 	ent->keys.val[i].mkvno = NULL;
182b528cefcSMark Murray 	ent->keys.val[i].key.keytype = key_data[i].key_data_type[0];
183b528cefcSMark Murray 	ret = krb5_data_copy(&ent->keys.val[i].key.keyvalue,
184b528cefcSMark Murray 			     key_data[i].key_data_contents[0],
185b528cefcSMark Murray 			     key_data[i].key_data_length[0]);
186b528cefcSMark Murray 	if(ret)
187b528cefcSMark Murray 	    return ret;
188b528cefcSMark Murray 	if(key_data[i].key_data_ver == 2) {
189b528cefcSMark Murray 	    Salt *salt;
190b528cefcSMark Murray 	    salt = malloc(sizeof(*salt));
191b528cefcSMark Murray 	    if(salt == NULL)
192b528cefcSMark Murray 		return ENOMEM;
193b528cefcSMark Murray 	    ent->keys.val[i].salt = salt;
194b528cefcSMark Murray 	    salt->type = key_data[i].key_data_type[1];
195b528cefcSMark Murray 	    krb5_data_copy(&salt->salt,
196b528cefcSMark Murray 			   key_data[i].key_data_contents[1],
197b528cefcSMark Murray 			   key_data[i].key_data_length[1]);
198b528cefcSMark Murray 	} else
199b528cefcSMark Murray 	    ent->keys.val[i].salt = NULL;
200b528cefcSMark Murray     }
201b528cefcSMark Murray     ent->kvno++;
202b528cefcSMark Murray     return 0;
203b528cefcSMark Murray }
204b528cefcSMark Murray 
205b528cefcSMark Murray /*
206b528cefcSMark Murray  * Set the keys of `ent' to random keys and return them in `n_keys'
207b528cefcSMark Murray  * and `new_keys'.
208b528cefcSMark Murray  */
209b528cefcSMark Murray 
210b528cefcSMark Murray kadm5_ret_t
211b528cefcSMark Murray _kadm5_set_keys_randomly (kadm5_server_context *context,
212b528cefcSMark Murray 			  hdb_entry *ent,
213b528cefcSMark Murray 			  krb5_keyblock **new_keys,
214b528cefcSMark Murray 			  int *n_keys)
215b528cefcSMark Murray {
216b528cefcSMark Murray     kadm5_ret_t ret = 0;
217b528cefcSMark Murray     int i;
218b528cefcSMark Murray     unsigned len;
219b528cefcSMark Murray     krb5_keyblock *keys;
220b528cefcSMark Murray     Key *hkeys;
221b528cefcSMark Murray 
222b528cefcSMark Murray     len  = n_des_types + 1;
223b528cefcSMark Murray     keys = malloc (len * sizeof(*keys));
224b528cefcSMark Murray     if (keys == NULL)
225b528cefcSMark Murray 	return ENOMEM;
226b528cefcSMark Murray 
227b528cefcSMark Murray     for (i = 0; i < len; ++i) {
228b528cefcSMark Murray 	keys[i].keyvalue.length = 0;
229b528cefcSMark Murray 	keys[i].keyvalue.data   = NULL;
230b528cefcSMark Murray     }
231b528cefcSMark Murray 
232b528cefcSMark Murray     hkeys = malloc (len * sizeof(*hkeys));
233b528cefcSMark Murray     if (hkeys == NULL) {
234b528cefcSMark Murray 	free (keys);
235b528cefcSMark Murray 	return ENOMEM;
236b528cefcSMark Murray     }
237b528cefcSMark Murray 
238b528cefcSMark Murray     init_keys (hkeys, len);
239b528cefcSMark Murray 
240b528cefcSMark Murray     ret = krb5_generate_random_keyblock (context->context,
241b528cefcSMark Murray 					 des_types[0],
242b528cefcSMark Murray 					 &keys[0]);
243b528cefcSMark Murray     if (ret)
244b528cefcSMark Murray 	goto out;
245b528cefcSMark Murray 
246b528cefcSMark Murray     ret = krb5_copy_keyblock_contents (context->context,
247b528cefcSMark Murray 				       &keys[0],
248b528cefcSMark Murray 				       &hkeys[0].key);
249b528cefcSMark Murray     if (ret)
250b528cefcSMark Murray 	goto out;
251b528cefcSMark Murray 
252b528cefcSMark Murray     for (i = 1; i < n_des_types; ++i) {
253b528cefcSMark Murray 	ret = krb5_copy_keyblock_contents (context->context,
254b528cefcSMark Murray 					   &keys[0],
255b528cefcSMark Murray 					   &keys[i]);
256b528cefcSMark Murray 	if (ret)
257b528cefcSMark Murray 	    goto out;
258b528cefcSMark Murray 	keys[i].keytype = des_types[i];
259b528cefcSMark Murray 	ret = krb5_copy_keyblock_contents (context->context,
260b528cefcSMark Murray 					   &keys[0],
261b528cefcSMark Murray 					   &hkeys[i].key);
262b528cefcSMark Murray 	if (ret)
263b528cefcSMark Murray 	    goto out;
264b528cefcSMark Murray 	hkeys[i].key.keytype = des_types[i];
265b528cefcSMark Murray     }
266b528cefcSMark Murray 
267b528cefcSMark Murray     ret = krb5_generate_random_keyblock (context->context,
268b528cefcSMark Murray 					 ETYPE_DES3_CBC_SHA1,
269b528cefcSMark Murray 					 &keys[n_des_types]);
270b528cefcSMark Murray     if (ret)
271b528cefcSMark Murray 	goto out;
272b528cefcSMark Murray 
273b528cefcSMark Murray     ret = krb5_copy_keyblock_contents (context->context,
274b528cefcSMark Murray 				       &keys[n_des_types],
275b528cefcSMark Murray 				       &hkeys[n_des_types].key);
276b528cefcSMark Murray     if (ret)
277b528cefcSMark Murray 	goto out;
278b528cefcSMark Murray 
279b528cefcSMark Murray     free_keys (context, ent->keys.len, ent->keys.val);
280b528cefcSMark Murray     ent->keys.len = len;
281b528cefcSMark Murray     ent->keys.val = hkeys;
282b528cefcSMark Murray     ent->kvno++;
283b528cefcSMark Murray     *new_keys     = keys;
284b528cefcSMark Murray     *n_keys       = len;
285b528cefcSMark Murray     return ret;
286b528cefcSMark Murray out:
287b528cefcSMark Murray     for (i = 0; i < len; ++i)
288b528cefcSMark Murray 	krb5_free_keyblock_contents (context->context, &keys[i]);
289b528cefcSMark Murray     free (keys);
290b528cefcSMark Murray     free_keys (context, len, hkeys);
291b528cefcSMark Murray     return ret;
292b528cefcSMark Murray }
293