Make OpenSSL an hcrypto backend proper
This adds a new backend for libhcrypto: the OpenSSL backend. Now libhcrypto has these backends: - hcrypto itself (i.e., the algorithms coded in lib/hcrypto) - Common Crypto (OS X) - PKCS#11 (specifically for Solaris, but not Solaris-specific) - Windows CNG (Windows) - OpenSSL (generic) The ./configure --with-openssl=... option no longer disables the use of hcrypto. Instead it enables the use of OpenSSL as a (and the default) backend in libhcrypto. The libhcrypto framework is now always used. OpenSSL should no longer be used directly within Heimdal, except in the OpenSSL hcrypto backend itself, and files where elliptic curve (EC) crypto is needed. Because libhcrypto's EC support is incomplete, we can only use OpenSSL for EC. Currently that means separating all EC-using code so that it does not use hcrypto, thus the libhx509/hxtool and PKINIT EC code has been moved out of the files it used to be in.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan
|
||||
* Copyright (c) 2003 - 2016 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -58,27 +58,6 @@ struct krb5_pk_cert {
|
||||
hx509_cert cert;
|
||||
};
|
||||
|
||||
struct krb5_pk_init_ctx_data {
|
||||
struct krb5_pk_identity *id;
|
||||
enum { USE_RSA, USE_DH, USE_ECDH } keyex;
|
||||
union {
|
||||
DH *dh;
|
||||
#ifdef HAVE_OPENSSL
|
||||
EC_KEY *eckey;
|
||||
#endif
|
||||
} u;
|
||||
krb5_data *clientDHNonce;
|
||||
struct krb5_dh_moduli **m;
|
||||
hx509_peer_info peer;
|
||||
enum krb5_pk_type type;
|
||||
unsigned int require_binding:1;
|
||||
unsigned int require_eku:1;
|
||||
unsigned int require_krbtgt_otherName:1;
|
||||
unsigned int require_hostname_match:1;
|
||||
unsigned int trustedCertifiers:1;
|
||||
unsigned int anonymous:1;
|
||||
};
|
||||
|
||||
static void
|
||||
pk_copy_error(krb5_context context,
|
||||
hx509_context hx509ctx,
|
||||
@@ -533,74 +512,14 @@ build_auth_pack(krb5_context context,
|
||||
return ret;
|
||||
if (size != dhbuf.length)
|
||||
krb5_abortx(context, "asn1 internal error");
|
||||
a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8;
|
||||
a->clientPublicValue->subjectPublicKey.data = dhbuf.data;
|
||||
} else if (ctx->keyex == USE_ECDH) {
|
||||
#ifdef HAVE_OPENSSL
|
||||
ECParameters ecp;
|
||||
unsigned char *p;
|
||||
int xlen;
|
||||
|
||||
/* copy in public key, XXX find the best curve that the server support or use the clients curve if possible */
|
||||
|
||||
ecp.element = choice_ECParameters_namedCurve;
|
||||
ret = der_copy_oid(&asn1_oid_id_ec_group_secp256r1,
|
||||
&ecp.u.namedCurve);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ALLOC(a->clientPublicValue->algorithm.parameters, 1);
|
||||
if (a->clientPublicValue->algorithm.parameters == NULL) {
|
||||
free_ECParameters(&ecp);
|
||||
return ENOMEM;
|
||||
}
|
||||
ASN1_MALLOC_ENCODE(ECParameters, p, xlen, &ecp, &size, ret);
|
||||
free_ECParameters(&ecp);
|
||||
if (ret)
|
||||
return ret;
|
||||
if ((int)size != xlen)
|
||||
krb5_abortx(context, "asn1 internal error");
|
||||
|
||||
a->clientPublicValue->algorithm.parameters->data = p;
|
||||
a->clientPublicValue->algorithm.parameters->length = size;
|
||||
|
||||
/* copy in public key */
|
||||
|
||||
ret = der_copy_oid(&asn1_oid_id_ecPublicKey,
|
||||
&a->clientPublicValue->algorithm.algorithm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctx->u.eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
if (ctx->u.eckey == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
ret = EC_KEY_generate_key(ctx->u.eckey);
|
||||
if (ret != 1)
|
||||
return EINVAL;
|
||||
|
||||
/* encode onto dhkey */
|
||||
|
||||
xlen = i2o_ECPublicKey(ctx->u.eckey, NULL);
|
||||
if (xlen <= 0)
|
||||
abort();
|
||||
|
||||
dhbuf.data = malloc(xlen);
|
||||
if (dhbuf.data == NULL)
|
||||
abort();
|
||||
dhbuf.length = xlen;
|
||||
p = dhbuf.data;
|
||||
|
||||
xlen = i2o_ECPublicKey(ctx->u.eckey, &p);
|
||||
if (xlen <= 0)
|
||||
abort();
|
||||
|
||||
/* XXX verify that this is right with RFC3279 */
|
||||
#else
|
||||
return EINVAL;
|
||||
#endif
|
||||
ret = _krb5_build_authpack_subjectPK_EC(context, ctx, a);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else
|
||||
krb5_abortx(context, "internal error");
|
||||
a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8;
|
||||
a->clientPublicValue->subjectPublicKey.data = dhbuf.data;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1443,51 +1362,11 @@ pk_rd_pa_reply_dh(krb5_context context,
|
||||
}
|
||||
|
||||
} else {
|
||||
#ifdef HAVE_OPENSSL
|
||||
const EC_GROUP *group;
|
||||
EC_KEY *public = NULL;
|
||||
|
||||
group = EC_KEY_get0_group(ctx->u.eckey);
|
||||
|
||||
public = EC_KEY_new();
|
||||
if (public == NULL) {
|
||||
ret = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (EC_KEY_set_group(public, group) != 1) {
|
||||
EC_KEY_free(public);
|
||||
ret = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (o2i_ECPublicKey(&public, &p, size) == NULL) {
|
||||
EC_KEY_free(public);
|
||||
ret = KRB5KRB_ERR_GENERIC;
|
||||
krb5_set_error_message(context, ret,
|
||||
N_("PKINIT: Can't parse ECDH public key", ""));
|
||||
goto out;
|
||||
}
|
||||
|
||||
size = (EC_GROUP_get_degree(group) + 7) / 8;
|
||||
dh_gen_key = malloc(size);
|
||||
if (dh_gen_key == NULL) {
|
||||
EC_KEY_free(public);
|
||||
ret = krb5_enomem(context);
|
||||
goto out;
|
||||
}
|
||||
dh_gen_keylen = ECDH_compute_key(dh_gen_key, size,
|
||||
EC_KEY_get0_public_key(public), ctx->u.eckey, NULL);
|
||||
EC_KEY_free(public);
|
||||
if (dh_gen_keylen == -1) {
|
||||
ret = KRB5KRB_ERR_GENERIC;
|
||||
dh_gen_keylen = 0;
|
||||
krb5_set_error_message(context, ret,
|
||||
N_("PKINIT: Can't compute ECDH public key", ""));
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
ret = EINVAL;
|
||||
#endif
|
||||
ret = _krb5_pk_rd_pa_reply_ecdh_compute_key(context, ctx, p,
|
||||
size, &dh_gen_key,
|
||||
&dh_gen_keylen);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dh_gen_keylen <= 0) {
|
||||
@@ -2309,10 +2188,8 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt)
|
||||
case USE_RSA:
|
||||
break;
|
||||
case USE_ECDH:
|
||||
#ifdef HAVE_OPENSSL
|
||||
if (ctx->u.eckey)
|
||||
EC_KEY_free(ctx->u.eckey);
|
||||
#endif
|
||||
_krb5_pk_eckey_free(ctx->u.eckey);
|
||||
break;
|
||||
}
|
||||
if (ctx->id) {
|
||||
|
Reference in New Issue
Block a user