Implement ECDH in the KDC.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@24695 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
126
kdc/pkinit.c
126
kdc/pkinit.c
@@ -53,6 +53,11 @@ struct pk_client_params {
|
|||||||
BIGNUM *public_key;
|
BIGNUM *public_key;
|
||||||
DH *key;
|
DH *key;
|
||||||
} dh;
|
} dh;
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
struct {
|
||||||
|
EC_KEY *public_key;
|
||||||
|
} ecdh;
|
||||||
|
#endif
|
||||||
} u;
|
} u;
|
||||||
hx509_cert cert;
|
hx509_cert cert;
|
||||||
unsigned nonce;
|
unsigned nonce;
|
||||||
@@ -232,6 +237,46 @@ generate_dh_keyblock(krb5_context context, pk_client_params *client_params,
|
|||||||
"Can't compute Diffie-Hellman key");
|
"Can't compute Diffie-Hellman key");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
ret = 0;
|
||||||
|
} else if (client_params->keyex == USE_ECDH) {
|
||||||
|
EC_KEY *key;
|
||||||
|
|
||||||
|
if (client_params->u.ecdh.public_key == NULL) {
|
||||||
|
ret = KRB5KRB_ERR_GENERIC;
|
||||||
|
krb5_set_error_message(context, ret, "public_key");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = EC_KEY_new();
|
||||||
|
if (key == NULL) {
|
||||||
|
ret = ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
EC_KEY_set_group(key, EC_KEY_get0_group(client_params->u.ecdh.public_key));
|
||||||
|
|
||||||
|
if (EC_KEY_generate_key(key) != 1) {
|
||||||
|
ret = ENOMEM;
|
||||||
|
EC_KEY_free(key);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = (EC_GROUP_get_degree(EC_KEY_get0_group(key)) + 7) / 8;
|
||||||
|
dh_gen_key = malloc(size);
|
||||||
|
if (dh_gen_key == NULL) {
|
||||||
|
EC_KEY_free(key);
|
||||||
|
ret = ENOMEM;
|
||||||
|
krb5_set_error_message(context, ret,
|
||||||
|
N_("malloc: out of memory", ""));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
dh_gen_keylen = ECDH_compute_key(dh_gen_key, size,
|
||||||
|
EC_KEY_get0_public_key(client_params->u.ecdh.public_key),
|
||||||
|
key, NULL);
|
||||||
|
EC_KEY_free(key);
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
ret = KRB5KRB_ERR_GENERIC;
|
ret = KRB5KRB_ERR_GENERIC;
|
||||||
krb5_set_error_message(context, ret,
|
krb5_set_error_message(context, ret,
|
||||||
@@ -281,6 +326,14 @@ get_dh_param(krb5_context context,
|
|||||||
|
|
||||||
memset(&dhparam, 0, sizeof(dhparam));
|
memset(&dhparam, 0, sizeof(dhparam));
|
||||||
|
|
||||||
|
if ((dh_key_info->subjectPublicKey.length % 8) != 0) {
|
||||||
|
ret = KRB5_BADMSGTYPE;
|
||||||
|
krb5_set_error_message(context, ret,
|
||||||
|
"PKINIT: subjectPublicKey not aligned "
|
||||||
|
"to 8 bit boundary");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (dh_key_info->algorithm.parameters == NULL) {
|
if (dh_key_info->algorithm.parameters == NULL) {
|
||||||
krb5_set_error_message(context, KRB5_BADMSGTYPE,
|
krb5_set_error_message(context, KRB5_BADMSGTYPE,
|
||||||
"PKINIT missing algorithm parameter "
|
"PKINIT missing algorithm parameter "
|
||||||
@@ -298,14 +351,6 @@ get_dh_param(krb5_context context,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dh_key_info->subjectPublicKey.length % 8) != 0) {
|
|
||||||
ret = KRB5_BADMSGTYPE;
|
|
||||||
krb5_set_error_message(context, ret,
|
|
||||||
"PKINIT: subjectPublicKey not aligned "
|
|
||||||
"to 8 bit boundary");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = _krb5_dh_group_ok(context, config->pkinit_dh_min_bits,
|
ret = _krb5_dh_group_ok(context, config->pkinit_dh_min_bits,
|
||||||
&dhparam.p, &dhparam.g, &dhparam.q, moduli,
|
&dhparam.p, &dhparam.g, &dhparam.q, moduli,
|
||||||
&client_params->dh_group_name);
|
&client_params->dh_group_name);
|
||||||
@@ -365,6 +410,67 @@ get_dh_param(krb5_context context,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static krb5_error_code
|
||||||
|
get_ecdh_param(krb5_context context,
|
||||||
|
krb5_kdc_configuration *config,
|
||||||
|
SubjectPublicKeyInfo *dh_key_info,
|
||||||
|
pk_client_params *client_params)
|
||||||
|
{
|
||||||
|
ECParameters ecp;
|
||||||
|
EC_KEY *public = NULL;
|
||||||
|
krb5_error_code ret;
|
||||||
|
const unsigned char *p;
|
||||||
|
size_t len;
|
||||||
|
int nid;
|
||||||
|
|
||||||
|
if (dh_key_info->algorithm.parameters == NULL) {
|
||||||
|
krb5_set_error_message(context, KRB5_BADMSGTYPE,
|
||||||
|
"PKINIT missing algorithm parameter "
|
||||||
|
"in clientPublicValue");
|
||||||
|
return KRB5_BADMSGTYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ecp, 0, sizeof(ecp));
|
||||||
|
|
||||||
|
ret = decode_ECParameters(dh_key_info->algorithm.parameters->data,
|
||||||
|
dh_key_info->algorithm.parameters->length, &ecp, &len);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (ecp.element != choice_ECParameters_namedCurve) {
|
||||||
|
ret = KRB5_BADMSGTYPE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (der_heim_oid_cmp(&ecp.u.namedCurve, &asn1_oid_id_ec_group_secp256r1) == 0)
|
||||||
|
nid = NID_X9_62_prime256v1;
|
||||||
|
else {
|
||||||
|
ret = KRB5_BADMSGTYPE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX verify group is ok */
|
||||||
|
|
||||||
|
public = EC_KEY_new_by_curve_name(nid);
|
||||||
|
|
||||||
|
p = dh_key_info->subjectPublicKey.data;
|
||||||
|
len = dh_key_info->subjectPublicKey.length / 8;
|
||||||
|
if (o2i_ECPublicKey(&public, &p, len) == NULL) {
|
||||||
|
ret = KRB5_BADMSGTYPE;
|
||||||
|
krb5_set_error_message(context, ret,
|
||||||
|
"PKINIT failed to decode ECDH key");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
client_params->u.ecdh.public_key = public;
|
||||||
|
public = NULL;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (public)
|
||||||
|
EC_KEY_free(public);
|
||||||
|
free_ECParameters(&ecp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
krb5_error_code
|
krb5_error_code
|
||||||
_kdc_pk_rd_padata(krb5_context context,
|
_kdc_pk_rd_padata(krb5_context context,
|
||||||
krb5_kdc_configuration *config,
|
krb5_kdc_configuration *config,
|
||||||
@@ -653,8 +759,8 @@ _kdc_pk_rd_padata(krb5_context context,
|
|||||||
ap.clientPublicValue, client_params);
|
ap.clientPublicValue, client_params);
|
||||||
} else if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_ecPublicKey) == 0) {
|
} else if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_ecPublicKey) == 0) {
|
||||||
client_params->keyex = USE_ECDH;
|
client_params->keyex = USE_ECDH;
|
||||||
ret = KRB5_BADMSGTYPE;
|
ret = get_ecdh_param(context, config,
|
||||||
krb5_set_error_message(context, ret, "PKINIT ECDH not supported yet");
|
ap.clientPublicValue, client_params);
|
||||||
} else {
|
} else {
|
||||||
ret = KRB5_BADMSGTYPE;
|
ret = KRB5_BADMSGTYPE;
|
||||||
krb5_set_error_message(context, ret, "PKINIT unknown DH mechanism");
|
krb5_set_error_message(context, ret, "PKINIT unknown DH mechanism");
|
||||||
|
Reference in New Issue
Block a user