diff options
Diffstat (limited to 'crypto/heimdal/lib/hdb/mkey.c')
| -rw-r--r-- | crypto/heimdal/lib/hdb/mkey.c | 512 | 
1 files changed, 0 insertions, 512 deletions
| diff --git a/crypto/heimdal/lib/hdb/mkey.c b/crypto/heimdal/lib/hdb/mkey.c deleted file mode 100644 index 13aae9d2c581..000000000000 --- a/crypto/heimdal/lib/hdb/mkey.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (c) 2000 - 2002 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden).  - * All rights reserved.  - * - * Redistribution and use in source and binary forms, with or without  - * modification, are permitted provided that the following conditions  - * are met:  - * - * 1. Redistributions of source code must retain the above copyright  - *    notice, this list of conditions and the following disclaimer.  - * - * 2. Redistributions in binary form must reproduce the above copyright  - *    notice, this list of conditions and the following disclaimer in the  - *    documentation and/or other materials provided with the distribution.  - * - * 3. Neither the name of the Institute nor the names of its contributors  - *    may be used to endorse or promote products derived from this software  - *    without specific prior written permission.  - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  - * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE  - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  - * SUCH DAMAGE.  - */ - -#include "hdb_locl.h" -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -RCSID("$Id: mkey.c,v 1.14 2002/08/16 18:59:49 assar Exp $"); - -struct hdb_master_key_data { -    krb5_keytab_entry keytab; -    krb5_crypto crypto; -    struct hdb_master_key_data *next; -}; - -void -hdb_free_master_key(krb5_context context, hdb_master_key mkey) -{ -    struct hdb_master_key_data *ptr; -    while(mkey) { -	krb5_kt_free_entry(context, &mkey->keytab); -	if (mkey->crypto) -	    krb5_crypto_destroy(context, mkey->crypto); -	ptr = mkey; -	mkey = mkey->next; -	free(ptr); -    } -} - -krb5_error_code -hdb_process_master_key(krb5_context context, -		       int kvno, krb5_keyblock *key, krb5_enctype etype, -		       hdb_master_key *mkey) -{ -    krb5_error_code ret; - -    *mkey = calloc(1, sizeof(**mkey)); -    if(*mkey == NULL) { -	krb5_set_error_string(context, "malloc: out of memory"); -	return ENOMEM; -    } -    (*mkey)->keytab.vno = kvno; -    ret = krb5_parse_name(context, "K/M", &(*mkey)->keytab.principal); -    if(ret) -	goto fail; -    ret = krb5_copy_keyblock_contents(context, key, &(*mkey)->keytab.keyblock); -    if(ret) -	goto fail; -    if(etype != 0) -	(*mkey)->keytab.keyblock.keytype = etype; -    (*mkey)->keytab.timestamp = time(NULL); -    ret = krb5_crypto_init(context, key, etype, &(*mkey)->crypto); -    if(ret) -	goto fail; -    return 0; - fail: -    hdb_free_master_key(context, *mkey); -    *mkey = NULL; -    return ret; -} - -krb5_error_code -hdb_add_master_key(krb5_context context, krb5_keyblock *key, -		   hdb_master_key *inout) -{ -    int vno = 0; -    hdb_master_key p; -    krb5_error_code ret; - -    for(p = *inout; p; p = p->next) -	vno = max(vno, p->keytab.vno); -    vno++; -    ret = hdb_process_master_key(context, vno, key, 0, &p); -    if(ret) -	return ret; -    p->next = *inout; -    *inout = p; -    return 0; -} - -static krb5_error_code -read_master_keytab(krb5_context context, const char *filename,  -		   hdb_master_key *mkey) -{ -    krb5_error_code ret; -    krb5_keytab id; -    krb5_kt_cursor cursor; -    krb5_keytab_entry entry; -    hdb_master_key p; -     -    ret = krb5_kt_resolve(context, filename, &id); -    if(ret) -	return ret; - -    ret = krb5_kt_start_seq_get(context, id, &cursor); -    if(ret) -	goto out; -    *mkey = NULL; -    while(krb5_kt_next_entry(context, id, &entry, &cursor) == 0) { -	p = calloc(1, sizeof(*p)); -	p->keytab = entry; -	ret = krb5_crypto_init(context, &p->keytab.keyblock, 0, &p->crypto); -	p->next = *mkey; -	*mkey = p; -    } -    krb5_kt_end_seq_get(context, id, &cursor); -  out: -    krb5_kt_close(context, id); -    return ret; -} - -/* read a MIT master keyfile */ -static krb5_error_code -read_master_mit(krb5_context context, const char *filename,  -		hdb_master_key *mkey) -{ -    int fd; -    krb5_error_code ret; -    krb5_storage *sp; -    u_int16_t enctype; -    krb5_keyblock key; -	        -    fd = open(filename, O_RDONLY | O_BINARY); -    if(fd < 0) { -	int save_errno = errno; -	krb5_set_error_string(context, "failed to open %s: %s", filename, -			      strerror(save_errno)); -	return save_errno; -    } -    sp = krb5_storage_from_fd(fd); -    if(sp == NULL) { -	close(fd); -	return errno; -    } -    krb5_storage_set_flags(sp, KRB5_STORAGE_HOST_BYTEORDER); -#if 0 -    /* could possibly use ret_keyblock here, but do it with more -       checks for now */ -    ret = krb5_ret_keyblock(sp, &key); -#else -    ret = krb5_ret_int16(sp, &enctype); -    if((htons(enctype) & 0xff00) == 0x3000) { -	krb5_set_error_string(context, "unknown keytype in %s: %#x, expected %#x",  -			      filename, htons(enctype), 0x3000); -	ret = HEIM_ERR_BAD_MKEY; -	goto out; -    } -    key.keytype = enctype; -    ret = krb5_ret_data(sp, &key.keyvalue); -    if(ret) -	goto out; -#endif -    ret = hdb_process_master_key(context, 0, &key, 0, mkey); -    krb5_free_keyblock_contents(context, &key); -  out: -    krb5_storage_free(sp); -    close(fd); -    return ret; -} - -/* read an old master key file */ -static krb5_error_code -read_master_encryptionkey(krb5_context context, const char *filename,  -			  hdb_master_key *mkey) -{ -    int fd; -    krb5_keyblock key; -    krb5_error_code ret; -    unsigned char buf[256]; -    ssize_t len; -    size_t ret_len; -	        -    fd = open(filename, O_RDONLY | O_BINARY); -    if(fd < 0) { -	int save_errno = errno; -	krb5_set_error_string(context, "failed to open %s: %s",  -			      filename, strerror(save_errno)); -	return save_errno; -    } -     -    len = read(fd, buf, sizeof(buf)); -    close(fd); -    if(len < 0) { -	int save_errno = errno; -	krb5_set_error_string(context, "error reading %s: %s",  -			      filename, strerror(save_errno)); -	return save_errno; -    } - -    ret = decode_EncryptionKey(buf, len, &key, &ret_len); -    memset(buf, 0, sizeof(buf)); -    if(ret) -	return ret; - -    /* Originally, the keytype was just that, and later it got changed -       to des-cbc-md5, but we always used des in cfb64 mode. This -       should cover all cases, but will break if someone has hacked -       this code to really use des-cbc-md5 -- but then that's not my -       problem. */ -    if(key.keytype == KEYTYPE_DES || key.keytype == ETYPE_DES_CBC_MD5) -	key.keytype = ETYPE_DES_CFB64_NONE; -     -    ret = hdb_process_master_key(context, 0, &key, 0, mkey); -    krb5_free_keyblock_contents(context, &key); -    return ret; -} - -/* read a krb4 /.k style file */ -static krb5_error_code -read_master_krb4(krb5_context context, const char *filename,  -		 hdb_master_key *mkey) -{ -    int fd; -    krb5_keyblock key; -    krb5_error_code ret; -    unsigned char buf[256]; -    ssize_t len; -	        -    fd = open(filename, O_RDONLY | O_BINARY); -    if(fd < 0) { -	int save_errno = errno; -	krb5_set_error_string(context, "failed to open %s: %s",  -			      filename, strerror(save_errno)); -	return save_errno; -    } -     -    len = read(fd, buf, sizeof(buf)); -    close(fd); -    if(len < 0) { -	int save_errno = errno; -	krb5_set_error_string(context, "error reading %s: %s",  -			      filename, strerror(save_errno)); -	return save_errno; -    } -    if(len != 8) { -	krb5_set_error_string(context, "bad contents of %s", filename); -	return HEIM_ERR_EOF; /* XXX file might be too large */ -    } - -    memset(&key, 0, sizeof(key)); -    key.keytype = ETYPE_DES_PCBC_NONE; -    ret = krb5_data_copy(&key.keyvalue, buf, len); -    memset(buf, 0, sizeof(buf)); -    if(ret)  -	return ret; - -    ret = hdb_process_master_key(context, 0, &key, 0, mkey); -    krb5_free_keyblock_contents(context, &key); -    return ret; -} - -krb5_error_code -hdb_read_master_key(krb5_context context, const char *filename,  -		    hdb_master_key *mkey) -{ -    FILE *f; -    unsigned char buf[16]; -    krb5_error_code ret; - -    off_t len; - -    *mkey = NULL; - -    if(filename == NULL) -	filename = HDB_DB_DIR "/m-key"; - -    f = fopen(filename, "r"); -    if(f == NULL) { -	int save_errno = errno; -	krb5_set_error_string(context, "failed to open %s: %s",  -			      filename, strerror(save_errno)); -	return save_errno; -    } -     -    if(fread(buf, 1, 2, f) != 2) { -	krb5_set_error_string(context, "end of file reading %s", filename); -	fclose(f); -	return HEIM_ERR_EOF; -    } -     -    fseek(f, 0, SEEK_END); -    len = ftell(f); - -    if(fclose(f) != 0) -	return errno; -     -    if(len < 0) -	return errno; -     -    if(len == 8) { -	ret = read_master_krb4(context, filename, mkey); -    } else if(buf[0] == 0x30 && len <= 127 && buf[1] == len - 2) { -	ret = read_master_encryptionkey(context, filename, mkey); -    } else if(buf[0] == 5 && buf[1] >= 1 && buf[1] <= 2) { -	ret = read_master_keytab(context, filename, mkey); -    } else { -	ret = read_master_mit(context, filename, mkey); -    } -    return ret; -} - -krb5_error_code -hdb_write_master_key(krb5_context context, const char *filename,  -		     hdb_master_key mkey) -{ -    krb5_error_code ret; -    hdb_master_key p; -    krb5_keytab kt; - -    if(filename == NULL) -	filename = HDB_DB_DIR "/m-key"; - -    ret = krb5_kt_resolve(context, filename, &kt); -    if(ret) -	return ret; - -    for(p = mkey; p; p = p->next) { -	ret = krb5_kt_add_entry(context, kt, &p->keytab); -    } - -    krb5_kt_close(context, kt); - -    return ret; -} - -static hdb_master_key -find_master_key(Key *key, hdb_master_key mkey) -{ -    hdb_master_key ret = NULL; -    while(mkey) { -	if(ret == NULL && mkey->keytab.vno == 0) -	    ret = mkey; -	if(key->mkvno == NULL) { -	    if(ret == NULL || mkey->keytab.vno > ret->keytab.vno) -		ret = mkey; -	} else if(mkey->keytab.vno == *key->mkvno) -	    return mkey; -	mkey = mkey->next; -    } -    return ret; -} - -krb5_error_code -hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey) -{ -    int i; -    krb5_error_code ret; -    krb5_data res; -    Key *k; - -    for(i = 0; i < ent->keys.len; i++){ -	hdb_master_key key; - -	k = &ent->keys.val[i]; -	if(k->mkvno == NULL) -	    continue; - -	key = find_master_key(&ent->keys.val[i], mkey); - -	if (key == NULL) -	    return HDB_ERR_NO_MKEY; - -	ret = krb5_decrypt(context, key->crypto, HDB_KU_MKEY, -			   k->key.keyvalue.data, -			   k->key.keyvalue.length, -			   &res); -	if (ret) -	    return ret; - -	memset(k->key.keyvalue.data, 0, k->key.keyvalue.length); -	free(k->key.keyvalue.data); -	k->key.keyvalue = res; -	free(k->mkvno); -	k->mkvno = NULL; -    } -    return 0; -} - -krb5_error_code -hdb_unseal_keys(krb5_context context, HDB *db, hdb_entry *ent) -{ -    if (db->master_key_set == 0) -	return 0; -    return hdb_unseal_keys_mkey(context, ent, db->master_key); -} - -krb5_error_code -hdb_seal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey) -{ -    int i; -    krb5_error_code ret; -    krb5_data res; -    for(i = 0; i < ent->keys.len; i++){ -	Key *k = &ent->keys.val[i]; -	hdb_master_key key; - -	if(k->mkvno != NULL) -	    continue; - -	key = find_master_key(k, mkey); - -	if (key == NULL) -	    return HDB_ERR_NO_MKEY; - -	ret = krb5_encrypt(context, key->crypto, HDB_KU_MKEY, -			   k->key.keyvalue.data, -			   k->key.keyvalue.length, -			   &res); -	if (ret) -	    return ret; - -	memset(k->key.keyvalue.data, 0, k->key.keyvalue.length); -	free(k->key.keyvalue.data); -	k->key.keyvalue = res; - -	k->mkvno = malloc(sizeof(*k->mkvno)); -	if (k->mkvno == NULL) -	    return ENOMEM; -	*k->mkvno = key->keytab.vno; -    } -    return 0; -} - -krb5_error_code -hdb_seal_keys(krb5_context context, HDB *db, hdb_entry *ent) -{ -    if (db->master_key_set == 0) -	return 0; -     -    return hdb_seal_keys_mkey(context, ent, db->master_key); -} - -krb5_error_code -hdb_set_master_key (krb5_context context, -		    HDB *db, -		    krb5_keyblock *key) -{ -    krb5_error_code ret; -    hdb_master_key mkey; - -    ret = hdb_process_master_key(context, 0, key, 0, &mkey); -    if (ret) -	return ret; -    db->master_key = mkey; -#if 0 /* XXX - why? */ -    des_set_random_generator_seed(key.keyvalue.data); -#endif -    db->master_key_set = 1; -    return 0; -} - -krb5_error_code -hdb_set_master_keyfile (krb5_context context, -			HDB *db, -			const char *keyfile) -{ -    hdb_master_key key; -    krb5_error_code ret; - -    ret = hdb_read_master_key(context, keyfile, &key); -    if (ret) { -	if (ret != ENOENT) -	    return ret; -	krb5_clear_error_string(context); -	return 0; -    } -    db->master_key = key; -    db->master_key_set = 1; -    return ret; -} - -krb5_error_code -hdb_clear_master_key (krb5_context context, -		      HDB *db) -{ -    if (db->master_key_set) { -	hdb_free_master_key(context, db->master_key); -	db->master_key_set = 0; -    } -    return 0; -} | 
