aikpub2: --handle option retrieves public key from TPM 2.0 NVRAM
This commit is contained in:
parent
87d356dc47
commit
6337770845
|
@ -6,7 +6,7 @@ aikpub2_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||||
aikpub2.o : $(top_builddir)/config.status
|
aikpub2.o : $(top_builddir)/config.status
|
||||||
|
|
||||||
if USE_TSS2
|
if USE_TSS2
|
||||||
aikpub2_LDADD += -ltss2
|
aikpub2_LDADD += -ltctisocket -ltss2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
AM_CPPFLAGS = \
|
AM_CPPFLAGS = \
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <asn1/oid.h>
|
#include <asn1/oid.h>
|
||||||
|
|
||||||
#include <tss2/tpm20.h>
|
#include <tss2/tpm20.h>
|
||||||
|
#include <tcti/tcti_socket.h>
|
||||||
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
@ -28,7 +29,6 @@
|
||||||
/* default directory where AIK keys are stored */
|
/* default directory where AIK keys are stored */
|
||||||
#define AIK_DIR IPSEC_CONFDIR "/pts/"
|
#define AIK_DIR IPSEC_CONFDIR "/pts/"
|
||||||
|
|
||||||
|
|
||||||
/* default name of AIK private key blob */
|
/* default name of AIK private key blob */
|
||||||
#define DEFAULT_FILENAME_AIKPUBKEY AIK_DIR "aikPub.der"
|
#define DEFAULT_FILENAME_AIKPUBKEY AIK_DIR "aikPub.der"
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ static level_t default_loglevel = 1;
|
||||||
options_t *options;
|
options_t *options;
|
||||||
|
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
chunk_t aik_blob;
|
||||||
chunk_t aik_pubkey;
|
chunk_t aik_pubkey;
|
||||||
chunk_t aik_keyid;
|
chunk_t aik_keyid;
|
||||||
|
|
||||||
|
@ -110,6 +111,7 @@ static void exit_aikpub2(err_t message, ...)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
|
free(aik_blob.ptr);
|
||||||
free(aik_pubkey.ptr);
|
free(aik_pubkey.ptr);
|
||||||
free(aik_keyid.ptr);
|
free(aik_keyid.ptr);
|
||||||
options->destroy(options);
|
options->destroy(options);
|
||||||
|
@ -140,13 +142,14 @@ static void exit_aikpub2(err_t message, ...)
|
||||||
static void usage(const char *message)
|
static void usage(const char *message)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: aikpub2 [--in <filename>] [--out <filename>]\n"
|
"Usage: aikpub2 [--in <filename>|--handle <handle>] --out <filename>\n"
|
||||||
" [--force] [--quiet] [--debug <level>]\n"
|
" [--force] [--quiet] [--debug <level>]\n"
|
||||||
" aikpub2 --help\n"
|
" aikpub2 --help\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" --in (-i) TSS 2.0 AIK public key blob\n"
|
" --in (-i) TSS 2.0 AIK public key blob\n"
|
||||||
" --out (-o) AIK public key in PKCS#1 format\n"
|
" --handle (-H) TSS 2.0 AIK object handle\n"
|
||||||
|
" --out (-o) AIK public key in PKCS #1 format\n"
|
||||||
" --force (-f) force to overwrite existing files\n"
|
" --force (-f) force to overwrite existing files\n"
|
||||||
" --help (-h) show usage and exit\n"
|
" --help (-h) show usage and exit\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -157,6 +160,103 @@ static void usage(const char *message)
|
||||||
exit_aikpub2(message);
|
exit_aikpub2(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some symbols required by libtctisocket
|
||||||
|
*/
|
||||||
|
FILE *outFp;
|
||||||
|
uint8_t simulator = 1;
|
||||||
|
|
||||||
|
int TpmClientPrintf (uint8_t type, const char *format, ...)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read the public key portion of a TSS 2.0 AIK key from NVRAM
|
||||||
|
*/
|
||||||
|
void read_public(TPMI_DH_OBJECT handle, TPM2B_PUBLIC *public)
|
||||||
|
{
|
||||||
|
size_t tcti_context_size;
|
||||||
|
uint32_t sys_context_size, rval;
|
||||||
|
|
||||||
|
TCTI_SOCKET_CONF rm_if_config = { DEFAULT_HOSTNAME,
|
||||||
|
DEFAULT_RESMGR_TPM_PORT
|
||||||
|
};
|
||||||
|
|
||||||
|
TSS2_ABI_VERSION abi_version = { TSSWG_INTEROP,
|
||||||
|
TSS_SAPI_FIRST_FAMILY,
|
||||||
|
TSS_SAPI_FIRST_LEVEL,
|
||||||
|
TSS_SAPI_FIRST_VERSION
|
||||||
|
};
|
||||||
|
|
||||||
|
TPM2B_NAME name = { { sizeof(TPM2B_NAME)-2, } };
|
||||||
|
TPM2B_NAME qualified_name = { { sizeof(TPM2B_NAME)-2, } };
|
||||||
|
|
||||||
|
TSS2_TCTI_CONTEXT *tcti_context;
|
||||||
|
TSS2_SYS_CONTEXT *sys_context;
|
||||||
|
|
||||||
|
TPMS_AUTH_RESPONSE session_data;
|
||||||
|
TSS2_SYS_RSP_AUTHS sessions_data;
|
||||||
|
TPMS_AUTH_RESPONSE *session_data_array[1];
|
||||||
|
|
||||||
|
session_data_array[0] = &session_data;
|
||||||
|
sessions_data.rspAuths = &session_data_array[0];
|
||||||
|
sessions_data.rspAuthsCount = 1;
|
||||||
|
|
||||||
|
/* determine size of tcti context */
|
||||||
|
rval = InitSocketTcti(NULL, &tcti_context_size, &rm_if_config, 0);
|
||||||
|
if (rval != TSS2_RC_SUCCESS)
|
||||||
|
{
|
||||||
|
exit_aikpub2("could not get tcti_context size: 0x%06x", rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate memory for tcti context */
|
||||||
|
tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
|
||||||
|
|
||||||
|
/* initialize tcti context */
|
||||||
|
rval = InitSocketTcti(tcti_context, &tcti_context_size, &rm_if_config, 0);
|
||||||
|
if (rval != TSS2_RC_SUCCESS)
|
||||||
|
{
|
||||||
|
exit_aikpub2("could not get tcti_context: 0x%06x", rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* determine size of sys context */
|
||||||
|
sys_context_size = Tss2_Sys_GetContextSize(0);
|
||||||
|
|
||||||
|
/* allocate memory for sys context */
|
||||||
|
sys_context = malloc(sys_context_size);
|
||||||
|
|
||||||
|
/* initialize sys context */
|
||||||
|
rval = Tss2_Sys_Initialize(sys_context, sys_context_size, tcti_context,
|
||||||
|
&abi_version);
|
||||||
|
if (rval != TSS2_RC_SUCCESS)
|
||||||
|
{
|
||||||
|
TeardownSocketTcti(tcti_context);
|
||||||
|
exit_aikpub2("could not get sys_context: 0x%06x", rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* always send simulator platform command, ignored by true RM */
|
||||||
|
PlatformCommand(tcti_context ,MS_SIM_POWER_ON );
|
||||||
|
PlatformCommand(tcti_context, MS_SIM_NV_ON );
|
||||||
|
|
||||||
|
/* read public key for a given object handle from TPM 2.0 NVRAM */
|
||||||
|
rval = Tss2_Sys_ReadPublic(sys_context, handle, 0, public, &name,
|
||||||
|
&qualified_name, &sessions_data);
|
||||||
|
|
||||||
|
PlatformCommand(tcti_context, MS_SIM_POWER_OFF);
|
||||||
|
|
||||||
|
/* clean up connection to TPM 2.0 */
|
||||||
|
TeardownSocketTcti(tcti_context);
|
||||||
|
Tss2_Sys_Finalize(sys_context);
|
||||||
|
free(sys_context);
|
||||||
|
|
||||||
|
if (rval != TPM_RC_SUCCESS)
|
||||||
|
{
|
||||||
|
exit_aikpub2("could not read TSS 2.0 public key from handle 0x%08x:"
|
||||||
|
" 0x%06x", handle, rval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief main of aikpub2 which generates an Attestation Identity Key (AIK)
|
* @brief main of aikpub2 which generates an Attestation Identity Key (AIK)
|
||||||
*
|
*
|
||||||
|
@ -169,14 +269,15 @@ int main(int argc, char *argv[])
|
||||||
extern char * optarg;
|
extern char * optarg;
|
||||||
extern int optind;
|
extern int optind;
|
||||||
|
|
||||||
char *aikblob_filename = NULL;
|
uint32_t aik_handle = 0;
|
||||||
char *aikpubkey_filename = DEFAULT_FILENAME_AIKPUBKEY;
|
char *aik_in_filename = NULL;
|
||||||
|
char *aik_out_filename = DEFAULT_FILENAME_AIKPUBKEY;
|
||||||
|
chunk_t *aik_mapped;
|
||||||
bool force = FALSE;
|
bool force = FALSE;
|
||||||
chunk_t *aikblob;
|
|
||||||
hasher_t *hasher;
|
hasher_t *hasher;
|
||||||
|
|
||||||
/* TSS 2.0 variables */
|
/* TSS 2.0 variables */
|
||||||
TPM2B_PUBLIC public;
|
TPM2B_PUBLIC public = { { 0, } };
|
||||||
|
|
||||||
atexit(library_deinit);
|
atexit(library_deinit);
|
||||||
if (!library_init(NULL, "aikpub2"))
|
if (!library_init(NULL, "aikpub2"))
|
||||||
|
@ -199,6 +300,7 @@ int main(int argc, char *argv[])
|
||||||
/* name, has_arg, flag, val */
|
/* name, has_arg, flag, val */
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "optionsfrom", required_argument, NULL, '+' },
|
{ "optionsfrom", required_argument, NULL, '+' },
|
||||||
|
{ "handle", required_argument, NULL, 'H' },
|
||||||
{ "in", required_argument, NULL, 'i' },
|
{ "in", required_argument, NULL, 'i' },
|
||||||
{ "out", required_argument, NULL, 'o' },
|
{ "out", required_argument, NULL, 'o' },
|
||||||
{ "force", no_argument, NULL, 'f' },
|
{ "force", no_argument, NULL, 'f' },
|
||||||
|
@ -208,7 +310,7 @@ int main(int argc, char *argv[])
|
||||||
};
|
};
|
||||||
|
|
||||||
/* parse next option */
|
/* parse next option */
|
||||||
int c = getopt_long(argc, argv, "ho:c:b:p:fqd:", long_opts, NULL);
|
int c = getopt_long(argc, argv, "h+:H:i:o:fql:", long_opts, NULL);
|
||||||
|
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
|
@ -225,12 +327,16 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
case 'H': /* --handle <handle> */
|
||||||
|
aik_handle = strtoll(optarg, NULL, 16);
|
||||||
|
continue;
|
||||||
|
|
||||||
case 'i': /* --in <filename> */
|
case 'i': /* --in <filename> */
|
||||||
aikblob_filename = optarg;
|
aik_in_filename = optarg;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'o': /* --out <filename> */
|
case 'o': /* --out <filename> */
|
||||||
aikpubkey_filename = optarg;
|
aik_out_filename = optarg;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'f': /* --force */
|
case 'f': /* --force */
|
||||||
|
@ -259,27 +365,38 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
exit_aikpub2("plugin loading failed");
|
exit_aikpub2("plugin loading failed");
|
||||||
}
|
}
|
||||||
|
if (!aik_in_filename && !aik_handle)
|
||||||
|
{
|
||||||
|
usage("either --in or --handle option is required");
|
||||||
|
}
|
||||||
|
|
||||||
/* read TSS 2.0 AIK public key blob */
|
if (aik_handle)
|
||||||
if (!aikblob_filename)
|
|
||||||
{
|
{
|
||||||
usage("--aikblob is required");
|
/* read public key blob directly from TPM 2.0 */
|
||||||
|
read_public(aik_handle, &public);
|
||||||
|
aik_blob = chunk_clone(chunk_create((u_char*)&public, sizeof(public)));
|
||||||
}
|
}
|
||||||
aikblob = chunk_map(aikblob_filename, FALSE);
|
else
|
||||||
if (!aikblob)
|
|
||||||
{
|
{
|
||||||
exit_aikpub2("could not read TSS 2.0 public key file '%s'",
|
/* read stored TPM 2.0 public key blob from a file */
|
||||||
aikblob_filename);
|
aik_mapped = chunk_map(aik_in_filename, FALSE);
|
||||||
}
|
if (!aik_mapped)
|
||||||
DBG3(DBG_LIB, "aikblob: %B", aikblob);
|
{
|
||||||
|
exit_aikpub2("could not read TSS 2.0 public key file '%s'",
|
||||||
|
aik_in_filename);
|
||||||
|
}
|
||||||
|
aik_blob = chunk_clone(*aik_mapped);
|
||||||
|
chunk_unmap(aik_mapped);
|
||||||
|
|
||||||
if (aikblob->len != sizeof(TPM2B_PUBLIC))
|
if (aik_blob.len != sizeof(TPM2B_PUBLIC))
|
||||||
{
|
{
|
||||||
chunk_unmap(aikblob);
|
exit_aikpub2("size of aikblob is not %d bytes",
|
||||||
exit_aikpub2("size of aikblob is not %d bytes", sizeof(TPM2B_PUBLIC));
|
sizeof(TPM2B_PUBLIC));
|
||||||
|
}
|
||||||
|
public = *(TPM2B_PUBLIC*)aik_blob.ptr;
|
||||||
}
|
}
|
||||||
public = *(TPM2B_PUBLIC*)aikblob->ptr;
|
DBG3(DBG_LIB, "TSS 2.0 AIK blob: %B", &aik_blob);
|
||||||
chunk_unmap(aikblob);
|
|
||||||
|
|
||||||
switch (public.t.publicArea.type)
|
switch (public.t.publicArea.type)
|
||||||
{
|
{
|
||||||
|
@ -335,13 +452,13 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store AIK subjectPublicKeyInfo to file */
|
/* store AIK subjectPublicKeyInfo to file */
|
||||||
if (!chunk_write(aik_pubkey, aikpubkey_filename, 0022, force))
|
if (!chunk_write(aik_pubkey, aik_out_filename, 0022, force))
|
||||||
{
|
{
|
||||||
exit_aikpub2("could not write AIK public key file '%s': %s",
|
exit_aikpub2("could not write AIK public key file '%s': %s",
|
||||||
aikpubkey_filename, strerror(errno));
|
aik_out_filename, strerror(errno));
|
||||||
}
|
}
|
||||||
DBG1(DBG_LIB, "AIK public key written to '%s' (%u bytes)",
|
DBG1(DBG_LIB, "AIK public key written to '%s' (%u bytes)",
|
||||||
aikpubkey_filename, aik_pubkey.len);
|
aik_out_filename, aik_pubkey.len);
|
||||||
|
|
||||||
/* AIK keyid derived from subjectPublicKeyInfo encoding */
|
/* AIK keyid derived from subjectPublicKeyInfo encoding */
|
||||||
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
|
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
|
||||||
|
|
Loading…
Reference in New Issue