When using PKINIT with DH, compute session key

RFC6112 provides a method of computing a session key when the PKINIT DH
is used, and mandates it for anonymous pkinit. The session key is computed
using KRB-FX-CF2 from the reply key and a random key chosen by the kdc.
The random key is provided to the client, which is supposed to verify
that the session key was computed this way.
This commit is contained in:
Chaskiel Grundman
2014-07-02 21:00:18 -04:00
parent bf7f31ee09
commit c2e2de7384

View File

@@ -1370,16 +1370,86 @@ _kdc_pk_mk_pa_reply(krb5_context context,
if (rep.u.encKeyPack.length != size)
krb5_abortx(context, "Internal ASN.1 encoder error");
/* XXX KRB-FX-CF2 */
ret = krb5_generate_random_keyblock(context, sessionetype,
sessionkey);
if (ret) {
free_PA_PK_AS_REP(&rep);
goto out;
/* generate the session key using the method from RFC6112 */
{
krb5_keyblock kdc_contribution_key;
krb5_crypto reply_crypto;
krb5_crypto kdccont_crypto;
krb5_data p1 = { strlen("PKINIT"), "PKINIT"};
krb5_data p2 = { strlen("KEYEXCHANGE"), "KEYEXCHANGE"};
void *kckdata;
size_t kcklen;
EncryptedData kx;
void *kxdata;
size_t kxlen;
ret = krb5_generate_random_keyblock(context, sessionetype,
&kdc_contribution_key);
if (ret) {
free_PA_PK_AS_REP(&rep);
goto out;
}
ret = krb5_crypto_init(context, &cp->reply_key, enctype, &reply_crypto);
if (ret) {
krb5_free_keyblock_contents(context, &kdc_contribution_key);
free_PA_PK_AS_REP(&rep);
goto out;
}
ret = krb5_crypto_init(context, &kdc_contribution_key, sessionetype, &kdccont_crypto);
if (ret) {
krb5_crypto_destroy(context, reply_crypto);
krb5_free_keyblock_contents(context, &kdc_contribution_key);
free_PA_PK_AS_REP(&rep);
goto out;
}
/* KRB-FX-CF2 */
ret = krb5_crypto_fx_cf2(context, kdccont_crypto, reply_crypto,
&p1, &p2, sessionetype, sessionkey);
krb5_crypto_destroy(context, kdccont_crypto);
if (ret) {
krb5_crypto_destroy(context, reply_crypto);
krb5_free_keyblock_contents(context, &kdc_contribution_key);
free_PA_PK_AS_REP(&rep);
goto out;
}
ASN1_MALLOC_ENCODE(EncryptionKey, kckdata, kcklen,
&kdc_contribution_key, &size, ret);
krb5_free_keyblock_contents(context, &kdc_contribution_key);
if (ret) {
krb5_set_error_message(context, ret, "encoding of PKINIT-KX Key failed %d", ret);
krb5_crypto_destroy(context, reply_crypto);
free_PA_PK_AS_REP(&rep);
goto out;
}
if (kcklen != size)
krb5_abortx(context, "Internal ASN.1 encoder error");
ret = krb5_encrypt_EncryptedData(context, reply_crypto, KRB5_KU_PA_PKINIT_KX,
kckdata, kcklen, 0, &kx);
krb5_crypto_destroy(context, reply_crypto);
free(kckdata);
if (ret) {
free_PA_PK_AS_REP(&rep);
goto out;
}
ASN1_MALLOC_ENCODE(EncryptedData, kxdata, kxlen,
&kx, &size, ret);
free_EncryptedData(&kx);
if (ret) {
krb5_set_error_message(context, ret, "encoding of PKINIT-KX failed %d", ret);
free_PA_PK_AS_REP(&rep);
goto out;
}
if (kxlen != size)
krb5_abortx(context, "Internal ASN.1 encoder error");
/* Add PA-PKINIT-KX */
ret = krb5_padata_add(context, md, KRB5_PADATA_PKINIT_KX, kxdata, kxlen);
if (ret) {
krb5_set_error_message(context, ret,
"Failed adding PKINIT-KX %d", ret);
free(buf);
goto out;
}
}
/* XXX Add PA-PKINIT-KX */
}
#define use_btmm_with_enckey 0