X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=moonshot%2Fmech_eap%2Futil_krb.c;h=32e28b438590ea4c56d6642c7dd2a656a87255fe;hb=refs%2Fheads%2Frfc3961-mic;hp=06da80e45930b18d97992de02662bcd79ed4eee9;hpb=7c34b0b06a708b217c3511b47e7c0d7afe67494b;p=moonshot.git diff --git a/moonshot/mech_eap/util_krb.c b/moonshot/mech_eap/util_krb.c index 06da80e..32e28b4 100644 --- a/moonshot/mech_eap/util_krb.c +++ b/moonshot/mech_eap/util_krb.c @@ -88,11 +88,16 @@ gssEapKerberosInit(OM_uint32 *minor, krb5_context *context) if (tld != NULL) { if (tld->krbContext == NULL) { *minor = initKrbContext(&tld->krbContext); - if (*minor == 0) - *context = tld->krbContext; + if (*minor != 0) + tld->krbContext = NULL; } + *context = tld->krbContext; + } else { + *minor = GSSEAP_GET_LAST_ERROR(); } + GSSEAP_ASSERT(*context != NULL || *minor != 0); + return (*minor == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; } @@ -104,6 +109,9 @@ gssEapKerberosInit(OM_uint32 *minor, krb5_context *context) * Tn = pseudo-random(KMSK, n || "rfc4121-gss-eap") * L = output key size * K = truncate(L, T1 || T2 || .. || Tn) + * + * The output must be freed by krb5_free_keyblock_contents(), + * not GSSEAP_FREE(). */ OM_uint32 gssEapDeriveRfc3961Key(OM_uint32 *minor, @@ -116,41 +124,31 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, #ifndef HAVE_HEIMDAL_VERSION krb5_data data; #endif - krb5_data ns, t, prfOut; + krb5_data ns, t, derivedKeyData; krb5_keyblock kd; krb5_error_code code; size_t randomLength, keyLength, prfLength; unsigned char constant[4 + sizeof("rfc4121-gss-eap") - 1], *p; ssize_t i, remain; - GSSEAP_ASSERT(encryptionType != ENCTYPE_NULL); - - memset(pKey, 0, sizeof(*pKey)); - GSSEAP_KRB_INIT(&krbContext); + GSSEAP_ASSERT(encryptionType != ENCTYPE_NULL); + KRB_KEY_INIT(pKey); KRB_KEY_INIT(&kd); KRB_KEY_TYPE(&kd) = encryptionType; - t.data = NULL; - t.length = 0; - - prfOut.data = NULL; - prfOut.length = 0; + KRB_DATA_INIT(&ns); + KRB_DATA_INIT(&t); + KRB_DATA_INIT(&derivedKeyData); code = krb5_c_keylengths(krbContext, encryptionType, &randomLength, &keyLength); if (code != 0) goto cleanup; - KRB_KEY_DATA(&kd) = GSSEAP_MALLOC(keyLength); - if (KRB_KEY_DATA(&kd) == NULL) { - code = ENOMEM; - goto cleanup; - } - KRB_KEY_LENGTH(&kd) = keyLength; + /* Convert EAP MSK into a Kerberos key */ - /* Convert MSK into a Kerberos key */ #ifdef HAVE_HEIMDAL_VERSION code = krb5_random_to_key(krbContext, encryptionType, inputKey, MIN(inputKeyLength, randomLength), &kd); @@ -158,8 +156,15 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, data.length = MIN(inputKeyLength, randomLength); data.data = (char *)inputKey; + KRB_KEY_DATA(&kd) = KRB_MALLOC(keyLength); + if (KRB_KEY_DATA(&kd) == NULL) { + code = ENOMEM; + goto cleanup; + } + KRB_KEY_LENGTH(&kd) = keyLength; + code = krb5_c_random_to_key(krbContext, encryptionType, &data, &kd); -#endif +#endif /* HAVE_HEIMDAL_VERSION */ if (code != 0) goto cleanup; @@ -174,21 +179,24 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, if (code != 0) goto cleanup; +#ifndef HAVE_HEIMDAL_VERSION + /* Same API, but different allocation rules, unfortunately. */ t.length = prfLength; t.data = GSSEAP_MALLOC(t.length); if (t.data == NULL) { code = ENOMEM; goto cleanup; } +#endif - prfOut.length = randomLength; - prfOut.data = GSSEAP_MALLOC(prfOut.length); - if (prfOut.data == NULL) { + derivedKeyData.length = randomLength; + derivedKeyData.data = GSSEAP_MALLOC(derivedKeyData.length); + if (derivedKeyData.data == NULL) { code = ENOMEM; goto cleanup; } - for (i = 0, p = (unsigned char *)prfOut.data, remain = randomLength; + for (i = 0, p = (unsigned char *)derivedKeyData.data, remain = randomLength; remain > 0; p += t.length, remain -= t.length, i++) { @@ -203,31 +211,38 @@ gssEapDeriveRfc3961Key(OM_uint32 *minor, /* Finally, convert PRF output into a new key which we will return */ #ifdef HAVE_HEIMDAL_VERSION + krb5_free_keyblock_contents(krbContext, &kd); + KRB_KEY_INIT(&kd); + code = krb5_random_to_key(krbContext, encryptionType, - prfOut.data, prfOut.length, &kd); + derivedKeyData.data, derivedKeyData.length, &kd); #else - code = krb5_c_random_to_key(krbContext, encryptionType, &prfOut, &kd); + code = krb5_c_random_to_key(krbContext, encryptionType, + &derivedKeyData, &kd); #endif if (code != 0) goto cleanup; *pKey = kd; - KRB_KEY_DATA(&kd) = NULL; cleanup: - if (KRB_KEY_DATA(&kd) != NULL) { - memset(KRB_KEY_DATA(&kd), 0, KRB_KEY_LENGTH(&kd)); - GSSEAP_FREE(KRB_KEY_DATA(&kd)); - } + if (code != 0) + krb5_free_keyblock_contents(krbContext, &kd); +#ifdef HAVE_HEIMDAL_VERSION + krb5_free_data_contents(krbContext, &t); +#else if (t.data != NULL) { memset(t.data, 0, t.length); GSSEAP_FREE(t.data); } - if (prfOut.data != NULL) { - memset(prfOut.data, 0, prfOut.length); - GSSEAP_FREE(prfOut.data); +#endif + if (derivedKeyData.data != NULL) { + memset(derivedKeyData.data, 0, derivedKeyData.length); + GSSEAP_FREE(derivedKeyData.data); } + *minor = code; + return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; } @@ -255,8 +270,7 @@ rfc3961ChecksumTypeForKey(OM_uint32 *minor, if (*minor != 0) return GSS_S_FAILURE; #else - data.length = 0; - data.data = NULL; + KRB_DATA_INIT(&data); memset(&cksum, 0, sizeof(cksum)); @@ -269,11 +283,7 @@ rfc3961ChecksumTypeForKey(OM_uint32 *minor, if (*minor != 0) return GSS_S_FAILURE; -#ifdef HAVE_HEIMDAL_VERSION - *cksumtype = cksum.cksumtype; -#else - *cksumtype = cksum.checksum_type; -#endif + *cksumtype = KRB_CHECKSUM_TYPE(&cksum); krb5_free_checksum_contents(krbContext, &cksum); #endif /* HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE */