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:
88
kdc/pkinit.c
88
kdc/pkinit.c
@@ -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
|
||||
|
Reference in New Issue
Block a user