summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/lib/hdb/mkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/lib/hdb/mkey.c')
-rw-r--r--crypto/heimdal/lib/hdb/mkey.c220
1 files changed, 149 insertions, 71 deletions
diff --git a/crypto/heimdal/lib/hdb/mkey.c b/crypto/heimdal/lib/hdb/mkey.c
index 92bcd86..05cf71c 100644
--- a/crypto/heimdal/lib/hdb/mkey.c
+++ b/crypto/heimdal/lib/hdb/mkey.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000 - 2002 Kungliga Tekniska Högskolan
+ * Copyright (c) 2000 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -36,7 +36,7 @@
#define O_BINARY 0
#endif
-RCSID("$Id: mkey.c,v 1.15 2003/03/28 02:01:33 lha Exp $");
+RCSID("$Id: mkey.c 21745 2007-07-31 16:11:25Z lha $");
struct hdb_master_key_data {
krb5_keytab_entry keytab;
@@ -129,6 +129,11 @@ read_master_keytab(krb5_context context, const char *filename,
*mkey = NULL;
while(krb5_kt_next_entry(context, id, &entry, &cursor) == 0) {
p = calloc(1, sizeof(*p));
+ if(p == NULL) {
+ krb5_kt_end_seq_get(context, id, &cursor);
+ ret = ENOMEM;
+ goto out;
+ }
p->keytab = entry;
ret = krb5_crypto_init(context, &p->keytab.keyblock, 0, &p->crypto);
p->next = *mkey;
@@ -148,7 +153,7 @@ read_master_mit(krb5_context context, const char *filename,
int fd;
krb5_error_code ret;
krb5_storage *sp;
- u_int16_t enctype;
+ int16_t enctype;
krb5_keyblock key;
fd = open(filename, O_RDONLY | O_BINARY);
@@ -354,68 +359,111 @@ hdb_write_master_key(krb5_context context, const char *filename,
return ret;
}
-static hdb_master_key
-find_master_key(Key *key, hdb_master_key mkey)
+hdb_master_key
+_hdb_find_master_key(uint32_t *mkvno, 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(mkvno == NULL) {
if(ret == NULL || mkey->keytab.vno > ret->keytab.vno)
ret = mkey;
- } else if(mkey->keytab.vno == *key->mkvno)
+ } else if(mkey->keytab.vno == *mkvno)
return mkey;
mkey = mkey->next;
}
return ret;
}
+int
+_hdb_mkey_version(hdb_master_key mkey)
+{
+ return mkey->keytab.vno;
+}
+
+int
+_hdb_mkey_decrypt(krb5_context context, hdb_master_key key,
+ krb5_key_usage usage,
+ void *ptr, size_t size, krb5_data *res)
+{
+ return krb5_decrypt(context, key->crypto, usage,
+ ptr, size, res);
+}
+
+int
+_hdb_mkey_encrypt(krb5_context context, hdb_master_key key,
+ krb5_key_usage usage,
+ const void *ptr, size_t size, krb5_data *res)
+{
+ return krb5_encrypt(context, key->crypto, usage,
+ ptr, size, res);
+}
+
krb5_error_code
-hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
+hdb_unseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
{
- int i;
+
krb5_error_code ret;
krb5_data res;
size_t keysize;
- Key *k;
- for(i = 0; i < ent->keys.len; i++){
- hdb_master_key key;
+ hdb_master_key key;
+
+ if(k->mkvno == NULL)
+ return 0;
+
+ key = _hdb_find_master_key(k->mkvno, mkey);
+
+ if (key == NULL)
+ return HDB_ERR_NO_MKEY;
+
+ ret = _hdb_mkey_decrypt(context, key, HDB_KU_MKEY,
+ k->key.keyvalue.data,
+ k->key.keyvalue.length,
+ &res);
+ if(ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+ /* try to decrypt with MIT key usage */
+ ret = _hdb_mkey_decrypt(context, key, 0,
+ k->key.keyvalue.data,
+ k->key.keyvalue.length,
+ &res);
+ }
+ if (ret)
+ return ret;
- k = &ent->keys.val[i];
- if(k->mkvno == NULL)
- continue;
+ /* fixup keylength if the key got padded when encrypting it */
+ ret = krb5_enctype_keysize(context, k->key.keytype, &keysize);
+ if (ret) {
+ krb5_data_free(&res);
+ return ret;
+ }
+ if (keysize > res.length) {
+ krb5_data_free(&res);
+ return KRB5_BAD_KEYSIZE;
+ }
- key = find_master_key(&ent->keys.val[i], mkey);
+ memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);
+ free(k->key.keyvalue.data);
+ k->key.keyvalue = res;
+ k->key.keyvalue.length = keysize;
+ free(k->mkvno);
+ k->mkvno = NULL;
- if (key == NULL)
- return HDB_ERR_NO_MKEY;
+ return 0;
+}
- ret = krb5_decrypt(context, key->crypto, HDB_KU_MKEY,
- k->key.keyvalue.data,
- k->key.keyvalue.length,
- &res);
- if (ret)
- return ret;
+krb5_error_code
+hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
+{
+ int i;
- /* fixup keylength if the key got padded when encrypting it */
- ret = krb5_enctype_keysize(context, k->key.keytype, &keysize);
- if (ret) {
- krb5_data_free(&res);
- return ret;
- }
- if (keysize > res.length) {
- krb5_data_free(&res);
- return KRB5_BAD_KEYSIZE;
- }
+ for(i = 0; i < ent->keys.len; i++){
+ krb5_error_code ret;
- memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);
- free(k->key.keyvalue.data);
- k->key.keyvalue = res;
- k->key.keyvalue.length = keysize;
- free(k->mkvno);
- k->mkvno = NULL;
+ ret = hdb_unseal_key_mkey(context, &ent->keys.val[i], mkey);
+ if (ret)
+ return ret;
}
return 0;
}
@@ -423,44 +471,65 @@ hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
krb5_error_code
hdb_unseal_keys(krb5_context context, HDB *db, hdb_entry *ent)
{
- if (db->master_key_set == 0)
+ if (db->hdb_master_key_set == 0)
return 0;
- return hdb_unseal_keys_mkey(context, ent, db->master_key);
+ return hdb_unseal_keys_mkey(context, ent, db->hdb_master_key);
}
krb5_error_code
-hdb_seal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
+hdb_unseal_key(krb5_context context, HDB *db, Key *k)
+{
+ if (db->hdb_master_key_set == 0)
+ return 0;
+ return hdb_unseal_key_mkey(context, k, db->hdb_master_key);
+}
+
+krb5_error_code
+hdb_seal_key_mkey(krb5_context context, Key *k, 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;
+ hdb_master_key key;
- if(k->mkvno != NULL)
- continue;
+ if(k->mkvno != NULL)
+ return 0;
- key = find_master_key(k, mkey);
+ key = _hdb_find_master_key(k->mkvno, mkey);
- if (key == NULL)
- return HDB_ERR_NO_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;
+ ret = _hdb_mkey_encrypt(context, key, 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;
+ memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);
+ free(k->key.keyvalue.data);
+ k->key.keyvalue = res;
+ if (k->mkvno == NULL) {
k->mkvno = malloc(sizeof(*k->mkvno));
if (k->mkvno == NULL)
return ENOMEM;
- *k->mkvno = key->keytab.vno;
+ }
+ *k->mkvno = key->keytab.vno;
+
+ return 0;
+}
+
+krb5_error_code
+hdb_seal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
+{
+ int i;
+ for(i = 0; i < ent->keys.len; i++){
+ krb5_error_code ret;
+
+ ret = hdb_seal_key_mkey(context, &ent->keys.val[i], mkey);
+ if (ret)
+ return ret;
}
return 0;
}
@@ -468,10 +537,19 @@ hdb_seal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
krb5_error_code
hdb_seal_keys(krb5_context context, HDB *db, hdb_entry *ent)
{
- if (db->master_key_set == 0)
+ if (db->hdb_master_key_set == 0)
+ return 0;
+
+ return hdb_seal_keys_mkey(context, ent, db->hdb_master_key);
+}
+
+krb5_error_code
+hdb_seal_key(krb5_context context, HDB *db, Key *k)
+{
+ if (db->hdb_master_key_set == 0)
return 0;
- return hdb_seal_keys_mkey(context, ent, db->master_key);
+ return hdb_seal_key_mkey(context, k, db->hdb_master_key);
}
krb5_error_code
@@ -485,11 +563,11 @@ hdb_set_master_key (krb5_context context,
ret = hdb_process_master_key(context, 0, key, 0, &mkey);
if (ret)
return ret;
- db->master_key = mkey;
+ db->hdb_master_key = mkey;
#if 0 /* XXX - why? */
des_set_random_generator_seed(key.keyvalue.data);
#endif
- db->master_key_set = 1;
+ db->hdb_master_key_set = 1;
return 0;
}
@@ -508,8 +586,8 @@ hdb_set_master_keyfile (krb5_context context,
krb5_clear_error_string(context);
return 0;
}
- db->master_key = key;
- db->master_key_set = 1;
+ db->hdb_master_key = key;
+ db->hdb_master_key_set = 1;
return ret;
}
@@ -517,9 +595,9 @@ 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;
+ if (db->hdb_master_key_set) {
+ hdb_free_master_key(context, db->hdb_master_key);
+ db->hdb_master_key_set = 0;
}
return 0;
}
OpenPOWER on IntegriCloud