From: David Woodhouse Date: Tue, 11 May 2021 21:09:24 +0000 (+0100) Subject: Support TLSv1.3 sign functions on SECP curves with TPMv2 X-Git-Tag: v8.20~201 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=4c225c0e68c7762d61bcdfc7392e2b638fc862b0;p=users%2Fdwmw2%2Fopenconnect.git Support TLSv1.3 sign functions on SECP curves with TPMv2 For these curves at least, it basically already works. Signed-off-by: David Woodhouse --- diff --git a/gnutls.h b/gnutls.h index 378937e8..d6f75dc6 100644 --- a/gnutls.h +++ b/gnutls.h @@ -44,6 +44,7 @@ int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, const gnutls_datum_t *data, gnutls_datum_t *sig); int oc_pkcs1_pad(struct openconnect_info *vpninfo, unsigned char *buf, int size, const gnutls_datum_t *data); +uint16_t tpm2_key_curve(struct openconnect_info *vpninfo, struct cert_info *certinfo); /* GnuTLS 3.6.0+ provides this. We have our own for older GnuTLS. There is * also _gnutls_encode_ber_rs_raw() in some older versions, but there were diff --git a/gnutls_tpm2.c b/gnutls_tpm2.c index a3ba3cdb..839e1b83 100644 --- a/gnutls_tpm2.c +++ b/gnutls_tpm2.c @@ -130,18 +130,34 @@ static int rsa_key_info(gnutls_privkey_t key, unsigned int flags, void *_certinf #if GNUTLS_VERSION_NUMBER >= 0x030400 static int ec_key_info(gnutls_privkey_t key, unsigned int flags, void *_certinfo) { + struct cert_info *certinfo = _certinfo; + struct openconnect_info *vpninfo = certinfo->vpninfo; + if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO) return GNUTLS_PK_EC; #ifdef GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO if (flags & GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO) { + uint16_t tpm2_curve = tpm2_key_curve(vpninfo, certinfo); gnutls_sign_algorithm_t algo = GNUTLS_FLAGS_TO_SIGN_ALGO(flags); switch (algo) { case GNUTLS_SIGN_ECDSA_SHA1: case GNUTLS_SIGN_ECDSA_SHA256: return 1; + case GNUTLS_SIGN_ECDSA_SECP256R1_SHA256: + return tpm2_curve == 0x0003; /* TPM2_ECC_NIST_P256 */ + + case GNUTLS_SIGN_ECDSA_SECP384R1_SHA384: + return tpm2_curve == 0x0004; /* TPM2_ECC_NIST_P384 */ + + case GNUTLS_SIGN_ECDSA_SECP521R1_SHA512: + return tpm2_curve == 0x0005; /* TPM2_ECC_NIST_P521 */ + default: + vpn_progress(vpninfo, PRG_DEBUG, + _("Not supporting EC sign algo %s\n"), + gnutls_sign_get_name(algo)); return 0; } } diff --git a/gnutls_tpm2_esys.c b/gnutls_tpm2_esys.c index a57b843f..26e9b05d 100644 --- a/gnutls_tpm2_esys.c +++ b/gnutls_tpm2_esys.c @@ -603,6 +603,10 @@ int install_tpm2_key(struct openconnect_info *vpninfo, struct cert_info *certinf return -EINVAL; } +uint16_t tpm2_key_curve(struct openconnect_info *vpninfo, struct cert_info *certinfo) +{ + return certinfo->tpm2->pub.publicArea.parameters.eccDetail.curveID; +} void release_tpm2_ctx(struct openconnect_info *vpninfo, struct cert_info *certinfo) { diff --git a/gnutls_tpm2_ibm.c b/gnutls_tpm2_ibm.c index fdf6fe56..16365dff 100644 --- a/gnutls_tpm2_ibm.c +++ b/gnutls_tpm2_ibm.c @@ -553,6 +553,10 @@ int install_tpm2_key(struct openconnect_info *vpninfo, struct cert_info *certinf return -EINVAL; } +uint16_t tpm2_key_curve(struct openconnect_info *vpninfo, struct cert_info *certinfo) +{ + return certinfo->tpm2->pub.publicArea.parameters.eccDetail.curveID; +} void release_tpm2_ctx(struct openconnect_info *vpninfo, struct cert_info *certinfo) {