mkey.c revision 1.1 1 1.1 elric /* $NetBSD: mkey.c,v 1.1 2011/04/13 18:14:42 elric Exp $ */
2 1.1 elric
3 1.1 elric /*
4 1.1 elric * Copyright (c) 2000 - 2004 Kungliga Tekniska Hgskolan
5 1.1 elric * (Royal Institute of Technology, Stockholm, Sweden).
6 1.1 elric * All rights reserved.
7 1.1 elric *
8 1.1 elric * Redistribution and use in source and binary forms, with or without
9 1.1 elric * modification, are permitted provided that the following conditions
10 1.1 elric * are met:
11 1.1 elric *
12 1.1 elric * 1. Redistributions of source code must retain the above copyright
13 1.1 elric * notice, this list of conditions and the following disclaimer.
14 1.1 elric *
15 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 elric * notice, this list of conditions and the following disclaimer in the
17 1.1 elric * documentation and/or other materials provided with the distribution.
18 1.1 elric *
19 1.1 elric * 3. Neither the name of the Institute nor the names of its contributors
20 1.1 elric * may be used to endorse or promote products derived from this software
21 1.1 elric * without specific prior written permission.
22 1.1 elric *
23 1.1 elric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 1.1 elric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 elric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 elric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 1.1 elric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 elric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 elric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 elric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 elric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 elric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 elric * SUCH DAMAGE.
34 1.1 elric */
35 1.1 elric
36 1.1 elric #include "hdb_locl.h"
37 1.1 elric #ifndef O_BINARY
38 1.1 elric #define O_BINARY 0
39 1.1 elric #endif
40 1.1 elric
41 1.1 elric struct hdb_master_key_data {
42 1.1 elric krb5_keytab_entry keytab;
43 1.1 elric krb5_crypto crypto;
44 1.1 elric struct hdb_master_key_data *next;
45 1.1 elric };
46 1.1 elric
47 1.1 elric void
48 1.1 elric hdb_free_master_key(krb5_context context, hdb_master_key mkey)
49 1.1 elric {
50 1.1 elric struct hdb_master_key_data *ptr;
51 1.1 elric while(mkey) {
52 1.1 elric krb5_kt_free_entry(context, &mkey->keytab);
53 1.1 elric if (mkey->crypto)
54 1.1 elric krb5_crypto_destroy(context, mkey->crypto);
55 1.1 elric ptr = mkey;
56 1.1 elric mkey = mkey->next;
57 1.1 elric free(ptr);
58 1.1 elric }
59 1.1 elric }
60 1.1 elric
61 1.1 elric krb5_error_code
62 1.1 elric hdb_process_master_key(krb5_context context,
63 1.1 elric int kvno, krb5_keyblock *key, krb5_enctype etype,
64 1.1 elric hdb_master_key *mkey)
65 1.1 elric {
66 1.1 elric krb5_error_code ret;
67 1.1 elric
68 1.1 elric *mkey = calloc(1, sizeof(**mkey));
69 1.1 elric if(*mkey == NULL) {
70 1.1 elric krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
71 1.1 elric return ENOMEM;
72 1.1 elric }
73 1.1 elric (*mkey)->keytab.vno = kvno;
74 1.1 elric ret = krb5_parse_name(context, "K/M", &(*mkey)->keytab.principal);
75 1.1 elric if(ret)
76 1.1 elric goto fail;
77 1.1 elric ret = krb5_copy_keyblock_contents(context, key, &(*mkey)->keytab.keyblock);
78 1.1 elric if(ret)
79 1.1 elric goto fail;
80 1.1 elric if(etype != 0)
81 1.1 elric (*mkey)->keytab.keyblock.keytype = etype;
82 1.1 elric (*mkey)->keytab.timestamp = time(NULL);
83 1.1 elric ret = krb5_crypto_init(context, key, etype, &(*mkey)->crypto);
84 1.1 elric if(ret)
85 1.1 elric goto fail;
86 1.1 elric return 0;
87 1.1 elric fail:
88 1.1 elric hdb_free_master_key(context, *mkey);
89 1.1 elric *mkey = NULL;
90 1.1 elric return ret;
91 1.1 elric }
92 1.1 elric
93 1.1 elric krb5_error_code
94 1.1 elric hdb_add_master_key(krb5_context context, krb5_keyblock *key,
95 1.1 elric hdb_master_key *inout)
96 1.1 elric {
97 1.1 elric int vno = 0;
98 1.1 elric hdb_master_key p;
99 1.1 elric krb5_error_code ret;
100 1.1 elric
101 1.1 elric for(p = *inout; p; p = p->next)
102 1.1 elric vno = max(vno, p->keytab.vno);
103 1.1 elric vno++;
104 1.1 elric ret = hdb_process_master_key(context, vno, key, 0, &p);
105 1.1 elric if(ret)
106 1.1 elric return ret;
107 1.1 elric p->next = *inout;
108 1.1 elric *inout = p;
109 1.1 elric return 0;
110 1.1 elric }
111 1.1 elric
112 1.1 elric static krb5_error_code
113 1.1 elric read_master_keytab(krb5_context context, const char *filename,
114 1.1 elric hdb_master_key *mkey)
115 1.1 elric {
116 1.1 elric krb5_error_code ret;
117 1.1 elric krb5_keytab id;
118 1.1 elric krb5_kt_cursor cursor;
119 1.1 elric krb5_keytab_entry entry;
120 1.1 elric hdb_master_key p;
121 1.1 elric
122 1.1 elric ret = krb5_kt_resolve(context, filename, &id);
123 1.1 elric if(ret)
124 1.1 elric return ret;
125 1.1 elric
126 1.1 elric ret = krb5_kt_start_seq_get(context, id, &cursor);
127 1.1 elric if(ret)
128 1.1 elric goto out;
129 1.1 elric *mkey = NULL;
130 1.1 elric while(krb5_kt_next_entry(context, id, &entry, &cursor) == 0) {
131 1.1 elric p = calloc(1, sizeof(*p));
132 1.1 elric if(p == NULL) {
133 1.1 elric krb5_kt_end_seq_get(context, id, &cursor);
134 1.1 elric ret = ENOMEM;
135 1.1 elric goto out;
136 1.1 elric }
137 1.1 elric p->keytab = entry;
138 1.1 elric ret = krb5_crypto_init(context, &p->keytab.keyblock, 0, &p->crypto);
139 1.1 elric p->next = *mkey;
140 1.1 elric *mkey = p;
141 1.1 elric }
142 1.1 elric krb5_kt_end_seq_get(context, id, &cursor);
143 1.1 elric out:
144 1.1 elric krb5_kt_close(context, id);
145 1.1 elric return ret;
146 1.1 elric }
147 1.1 elric
148 1.1 elric /* read a MIT master keyfile */
149 1.1 elric static krb5_error_code
150 1.1 elric read_master_mit(krb5_context context, const char *filename,
151 1.1 elric int byteorder, hdb_master_key *mkey)
152 1.1 elric {
153 1.1 elric int fd;
154 1.1 elric krb5_error_code ret;
155 1.1 elric krb5_storage *sp;
156 1.1 elric int16_t enctype;
157 1.1 elric krb5_keyblock key;
158 1.1 elric
159 1.1 elric fd = open(filename, O_RDONLY | O_BINARY);
160 1.1 elric if(fd < 0) {
161 1.1 elric int save_errno = errno;
162 1.1 elric krb5_set_error_message(context, save_errno, "failed to open %s: %s",
163 1.1 elric filename, strerror(save_errno));
164 1.1 elric return save_errno;
165 1.1 elric }
166 1.1 elric sp = krb5_storage_from_fd(fd);
167 1.1 elric if(sp == NULL) {
168 1.1 elric close(fd);
169 1.1 elric return errno;
170 1.1 elric }
171 1.1 elric krb5_storage_set_flags(sp, byteorder);
172 1.1 elric /* could possibly use ret_keyblock here, but do it with more
173 1.1 elric checks for now */
174 1.1 elric {
175 1.1 elric ret = krb5_ret_int16(sp, &enctype);
176 1.1 elric if (ret)
177 1.1 elric goto out;
178 1.1 elric ret = krb5_enctype_valid(context, enctype);
179 1.1 elric if (ret)
180 1.1 elric goto out;
181 1.1 elric key.keytype = enctype;
182 1.1 elric ret = krb5_ret_data(sp, &key.keyvalue);
183 1.1 elric if(ret)
184 1.1 elric goto out;
185 1.1 elric }
186 1.1 elric ret = hdb_process_master_key(context, 1, &key, 0, mkey);
187 1.1 elric krb5_free_keyblock_contents(context, &key);
188 1.1 elric out:
189 1.1 elric krb5_storage_free(sp);
190 1.1 elric close(fd);
191 1.1 elric return ret;
192 1.1 elric }
193 1.1 elric
194 1.1 elric /* read an old master key file */
195 1.1 elric static krb5_error_code
196 1.1 elric read_master_encryptionkey(krb5_context context, const char *filename,
197 1.1 elric hdb_master_key *mkey)
198 1.1 elric {
199 1.1 elric int fd;
200 1.1 elric krb5_keyblock key;
201 1.1 elric krb5_error_code ret;
202 1.1 elric unsigned char buf[256];
203 1.1 elric ssize_t len;
204 1.1 elric size_t ret_len;
205 1.1 elric
206 1.1 elric fd = open(filename, O_RDONLY | O_BINARY);
207 1.1 elric if(fd < 0) {
208 1.1 elric int save_errno = errno;
209 1.1 elric krb5_set_error_message(context, save_errno, "failed to open %s: %s",
210 1.1 elric filename, strerror(save_errno));
211 1.1 elric return save_errno;
212 1.1 elric }
213 1.1 elric
214 1.1 elric len = read(fd, buf, sizeof(buf));
215 1.1 elric close(fd);
216 1.1 elric if(len < 0) {
217 1.1 elric int save_errno = errno;
218 1.1 elric krb5_set_error_message(context, save_errno, "error reading %s: %s",
219 1.1 elric filename, strerror(save_errno));
220 1.1 elric return save_errno;
221 1.1 elric }
222 1.1 elric
223 1.1 elric ret = decode_EncryptionKey(buf, len, &key, &ret_len);
224 1.1 elric memset(buf, 0, sizeof(buf));
225 1.1 elric if(ret)
226 1.1 elric return ret;
227 1.1 elric
228 1.1 elric /* Originally, the keytype was just that, and later it got changed
229 1.1 elric to des-cbc-md5, but we always used des in cfb64 mode. This
230 1.1 elric should cover all cases, but will break if someone has hacked
231 1.1 elric this code to really use des-cbc-md5 -- but then that's not my
232 1.1 elric problem. */
233 1.1 elric if(key.keytype == KEYTYPE_DES || key.keytype == ETYPE_DES_CBC_MD5)
234 1.1 elric key.keytype = ETYPE_DES_CFB64_NONE;
235 1.1 elric
236 1.1 elric ret = hdb_process_master_key(context, 0, &key, 0, mkey);
237 1.1 elric krb5_free_keyblock_contents(context, &key);
238 1.1 elric return ret;
239 1.1 elric }
240 1.1 elric
241 1.1 elric /* read a krb4 /.k style file */
242 1.1 elric static krb5_error_code
243 1.1 elric read_master_krb4(krb5_context context, const char *filename,
244 1.1 elric hdb_master_key *mkey)
245 1.1 elric {
246 1.1 elric int fd;
247 1.1 elric krb5_keyblock key;
248 1.1 elric krb5_error_code ret;
249 1.1 elric unsigned char buf[256];
250 1.1 elric ssize_t len;
251 1.1 elric
252 1.1 elric fd = open(filename, O_RDONLY | O_BINARY);
253 1.1 elric if(fd < 0) {
254 1.1 elric int save_errno = errno;
255 1.1 elric krb5_set_error_message(context, save_errno, "failed to open %s: %s",
256 1.1 elric filename, strerror(save_errno));
257 1.1 elric return save_errno;
258 1.1 elric }
259 1.1 elric
260 1.1 elric len = read(fd, buf, sizeof(buf));
261 1.1 elric close(fd);
262 1.1 elric if(len < 0) {
263 1.1 elric int save_errno = errno;
264 1.1 elric krb5_set_error_message(context, save_errno, "error reading %s: %s",
265 1.1 elric filename, strerror(save_errno));
266 1.1 elric return save_errno;
267 1.1 elric }
268 1.1 elric if(len != 8) {
269 1.1 elric krb5_set_error_message(context, HEIM_ERR_EOF,
270 1.1 elric "bad contents of %s", filename);
271 1.1 elric return HEIM_ERR_EOF; /* XXX file might be too large */
272 1.1 elric }
273 1.1 elric
274 1.1 elric memset(&key, 0, sizeof(key));
275 1.1 elric key.keytype = ETYPE_DES_PCBC_NONE;
276 1.1 elric ret = krb5_data_copy(&key.keyvalue, buf, len);
277 1.1 elric memset(buf, 0, sizeof(buf));
278 1.1 elric if(ret)
279 1.1 elric return ret;
280 1.1 elric
281 1.1 elric ret = hdb_process_master_key(context, 0, &key, 0, mkey);
282 1.1 elric krb5_free_keyblock_contents(context, &key);
283 1.1 elric return ret;
284 1.1 elric }
285 1.1 elric
286 1.1 elric krb5_error_code
287 1.1 elric hdb_read_master_key(krb5_context context, const char *filename,
288 1.1 elric hdb_master_key *mkey)
289 1.1 elric {
290 1.1 elric FILE *f;
291 1.1 elric unsigned char buf[16];
292 1.1 elric krb5_error_code ret;
293 1.1 elric
294 1.1 elric off_t len;
295 1.1 elric
296 1.1 elric *mkey = NULL;
297 1.1 elric
298 1.1 elric if(filename == NULL)
299 1.1 elric filename = HDB_DB_DIR "/m-key";
300 1.1 elric
301 1.1 elric f = fopen(filename, "r");
302 1.1 elric if(f == NULL) {
303 1.1 elric int save_errno = errno;
304 1.1 elric krb5_set_error_message(context, save_errno, "failed to open %s: %s",
305 1.1 elric filename, strerror(save_errno));
306 1.1 elric return save_errno;
307 1.1 elric }
308 1.1 elric
309 1.1 elric if(fread(buf, 1, 2, f) != 2) {
310 1.1 elric fclose(f);
311 1.1 elric krb5_set_error_message(context, HEIM_ERR_EOF, "end of file reading %s", filename);
312 1.1 elric return HEIM_ERR_EOF;
313 1.1 elric }
314 1.1 elric
315 1.1 elric fseek(f, 0, SEEK_END);
316 1.1 elric len = ftell(f);
317 1.1 elric
318 1.1 elric if(fclose(f) != 0)
319 1.1 elric return errno;
320 1.1 elric
321 1.1 elric if(len < 0)
322 1.1 elric return errno;
323 1.1 elric
324 1.1 elric if(len == 8) {
325 1.1 elric ret = read_master_krb4(context, filename, mkey);
326 1.1 elric } else if(buf[0] == 0x30 && len <= 127 && buf[1] == len - 2) {
327 1.1 elric ret = read_master_encryptionkey(context, filename, mkey);
328 1.1 elric } else if(buf[0] == 5 && buf[1] >= 1 && buf[1] <= 2) {
329 1.1 elric ret = read_master_keytab(context, filename, mkey);
330 1.1 elric } else {
331 1.1 elric /*
332 1.1 elric * Check both LittleEndian and BigEndian since they key file
333 1.1 elric * might be moved from a machine with diffrent byte order, or
334 1.1 elric * its running on MacOS X that always uses BE master keys.
335 1.1 elric */
336 1.1 elric ret = read_master_mit(context, filename, KRB5_STORAGE_BYTEORDER_LE, mkey);
337 1.1 elric if (ret)
338 1.1 elric ret = read_master_mit(context, filename, KRB5_STORAGE_BYTEORDER_BE, mkey);
339 1.1 elric }
340 1.1 elric return ret;
341 1.1 elric }
342 1.1 elric
343 1.1 elric krb5_error_code
344 1.1 elric hdb_write_master_key(krb5_context context, const char *filename,
345 1.1 elric hdb_master_key mkey)
346 1.1 elric {
347 1.1 elric krb5_error_code ret;
348 1.1 elric hdb_master_key p;
349 1.1 elric krb5_keytab kt;
350 1.1 elric
351 1.1 elric if(filename == NULL)
352 1.1 elric filename = HDB_DB_DIR "/m-key";
353 1.1 elric
354 1.1 elric ret = krb5_kt_resolve(context, filename, &kt);
355 1.1 elric if(ret)
356 1.1 elric return ret;
357 1.1 elric
358 1.1 elric for(p = mkey; p; p = p->next) {
359 1.1 elric ret = krb5_kt_add_entry(context, kt, &p->keytab);
360 1.1 elric }
361 1.1 elric
362 1.1 elric krb5_kt_close(context, kt);
363 1.1 elric
364 1.1 elric return ret;
365 1.1 elric }
366 1.1 elric
367 1.1 elric hdb_master_key
368 1.1 elric _hdb_find_master_key(uint32_t *mkvno, hdb_master_key mkey)
369 1.1 elric {
370 1.1 elric hdb_master_key ret = NULL;
371 1.1 elric while(mkey) {
372 1.1 elric if(ret == NULL && mkey->keytab.vno == 0)
373 1.1 elric ret = mkey;
374 1.1 elric if(mkvno == NULL) {
375 1.1 elric if(ret == NULL || mkey->keytab.vno > ret->keytab.vno)
376 1.1 elric ret = mkey;
377 1.1 elric } else if(mkey->keytab.vno == *mkvno)
378 1.1 elric return mkey;
379 1.1 elric mkey = mkey->next;
380 1.1 elric }
381 1.1 elric return ret;
382 1.1 elric }
383 1.1 elric
384 1.1 elric int
385 1.1 elric _hdb_mkey_version(hdb_master_key mkey)
386 1.1 elric {
387 1.1 elric return mkey->keytab.vno;
388 1.1 elric }
389 1.1 elric
390 1.1 elric int
391 1.1 elric _hdb_mkey_decrypt(krb5_context context, hdb_master_key key,
392 1.1 elric krb5_key_usage usage,
393 1.1 elric void *ptr, size_t size, krb5_data *res)
394 1.1 elric {
395 1.1 elric return krb5_decrypt(context, key->crypto, usage,
396 1.1 elric ptr, size, res);
397 1.1 elric }
398 1.1 elric
399 1.1 elric int
400 1.1 elric _hdb_mkey_encrypt(krb5_context context, hdb_master_key key,
401 1.1 elric krb5_key_usage usage,
402 1.1 elric const void *ptr, size_t size, krb5_data *res)
403 1.1 elric {
404 1.1 elric return krb5_encrypt(context, key->crypto, usage,
405 1.1 elric ptr, size, res);
406 1.1 elric }
407 1.1 elric
408 1.1 elric krb5_error_code
409 1.1 elric hdb_unseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
410 1.1 elric {
411 1.1 elric
412 1.1 elric krb5_error_code ret;
413 1.1 elric krb5_data res;
414 1.1 elric size_t keysize;
415 1.1 elric
416 1.1 elric hdb_master_key key;
417 1.1 elric
418 1.1 elric if(k->mkvno == NULL)
419 1.1 elric return 0;
420 1.1 elric
421 1.1 elric key = _hdb_find_master_key(k->mkvno, mkey);
422 1.1 elric
423 1.1 elric if (key == NULL)
424 1.1 elric return HDB_ERR_NO_MKEY;
425 1.1 elric
426 1.1 elric ret = _hdb_mkey_decrypt(context, key, HDB_KU_MKEY,
427 1.1 elric k->key.keyvalue.data,
428 1.1 elric k->key.keyvalue.length,
429 1.1 elric &res);
430 1.1 elric if(ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
431 1.1 elric /* try to decrypt with MIT key usage */
432 1.1 elric ret = _hdb_mkey_decrypt(context, key, 0,
433 1.1 elric k->key.keyvalue.data,
434 1.1 elric k->key.keyvalue.length,
435 1.1 elric &res);
436 1.1 elric }
437 1.1 elric if (ret)
438 1.1 elric return ret;
439 1.1 elric
440 1.1 elric /* fixup keylength if the key got padded when encrypting it */
441 1.1 elric ret = krb5_enctype_keysize(context, k->key.keytype, &keysize);
442 1.1 elric if (ret) {
443 1.1 elric krb5_data_free(&res);
444 1.1 elric return ret;
445 1.1 elric }
446 1.1 elric if (keysize > res.length) {
447 1.1 elric krb5_data_free(&res);
448 1.1 elric return KRB5_BAD_KEYSIZE;
449 1.1 elric }
450 1.1 elric
451 1.1 elric memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);
452 1.1 elric free(k->key.keyvalue.data);
453 1.1 elric k->key.keyvalue = res;
454 1.1 elric k->key.keyvalue.length = keysize;
455 1.1 elric free(k->mkvno);
456 1.1 elric k->mkvno = NULL;
457 1.1 elric
458 1.1 elric return 0;
459 1.1 elric }
460 1.1 elric
461 1.1 elric krb5_error_code
462 1.1 elric hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
463 1.1 elric {
464 1.1 elric int i;
465 1.1 elric
466 1.1 elric for(i = 0; i < ent->keys.len; i++){
467 1.1 elric krb5_error_code ret;
468 1.1 elric
469 1.1 elric ret = hdb_unseal_key_mkey(context, &ent->keys.val[i], mkey);
470 1.1 elric if (ret)
471 1.1 elric return ret;
472 1.1 elric }
473 1.1 elric return 0;
474 1.1 elric }
475 1.1 elric
476 1.1 elric krb5_error_code
477 1.1 elric hdb_unseal_keys(krb5_context context, HDB *db, hdb_entry *ent)
478 1.1 elric {
479 1.1 elric if (db->hdb_master_key_set == 0)
480 1.1 elric return 0;
481 1.1 elric return hdb_unseal_keys_mkey(context, ent, db->hdb_master_key);
482 1.1 elric }
483 1.1 elric
484 1.1 elric krb5_error_code
485 1.1 elric hdb_unseal_key(krb5_context context, HDB *db, Key *k)
486 1.1 elric {
487 1.1 elric if (db->hdb_master_key_set == 0)
488 1.1 elric return 0;
489 1.1 elric return hdb_unseal_key_mkey(context, k, db->hdb_master_key);
490 1.1 elric }
491 1.1 elric
492 1.1 elric krb5_error_code
493 1.1 elric hdb_seal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
494 1.1 elric {
495 1.1 elric krb5_error_code ret;
496 1.1 elric krb5_data res;
497 1.1 elric hdb_master_key key;
498 1.1 elric
499 1.1 elric if(k->mkvno != NULL)
500 1.1 elric return 0;
501 1.1 elric
502 1.1 elric key = _hdb_find_master_key(k->mkvno, mkey);
503 1.1 elric
504 1.1 elric if (key == NULL)
505 1.1 elric return HDB_ERR_NO_MKEY;
506 1.1 elric
507 1.1 elric ret = _hdb_mkey_encrypt(context, key, HDB_KU_MKEY,
508 1.1 elric k->key.keyvalue.data,
509 1.1 elric k->key.keyvalue.length,
510 1.1 elric &res);
511 1.1 elric if (ret)
512 1.1 elric return ret;
513 1.1 elric
514 1.1 elric memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);
515 1.1 elric free(k->key.keyvalue.data);
516 1.1 elric k->key.keyvalue = res;
517 1.1 elric
518 1.1 elric if (k->mkvno == NULL) {
519 1.1 elric k->mkvno = malloc(sizeof(*k->mkvno));
520 1.1 elric if (k->mkvno == NULL)
521 1.1 elric return ENOMEM;
522 1.1 elric }
523 1.1 elric *k->mkvno = key->keytab.vno;
524 1.1 elric
525 1.1 elric return 0;
526 1.1 elric }
527 1.1 elric
528 1.1 elric krb5_error_code
529 1.1 elric hdb_seal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
530 1.1 elric {
531 1.1 elric int i;
532 1.1 elric for(i = 0; i < ent->keys.len; i++){
533 1.1 elric krb5_error_code ret;
534 1.1 elric
535 1.1 elric ret = hdb_seal_key_mkey(context, &ent->keys.val[i], mkey);
536 1.1 elric if (ret)
537 1.1 elric return ret;
538 1.1 elric }
539 1.1 elric return 0;
540 1.1 elric }
541 1.1 elric
542 1.1 elric krb5_error_code
543 1.1 elric hdb_seal_keys(krb5_context context, HDB *db, hdb_entry *ent)
544 1.1 elric {
545 1.1 elric if (db->hdb_master_key_set == 0)
546 1.1 elric return 0;
547 1.1 elric
548 1.1 elric return hdb_seal_keys_mkey(context, ent, db->hdb_master_key);
549 1.1 elric }
550 1.1 elric
551 1.1 elric krb5_error_code
552 1.1 elric hdb_seal_key(krb5_context context, HDB *db, Key *k)
553 1.1 elric {
554 1.1 elric if (db->hdb_master_key_set == 0)
555 1.1 elric return 0;
556 1.1 elric
557 1.1 elric return hdb_seal_key_mkey(context, k, db->hdb_master_key);
558 1.1 elric }
559 1.1 elric
560 1.1 elric krb5_error_code
561 1.1 elric hdb_set_master_key (krb5_context context,
562 1.1 elric HDB *db,
563 1.1 elric krb5_keyblock *key)
564 1.1 elric {
565 1.1 elric krb5_error_code ret;
566 1.1 elric hdb_master_key mkey;
567 1.1 elric
568 1.1 elric ret = hdb_process_master_key(context, 0, key, 0, &mkey);
569 1.1 elric if (ret)
570 1.1 elric return ret;
571 1.1 elric db->hdb_master_key = mkey;
572 1.1 elric #if 0 /* XXX - why? */
573 1.1 elric des_set_random_generator_seed(key.keyvalue.data);
574 1.1 elric #endif
575 1.1 elric db->hdb_master_key_set = 1;
576 1.1 elric return 0;
577 1.1 elric }
578 1.1 elric
579 1.1 elric krb5_error_code
580 1.1 elric hdb_set_master_keyfile (krb5_context context,
581 1.1 elric HDB *db,
582 1.1 elric const char *keyfile)
583 1.1 elric {
584 1.1 elric hdb_master_key key;
585 1.1 elric krb5_error_code ret;
586 1.1 elric
587 1.1 elric ret = hdb_read_master_key(context, keyfile, &key);
588 1.1 elric if (ret) {
589 1.1 elric if (ret != ENOENT)
590 1.1 elric return ret;
591 1.1 elric krb5_clear_error_message(context);
592 1.1 elric return 0;
593 1.1 elric }
594 1.1 elric db->hdb_master_key = key;
595 1.1 elric db->hdb_master_key_set = 1;
596 1.1 elric return ret;
597 1.1 elric }
598 1.1 elric
599 1.1 elric krb5_error_code
600 1.1 elric hdb_clear_master_key (krb5_context context,
601 1.1 elric HDB *db)
602 1.1 elric {
603 1.1 elric if (db->hdb_master_key_set) {
604 1.1 elric hdb_free_master_key(context, db->hdb_master_key);
605 1.1 elric db->hdb_master_key_set = 0;
606 1.1 elric }
607 1.1 elric return 0;
608 1.1 elric }
609