Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/hdb/mkey.c
105320 views
1
/*
2
* Copyright (c) 2000 - 2004 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
*
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
*
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.
16
*
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.
20
*
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.
32
*/
33
34
#include "hdb_locl.h"
35
#include <assert.h>
36
#ifndef O_BINARY
37
#define O_BINARY 0
38
#endif
39
40
struct hdb_master_key_data {
41
krb5_keytab_entry keytab;
42
krb5_crypto crypto;
43
struct hdb_master_key_data *next;
44
unsigned int key_usage;
45
};
46
47
void
48
hdb_free_master_key(krb5_context context, hdb_master_key mkey)
49
{
50
struct hdb_master_key_data *ptr;
51
while(mkey) {
52
krb5_kt_free_entry(context, &mkey->keytab);
53
if (mkey->crypto)
54
krb5_crypto_destroy(context, mkey->crypto);
55
ptr = mkey;
56
mkey = mkey->next;
57
free(ptr);
58
}
59
}
60
61
krb5_error_code
62
hdb_process_master_key(krb5_context context,
63
int kvno, krb5_keyblock *key, krb5_enctype etype,
64
hdb_master_key *mkey)
65
{
66
krb5_error_code ret;
67
68
*mkey = calloc(1, sizeof(**mkey));
69
if(*mkey == NULL) {
70
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
71
return ENOMEM;
72
}
73
(*mkey)->key_usage = HDB_KU_MKEY;
74
(*mkey)->keytab.vno = kvno;
75
ret = krb5_parse_name(context, "K/M", &(*mkey)->keytab.principal);
76
if(ret)
77
goto fail;
78
ret = krb5_copy_keyblock_contents(context, key, &(*mkey)->keytab.keyblock);
79
if(ret)
80
goto fail;
81
if(etype != 0)
82
(*mkey)->keytab.keyblock.keytype = etype;
83
(*mkey)->keytab.timestamp = time(NULL);
84
ret = krb5_crypto_init(context, key, etype, &(*mkey)->crypto);
85
if(ret)
86
goto fail;
87
return 0;
88
fail:
89
hdb_free_master_key(context, *mkey);
90
*mkey = NULL;
91
return ret;
92
}
93
94
krb5_error_code
95
hdb_add_master_key(krb5_context context, krb5_keyblock *key,
96
hdb_master_key *inout)
97
{
98
int vno = 0;
99
hdb_master_key p;
100
krb5_error_code ret;
101
102
for(p = *inout; p; p = p->next)
103
vno = max(vno, p->keytab.vno);
104
vno++;
105
ret = hdb_process_master_key(context, vno, key, 0, &p);
106
if(ret)
107
return ret;
108
p->next = *inout;
109
*inout = p;
110
return 0;
111
}
112
113
static krb5_error_code
114
read_master_keytab(krb5_context context, const char *filename,
115
hdb_master_key *mkey)
116
{
117
krb5_error_code ret;
118
krb5_keytab id;
119
krb5_kt_cursor cursor;
120
krb5_keytab_entry entry;
121
hdb_master_key p;
122
123
ret = krb5_kt_resolve(context, filename, &id);
124
if(ret)
125
return ret;
126
127
ret = krb5_kt_start_seq_get(context, id, &cursor);
128
if(ret)
129
goto out;
130
*mkey = NULL;
131
while(krb5_kt_next_entry(context, id, &entry, &cursor) == 0) {
132
p = calloc(1, sizeof(*p));
133
if(p == NULL) {
134
krb5_kt_end_seq_get(context, id, &cursor);
135
ret = ENOMEM;
136
goto out;
137
}
138
p->keytab = entry;
139
ret = krb5_crypto_init(context, &p->keytab.keyblock, 0, &p->crypto);
140
p->next = *mkey;
141
*mkey = p;
142
}
143
krb5_kt_end_seq_get(context, id, &cursor);
144
out:
145
krb5_kt_close(context, id);
146
return ret;
147
}
148
149
/* read a MIT master keyfile */
150
static krb5_error_code
151
read_master_mit(krb5_context context, const char *filename,
152
int byteorder, hdb_master_key *mkey)
153
{
154
int fd;
155
krb5_error_code ret;
156
krb5_storage *sp;
157
int16_t enctype;
158
krb5_keyblock key;
159
160
fd = open(filename, O_RDONLY | O_BINARY);
161
if(fd < 0) {
162
int save_errno = errno;
163
krb5_set_error_message(context, save_errno, "failed to open %s: %s",
164
filename, strerror(save_errno));
165
return save_errno;
166
}
167
sp = krb5_storage_from_fd(fd);
168
if(sp == NULL) {
169
close(fd);
170
return errno;
171
}
172
krb5_storage_set_flags(sp, byteorder);
173
/* could possibly use ret_keyblock here, but do it with more
174
checks for now */
175
{
176
ret = krb5_ret_int16(sp, &enctype);
177
if (ret)
178
goto out;
179
ret = krb5_enctype_valid(context, enctype);
180
if (ret)
181
goto out;
182
key.keytype = enctype;
183
ret = krb5_ret_data(sp, &key.keyvalue);
184
if(ret)
185
goto out;
186
}
187
ret = hdb_process_master_key(context, 1, &key, 0, mkey);
188
krb5_free_keyblock_contents(context, &key);
189
out:
190
krb5_storage_free(sp);
191
close(fd);
192
return ret;
193
}
194
195
/* read an old master key file */
196
static krb5_error_code
197
read_master_encryptionkey(krb5_context context, const char *filename,
198
hdb_master_key *mkey)
199
{
200
int fd;
201
krb5_keyblock key;
202
krb5_error_code ret;
203
unsigned char buf[256];
204
ssize_t len;
205
size_t ret_len;
206
207
fd = open(filename, O_RDONLY | O_BINARY);
208
if(fd < 0) {
209
int save_errno = errno;
210
krb5_set_error_message(context, save_errno, "failed to open %s: %s",
211
filename, strerror(save_errno));
212
return save_errno;
213
}
214
215
len = read(fd, buf, sizeof(buf));
216
close(fd);
217
if(len < 0) {
218
int save_errno = errno;
219
krb5_set_error_message(context, save_errno, "error reading %s: %s",
220
filename, strerror(save_errno));
221
return save_errno;
222
}
223
224
ret = decode_EncryptionKey(buf, len, &key, &ret_len);
225
memset(buf, 0, sizeof(buf));
226
if(ret)
227
return ret;
228
229
/* Originally, the keytype was just that, and later it got changed
230
to des-cbc-md5, but we always used des in cfb64 mode. This
231
should cover all cases, but will break if someone has hacked
232
this code to really use des-cbc-md5 -- but then that's not my
233
problem. */
234
if(key.keytype == ETYPE_DES_CBC_CRC || key.keytype == ETYPE_DES_CBC_MD5)
235
key.keytype = ETYPE_DES_CFB64_NONE;
236
237
ret = hdb_process_master_key(context, 0, &key, 0, mkey);
238
krb5_free_keyblock_contents(context, &key);
239
return ret;
240
}
241
242
/* read a krb4 /.k style file */
243
static krb5_error_code
244
read_master_krb4(krb5_context context, const char *filename,
245
hdb_master_key *mkey)
246
{
247
int fd;
248
krb5_keyblock key;
249
krb5_error_code ret;
250
unsigned char buf[256];
251
ssize_t len;
252
253
fd = open(filename, O_RDONLY | O_BINARY);
254
if(fd < 0) {
255
int save_errno = errno;
256
krb5_set_error_message(context, save_errno, "failed to open %s: %s",
257
filename, strerror(save_errno));
258
return save_errno;
259
}
260
261
len = read(fd, buf, sizeof(buf));
262
close(fd);
263
if(len < 0) {
264
int save_errno = errno;
265
krb5_set_error_message(context, save_errno, "error reading %s: %s",
266
filename, strerror(save_errno));
267
return save_errno;
268
}
269
if(len != 8) {
270
krb5_set_error_message(context, HEIM_ERR_EOF,
271
"bad contents of %s", filename);
272
return HEIM_ERR_EOF; /* XXX file might be too large */
273
}
274
275
memset(&key, 0, sizeof(key));
276
key.keytype = ETYPE_DES_PCBC_NONE;
277
ret = krb5_data_copy(&key.keyvalue, buf, len);
278
memset(buf, 0, sizeof(buf));
279
if(ret)
280
return ret;
281
282
ret = hdb_process_master_key(context, 0, &key, 0, mkey);
283
krb5_free_keyblock_contents(context, &key);
284
return ret;
285
}
286
287
krb5_error_code
288
hdb_read_master_key(krb5_context context, const char *filename,
289
hdb_master_key *mkey)
290
{
291
FILE *f;
292
unsigned char buf[16];
293
krb5_error_code ret;
294
295
off_t len;
296
297
*mkey = NULL;
298
299
if(filename == NULL)
300
filename = HDB_DB_DIR "/m-key";
301
302
f = fopen(filename, "r");
303
if(f == NULL) {
304
int save_errno = errno;
305
krb5_set_error_message(context, save_errno, "failed to open %s: %s",
306
filename, strerror(save_errno));
307
return save_errno;
308
}
309
310
if(fread(buf, 1, 2, f) != 2) {
311
fclose(f);
312
krb5_set_error_message(context, HEIM_ERR_EOF, "end of file reading %s", filename);
313
return HEIM_ERR_EOF;
314
}
315
316
fseek(f, 0, SEEK_END);
317
len = ftell(f);
318
319
if(fclose(f) != 0)
320
return errno;
321
322
if(len < 0)
323
return errno;
324
325
if(len == 8) {
326
ret = read_master_krb4(context, filename, mkey);
327
} else if(buf[0] == 0x30 && len <= 127 && buf[1] == len - 2) {
328
ret = read_master_encryptionkey(context, filename, mkey);
329
} else if(buf[0] == 5 && buf[1] >= 1 && buf[1] <= 2) {
330
ret = read_master_keytab(context, filename, mkey);
331
} else {
332
/*
333
* Check both LittleEndian and BigEndian since they key file
334
* might be moved from a machine with diffrent byte order, or
335
* its running on MacOS X that always uses BE master keys.
336
*/
337
ret = read_master_mit(context, filename, KRB5_STORAGE_BYTEORDER_LE, mkey);
338
if (ret)
339
ret = read_master_mit(context, filename, KRB5_STORAGE_BYTEORDER_BE, mkey);
340
}
341
return ret;
342
}
343
344
krb5_error_code
345
hdb_write_master_key(krb5_context context, const char *filename,
346
hdb_master_key mkey)
347
{
348
krb5_error_code ret;
349
hdb_master_key p;
350
krb5_keytab kt;
351
352
if(filename == NULL)
353
filename = HDB_DB_DIR "/m-key";
354
355
ret = krb5_kt_resolve(context, filename, &kt);
356
if(ret)
357
return ret;
358
359
for(p = mkey; p; p = p->next) {
360
ret = krb5_kt_add_entry(context, kt, &p->keytab);
361
}
362
363
krb5_kt_close(context, kt);
364
365
return ret;
366
}
367
368
krb5_error_code
369
_hdb_set_master_key_usage(krb5_context context, HDB *db, unsigned int key_usage)
370
{
371
if (db->hdb_master_key_set == 0)
372
return HDB_ERR_NO_MKEY;
373
db->hdb_master_key->key_usage = key_usage;
374
return 0;
375
}
376
377
hdb_master_key
378
_hdb_find_master_key(uint32_t *mkvno, hdb_master_key mkey)
379
{
380
hdb_master_key ret = NULL;
381
while(mkey) {
382
if(ret == NULL && mkey->keytab.vno == 0)
383
ret = mkey;
384
if(mkvno == NULL) {
385
if(ret == NULL || mkey->keytab.vno > ret->keytab.vno)
386
ret = mkey;
387
} else if((uint32_t)mkey->keytab.vno == *mkvno)
388
return mkey;
389
mkey = mkey->next;
390
}
391
return ret;
392
}
393
394
int
395
_hdb_mkey_version(hdb_master_key mkey)
396
{
397
return mkey->keytab.vno;
398
}
399
400
int
401
_hdb_mkey_decrypt(krb5_context context, hdb_master_key key,
402
krb5_key_usage usage,
403
void *ptr, size_t size, krb5_data *res)
404
{
405
return krb5_decrypt(context, key->crypto, usage,
406
ptr, size, res);
407
}
408
409
int
410
_hdb_mkey_encrypt(krb5_context context, hdb_master_key key,
411
krb5_key_usage usage,
412
const void *ptr, size_t size, krb5_data *res)
413
{
414
return krb5_encrypt(context, key->crypto, usage,
415
ptr, size, res);
416
}
417
418
/*
419
* Unseal and optionally reseal the key in the MIT KDC master key.
420
* If mit_key != NULL, the key is sealed using this key.
421
*/
422
static krb5_error_code
423
_hdb_reseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey,
424
hdb_master_key mit_key)
425
{
426
427
krb5_error_code ret;
428
krb5_data mitres, res;
429
size_t keysize;
430
431
hdb_master_key key, mitkey;
432
433
if(k->mkvno == NULL)
434
return 0;
435
436
key = _hdb_find_master_key(k->mkvno, mkey);
437
438
if (key == NULL)
439
return HDB_ERR_NO_MKEY;
440
441
ret = _hdb_mkey_decrypt(context, key, HDB_KU_MKEY,
442
k->key.keyvalue.data,
443
k->key.keyvalue.length,
444
&res);
445
if(ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
446
/* try to decrypt with MIT key usage */
447
ret = _hdb_mkey_decrypt(context, key, 0,
448
k->key.keyvalue.data,
449
k->key.keyvalue.length,
450
&res);
451
}
452
if (ret)
453
return ret;
454
455
/* fixup keylength if the key got padded when encrypting it */
456
ret = krb5_enctype_keysize(context, k->key.keytype, &keysize);
457
if (ret) {
458
krb5_data_free(&res);
459
return ret;
460
}
461
if (keysize > res.length) {
462
krb5_data_free(&res);
463
return KRB5_BAD_KEYSIZE;
464
}
465
466
/* For mit_key != NULL, re-encrypt the key using the mitkey. */
467
if (mit_key != NULL) {
468
mitkey = _hdb_find_master_key(NULL, mit_key);
469
if (mitkey == NULL) {
470
krb5_data_free(&res);
471
return HDB_ERR_NO_MKEY;
472
}
473
474
ret = _hdb_mkey_encrypt(context, mitkey, 0,
475
res.data,
476
keysize,
477
&mitres);
478
krb5_data_free(&res);
479
if (ret)
480
return ret;
481
}
482
483
krb5_data_free(&k->key.keyvalue);
484
if (mit_key == NULL) {
485
k->key.keyvalue = res;
486
k->key.keyvalue.length = keysize;
487
free(k->mkvno);
488
k->mkvno = NULL;
489
} else {
490
k->key.keyvalue = mitres;
491
*k->mkvno = mitkey->keytab.vno;
492
}
493
494
return 0;
495
}
496
497
krb5_error_code
498
hdb_unseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
499
{
500
501
krb5_error_code ret;
502
503
ret = _hdb_reseal_key_mkey(context, k, mkey, NULL);
504
return ret;
505
}
506
507
static krb5_error_code
508
_hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey,
509
hdb_master_key mitkey)
510
{
511
krb5_error_code ret;
512
size_t i;
513
int got_one = 0;
514
515
for(i = 0; i < ent->keys.len; i++){
516
if (mitkey == NULL || mit_strong_etype(ent->keys.val[i].key.keytype)) {
517
ret = _hdb_reseal_key_mkey(context, &ent->keys.val[i], mkey,
518
mitkey);
519
if (ret)
520
return ret;
521
got_one = 1;
522
}
523
}
524
525
/*
526
* If none of the keys were string enough, create a strong key,
527
* but one that is not encrypted in the MIT master key. As such,
528
* it will require a "change_password" once in the MIT KDC to
529
* make it work.
530
*/
531
if (got_one == 0 && mitkey != NULL && ent->keys.len > 0) {
532
krb5_keyblock key;
533
krb5_salt salt;
534
535
krb5_free_keyblock_contents(context, &ent->keys.val[0].key);
536
salt.salttype = KRB5_PW_SALT;
537
salt.saltvalue.data = NULL;
538
salt.saltvalue.length = 0;
539
ret = krb5_string_to_key_salt(context, ETYPE_AES256_CTS_HMAC_SHA1_96,
540
"XXXX", salt, &ent->keys.val[0].key);
541
if (ret)
542
return ret;
543
}
544
return 0;
545
}
546
547
krb5_error_code
548
hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
549
{
550
krb5_error_code ret;
551
552
ret = _hdb_unseal_keys_mkey(context, ent, mkey, NULL);
553
return ret;
554
}
555
556
krb5_error_code
557
hdb_unseal_keys(krb5_context context, HDB *db, hdb_entry *ent)
558
{
559
if (db->hdb_master_key_set == 0)
560
return 0;
561
if (db->hdb_mit_key_set != 0)
562
return _hdb_unseal_keys_mkey(context, ent, db->hdb_master_key,
563
db->hdb_mit_key);
564
else
565
return _hdb_unseal_keys_mkey(context, ent, db->hdb_master_key,
566
NULL);
567
}
568
569
#ifdef notnow
570
krb5_error_code
571
hdb_unseal_keys_kvno(krb5_context context, HDB *db, krb5_kvno kvno,
572
hdb_entry *ent)
573
{
574
krb5_error_code ret = KRB5KRB_AP_ERR_NOKEY; /* XXX need a better code? */
575
HDB_extension *tmp;
576
HDB_Ext_KeySet *hist_keys;
577
hdb_keyset *tmp_keys;
578
Key *tmp_val;
579
unsigned int tmp_len;
580
krb5_kvno tmp_kvno;
581
int i, k;
582
583
assert(kvno == 0 || kvno < ent->kvno);
584
585
tmp = hdb_find_extension(ent, choice_HDB_extension_data_hist_keys);
586
if (tmp == NULL)
587
return ret;
588
589
tmp_len = ent->keys.len;
590
tmp_val = ent->keys.val;
591
tmp_kvno = ent->kvno;
592
593
hist_keys = &tmp->data.u.hist_keys;
594
595
for (i = hist_keys->len - 1; i >= 0; i++) {
596
if (kvno != 0 && hist_keys->val[i].kvno != kvno)
597
continue;
598
for (k = 0; k < hist_keys->val[i].keys.len; k++) {
599
ret = _hdb_reseal_key_mkey(context,
600
&hist_keys->val[i].keys.val[k],
601
db->hdb_master_key, NULL);
602
if (ret)
603
return (ret);
604
}
605
606
if (kvno == 0)
607
continue;
608
609
/*
610
* NOTE: What follows is a bit of an ugly hack.
611
*
612
* This is the keyset we're being asked for, so we add the
613
* current keyset to the history, leave the one we were asked
614
* for in the history, and pretend the one we were asked for is
615
* also the current keyset.
616
*
617
* This is a bit of a defensive hack in case an entry fetched
618
* this way ever gets modified then stored: if the keyset is not
619
* changed we can detect this and put things back, else we won't
620
* drop any keysets from history by accident.
621
*
622
* Note too that we only ever get called with a non-zero kvno
623
* either in the KDC or in cases where we aren't changing the
624
* HDB entry anyways, which is why this is just a defensive
625
* hack. We also don't fetch specific kvnos in the dump case,
626
* so there's no danger that we'll dump this entry and load it
627
* again, repeatedly causing the history to grow boundelessly.
628
*/
629
tmp_keys = realloc(hist_keys->val,
630
sizeof (*hist_keys->val) * (hist_keys->len + 1));
631
if (tmp_keys == NULL)
632
return ENOMEM;
633
634
memmove(&tmp_keys[1], tmp_keys,
635
sizeof (*hist_keys->val) * hist_keys->len++);
636
tmp_keys[0].keys.len = ent->keys.len;
637
tmp_keys[0].keys.val = ent->keys.val;
638
tmp_keys[0].kvno = ent->kvno;
639
tmp_keys[0].replace_time = time(NULL);
640
i++;
641
ent->keys.len = hist_keys->val[i].keys.len;
642
ent->keys.val = hist_keys->val[i].keys.val;
643
ent->kvno = kvno;
644
}
645
646
return (ret);
647
}
648
#endif
649
650
krb5_error_code
651
hdb_unseal_key(krb5_context context, HDB *db, Key *k)
652
{
653
if (db->hdb_master_key_set == 0)
654
return 0;
655
return _hdb_reseal_key_mkey(context, k, db->hdb_master_key, NULL);
656
}
657
658
krb5_error_code
659
hdb_seal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
660
{
661
krb5_error_code ret;
662
krb5_data res;
663
hdb_master_key key;
664
665
if(k->mkvno != NULL)
666
return 0;
667
668
key = _hdb_find_master_key(k->mkvno, mkey);
669
670
if (key == NULL)
671
return HDB_ERR_NO_MKEY;
672
673
ret = _hdb_mkey_encrypt(context, key, HDB_KU_MKEY,
674
k->key.keyvalue.data,
675
k->key.keyvalue.length,
676
&res);
677
if (ret)
678
return ret;
679
680
memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);
681
free(k->key.keyvalue.data);
682
k->key.keyvalue = res;
683
684
if (k->mkvno == NULL) {
685
k->mkvno = malloc(sizeof(*k->mkvno));
686
if (k->mkvno == NULL)
687
return ENOMEM;
688
}
689
*k->mkvno = key->keytab.vno;
690
691
return 0;
692
}
693
694
krb5_error_code
695
hdb_seal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
696
{
697
size_t i;
698
for(i = 0; i < ent->keys.len; i++){
699
krb5_error_code ret;
700
701
ret = hdb_seal_key_mkey(context, &ent->keys.val[i], mkey);
702
if (ret)
703
return ret;
704
}
705
return 0;
706
}
707
708
krb5_error_code
709
hdb_seal_keys(krb5_context context, HDB *db, hdb_entry *ent)
710
{
711
if (db->hdb_master_key_set == 0)
712
return 0;
713
714
return hdb_seal_keys_mkey(context, ent, db->hdb_master_key);
715
}
716
717
krb5_error_code
718
hdb_seal_key(krb5_context context, HDB *db, Key *k)
719
{
720
if (db->hdb_master_key_set == 0)
721
return 0;
722
723
return hdb_seal_key_mkey(context, k, db->hdb_master_key);
724
}
725
726
krb5_error_code
727
hdb_set_master_key(krb5_context context,
728
HDB *db,
729
krb5_keyblock *key)
730
{
731
krb5_error_code ret;
732
hdb_master_key mkey;
733
734
ret = hdb_process_master_key(context, 0, key, 0, &mkey);
735
if (ret)
736
return ret;
737
db->hdb_master_key = mkey;
738
#if 0 /* XXX - why? */
739
des_set_random_generator_seed(key.keyvalue.data);
740
#endif
741
db->hdb_master_key_set = 1;
742
db->hdb_master_key->key_usage = HDB_KU_MKEY;
743
return 0;
744
}
745
746
krb5_error_code
747
hdb_set_master_keyfile (krb5_context context,
748
HDB *db,
749
const char *keyfile)
750
{
751
hdb_master_key key;
752
krb5_error_code ret;
753
754
ret = hdb_read_master_key(context, keyfile, &key);
755
if (ret) {
756
if (ret != ENOENT)
757
return ret;
758
krb5_clear_error_message(context);
759
return 0;
760
}
761
db->hdb_master_key = key;
762
db->hdb_master_key_set = 1;
763
return ret;
764
}
765
766
krb5_error_code
767
hdb_clear_master_key (krb5_context context,
768
HDB *db)
769
{
770
if (db->hdb_master_key_set) {
771
hdb_free_master_key(context, db->hdb_master_key);
772
db->hdb_master_key_set = 0;
773
}
774
return 0;
775
}
776
777