Home | History | Annotate | Line # | Download | only in hdb
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