From 3540b40f0fdb103dc92eccac43fdf8c45e1e6bb2 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 7 May 2021 16:01:43 +0100 Subject: [PATCH] GnuTLS: Extend certinfo to callbacks Now that the cert_info struct has a back-reference to the vpninfo, we can use it as the private data for callbacks. Signed-off-by: David Woodhouse --- gnutls.c | 20 +++++++++++--------- gnutls.h | 11 ++++++----- gnutls_tpm2.c | 31 ++++++++++++++++--------------- gnutls_tpm2_esys.c | 31 ++++++++++++++++++------------- gnutls_tpm2_ibm.c | 13 ++++++++----- 5 files changed, 59 insertions(+), 47 deletions(-) diff --git a/gnutls.c b/gnutls.c index e1eeee8d..00860af8 100644 --- a/gnutls.c +++ b/gnutls.c @@ -991,6 +991,7 @@ static int load_certificate(struct openconnect_info *vpninfo, struct cert_info * size_t key_id_size = sizeof(key_id); char name[80]; + certinfo->vpninfo = vpninfo; fdata.data = NULL; key_is_p11 = !strncmp(certinfo->key, "pkcs11:", 7); @@ -1063,7 +1064,7 @@ static int load_certificate(struct openconnect_info *vpninfo, struct cert_info * goto out; } - gnutls_x509_crt_set_pin_function(cert, gnutls_pin_callback, vpninfo); + gnutls_x509_crt_set_pin_function(cert, gnutls_pin_callback, certinfo); /* Yes, even for *system* URLs the only API GnuTLS offers us is ...import_pkcs11_url(). */ @@ -1170,7 +1171,7 @@ static int load_certificate(struct openconnect_info *vpninfo, struct cert_info * goto out; } - gnutls_privkey_set_pin_function(gci->pkey, gnutls_pin_callback, vpninfo); + gnutls_privkey_set_pin_function(gci->pkey, gnutls_pin_callback, certinfo); err = gnutls_privkey_import_url(gci->pkey, certinfo->key, 0); if (err) { @@ -1197,7 +1198,7 @@ static int load_certificate(struct openconnect_info *vpninfo, struct cert_info * goto out; } - gnutls_pkcs11_privkey_set_pin_function(p11key, gnutls_pin_callback, vpninfo); + gnutls_pkcs11_privkey_set_pin_function(p11key, gnutls_pin_callback, certinfo); err = gnutls_pkcs11_privkey_import_url(p11key, key_url, 0); @@ -1369,7 +1370,7 @@ static int load_certificate(struct openconnect_info *vpninfo, struct cert_info * _("This version of OpenConnect was built without TPM2 support\n")); return -EINVAL; #else - ret = load_tpm2_key(vpninfo, &fdata, &gci->pkey, &pkey_sig); + ret = load_tpm2_key(vpninfo, certinfo, &fdata, &gci->pkey, &pkey_sig); if (ret) goto out; @@ -2518,7 +2519,8 @@ static int gnutls_pin_callback(void *priv, int attempt, const char *uri, const char *token_label, unsigned int flags, char *pin, size_t pin_max) { - struct openconnect_info *vpninfo = priv; + struct cert_info *certinfo = priv; + struct openconnect_info *vpninfo = certinfo->vpninfo; struct pin_cache **cache = &vpninfo->pin_cache; struct oc_auth_form f; struct oc_form_opt o; @@ -2551,10 +2553,10 @@ static int gnutls_pin_callback(void *priv, int attempt, const char *uri, (*cache)->token = strdup(uri); } - if (!attempt && vpninfo->certinfo[0].password) { - snprintf(pin, pin_max, "%s", vpninfo->certinfo[0].password); - (*cache)->pin = vpninfo->certinfo[0].password; - vpninfo->certinfo[0].password = NULL; + if (!attempt && certinfo->password) { + snprintf(pin, pin_max, "%s", certinfo->password); + (*cache)->pin = certinfo->password; + certinfo->password = NULL; return 0; } diff --git a/gnutls.h b/gnutls.h index f6976680..5705bb7b 100644 --- a/gnutls.h +++ b/gnutls.h @@ -28,18 +28,19 @@ int load_tpm1_key(struct openconnect_info *vpninfo, struct cert_info *certinfo, gnutls_datum_t *fdata, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig); void release_tpm1_ctx(struct openconnect_info *info); -int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, - gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig); +int load_tpm2_key(struct openconnect_info *vpninfo, struct cert_info *certinfo, + gnutls_datum_t *fdata, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig); void release_tpm2_ctx(struct openconnect_info *info); -int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, +int install_tpm2_key(struct openconnect_info *vpninfo, struct cert_info *certinfo, + gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, unsigned int parent, int emptyauth, int legacy, gnutls_datum_t *privdata, gnutls_datum_t *pubdata); int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, - void *_vpninfo, unsigned int flags, + void *_certinfo, unsigned int flags, const gnutls_datum_t *data, gnutls_datum_t *sig); int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, - void *_vpninfo, unsigned int flags, + void *_certinfo, unsigned int flags, 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); diff --git a/gnutls_tpm2.c b/gnutls_tpm2.c index 698a9e2e..467cd1d1 100644 --- a/gnutls_tpm2.c +++ b/gnutls_tpm2.c @@ -69,17 +69,18 @@ static const char OID_legacy_loadableKey[] = "2.23.133.10.2"; static const char OID_loadableKey[] = "2.23.133.10.1.3"; #if GNUTLS_VERSION_NUMBER < 0x030600 -static int tpm2_rsa_sign_fn(gnutls_privkey_t key, void *_vpninfo, +static int tpm2_rsa_sign_fn(gnutls_privkey_t key, void *_certinfo, const gnutls_datum_t *data, gnutls_datum_t *sig) { - return tpm2_rsa_sign_hash_fn(key, GNUTLS_SIGN_UNKNOWN, _vpninfo, 0, data, sig); + return tpm2_rsa_sign_hash_fn(key, GNUTLS_SIGN_UNKNOWN, _certinfo, 0, data, sig); } -static int tpm2_ec_sign_fn(gnutls_privkey_t key, void *_vpninfo, +static int tpm2_ec_sign_fn(gnutls_privkey_t key, void *_certinfo, const gnutls_datum_t *data, gnutls_datum_t *sig) { - struct openconnect_info *vpninfo = _vpninfo; + struct cert_info *certinfo = _certinfo; + struct openconnect_info *vpninfo = certinfo->vpninfo; gnutls_sign_algorithm_t algo; switch (data->size) { @@ -94,12 +95,12 @@ static int tpm2_ec_sign_fn(gnutls_privkey_t key, void *_vpninfo, return GNUTLS_E_PK_SIGN_FAILED; } - return tpm2_ec_sign_hash_fn(key, algo, vpninfo, 0, data, sig); + return tpm2_ec_sign_hash_fn(key, algo, certinfo, 0, data, sig); } #endif #if GNUTLS_VERSION_NUMBER >= 0x030600 -static int rsa_key_info(gnutls_privkey_t key, unsigned int flags, void *_vpninfo) +static int rsa_key_info(gnutls_privkey_t key, unsigned int flags, void *_certinfo) { if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO) return GNUTLS_PK_RSA; @@ -127,7 +128,7 @@ static int rsa_key_info(gnutls_privkey_t key, unsigned int flags, void *_vpninfo #endif #if GNUTLS_VERSION_NUMBER >= 0x030400 -static int ec_key_info(gnutls_privkey_t key, unsigned int flags, void *_vpninfo) +static int ec_key_info(gnutls_privkey_t key, unsigned int flags, void *_certinfo) { if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO) return GNUTLS_PK_EC; @@ -174,8 +175,8 @@ static int decode_data(ASN1_TYPE n, gnutls_datum_t *r) return 0; } -int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, - gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig) +int load_tpm2_key(struct openconnect_info *vpninfo, struct cert_info *certinfo, + gnutls_datum_t *fdata, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig) { gnutls_datum_t asn1, pubdata, privdata; ASN1_TYPE tpmkey_def = ASN1_TYPE_EMPTY, tpmkey = ASN1_TYPE_EMPTY; @@ -282,7 +283,7 @@ int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, /* Now we've extracted what we need from the ASN.1, invoke the * actual TPM2 code (whichever implementation we end up with */ - ret = install_tpm2_key(vpninfo, pkey, pkey_sig, parent, emptyauth, + ret = install_tpm2_key(vpninfo, certinfo, pkey, pkey_sig, parent, emptyauth, asn1tab == tpmkey_asn1_tab_old, &privdata, &pubdata); if (ret < 0) goto out_tpmkey; @@ -292,19 +293,19 @@ int load_tpm2_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, switch(ret) { case GNUTLS_PK_RSA: #if GNUTLS_VERSION_NUMBER >= 0x030600 - gnutls_privkey_import_ext4(*pkey, vpninfo, NULL, tpm2_rsa_sign_hash_fn, NULL, NULL, rsa_key_info, 0); + gnutls_privkey_import_ext4(*pkey, certinfo, NULL, tpm2_rsa_sign_hash_fn, NULL, NULL, rsa_key_info, 0); #else - gnutls_privkey_import_ext(*pkey, GNUTLS_PK_RSA, vpninfo, tpm2_rsa_sign_fn, NULL, 0); + gnutls_privkey_import_ext(*pkey, GNUTLS_PK_RSA, certinfo, tpm2_rsa_sign_fn, NULL, 0); #endif break; case GNUTLS_PK_ECC: #if GNUTLS_VERSION_NUMBER >= 0x030600 - gnutls_privkey_import_ext4(*pkey, vpninfo, NULL, tpm2_ec_sign_hash_fn, NULL, NULL, ec_key_info, 0); + gnutls_privkey_import_ext4(*pkey, certinfo, NULL, tpm2_ec_sign_hash_fn, NULL, NULL, ec_key_info, 0); #elif GNUTLS_VERSION_NUMBER >= 0x030400 - gnutls_privkey_import_ext3(*pkey, vpninfo, tpm2_ec_sign_fn, NULL, NULL, ec_key_info, 0); + gnutls_privkey_import_ext3(*pkey, certinfo, tpm2_ec_sign_fn, NULL, NULL, ec_key_info, 0); #else - gnutls_privkey_import_ext(*pkey, GNUTLS_PK_EC, vpninfo, tpm2_ec_sign_fn, NULL, 0); + gnutls_privkey_import_ext(*pkey, GNUTLS_PK_EC, certinfo, tpm2_ec_sign_fn, NULL, 0); #endif break; } diff --git a/gnutls_tpm2_esys.c b/gnutls_tpm2_esys.c index 25819843..7b8a4417 100644 --- a/gnutls_tpm2_esys.c +++ b/gnutls_tpm2_esys.c @@ -352,16 +352,17 @@ static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *keyHandle, return -EIO; } -static int auth_tpm2_key(struct openconnect_info *vpninfo, ESYS_CONTEXT *ctx, ESYS_TR key_handle) +static int auth_tpm2_key(struct openconnect_info *vpninfo, struct cert_info *certinfo, + ESYS_CONTEXT *ctx, ESYS_TR key_handle) { TSS2_RC r; - if (vpninfo->tpm2->need_userauth || vpninfo->certinfo[0].password) { + if (vpninfo->tpm2->need_userauth || certinfo->password) { char *pass = NULL; - if (vpninfo->certinfo[0].password) { - pass = vpninfo->certinfo[0].password; - vpninfo->certinfo[0].password = NULL; + if (certinfo->password) { + pass = certinfo->password; + certinfo->password = NULL; } else { int err = request_passphrase(vpninfo, "openconnect_tpm2_key", &pass, _("Enter TPM2 key password:")); @@ -383,10 +384,11 @@ static int auth_tpm2_key(struct openconnect_info *vpninfo, ESYS_CONTEXT *ctx, ES } int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, - void *_vpninfo, unsigned int flags, + void *_certinfo, unsigned int flags, const gnutls_datum_t *data, gnutls_datum_t *sig) { - struct openconnect_info *vpninfo = _vpninfo; + struct cert_info *certinfo = _certinfo; + struct openconnect_info *vpninfo = certinfo->vpninfo; int ret = GNUTLS_E_PK_SIGN_FAILED; ESYS_CONTEXT *ectx = NULL; TPM2B_PUBLIC_KEY_RSA digest, *tsig = NULL; @@ -407,7 +409,7 @@ int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, if (init_tpm2_key(&ectx, &key_handle, vpninfo)) goto out; reauth: - if (auth_tpm2_key(vpninfo, ectx, key_handle)) + if (auth_tpm2_key(vpninfo, certinfo, ectx, key_handle)) goto out; r = Esys_RSA_Decrypt(ectx, key_handle, @@ -448,10 +450,11 @@ int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, } int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, - void *_vpninfo, unsigned int flags, + void *_certinfo, unsigned int flags, const gnutls_datum_t *data, gnutls_datum_t *sig) { - struct openconnect_info *vpninfo = _vpninfo; + struct cert_info *certinfo = _certinfo; + struct openconnect_info *vpninfo = certinfo->vpninfo; int ret = GNUTLS_E_PK_SIGN_FAILED; ESYS_CONTEXT *ectx = NULL; TPM2B_DIGEST digest; @@ -486,7 +489,7 @@ int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, if (init_tpm2_key(&ectx, &key_handle, vpninfo)) goto out; reauth: - if (auth_tpm2_key(vpninfo, ectx, key_handle)) + if (auth_tpm2_key(vpninfo, certinfo, ectx, key_handle)) goto out; r = Esys_Sign(ectx, key_handle, @@ -524,8 +527,10 @@ int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, return ret; } -int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, - unsigned int parent, int emptyauth, int legacy, gnutls_datum_t *privdata, gnutls_datum_t *pubdata) +int install_tpm2_key(struct openconnect_info *vpninfo, struct cert_info *certinfo, + gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, + unsigned int parent, int emptyauth, int legacy, + gnutls_datum_t *privdata, gnutls_datum_t *pubdata) { TSS2_RC r; diff --git a/gnutls_tpm2_ibm.c b/gnutls_tpm2_ibm.c index 3fe33b6c..2f9a693a 100644 --- a/gnutls_tpm2_ibm.c +++ b/gnutls_tpm2_ibm.c @@ -318,10 +318,11 @@ static void tpm2_unload_key(TSS_CONTEXT *tssContext, TPM_HANDLE key) } int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, - void *_vpninfo, unsigned int flags, + void *_certinfo, unsigned int flags, const gnutls_datum_t *data, gnutls_datum_t *sig) { - struct openconnect_info *vpninfo = _vpninfo; + struct cert_info *certinfo = _certinfo; + struct openconnect_info *vpninfo = certinfo->vpninfo; TSS_CONTEXT *tssContext = NULL; RSA_Decrypt_In in; RSA_Decrypt_Out out; @@ -386,10 +387,11 @@ int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, } int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, - void *_vpninfo, unsigned int flags, + void *_certinfo, unsigned int flags, const gnutls_datum_t *data, gnutls_datum_t *sig) { - struct openconnect_info *vpninfo = _vpninfo; + struct cert_info *certinfo = _certinfo; + struct openconnect_info *vpninfo = certinfo->vpninfo; TSS_CONTEXT *tssContext = NULL; Sign_In in; Sign_Out out; @@ -470,7 +472,8 @@ int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo, return ret; } -int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, +int install_tpm2_key(struct openconnect_info *vpninfo, struct cert_info *certinfo, + gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig, unsigned int parent, int emptyauth, int legacy, gnutls_datum_t *privdata, gnutls_datum_t *pubdata) { -- 2.50.1