]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added tpmtool.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 6 Jul 2012 20:27:38 +0000 (22:27 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 6 Jul 2012 20:30:33 +0000 (22:30 +0200)
It is a tool to generate TPM private keys. In addition
gnutls_tpm_privkey_generate() was added.

15 files changed:
NEWS
lib/gnutls_errors.c
lib/includes/Makefile.am
lib/includes/gnutls/gnutls.h.in
lib/includes/gnutls/tpm.h [new file with mode: 0644]
lib/libgnutls.map
lib/pkcs11_privkey.c
lib/tpm.c
lib/x509/common.c
lib/x509/common.h
src/Makefile.am
src/tpmtool-args.c [new file with mode: 0644]
src/tpmtool-args.def [new file with mode: 0644]
src/tpmtool-args.h [new file with mode: 0644]
src/tpmtool.c [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 20e8886854c52c87de8ef1ee0bb9bd7b691d761f..04e8a727653f63b0e3fa0efc8a6590cb8a3379bd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ See the end for copying conditions.
 
 * Version 3.1.0 (unreleased)
 
+** tpmtool: Added. It is a tool to generate private keys in the
+TPM.
+
 ** gnutls-cli: --benchmark-tls was split to --benchmark-tls-kx
 and --benchmark-tls-ciphers
 
@@ -49,6 +52,7 @@ gnutls_privkey_import_pkcs11_url: Added
 gnutls_privkey_import_openpgp_raw: Added
 gnutls_privkey_import_x509_raw: Added
 gnutls_privkey_import_ext2: Added
+gnutls_tpm_privkey_generate: Added
 gnutls_x509_privkey_import2: Added
 gnutls_x509_privkey_import_openssl: Added
 gnutls_load_file: Added
index ec90423dfa53b99f38313b5bd4c38e2b1e31dce7..83e78db669e9b407f5b6f579f15aeabceac0cffb 100644 (file)
@@ -296,10 +296,10 @@ static const gnutls_error_entry error_algorithms[] = {
                GNUTLS_E_PARSING_ERROR, 1),
   ERROR_ENTRY (N_("Error in provided PIN."),
                GNUTLS_E_PKCS11_PIN_ERROR, 1),
-  ERROR_ENTRY (N_("Error in provided password for TPM."),
-               GNUTLS_E_TPM_PASSWORD_ERROR, 1),
-  ERROR_ENTRY (N_("Error in provided password for key to be loaded in TPM."),
+  ERROR_ENTRY (N_("Error in provided SRK password for TPM."),
                GNUTLS_E_TPM_SRK_PASSWORD_ERROR, 1),
+  ERROR_ENTRY (N_("Error in provided password for key to be loaded in TPM."),
+               GNUTLS_E_TPM_KEY_PASSWORD_ERROR, 1),
   ERROR_ENTRY (N_("PKCS #11 error in slot"),
                GNUTLS_E_PKCS11_SLOT_ERROR, 1),
   ERROR_ENTRY (N_("Thread locking error"),
index 31650c1c3e1cb50b31a8d32adb82b850c3e7e2e8..bf32cdb4c8478ea5114e362910d3f102fdc20abd 100644 (file)
@@ -20,7 +20,7 @@
 
 nobase_include_HEADERS = gnutls/x509.h gnutls/pkcs12.h gnutls/compat.h \
        gnutls/openpgp.h gnutls/crypto.h gnutls/pkcs11.h                \
-       gnutls/abstract.h gnutls/dtls.h gnutls/ocsp.h
+       gnutls/abstract.h gnutls/dtls.h gnutls/ocsp.h gnutls/tpm.h
 
 if ENABLE_CXX
 nobase_include_HEADERS += gnutls/gnutlsxx.h
index c729ae046dc54543b84b9802f4ac623e32315117..35c9367f376ca2f7bc0fde9ac587ddf3283bdc85 100644 (file)
@@ -1915,7 +1915,7 @@ int gnutls_load_file(const char* filename, gnutls_datum_t * data);
 #define GNUTLS_E_SESSION_EOF -328
 
 #define GNUTLS_E_TPM_ERROR -329
-#define GNUTLS_E_TPM_PASSWORD_ERROR -330
+#define GNUTLS_E_TPM_KEY_PASSWORD_ERROR -330
 #define GNUTLS_E_TPM_SRK_PASSWORD_ERROR -331
 
 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
diff --git a/lib/includes/gnutls/tpm.h b/lib/includes/gnutls/tpm.h
new file mode 100644 (file)
index 0000000..9eb3c92
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010-2012 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef __GNUTLS_TPM_H
+#define __GNUTLS_TPM_H
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define GNUTLS_TPM_SIG_PKCS1V15 1
+#define GNUTLS_TPM_SIG_PKCS1V15_SHA1 2
+
+int
+gnutls_tpm_privkey_generate (gnutls_pk_algorithm_t pk, unsigned int bits, 
+                             const char* srk_password,
+                             const char* key_password,
+                             gnutls_x509_crt_fmt_t format,
+                             gnutls_datum_t* privkey, 
+                             gnutls_datum_t* pubkey,
+                             unsigned int flags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index cf7a7dc6081c687cf9474203e3f7a41526a36d6e..54034150dd6662ebefeccc04187ed9a585c72d96 100644 (file)
@@ -807,6 +807,7 @@ GNUTLS_3_1_0 {
        gnutls_x509_privkey_import2;
        gnutls_privkey_import_ext2;
        gnutls_privkey_import_tpm_raw;
+        gnutls_tpm_privkey_generate;
 } GNUTLS_3_0_0;
 
 GNUTLS_PRIVATE {
index 487230cdcff0af3728ba0e9d403bed9a8c490c24..1cc4d18c6b809def61e98a51a590ca35955e3c95 100644 (file)
@@ -451,7 +451,7 @@ gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key,
  * @flags: should be zero
  *
  * This function will generate a private key in the specified
- * by the @url token. The pivate key will be generate within
+ * by the @url token. The private key will be generate within
  * the token and will not be exportable.
  *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
index 366b56015820f6ccfc29f6fc123c5cb0184b6f6b..221836414b9c70fb52dfda225a921793eb7b95f5 100644 (file)
--- a/lib/tpm.c
+++ b/lib/tpm.c
 
 #include <gnutls/gnutls.h>
 #include <gnutls/abstract.h>
+#include <gnutls/tpm.h>
 
 #include <gnutls_int.h>
 #include <gnutls_errors.h>
 #include <pkcs11_int.h>
 #include <x509/common.h>
+#include <x509_b64.h>
 
 #include <trousers/tss.h>
 #include <trousers/trousers.h>
@@ -108,20 +110,21 @@ tpm_sign_fn (gnutls_privkey_t key, void *_s,
   return 0;
 }
 
+static const unsigned char nullpass[20];
 
 /**
  * gnutls_privkey_import_tpm_raw:
  * @pkey: The private key
  * @fdata: The TPM key to be imported
  * @format: The format of the private key
- * @srk_password: A password for the key (optional)
- * @tpm_password: A password for the TPM (optional)
+ * @srk_password: The password for the SRK key (optional)
+ * @key_password: A password for the key (optional)
  *
  * This function will import the given private key to the abstract
  * #gnutls_privkey_t structure. If a password is needed to decrypt
  * the provided key or the provided password is wrong, then 
  * %GNUTLS_E_TPM_SRK_PASSWORD_ERROR is returned. If the TPM password
- * is wrong or not provided then %GNUTLS_E_TPM_PASSWORD_ERROR
+ * is wrong or not provided then %GNUTLS_E_TPM_KEY_PASSWORD_ERROR
  * is returned. 
  *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
@@ -135,7 +138,7 @@ gnutls_privkey_import_tpm_raw (gnutls_privkey_t pkey,
                               const gnutls_datum_t * fdata,
                               gnutls_x509_crt_fmt_t format,
                               const char *srk_password,
-                              const char *tpm_password)
+                              const char *key_password)
 {
   static const TSS_UUID SRK_UUID = TSS_UUID_SRK;
   gnutls_datum_t asn1;
@@ -143,7 +146,6 @@ gnutls_privkey_import_tpm_raw (gnutls_privkey_t pkey,
   int err, ret;
   struct tpm_ctx_st *s;
   gnutls_datum_t tmp_sig;
-  static const char nullpass[20];
 
   ret = gnutls_pem_base64_decode_alloc ("TSS KEY BLOB", fdata, &asn1);
   if (ret)
@@ -263,7 +265,6 @@ gnutls_privkey_import_tpm_raw (gnutls_privkey_t pkey,
       goto out_srkpol;
     }
 
-retry_sign:
   ret =
       gnutls_privkey_sign_data (pkey, GNUTLS_DIG_SHA1, 0, fdata, &tmp_sig);
   if (ret == GNUTLS_E_INSUFFICIENT_CREDENTIALS)
@@ -283,6 +284,7 @@ retry_sign:
              ret = GNUTLS_E_TPM_ERROR;
              goto out_key;
            }
+
          err = Tspi_Policy_AssignToObject (s->tpm_key_policy, s->tpm_key);
          if (err)
            {
@@ -296,17 +298,16 @@ retry_sign:
 
       err = Tspi_Policy_SetSecret (s->tpm_key_policy,
                                   TSS_SECRET_MODE_PLAIN,
-                                  strlen (tpm_password), (void *) tpm_password);
+                                  strlen (key_password), (void *) key_password);
 
       if (err)
        {
          gnutls_assert ();
          _gnutls_debug_log ("Failed to set key PIN: %s\n",
                             Trspi_Error_String (err));
-          ret = GNUTLS_E_TPM_PASSWORD_ERROR;
+          ret = GNUTLS_E_TPM_KEY_PASSWORD_ERROR;
          goto out_key_policy;
        }
-      goto retry_sign;
     }
   else if (ret < 0)
     {
@@ -338,3 +339,291 @@ out_blob:
   return ret;
 }
 
+const TSS_UUID srk_uuid = TSS_UUID_SRK;
+
+/**
+ * gnutls_tpm_privkey_generate:
+ * @pk: the public key algorithm
+ * @bits: the security bits
+ * @srk_password: a password to protect the exported key (optional)
+ * @key_password: the password for the TPM (optional)
+ * @privkey: the generated key
+ * @pubkey: the corresponding public key
+ * @flags: should be a list of %GNUTLS_TPM flags
+ *
+ * This function will generate a private key in the TPM
+ * chip. The private key will be generated within the chip
+ * and will be exported in a wrapped with TPM's master key
+ * form. Furthermore the wrapped key can be protected with
+ * the provided @password.
+ *
+ * Allowed flags are %GNUTLS_TPM_SIG_PKCS1V15 and %GNUTLS_TPM_SIG_PKCS1V15_SHA1.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ * Since: 3.1.0
+ **/
+int
+gnutls_tpm_privkey_generate (gnutls_pk_algorithm_t pk, unsigned int bits, 
+                             const char* srk_password,
+                             const char* key_password,
+                             gnutls_x509_crt_fmt_t format,
+                             gnutls_datum_t* privkey, 
+                             gnutls_datum_t* pubkey,
+                             unsigned int flags)
+{
+TSS_HCONTEXT ctx;
+TSS_FLAG tpm_flags = TSS_KEY_TYPE_LEGACY | TSS_KEY_VOLATILE;
+TSS_HKEY key_ctx; 
+TSS_HKEY srk_ctx;
+TSS_RESULT tssret;
+int ret;
+void* tdata;
+UINT32 tint;
+gnutls_datum_t tmpkey;
+TSS_HPOLICY srk_policy, key_policy;
+unsigned int sig;
+gnutls_pubkey_t pub;
+
+  switch(bits) {
+    case 512:
+      tpm_flags |= TSS_KEY_SIZE_512;
+      break;
+    case 1024:
+      tpm_flags |= TSS_KEY_SIZE_1024;
+      break;
+    case 2048:
+      tpm_flags |= TSS_KEY_SIZE_2048;
+      break;
+    case 4096:
+      tpm_flags |= TSS_KEY_SIZE_4096;
+      break;
+    case 8192:
+      tpm_flags |= TSS_KEY_SIZE_8192;
+      break;
+    case 16384:
+      tpm_flags |= TSS_KEY_SIZE_16384;
+      break;
+    default:
+      return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+  }
+  
+  tssret = Tspi_Context_Create(&ctx);
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      return GNUTLS_E_TPM_ERROR;
+    }
+    
+  tssret = Tspi_Context_Connect(ctx, NULL);
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      ret = GNUTLS_E_TPM_ERROR;
+      goto err_cc;
+    }
+
+  tssret = Tspi_Context_CreateObject(ctx, TSS_OBJECT_TYPE_RSAKEY, tpm_flags, &key_ctx);
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      ret = GNUTLS_E_TPM_ERROR;
+      goto err_cc;
+    }
+    
+  if (flags & GNUTLS_TPM_SIG_PKCS1V15_SHA1)
+    sig = TSS_SS_RSASSAPKCS1V15_SHA1;
+  else
+    sig = TSS_SS_RSASSAPKCS1V15_DER;
+
+  tssret = Tspi_SetAttribUint32(key_ctx, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
+                                sig);
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      ret = GNUTLS_E_TPM_ERROR;
+      goto err_sa;
+    }
+  
+  tssret = Tspi_Context_LoadKeyByUUID(ctx, TSS_PS_TYPE_SYSTEM, srk_uuid,
+                                   &srk_ctx);
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      ret = GNUTLS_E_TPM_ERROR;
+      goto err_sa;
+    }
+
+  /* set SRK key */
+  tssret = Tspi_GetPolicyObject(srk_ctx, TSS_POLICY_USAGE, &srk_policy);
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      ret = GNUTLS_E_TPM_ERROR;
+      goto err_sa;
+    }
+
+  if (srk_password == NULL)
+    {
+      tssret = Tspi_Policy_SetSecret(srk_policy, TSS_SECRET_MODE_SHA1,
+                                     20, (void*)nullpass);
+    }
+  else
+    {
+      tssret = Tspi_Policy_SetSecret(srk_policy, TSS_SECRET_MODE_PLAIN,
+                                     strlen(srk_password), (void*)srk_password);
+    }
+  
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      ret = GNUTLS_E_TPM_SRK_PASSWORD_ERROR;
+      goto err_sa;
+    }
+    
+  /* set the key of the actual key */
+  if (key_password)
+    {
+      tssret = Tspi_GetPolicyObject(key_ctx, TSS_POLICY_USAGE, &key_policy);
+      if (tssret != 0)
+        {
+          gnutls_assert();
+          ret = GNUTLS_E_TPM_ERROR;
+          goto err_sa;
+        }
+
+      tssret = Tspi_Policy_SetSecret(key_policy, TSS_SECRET_MODE_PLAIN, 
+                                     strlen(key_password), (void*)key_password);
+      if (tssret != 0)
+        {
+          gnutls_assert();
+          ret = GNUTLS_E_TPM_ERROR;
+          goto err_sa;
+        }
+    }
+
+  tssret = Tspi_Key_CreateKey(key_ctx, srk_ctx, 0);
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      if (tssret == TPM_E_AUTHFAIL)
+        ret = GNUTLS_E_TPM_SRK_PASSWORD_ERROR;
+      else
+        ret = GNUTLS_E_TPM_ERROR;
+      goto err_sa;
+    }
+
+  tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_KEY_BLOB,
+                              TSS_TSPATTRIB_KEYBLOB_BLOB, &tint, (void*)&tdata);
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      ret = GNUTLS_E_TPM_ERROR;
+      goto err_sa;
+    }
+
+  ret = _gnutls_x509_encode_octet_string(tdata, tint, &tmpkey);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+  
+  if (format == GNUTLS_X509_FMT_PEM)
+    {
+      ret = _gnutls_fbase64_encode ("TSS KEY BLOB", tmpkey.data, tmpkey.size, &privkey->data);
+      if (ret < 0)
+        {
+          gnutls_assert();
+          goto cleanup;
+        }
+      privkey->size = ret;
+    }
+  else
+    {
+      privkey->data = tmpkey.data;
+      privkey->size = tmpkey.size;
+      tmpkey.data = NULL;
+    }
+
+  {
+    gnutls_datum_t m, e;
+    size_t psize;
+
+    ret = gnutls_pubkey_init(&pub);
+    if (ret < 0)
+      {
+        gnutls_assert();
+        goto privkey_cleanup;
+      }
+    
+    tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
+                                TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &tint, (void*)&tdata);
+    if (tssret != 0)
+      {
+        gnutls_assert();
+        ret = GNUTLS_E_TPM_ERROR;
+        goto pubkey_cleanup;
+      }
+    
+    m.data = tdata;
+    m.size = tint;
+
+    tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
+                                TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT, &tint, (void*)&tdata);
+    if (tssret != 0)
+      {
+        gnutls_assert();
+        Tspi_Context_FreeMemory(key_ctx, m.data);
+        ret = GNUTLS_E_TPM_ERROR;
+        goto pubkey_cleanup;
+      }
+    
+    e.data = tdata;
+    e.size = tint;
+    
+    ret = gnutls_pubkey_import_rsa_raw(pub, &m, &e);
+    if (ret < 0)
+      {
+        gnutls_assert();
+        goto pubkey_cleanup;
+      }
+    
+    psize = e.size+m.size+512;
+    pubkey->data = gnutls_malloc(psize);
+    if (pubkey->data == NULL)
+      {
+        gnutls_assert();
+        ret = GNUTLS_E_MEMORY_ERROR;
+        goto pubkey_cleanup;
+      }
+    
+    ret = gnutls_pubkey_export(pub, format, pubkey->data, &psize);
+    if (ret < 0)
+      {
+        gnutls_assert();
+        goto pubkey_cleanup;
+      }
+    pubkey->size = psize;
+
+    gnutls_pubkey_deinit(pub);
+  }
+
+  ret = 0;
+  goto cleanup;
+  
+pubkey_cleanup:
+  gnutls_pubkey_deinit(pub);
+privkey_cleanup:
+  gnutls_free(privkey->data);
+  privkey->data = NULL;
+cleanup:  
+  gnutls_free(tmpkey.data);
+  tmpkey.data = NULL;
+err_sa:
+  Tspi_Context_CloseObject(ctx, key_ctx);
+err_cc:
+  Tspi_Context_Close(ctx);
+  return ret;
+}
index 052eb7cd732fcd75210300daf83ab1c19f378bbc..2e4ff2e500fb06f7b9a84df6094c174247123c3c 100644 (file)
@@ -996,6 +996,42 @@ cleanup:
 
 }
 
+int _gnutls_x509_encode_octet_string(const void* input_data, size_t input_size,
+                                     gnutls_datum_t* output)
+{
+  int ret;
+  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+
+  if ((ret = asn1_create_element
+       (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+
+  ret = asn1_write_value (c2, "", input_data, input_size);
+  if (ret != ASN1_SUCCESS)
+    {
+      gnutls_assert ();
+      ret = _gnutls_asn2err (ret);
+      goto cleanup;
+    }
+
+  ret = _gnutls_x509_der_encode(c2, "", output, 0);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  ret = 0;
+
+cleanup:
+  asn1_delete_structure (&c2);
+  return ret;
+}
+
 /* DER Encodes the src ASN1_TYPE and stores it to
  * the given datum. If str is non zero then the data are encoded as
  * an OCTET STRING.
index 1d7116ccb6e51c72181298f96b01af87fbf9f83d..e48e0f88e53d33fe0e338a169dc40842295c26be 100644 (file)
@@ -71,6 +71,9 @@ int _gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim, int gene
 int _gnutls_x509_decode_octet_string (const char *string_type,
                                       const uint8_t * der, size_t der_size,
                                       uint8_t * output, size_t * output_size);
+int _gnutls_x509_encode_octet_string(const void* input_data, size_t input_size,
+                                     gnutls_datum_t* output);
+
 int _gnutls_x509_oid_data2string (const char *OID, void *value,
                                   int value_size, char *res,
                                   size_t * res_size);
index 48f32861ad8d06ec644e887f294051d8c9743baa..cf775c3944585416ee66a2b8ee5089f517707cb2 100644 (file)
@@ -46,6 +46,10 @@ if ENABLE_OCSP
 bin_PROGRAMS += ocsptool
 endif
 
+if ENABLE_TROUSERS
+bin_PROGRAMS += tpmtool
+endif
+
 if ENABLE_PKCS11
 bin_PROGRAMS += p11tool
 PKCS11_SRCS = p11common.c p11common.h
@@ -150,11 +154,29 @@ libcmd_p11tool_la_LIBADD += ../gl/libgnu.la $(INET_PTON_LIB)
 
 endif # ENABLE_PKCS11
 
+if ENABLE_TROUSERS
+
+tpmtool_SOURCES = tpmtool-args.def tpmtool.c certtool-common.c certtool-extras.c
+tpmtool_LDADD = ../lib/libgnutls.la $(LIBOPTS_LDADD) $(LTLIBINTL)
+tpmtool_LDADD += libcmd-tpmtool.la ../gl/libgnu.la
+
+noinst_LTLIBRARIES += libcmd-tpmtool.la
+libcmd_tpmtool_la_CFLAGS =
+libcmd_tpmtool_la_SOURCES = tpmtool-args.def tpmtool-args.c tpmtool-args.h \
+       certtool-cfg.h certtool-cfg.c
+libcmd_tpmtool_la_LIBADD = ../gl/libgnu.la $(LTLIBREADLINE)
+libcmd_tpmtool_la_LIBADD += ../lib/libgnutls.la
+libcmd_tpmtool_la_LIBADD += ../gl/libgnu.la $(INET_PTON_LIB)
+
+endif # ENABLE_TROUSERS
+
 BUILT_SOURCES = ocsptool-args.c p11tool-args.c psk-args.c cli-debug-args.c \
                cli-args.c serv-args.c srptool-args.c certtool-args.c
 
 ocsptool-args.c: $(srcdir)/args-std.def $(srcdir)/ocsptool-args.def
        -autogen ocsptool-args.def
+tpmtool-args.c: $(srcdir)/args-std.def $(srcdir)/tpmtool-args.def
+       -autogen tpmtool-args.def
 p11tool-args.c: $(srcdir)/args-std.def $(srcdir)/p11tool-args.def
        -autogen p11tool-args.def
 psk-args.c: $(srcdir)/args-std.def $(srcdir)/psk-args.def
diff --git a/src/tpmtool-args.c b/src/tpmtool-args.c
new file mode 100644 (file)
index 0000000..8e77bb4
--- /dev/null
@@ -0,0 +1,531 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (tpmtool-args.c)
+ *  
+ *  It has been AutoGen-ed  July  6, 2012 at 09:41:37 PM by AutoGen 5.16
+ *  From the definitions    tpmtool-args.def
+ *  and the template file   options
+ *
+ * Generated from AutoOpts 36:4:11 templates.
+ *
+ *  AutoOpts is a copyrighted work.  This source file is not encumbered
+ *  by AutoOpts licensing, but is provided under the licensing terms chosen
+ *  by the tpmtool author or copyright holder.  AutoOpts is
+ *  licensed under the terms of the LGPL.  The redistributable library
+ *  (``libopts'') is licensed under the terms of either the LGPL or, at the
+ *  users discretion, the BSD license.  See the AutoOpts and/or libopts sources
+ *  for details.
+ *
+ * The tpmtool program is copyrighted and licensed
+ * under the following terms:
+ *
+ *  Copyright (C) 2000-2012 Free Software Foundation, all rights reserved.
+ *  This is free software. It is licensed for use, modification and
+ *  redistribution under the terms of the
+ *  GNU General Public License, version 3 or later
+ *      <http://gnu.org/licenses/gpl.html>
+ *
+ *  tpmtool is free software: you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  tpmtool is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *  See the GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __doxygen__
+#define OPTION_CODE_COMPILE 1
+#include "tpmtool-args.h"
+#include <sys/types.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+extern FILE * option_usage_fp;
+
+/* TRANSLATORS: choose the translation for option names wisely because you
+                cannot ever change your mind. */
+#define zCopyright      (tpmtool_opt_strs+0)
+#define zLicenseDescrip (tpmtool_opt_strs+278)
+
+
+#ifndef NULL
+#  define NULL 0
+#endif
+
+/*
+ *  tpmtool option static const strings
+ */
+static char const tpmtool_opt_strs[1489] =
+/*     0 */ "tpmtool @VERSION@\n"
+            "Copyright (C) 2000-2012 Free Software Foundation, all rights reserved.\n"
+            "This is free software. It is licensed for use, modification and\n"
+            "redistribution under the terms of the\n"
+            "GNU General Public License, version 3 or later\n"
+            "    <http://gnu.org/licenses/gpl.html>\n\0"
+/*   278 */ "tpmtool is free software: you can redistribute it and/or modify it under\n"
+            "the terms of the GNU General Public License as published by the Free\n"
+            "Software Foundation, either version 3 of the License, or (at your option)\n"
+            "any later version.\n\n"
+            "tpmtool is distributed in the hope that it will be useful, but WITHOUT ANY\n"
+            "WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n"
+            "FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n"
+            "details.\n\n"
+            "You should have received a copy of the GNU General Public License along\n"
+            "with this program.  If not, see <http://www.gnu.org/licenses/>.\n\0"
+/*   881 */ "Enable debugging.\0"
+/*   899 */ "DEBUG\0"
+/*   905 */ "debug\0"
+/*   911 */ "Output file\0"
+/*   923 */ "OUTFILE\0"
+/*   931 */ "outfile\0"
+/*   939 */ "Generate an RSA private-public key pair\0"
+/*   979 */ "GENERATE_RSA\0"
+/*   992 */ "generate-rsa\0"
+/*  1005 */ "Specify the number of bits for key generate\0"
+/*  1049 */ "BITS\0"
+/*  1054 */ "bits\0"
+/*  1059 */ "Display extended usage information and exit\0"
+/*  1103 */ "help\0"
+/*  1108 */ "Extended usage information passed thru pager\0"
+/*  1153 */ "more-help\0"
+/*  1163 */ "Output version information and exit\0"
+/*  1199 */ "version\0"
+/*  1207 */ "TPMTOOL\0"
+/*  1215 */ "tpmtool - GnuTLS TPM tool - Ver. @VERSION@\n"
+            "USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n\0"
+/*  1316 */ "bug-gnutls@gnu.org\0"
+/*  1335 */ "\n\n\0"
+/*  1338 */ "\n"
+            "Program that allows handling cryptographic data from the TPM chip.\n\0"
+/*  1407 */ "tpmtool @VERSION@\0"
+/*  1425 */ "tpmtool [options] [url]\n"
+            "tpmtool --help for usage instructions.\n";
+
+/*
+ *  debug option description:
+ */
+#define DEBUG_DESC      (tpmtool_opt_strs+881)
+#define DEBUG_NAME      (tpmtool_opt_strs+899)
+#define DEBUG_name      (tpmtool_opt_strs+905)
+#define DEBUG_FLAGS     (OPTST_DISABLED \
+        | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ *  outfile option description:
+ */
+#define OUTFILE_DESC      (tpmtool_opt_strs+911)
+#define OUTFILE_NAME      (tpmtool_opt_strs+923)
+#define OUTFILE_name      (tpmtool_opt_strs+931)
+#define OUTFILE_FLAGS     (OPTST_DISABLED \
+        | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  generate-rsa option description:
+ */
+#define GENERATE_RSA_DESC      (tpmtool_opt_strs+939)
+#define GENERATE_RSA_NAME      (tpmtool_opt_strs+979)
+#define GENERATE_RSA_name      (tpmtool_opt_strs+992)
+#define GENERATE_RSA_FLAGS     (OPTST_DISABLED)
+
+/*
+ *  bits option description:
+ */
+#define BITS_DESC      (tpmtool_opt_strs+1005)
+#define BITS_NAME      (tpmtool_opt_strs+1049)
+#define BITS_name      (tpmtool_opt_strs+1054)
+#define BITS_FLAGS     (OPTST_DISABLED \
+        | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+#define HELP_DESC       (tpmtool_opt_strs+1059)
+#define HELP_name       (tpmtool_opt_strs+1103)
+#ifdef HAVE_WORKING_FORK
+#define MORE_HELP_DESC  (tpmtool_opt_strs+1108)
+#define MORE_HELP_name  (tpmtool_opt_strs+1153)
+#define MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT)
+#else
+#define MORE_HELP_DESC  NULL
+#define MORE_HELP_name  NULL
+#define MORE_HELP_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#endif
+#ifdef NO_OPTIONAL_OPT_ARGS
+#  define VER_FLAGS     (OPTST_IMM | OPTST_NO_INIT)
+#else
+#  define VER_FLAGS     (OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
+                         OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT)
+#endif
+#define VER_DESC        (tpmtool_opt_strs+1163)
+#define VER_name        (tpmtool_opt_strs+1199)
+/*
+ *  Declare option callback procedures
+ */
+extern tOptProc
+    optionBooleanVal,   optionNestedVal,    optionNumericVal,
+    optionPagedUsage,   optionPrintVersion, optionResetOpt,
+    optionStackArg,     optionTimeDate,     optionTimeVal,
+    optionUnstackArg,   optionVendorOption;
+static tOptProc
+    doOptDebug, doUsageOpt;
+#define VER_PROC        optionPrintVersion
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/**
+ *  Define the tpmtool Option Descriptions.
+ * This is an array of OPTION_CT entries, one for each
+ * option that the tpmtool program responds to.
+ */
+static tOptDesc optDesc[OPTION_CT] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_DEBUG,
+     /* equiv idx, value */ 0, VALUE_OPT_DEBUG,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ DEBUG_FLAGS, 0,
+     /* last opt argumnt */ { NULL }, /* --debug */
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doOptDebug,
+     /* desc, NAME, name */ DEBUG_DESC, DEBUG_NAME, DEBUG_name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_OUTFILE,
+     /* equiv idx, value */ 1, VALUE_OPT_OUTFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OUTFILE_FLAGS, 0,
+     /* last opt argumnt */ { NULL }, /* --outfile */
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ OUTFILE_DESC, OUTFILE_NAME, OUTFILE_name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 2, VALUE_OPT_GENERATE_RSA,
+     /* equiv idx, value */ 2, VALUE_OPT_GENERATE_RSA,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ GENERATE_RSA_FLAGS, 0,
+     /* last opt argumnt */ { NULL }, /* --generate-rsa */
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ GENERATE_RSA_DESC, GENERATE_RSA_NAME, GENERATE_RSA_name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 3, VALUE_OPT_BITS,
+     /* equiv idx, value */ 3, VALUE_OPT_BITS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ BITS_FLAGS, 0,
+     /* last opt argumnt */ { NULL }, /* --bits */
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionNumericVal,
+     /* desc, NAME, name */ BITS_DESC, BITS_NAME, BITS_name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, VALUE_OPT_VERSION,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ VER_FLAGS, 0,
+     /* last opt argumnt */ { NULL },
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ VER_PROC,
+     /* desc, NAME, name */ VER_DESC, NULL, VER_name,
+     /* disablement strs */ NULL, NULL },
+
+
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, VALUE_OPT_HELP,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM | OPTST_NO_INIT, 0,
+     /* last opt argumnt */ { NULL },
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ HELP_DESC, NULL, HELP_name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, VALUE_OPT_MORE_HELP,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ MORE_HELP_FLAGS, 0,
+     /* last opt argumnt */ { NULL },
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ MORE_HELP_DESC, NULL, MORE_HELP_name,
+     /* disablement strs */ NULL, NULL }
+};
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the tpmtool Option Environment
+ */
+#define zPROGNAME       (tpmtool_opt_strs+1207)
+#define zUsageTitle     (tpmtool_opt_strs+1215)
+#define zRcName         NULL
+#define apzHomeList     NULL
+#define zBugsAddr       (tpmtool_opt_strs+1316)
+#define zExplain        (tpmtool_opt_strs+1335)
+#define zDetail         (tpmtool_opt_strs+1338)
+#define zFullVersion    (tpmtool_opt_strs+1407)
+/* extracted from optcode.tlib near line 350 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE | OPTPROC_NXLAT_OPT
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+
+#define tpmtool_full_usage (NULL)
+
+#define tpmtool_short_usage (tpmtool_opt_strs+1425)
+
+#endif /* not defined __doxygen__ */
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+/**
+ * The callout function that invokes the optionUsage function.
+ *
+ * @param pOptions the AutoOpts option description structure
+ * @param pOptDesc the descriptor for the "help" (usage) option.
+ * @noreturn
+ */
+static void
+doUsageOpt(tOptions * pOptions, tOptDesc * pOptDesc)
+{
+    optionUsage(&tpmtoolOptions, TPMTOOL_EXIT_SUCCESS);
+    /* NOTREACHED */
+    (void)pOptDesc;
+    (void)pOptions;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/**
+ * Code to handle the debug option.
+ *
+ * @param pOptions the tpmtool options data structure
+ * @param pOptDesc the option descriptor for this option.
+ */
+static void
+doOptDebug(tOptions* pOptions, tOptDesc* pOptDesc)
+{
+    static struct {long rmin, rmax;} const rng[1] = {
+        { 0 ,  9999 } };
+    int  ix;
+
+    if (pOptions <= OPTPROC_EMIT_LIMIT)
+        goto emit_ranges;
+    optionNumericVal(pOptions, pOptDesc);
+
+    for (ix = 0; ix < 1; ix++) {
+        if (pOptDesc->optArg.argInt < rng[ix].rmin)
+            continue;  /* ranges need not be ordered. */
+        if (pOptDesc->optArg.argInt == rng[ix].rmin)
+            return;
+        if (rng[ix].rmax == LONG_MIN)
+            continue;
+        if (pOptDesc->optArg.argInt <= rng[ix].rmax)
+            return;
+    }
+
+    option_usage_fp = stderr;
+
+emit_ranges:
+
+    optionShowRange(pOptions, pOptDesc, (void *)rng, 1);
+}
+/* extracted from optmain.tlib near line 1113 */
+
+/**
+ * The directory containing the data associated with tpmtool.
+ */
+#ifndef  PKGDATADIR
+# define PKGDATADIR ""
+#endif
+
+/**
+ * Information about the person or institution that packaged tpmtool
+ * for the current distribution.
+ */
+#ifndef  WITH_PACKAGER
+# define tpmtool_packager_info NULL
+#else
+static char const tpmtool_packager_info[] =
+    "Packaged by " WITH_PACKAGER
+
+# ifdef WITH_PACKAGER_VERSION
+        " ("WITH_PACKAGER_VERSION")"
+# endif
+
+# ifdef WITH_PACKAGER_BUG_REPORTS
+    "\nReport tpmtool bugs to " WITH_PACKAGER_BUG_REPORTS
+# endif
+    "\n";
+#endif
+#ifndef __doxygen__
+
+#endif /* __doxygen__ */
+/**
+ * The option definitions for tpmtool.  The one structure that
+ * binds them all.
+ */
+tOptions tpmtoolOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_NO_ARGS
+    + OPTPROC_GNUUSAGE
+    + OPTPROC_MISUSE ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zLicenseDescrip,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    optionUsage, /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP, /* more-help option index */
+      NO_EQUIVALENT, /* save option index */
+      NO_EQUIVALENT, /* '-#' option index */
+      NO_EQUIVALENT /* index of default opt */
+    },
+    7 /* full option count */, 4 /* user option count */,
+    tpmtool_full_usage, tpmtool_short_usage,
+    NULL, NULL,
+    PKGDATADIR, tpmtool_packager_info
+};
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char* AO_gettext(char const* pz);
+static void  coerce_it(void** s);
+
+/**
+ * AutoGen specific wrapper function for gettext.
+ * It relies on the macro _() to convert from English to the target
+ * language, then strdup-duplicates the result string.
+ *
+ * @param[in] pz the input text used as a lookup key.
+ * @returns the translated text (if there is one),
+ *   or the original text (if not).
+ */
+static char *
+AO_gettext(char const* pz)
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup(pzRes);
+    if (pzRes == NULL) {
+        fputs(_("No memory for duping translated strings\n"), stderr);
+        exit(TPMTOOL_EXIT_FAILURE);
+    }
+    return pzRes;
+}
+
+static void coerce_it(void** s) { *s = AO_gettext(*s);
+}
+
+/**
+ * Translate all the translatable strings in the tpmtoolOptions
+ * structure defined above.  This is done only once.
+ */
+static void
+translate_option_strings(void)
+{
+    tOptions * const pOpt = &tpmtoolOptions;
+
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct != 0) {
+        /*
+         *  Do the translations.  The first pointer follows the field count
+         *  field.  The field count field is the size of a pointer.
+         */
+        tOptDesc * pOD = pOpt->pOptDesc;
+        char **    ppz = (char**)(void*)&(option_usage_text);
+        int        ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+
+        coerce_it((void*)&(pOpt->pzCopyright));
+        coerce_it((void*)&(pOpt->pzCopyNotice));
+        coerce_it((void*)&(pOpt->pzFullVersion));
+        coerce_it((void*)&(pOpt->pzUsageTitle));
+        coerce_it((void*)&(pOpt->pzExplain));
+        coerce_it((void*)&(pOpt->pzDetail));
+        coerce_it((void*)&(pOpt->pzPackager));
+        coerce_it((void*)&(pOpt->pzShortUsage));
+        option_usage_text.field_ct = 0;
+
+        for (ix = pOpt->optCt; ix > 0; ix--, pOD++)
+            coerce_it((void*)&(pOD->pzText));
+    }
+
+    if ((pOpt->fOptSet & OPTPROC_NXLAT_OPT_CFG) == 0) {
+        tOptDesc * pOD = pOpt->pOptDesc;
+        int        ix;
+
+        for (ix = pOpt->optCt; ix > 0; ix--, pOD++) {
+            coerce_it((void*)&(pOD->pz_Name));
+            coerce_it((void*)&(pOD->pz_DisableName));
+            coerce_it((void*)&(pOD->pz_DisablePfx));
+        }
+        /* prevent re-translation */
+        tpmtoolOptions.fOptSet |= OPTPROC_NXLAT_OPT_CFG | OPTPROC_NXLAT_OPT;
+    }
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
+/* tpmtool-args.c ends here */
diff --git a/src/tpmtool-args.def b/src/tpmtool-args.def
new file mode 100644 (file)
index 0000000..a14fa64
--- /dev/null
@@ -0,0 +1,43 @@
+AutoGen Definitions options;
+prog-name     = tpmtool;
+prog-title    = "GnuTLS TPM tool";
+prog-desc     = "Program to handle TPM as a cryptographic device.\n";
+detail    = "Program that allows handling cryptographic data from the TPM chip.";
+short-usage   = "tpmtool [options] [url]\ntpmtool --help for usage instructions.\n";
+explain       = "";
+
+#define  OUTFILE_OPT   1
+#include args-std.def
+
+flag = {
+    name      = generate-rsa;
+    descrip   = "Generate an RSA private-public key pair";
+    doc = "Generates an RSA private-public key pair on the specified token.";
+};
+
+flag = {
+    name      = bits;
+    arg-type  = number;
+    descrip   = "Specify the number of bits for key generate";
+    doc      = "";
+};
+
+doc-section = {
+  ds-type = 'SEE ALSO';
+  ds-format = 'texi';
+  ds-text   = <<-_EOT_
+    p11tool (1), certtool (1)
+_EOT_;
+};
+
+doc-section = {
+  ds-type = 'EXAMPLES';
+  ds-format = 'texi';
+  ds-text   = <<-_EOT_
+To generate a public key use:
+@example
+$ tpmtool --generate-rsa --bits 1024
+@end example
+_EOT_;
+};
+
diff --git a/src/tpmtool-args.h b/src/tpmtool-args.h
new file mode 100644 (file)
index 0000000..ea6625c
--- /dev/null
@@ -0,0 +1,191 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (tpmtool-args.h)
+ *  
+ *  It has been AutoGen-ed  July  6, 2012 at 09:41:37 PM by AutoGen 5.16
+ *  From the definitions    tpmtool-args.def
+ *  and the template file   options
+ *
+ * Generated from AutoOpts 36:4:11 templates.
+ *
+ *  AutoOpts is a copyrighted work.  This header file is not encumbered
+ *  by AutoOpts licensing, but is provided under the licensing terms chosen
+ *  by the tpmtool author or copyright holder.  AutoOpts is
+ *  licensed under the terms of the LGPL.  The redistributable library
+ *  (``libopts'') is licensed under the terms of either the LGPL or, at the
+ *  users discretion, the BSD license.  See the AutoOpts and/or libopts sources
+ *  for details.
+ *
+ * The tpmtool program is copyrighted and licensed
+ * under the following terms:
+ *
+ *  Copyright (C) 2000-2012 Free Software Foundation, all rights reserved.
+ *  This is free software. It is licensed for use, modification and
+ *  redistribution under the terms of the
+ *  GNU General Public License, version 3 or later
+ *      <http://gnu.org/licenses/gpl.html>
+ *
+ *  tpmtool is free software: you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  tpmtool is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *  See the GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the tpmtool program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_TPMTOOL_ARGS_H_GUARD
+#define AUTOOPTS_TPMTOOL_ARGS_H_GUARD 1
+#include "config.h"
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 147460
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+  Choke Me.
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+    INDEX_OPT_DEBUG         =  0,
+    INDEX_OPT_OUTFILE       =  1,
+    INDEX_OPT_GENERATE_RSA  =  2,
+    INDEX_OPT_BITS          =  3,
+    INDEX_OPT_VERSION       =  4,
+    INDEX_OPT_HELP          =  5,
+    INDEX_OPT_MORE_HELP     =  6
+} teOptIndex;
+
+#define OPTION_CT    7
+#define TPMTOOL_VERSION       "@VERSION@"
+#define TPMTOOL_FULL_VERSION  "tpmtool @VERSION@"
+
+/*
+ *  Interface defines for all options.  Replace "n" with the UPPER_CASED
+ *  option name (as in the teOptIndex enumeration above).
+ *  e.g. HAVE_OPT(DEBUG)
+ */
+#define         DESC(n) (tpmtoolOptions.pOptDesc[INDEX_OPT_## n])
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).optArg.argString)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT_MASK;   \
+                if ((DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/* * * * * *
+ *
+ *  Enumeration of tpmtool exit codes
+ */
+typedef enum {
+    TPMTOOL_EXIT_SUCCESS = 0,
+    TPMTOOL_EXIT_FAILURE = 1,
+    TPMTOOL_EXIT_LIBOPTS_FAILURE = 70
+} tpmtool_exit_code_t;
+/* * * * * *
+ *
+ *  Interface defines for specific options.
+ */
+#define VALUE_OPT_DEBUG          'd'
+
+#define OPT_VALUE_DEBUG          (DESC(DEBUG).optArg.argInt)
+#define VALUE_OPT_OUTFILE        1
+#define VALUE_OPT_GENERATE_RSA   2
+#define VALUE_OPT_BITS           3
+
+#define OPT_VALUE_BITS           (DESC(BITS).optArg.argInt)
+#define VALUE_OPT_HELP          'h'
+#define VALUE_OPT_MORE_HELP     '!'
+#define VALUE_OPT_VERSION       'v'
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS(tpmtoolOptions.fOptSet &= ~OPTPROC_ERRSTOP)
+#define ERRSTOP_OPTERR  STMTS(tpmtoolOptions.fOptSet |= OPTPROC_ERRSTOP)
+#define RESTART_OPT(n)  STMTS( \
+                tpmtoolOptions.curOptIdx = (n); \
+                tpmtoolOptions.pzCurOpt  = NULL)
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*tpmtoolOptions.pUsageProc)(&tpmtoolOptions, c)
+/* extracted from opthead.tlib near line 484 */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+/*
+ *  global exported definitions
+ */
+#include <gettext.h>
+
+
+/* * * * * *
+ *
+ *  Declare the tpmtool option descriptor.
+ */
+extern tOptions tpmtoolOptions;
+
+#if defined(ENABLE_NLS)
+# ifndef _
+#   include <stdio.h>
+static inline char* aoGetsText(char const* pz) {
+    if (pz == NULL) return NULL;
+    return (char*)gettext(pz);
+}
+#   define _(s)  aoGetsText(s)
+# endif /* _() */
+
+# define OPT_NO_XLAT_CFG_NAMES  STMTS(tpmtoolOptions.fOptSet |= \
+                                    OPTPROC_NXLAT_OPT_CFG;)
+# define OPT_NO_XLAT_OPT_NAMES  STMTS(tpmtoolOptions.fOptSet |= \
+                                    OPTPROC_NXLAT_OPT|OPTPROC_NXLAT_OPT_CFG;)
+
+# define OPT_XLAT_CFG_NAMES     STMTS(tpmtoolOptions.fOptSet &= \
+                                  ~(OPTPROC_NXLAT_OPT|OPTPROC_NXLAT_OPT_CFG);)
+# define OPT_XLAT_OPT_NAMES     STMTS(tpmtoolOptions.fOptSet &= \
+                                  ~OPTPROC_NXLAT_OPT;)
+
+#else   /* ENABLE_NLS */
+# define OPT_NO_XLAT_CFG_NAMES
+# define OPT_NO_XLAT_OPT_NAMES
+
+# define OPT_XLAT_CFG_NAMES
+# define OPT_XLAT_OPT_NAMES
+
+# ifndef _
+#   define _(_s)  _s
+# endif
+#endif  /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_TPMTOOL_ARGS_H_GUARD */
+/* tpmtool-args.h ends here */
diff --git a/src/tpmtool.c b/src/tpmtool.c
new file mode 100644 (file)
index 0000000..bc26e2c
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2010-2012 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/openpgp.h>
+#include <gnutls/pkcs12.h>
+#include <gnutls/tpm.h>
+#include <gnutls/abstract.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <error.h>
+
+/* Gnulib portability files. */
+#include <read-file.h>
+#include <progname.h>
+#include <version-etc.h>
+
+#include "certtool-common.h"
+#include "tpmtool-args.h"
+
+static void cmd_parser (int argc, char **argv);
+static void tpm_generate(FILE* outfile, unsigned int key_type, unsigned int bits);
+
+static FILE *outfile;
+int batch = 0;
+
+static void
+tls_log_func (int level, const char *str)
+{
+  fprintf (stderr, "|<%d>| %s", level, str);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  set_program_name (argv[0]);
+  cmd_parser (argc, argv);
+
+  return 0;
+}
+
+static void
+cmd_parser (int argc, char **argv)
+{
+  int ret, debug = 0;
+  unsigned int optct;
+  unsigned int key_type = GNUTLS_PK_UNKNOWN;
+  unsigned int bits = 0;
+  
+  optct = optionProcess( &tpmtoolOptions, argc, argv);
+  argc += optct;
+  argv += optct;
+  if (HAVE_OPT(DEBUG))
+    debug = OPT_VALUE_DEBUG;
+
+  gnutls_global_set_log_function (tls_log_func);
+  gnutls_global_set_log_level (debug);
+  if (debug > 1)
+    printf ("Setting log level to %d\n", debug);
+
+  if ((ret = gnutls_global_init ()) < 0)
+    error (EXIT_FAILURE, 0, "global_init: %s", gnutls_strerror (ret));
+
+  if (HAVE_OPT(OUTFILE))
+    {
+      outfile = safe_open_rw (OPT_ARG(OUTFILE), 0);
+      if (outfile == NULL)
+        error (EXIT_FAILURE, errno, "%s", OPT_ARG(OUTFILE));
+    }
+  else
+    outfile = stdout;
+
+  if (HAVE_OPT(BITS))
+    bits = OPT_VALUE_BITS;
+  else
+    bits = 2048;
+
+  if (HAVE_OPT(GENERATE_RSA))
+    {
+      key_type = GNUTLS_PK_RSA;
+      tpm_generate (outfile, key_type, bits);
+    }
+  else 
+    {
+      USAGE(1);
+    }
+    
+  fclose (outfile);
+
+  gnutls_global_deinit ();
+}
+
+static void tpm_generate(FILE* outfile, unsigned int key_type, unsigned int bits)
+{
+  int ret;
+  char* srk_pass, *key_pass;
+  gnutls_datum_t privkey, pubkey;
+  
+  srk_pass = getpass ("Enter SRK password: ");
+  if (srk_pass != NULL)
+    srk_pass = strdup(srk_pass);
+
+  key_pass = getpass ("Enter key password: ");
+  if (key_pass != NULL)
+    key_pass = strdup(srk_pass);
+  
+  ret = gnutls_tpm_privkey_generate(key_type, bits, srk_pass, key_pass,
+                                    GNUTLS_X509_FMT_PEM, &privkey, &pubkey,
+                                    GNUTLS_TPM_SIG_PKCS1V15);
+
+  free(key_pass);
+  free(srk_pass);
+
+  if (ret < 0)
+    error (EXIT_FAILURE, 0, "gnutls_tpm_privkey_generate: %s", gnutls_strerror (ret));
+
+  fwrite (pubkey.data, 1, pubkey.size, outfile);
+  fputs ("\n", outfile);
+  fwrite (privkey.data, 1, privkey.size, outfile);
+}