]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Move non-TSS-specific code to gnutls_tpm2.c
authorDavid Woodhouse <dwmw2@infradead.org>
Tue, 9 Oct 2018 09:01:07 +0000 (10:01 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Thu, 11 Oct 2018 00:59:46 +0000 (17:59 -0700)
In preparation for potentially implementing a version using ibmtss.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
gnutls.h
gnutls_tpm2.c
gnutls_tpm2_esys.c

index 7e40707bc3423a92bb9b08b1d27fa0860b55dbfe..0e28ed9f95fdf1f37c9ab7cdc64e9f3d665a5fe7 100644 (file)
--- a/gnutls.h
+++ b/gnutls.h
@@ -34,6 +34,13 @@ 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,
                     unsigned int parent, int emptyauth, 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,
+                         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,
+                        const gnutls_datum_t *data, gnutls_datum_t *sig);
+
 /* 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
  * zero-padding bugs in that, and some of the... less diligently maintained
index 34b9f0cbac292ee8f5e0095b058fa53243eca11b..618fdd1819b4b6e76a87fac94a95dc4c9ba29800 100644 (file)
@@ -45,6 +45,90 @@ const asn1_static_node tpmkey_asn1_tab[] = {
   { NULL, 0, NULL }
 };
 
+#if GNUTLS_VERSION_NUMBER < 0x030600
+static int tpm2_rsa_sign_fn(gnutls_privkey_t key, void *_vpninfo,
+                           const gnutls_datum_t *data, gnutls_datum_t *sig)
+{
+       return tpm2_rsa_sign_hash_fn(key, GNUTLS_SIGN_UNKNOWN, _vpninfo, 0, data, sig);
+}
+
+
+static int tpm2_ec_sign_fn(gnutls_privkey_t key, void *_vpninfo,
+                          const gnutls_datum_t *data, gnutls_datum_t *sig)
+{
+       struct openconnect_info *vpninfo = _vpninfo;
+       gnutls_sign_algorithm_t algo;
+
+       switch (data->size) {
+       case 20: algo = GNUTLS_SIGN_ECDSA_SHA1; break;
+       case 32: algo = GNUTLS_SIGN_ECDSA_SHA256; break;
+       case 48: algo = GNUTLS_SIGN_ECDSA_SHA384; break;
+       case 64: algo = GNUTLS_SIGN_ECDSA_SHA512; break;
+       default:
+               vpn_progress(vpninfo, PRG_ERR,
+                            _("Unknown TPM2 EC digest size %d\n"),
+                            data->size);
+               return GNUTLS_E_PK_SIGN_FAILED;
+       }
+
+       return tpm2_ec_sign_hash_fn(key, algo, vpninfo, 0, data, sig);
+}
+#endif
+
+#if GNUTLS_VERSION_NUMBER >= 0x030600
+static int rsa_key_info(gnutls_privkey_t key, unsigned int flags, void *_vpninfo)
+{
+       if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO)
+               return GNUTLS_PK_RSA;
+
+       if (flags & GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO) {
+               gnutls_sign_algorithm_t algo = GNUTLS_FLAGS_TO_SIGN_ALGO(flags);
+               switch (algo) {
+               case GNUTLS_SIGN_RSA_RAW:
+               case GNUTLS_SIGN_RSA_SHA1:
+               case GNUTLS_SIGN_RSA_SHA256:
+               case GNUTLS_SIGN_RSA_SHA384:
+               case GNUTLS_SIGN_RSA_SHA512:
+                       return 1;
+
+               default:
+                       return 0;
+               }
+       }
+
+       if (flags & GNUTLS_PRIVKEY_INFO_SIGN_ALGO)
+               return GNUTLS_SIGN_RSA_RAW;
+
+       return -1;
+}
+#endif
+
+#if GNUTLS_VERSION_NUMBER >= 0x030400
+static int ec_key_info(gnutls_privkey_t key, unsigned int flags, void *_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) {
+               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;
+
+               default:
+                       return 0;
+               }
+       }
+#endif
+
+       if (flags & GNUTLS_PRIVKEY_INFO_SIGN_ALGO)
+               return GNUTLS_SIGN_ECDSA_SHA256;
+
+       return -1;
+}
+#endif
 
 static int decode_data(ASN1_TYPE n, gnutls_datum_t *r)
 {
@@ -159,6 +243,31 @@ 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, &privdata, &pubdata);
+       if (ret < 0)
+               goto out_tpmkey;
+
+       gnutls_privkey_init(pkey);
+
+       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);
+#else
+               gnutls_privkey_import_ext(*pkey, GNUTLS_PK_RSA, vpninfo, tpm2_rsa_sign_fn, NULL, 0);
+#endif
+               break;
+
+       case GNUTLS_PK_ECDSA:
+#if GNUTLS_VERSION_NUMBER >= 0x030600
+               gnutls_privkey_import_ext4(*pkey, vpninfo, 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);
+#else
+               gnutls_privkey_import_ext(*pkey, GNUTLS_PK_EC, vpninfo, tpm2_ec_sign_fn, NULL, 0);
+#endif
+               break;
+       }
+       ret = 0;
 
  out_tpmkey:
        asn1_delete_structure(&tpmkey);
index 438fea8659049692f5744ed6044069b772a1a160..677cd6ca35751609187126cfc67399d494ce4b9c 100644 (file)
@@ -312,10 +312,9 @@ static int auth_tpm2_key(struct openconnect_info *vpninfo, ESYS_CONTEXT *ctx, ES
 
 #define PKCS1_PAD_OVERHEAD 11
 
-/* Signing function for TPM privkeys, set with gnutls_privkey_import_ext() */
-static int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo,
-                                void *_vpninfo, unsigned int flags,
-                                const gnutls_datum_t *data, gnutls_datum_t *sig)
+int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo,
+                         void *_vpninfo, unsigned int flags,
+                         const gnutls_datum_t *data, gnutls_datum_t *sig)
 {
        struct openconnect_info *vpninfo = _vpninfo;
        int ret = GNUTLS_E_PK_SIGN_FAILED;
@@ -389,10 +388,9 @@ static int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t a
        return ret;
 }
 
-/* Signing function for TPM privkeys, set with gnutls_privkey_import_ext() */
-static int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo,
-                               void *_vpninfo, 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,
+                        const gnutls_datum_t *data, gnutls_datum_t *sig)
 {
        struct openconnect_info *vpninfo = _vpninfo;
        int ret = GNUTLS_E_PK_SIGN_FAILED;
@@ -467,91 +465,6 @@ static int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t al
        return ret;
 }
 
-#if GNUTLS_VERSION_NUMBER < 0x030600
-static int tpm2_rsa_sign_fn(gnutls_privkey_t key, void *_vpninfo,
-                           const gnutls_datum_t *data, gnutls_datum_t *sig)
-{
-       return tpm2_rsa_sign_hash_fn(key, GNUTLS_SIGN_UNKNOWN, _vpninfo, 0, data, sig);
-}
-
-
-static int tpm2_ec_sign_fn(gnutls_privkey_t key, void *_vpninfo,
-                          const gnutls_datum_t *data, gnutls_datum_t *sig)
-{
-       struct openconnect_info *vpninfo = _vpninfo;
-       gnutls_sign_algorithm_t algo;
-
-       switch (data->size) {
-       case 20: algo = GNUTLS_SIGN_ECDSA_SHA1; break;
-       case 32: algo = GNUTLS_SIGN_ECDSA_SHA256; break;
-       case 48: algo = GNUTLS_SIGN_ECDSA_SHA384; break;
-       case 64: algo = GNUTLS_SIGN_ECDSA_SHA512; break;
-       default:
-               vpn_progress(vpninfo, PRG_ERR,
-                            _("Unknown TPM2 EC digest size %d\n"),
-                            data->size);
-               return GNUTLS_E_PK_SIGN_FAILED;
-       }
-
-       return tpm2_ec_sign_hash_fn(key, algo, vpninfo, 0, data, sig);
-}
-#endif
-
-#if GNUTLS_VERSION_NUMBER >= 0x030600
-static int rsa_key_info(gnutls_privkey_t key, unsigned int flags, void *_vpninfo)
-{
-       if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO)
-               return GNUTLS_PK_RSA;
-
-       if (flags & GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO) {
-               gnutls_sign_algorithm_t algo = GNUTLS_FLAGS_TO_SIGN_ALGO(flags);
-               switch (algo) {
-               case GNUTLS_SIGN_RSA_RAW:
-               case GNUTLS_SIGN_RSA_SHA1:
-               case GNUTLS_SIGN_RSA_SHA256:
-               case GNUTLS_SIGN_RSA_SHA384:
-               case GNUTLS_SIGN_RSA_SHA512:
-                       return 1;
-
-               default:
-                       return 0;
-               }
-       }
-
-       if (flags & GNUTLS_PRIVKEY_INFO_SIGN_ALGO)
-               return GNUTLS_SIGN_RSA_RAW;
-
-       return -1;
-}
-#endif
-
-#if GNUTLS_VERSION_NUMBER >= 0x030400
-static int ec_key_info(gnutls_privkey_t key, unsigned int flags, void *_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) {
-               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;
-
-               default:
-                       return 0;
-               }
-       }
-#endif
-
-       if (flags & GNUTLS_PRIVKEY_INFO_SIGN_ALGO)
-               return GNUTLS_SIGN_ECDSA_SHA256;
-
-       return -1;
-}
-#endif
-
 int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig,
                     unsigned int parent, int emptyauth, gnutls_datum_t *privdata, gnutls_datum_t *pubdata)
 {
@@ -574,9 +487,7 @@ int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, g
                vpn_progress(vpninfo, PRG_ERR,
                             _("Failed to import TPM2 private key data: 0x%x\n"),
                             r);
-       err_out:
-               release_tpm2_ctx(vpninfo);
-               return -EINVAL;
+               goto err_out;
        }
 
        r = Tss2_MU_TPM2B_PUBLIC_Unmarshal(pubdata->data, pubdata->size, NULL,
@@ -590,37 +501,17 @@ int install_tpm2_key(struct openconnect_info *vpninfo, gnutls_privkey_t *pkey, g
 
        vpninfo->tpm2->need_userauth = !emptyauth;
 
-       gnutls_privkey_init(pkey);
-
        switch(vpninfo->tpm2->pub.publicArea.type) {
-       case TPM2_ALG_RSA:
-#if GNUTLS_VERSION_NUMBER >= 0x030600
-               gnutls_privkey_import_ext4(*pkey, vpninfo, 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);
-#endif
-               break;
-
-       case TPM2_ALG_ECC:
-#if GNUTLS_VERSION_NUMBER >= 0x030600
-               gnutls_privkey_import_ext4(*pkey, vpninfo, 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);
-#else
-               gnutls_privkey_import_ext(*pkey, GNUTLS_PK_EC, vpninfo, tpm2_ec_sign_fn, NULL, 0);
-#endif
-               break;
-
-       default:
-               vpn_progress(vpninfo, PRG_ERR,
-                            _("Unsupported TPM2 key type %d\n"),
-                            vpninfo->tpm2->pub.publicArea.type);
-               gnutls_privkey_deinit(*pkey);
-               *pkey = NULL;
-               goto err_out;
+       case TPM2_ALG_RSA: return GNUTLS_PK_RSA;
+       case TPM2_ALG_ECC: return GNUTLS_PK_ECDSA;
        }
 
-       return 0;
+       vpn_progress(vpninfo, PRG_ERR,
+                    _("Unsupported TPM2 key type %d\n"),
+                    vpninfo->tpm2->pub.publicArea.type);
+ err_out:
+       release_tpm2_ctx(vpninfo);
+       return -EINVAL;
 }