[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: kdc upgrade gives key length error
On Mon, Oct 14, 2002 at 01:50:19AM -0400, Aidan Cully wrote:
> Hi, tonight I upgraded my KDC to NetBSD-current, which appears to be
> Heimdal 0.5, and now I can't kinit due to the KDC getting a
> KRB5_BAD_KEYSIZE error in krb5_crypto_init... This appears to be when
> trying the kdc tries to load the krbtgt/REALM@REALM principal from the
> database. I dug a bit, and the key in the database has a length 4
> bytes longer than the enctype would expect. The extra four (invalid)
> bytes of the key are all 0s... I'm not sure, but this also looks like
> it's the case with my user principal, as it also has the last four
> bytes of the key being 0. Is this a known problem, or should I try
> and dig further?
Operating under the assumption that this wasn't a known problem, I dug
further... I've just discovered that the problem stems from using a
master key with a type of DES_CBC_CRC (yeah, it's old), though it may
be more generic than that...
I traced through the code path for the 'cpw' command in kadmin -l, and
finally noticed it generating a correct looking key, then sealing it
with krb5_encrypt (via hdb_seal_keys_mkey) before storing the key to
the database. Inside encrypt_internal, there's the following block of
block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
The length of the encrypted block is set to block_sz:
result->data = p;
result->length = block_sz;
checksm_sz == 4, so block_sz == len + 8, with 4 extra bytes for
encryption padding. The unseal_keys_mkey does not remove this padding,
and returns a length that's 4 bytes too long, which is why my KDC has
been sucking. The length of a key on input to hdb_seal_keys is 24, and
when I call hdb_unseal_keys, I get one of length 28, hence the
I don't know a good solution to this problem... In the meantime, I'm
--- lib/hdb/mkey.c.orig Sun Oct 20 23:38:03 2002
+++ lib/hdb/mkey.c Sun Oct 20 23:48:07 2002
@@ -376,6 +376,7 @@
hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
+ int keysize;
@@ -402,6 +403,25 @@
memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);
k->key.keyvalue = res;
+ * XXX: krb5_encrypt puts on an unknown amount of encryption padding
+ * when encrypting a block, which krb5_decrypt can't figure out, so
+ * it assumes no padding. When this happens with a key being sealed,
+ * a future call to attempt to use this key will generate a
+ * KRB5_BAD_KEYSIZE error, so force the size to match the key when
+ * unsealing an entry.
+ * A better way to do this would be to store the key size in the
+ * database, but that breaks binary compatibility.
+ ret = XXX_krb5_keysize(k->key.keytype, &keysize);
+ if (ret)
+ return ret;
+ if (keysize > k->key.keyvalue.length)
+ return HDB_ERR_KEYSIZE_MISMATCH;
+ k->key.keyvalue.length = keysize;
k->mkvno = NULL;
--- lib/hdb/hdb_err.et.orig Sun Oct 20 23:42:57 2002
+++ lib/hdb/hdb_err.et Sun Oct 20 23:43:47 2002
@@ -23,5 +23,6 @@
error_code EXISTS, "Entry already exists in database"
error_code BADVERSION, "Wrong database version"
error_code NO_MKEY, "No correct master key"
+error_code KEYSIZE_MISMATCH, "Key size mismatch"
--- lib/krb5/crypto.c.orig Sun Oct 20 23:35:14 2002
+++ lib/krb5/crypto.c Sun Oct 20 23:37:32 2002
@@ -2967,6 +2967,19 @@
+XXX_krb5_keysize(krb5_enctype etype, int *size)
+ struct encryption_type *et;
+ et = _find_enctype(etype);
+ if (et == NULL)
+ return KRB5_PROG_ETYPE_NOSUPP;
+ *size = et->keytype->size;
+ return 0;
const krb5_keyblock *key,
which seems to have solved things...