diff options
Diffstat (limited to 'crypto/heimdal/lib/hdb/mkey.c')
-rw-r--r-- | crypto/heimdal/lib/hdb/mkey.c | 220 |
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; } |