Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added integration of TPM 2.0 into wolfSSH #376

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ AC_ARG_ENABLE([certs],
[AS_HELP_STRING([--enable-certs],[Enable X.509 cert support (default: disabled)])],
[ENABLED_CERTS=$enableval],[ENABLED_CERTS=no])

# TPM 2.0 Support
AC_ARG_ENABLE([tpm],
[AS_HELP_STRING([--enable-tpm],[Enable TPM 2.0 support (default: disabled)])],
[ENABLED_TPM=$enableval],[ENABLED_TPM=no])

# smallstack
AC_ARG_ENABLE([smallstack],
[AS_HELP_STRING([--enable-smallstack],[Enable small stack (default: disabled)])],
Expand Down Expand Up @@ -246,12 +251,16 @@ AS_IF([test "x$ENABLED_PTERM" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_TERM"])
AS_IF([test "x$ENABLED_SHELL" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SHELL"])
AS_IF([test "x$ENABLED_AGENT" = "xyes"],[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_AGENT"])
AS_IF([test "x$ENABLED_CERTS" = "xyes"],[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_CERTS"])
AS_IF([test "x$ENABLED_AGENT" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_AGENT"])
AS_IF([test "x$ENABLED_CERTS" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_CERTS"])
AS_IF([test "x$ENABLED_TPM" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_TPM"])
AS_IF([test "x$ENABLED_SMALLSTACK" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SMALL_STACK"])
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SMALL_STACK"])
AS_IF([test "x$ENABLED_SSHD" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SSHD"])
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SSHD"])

if test "$ENABLED_SSHD" = "yes"; then
if test -n "$PAM_LIB"
Expand Down Expand Up @@ -291,6 +300,11 @@ if test "$ENABLED_SSHD" = "yes"; then
fi
fi

if test "x$ENABLED_TPM" = "xyes" ; then
AC_CHECK_LIB([wolftpm],[wolfTPM2_Init],,
[AC_MSG_ERROR([libwolftpm is required for ${PACKAGE}. It can be obtained from https://www.wolfssl.com/download.html/ .])])
fi


# Set the automake conditionals.
AM_CONDITIONAL([BUILD_EXAMPLE_SERVERS],[test "x$ENABLED_EXAMPLES" = "xyes"])
Expand All @@ -305,6 +319,7 @@ AM_CONDITIONAL([BUILD_SHELL],[test "x$ENABLED_SHELL" = "xyes"])
AM_CONDITIONAL([BUILD_AGENT],[test "x$ENABLED_AGENT" = "xyes"])
AM_CONDITIONAL([BUILD_SSHD],[test "x$ENABLED_SSHD" = "xyes"])
AM_CONDITIONAL([BUILD_CERTS],[test "x$ENABLED_CERTS" = "xyes"])
AM_CONDITIONAL([BUILD_TPM],[test "x$ENABLED_TPM" = "xyes"])

AX_HARDEN_CC_COMPILER_FLAGS

Expand Down Expand Up @@ -347,6 +362,7 @@ AS_ECHO([" * scp: $ENABLED_SCP"])
AS_ECHO([" * sftp: $ENABLED_SFTP"])
AS_ECHO([" * sshd: $ENABLED_SSHD"])
AS_ECHO([" * agent: $ENABLED_AGENT"])
AS_ECHO([" * TPM 2.0 support: $ENABLED_TPM"])
AS_ECHO([" * TCP/IP Forwarding: $ENABLED_FWD"])
AS_ECHO([" * X.509 Certs: $ENABLED_CERTS"])
AS_ECHO([" * Examples: $ENABLED_EXAMPLES"])
Expand Down
226 changes: 225 additions & 1 deletion examples/client/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@
#include <wolfssl/wolfcrypt/asn.h>
#endif

#ifdef WOLFSSH_TPM
#include <wolftpm/tpm2_wrap.h>
#include "../../wolfTPM/examples/tpm_io.h"
#endif /* WOLFSSH_TPM */

#ifndef NO_WOLFSSH_CLIENT

Expand Down Expand Up @@ -702,6 +706,13 @@ static THREAD_RET readInput(void* in)
}


#ifdef WOLFSSH_AGENT
static inline void ato32(const byte* c, word32* u32)
{
*u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
}
#endif

static THREAD_RET readPeer(void* in)
{
byte buf[80];
Expand Down Expand Up @@ -817,6 +828,132 @@ static THREAD_RET readPeer(void* in)
#endif /* !SINGLE_THREADED && !WOLFSSL_NUCLEUS */



#ifdef WOLFSSH_TPM

#define TPM2_DEMO_STORAGE_KEY_HANDLE 0x81000200 /* Persistent Storage Key Handle (RSA) */

static const char gStorageKeyAuth[] = "ThisIsMyStorageKeyAuth";

static int getPrimaryStoragekey(WOLFTPM2_DEV* pDev,
WOLFTPM2_KEY* pStorageKey,
TPM_ALG_ID alg)
{
int rc;

/* See if SRK already exists */
rc = wolfTPM2_ReadPublicKey(pDev, pStorageKey, TPM2_DEMO_STORAGE_KEY_HANDLE);
if (rc != 0) {
/* Create primary storage key */
rc = wolfTPM2_CreateSRK(pDev, pStorageKey, alg,
(byte*)gStorageKeyAuth, sizeof(gStorageKeyAuth)-1);
#ifndef WOLFTPM_WINAPI
if (rc == TPM_RC_SUCCESS) {
/* Move storage key into persistent NV */
rc = wolfTPM2_NVStoreKey(pDev, TPM_RH_OWNER, pStorageKey,
TPM2_DEMO_STORAGE_KEY_HANDLE);
}
#endif
}
else {
/* specify auth password for storage key */
pStorageKey->handle.auth.size = sizeof(gStorageKeyAuth)-1;
WMEMCPY(pStorageKey->handle.auth.buffer, gStorageKeyAuth,
pStorageKey->handle.auth.size);
}
if (rc != 0) {
printf("Loading SRK: Storage failed 0x%x: %s\n", rc,
TPM2_GetRCString(rc));
return rc;
}
printf("Loading SRK: Storage 0x%x (%d bytes)\n",
(word32)pStorageKey->handle.hndl, pStorageKey->pub.size);
return rc;
}


static int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key)
{
int rc = 0;
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
WFILE *fp = NULL;
size_t fileSz = 0;
size_t bytes_read = 0;
byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)];
int pubAreaSize;

WMEMSET(key, 0, sizeof(WOLFTPM2_KEYBLOB));

if (WFOPEN(&fp, filename, "rb") == 0) {
WFSEEK(fp, 0, XSEEK_END);
fileSz = WFTELL(fp);
WREWIND(fp);
if (fileSz > sizeof(key->priv) + sizeof(key->pub)) {
printf("File size check failed\n");
rc = BUFFER_E; goto exit;
}
printf("Reading %d bytes from %s\n", (int)fileSz, filename);

bytes_read = WFREAD(&key->pub.size, 1, sizeof(key->pub.size), fp);
if (bytes_read != sizeof(key->pub.size)) {
printf("Read %zu, expected size marker of %zu bytes\n",
bytes_read, sizeof(key->pub.size));
goto exit;
}
fileSz -= bytes_read;

bytes_read = WFREAD(pubAreaBuffer, 1, sizeof(UINT16) + key->pub.size, fp);
if (bytes_read != sizeof(UINT16) + key->pub.size) {
printf("Read %zu, expected public blob %zu bytes\n",
bytes_read, sizeof(UINT16) + key->pub.size);
goto exit;
}
fileSz -= bytes_read; /* Reminder bytes for private key part */

/* Decode the byte stream into a publicArea structure ready for use */
rc = TPM2_ParsePublic(&key->pub, pubAreaBuffer,
(word32)sizeof(pubAreaBuffer), &pubAreaSize);
if (rc != TPM_RC_SUCCESS) return rc;

if (fileSz > 0) {
printf("Reading the private part of the key\n");
bytes_read = WFREAD(&key->priv, 1, fileSz, fp);
if (bytes_read != fileSz) {
printf("Read %zu, expected private blob %zu bytes\n",
bytes_read, fileSz);
goto exit;
}
rc = 0; /* success */
}

/* sanity check the sizes */
if (pubAreaSize != (key->pub.size + (int)sizeof(key->pub.size)) ||
key->priv.size > sizeof(key->priv.buffer)) {
printf("Struct size check failed (pub %d, priv %d)\n",
key->pub.size, key->priv.size);
rc = BUFFER_E;
}
}
else {
rc = BUFFER_E;
printf("File %s not found!\n", filename);
printf("Keys can be generated by running:\n"
" ./examples/keygen/keygen rsa_test_blob.raw -rsa -t\n"
" ./examples/keygen/keygen ecc_test_blob.raw -ecc -t\n");
}

exit:
if (fp)
WFCLOSE(fp);
#else
(void)filename;
(void)key;
#endif /* !NO_FILESYSTEM && !NO_WRITE_TEMP_FILES */
return rc;
}

#endif /* WOLFSSH_TPM */

#ifdef WOLFSSH_CERTS

static int load_der_file(const char* filename, byte** out, word32* outSz)
Expand Down Expand Up @@ -995,6 +1132,65 @@ static int wolfSSH_AGENT_IO_Cb(WS_AgentIoCbAction action,
#endif /* WOLFSSH_AGENT */


#ifdef WOLFSSH_TPM
static int wolfSSH_TPM_InitKey(WOLFTPM2_DEV* dev, const char* name, WOLFTPM2_KEY* tpmKey)
{
WOLFTPM2_KEY storage;
WOLFTPM2_KEYBLOB tpmKeyBlob;

if (wolfTPM2_Init(dev, TPM2_IoCb, NULL) != TPM_RC_SUCCESS) {
#ifdef DEBUG_WOLFSSH
printf("TPM 2.0 Device initialization failed\n");
#endif
return WOLFSSH_TPM_FAILED_INIT;
}

/* TPM 2.0 keys live under a Primary Key, acquire such key */
if (getPrimaryStoragekey(dev, &storage, TPM_ALG_RSA)) {
#ifdef DEBUG_WOLFSSH
printf("Acquiring a Primary TPM 2.0 Key failed\n");
#endif
return WOLFSSH_TPM_FAILED_LOAD_PRIMARY;
}

/* Load the TPM 2.0 key blob from disk */
if (readKeyBlob(name, &tpmKeyBlob) != TPM_RC_SUCCESS) {
#ifdef DEBUG_WOLFSSH
printf("Reading key blob from disk failed\n");
#endif
return WOLFSSH_TPM_FAILED_READ_KEYBLOB;
}

/* Load the key into the TPM device */
if (wolfTPM2_LoadKey(dev, &tpmKeyBlob, &storage.handle) != TPM_RC_SUCCESS) {
#ifdef DEBUG_WOLFSSH
printf("wolfTPM2_LoadKey failed\n");
#endif
return WOLFSSH_TPM_FAILED_LOAD_KEY;
}
#ifdef DEBUG_WOLFSSH
printf("Loaded key to 0x%x\n", (word32)tpmKeyBlob.handle.hndl);
#endif

WMEMCPY(&tpmKey->handle, &tpmKeyBlob.handle, sizeof(tpmKey->handle));
WMEMCPY(&tpmKey->pub, &tpmKeyBlob.pub, sizeof(tpmKey->pub));
return WOLFSSH_TPM_SUCCESS;
}


static void wolfSSH_TPM_Cleanup(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key)
{
if (key != NULL) {
wolfTPM2_UnloadHandle(dev, &key->handle);
}

if (dev != NULL) {
wolfTPM2_Cleanup(dev);
}
}
#endif /* WOLFSSH_TPM */


THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
{
WOLFSSH_CTX* ctx = NULL;
Expand Down Expand Up @@ -1022,6 +1218,10 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
byte useAgent = 0;
WS_AgentCbActionCtx agentCbCtx;
#endif
#ifdef WOLFSSH_TPM
WOLFTPM2_DEV tpmDev;
WOLFTPM2_KEY tpmKey;
#endif

int argc = ((func_args*)args)->argc;
char** argv = ((func_args*)args)->argv;
Expand Down Expand Up @@ -1157,7 +1357,18 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
if (ret != 0) err_sys("Couldn't load private key buffer.");
}
else {
#ifndef NO_FILESYSTEM
#if defined(WOLFSSH_TPM)
/* Protecting the SSH Private Key using a TPM 2.0 device
*
* TPM-backed keys do not require a user buffer, because
* the private key is loaded securely inside the TPM and
* used only from within the TPM for higher security.
*
* Successfully loaded TPM key has a TPM Handle that is
* later passed to wolfSSH for use
*/
ret = wolfSSH_TPM_InitKey(&tpmDev, privKeyName, &tpmKey);
#elif !defined(NO_FILESYSTEM)
userPrivateKey = NULL; /* create new buffer based on parsed input */
ret = wolfSSH_ReadKey_file(privKeyName,
(byte**)&userPrivateKey, &userPrivateKeySz,
Expand Down Expand Up @@ -1239,6 +1450,15 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
if (ssh == NULL)
err_sys("Couldn't create wolfSSH session.");

#ifdef WOLFSSH_TPM
/* Link the TPM 2.0 device to the SSH session
* This way, SSH client operations that can
* take advantage of the hardware security
* will have access to the TPM 2.0 device */
wolfSSH_SetTpmDev(ssh, &tpmDev);
wolfSSH_SetTpmKey(ssh, &tpmKey);
#endif

#if defined(WOLFSSL_PTHREADS) && defined(WOLFSSL_TEST_GLOBAL_REQ)
wolfSSH_SetGlobalReq(ctx, callbackGlobalReq);
wolfSSH_SetGlobalReqCtx(ssh, &ssh); /* dummy ctx */
Expand Down Expand Up @@ -1399,6 +1619,10 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
if (privKeyName != NULL && userPrivateKey != NULL) {
WFREE(userPrivateKey, NULL, DYNTYPE_PRIVKEY);
}
#ifdef WOLFSSH_TPM
wolfSSH_TPM_Cleanup(&tpmDev, &tpmKey);
#endif

#if !defined(WOLFSSH_NO_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS)
wc_ecc_fp_free(); /* free per thread cache */
#endif
Expand Down
4 changes: 4 additions & 0 deletions examples/client/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ examples_client_client_SOURCES = examples/client/client.c \
examples/client/client.h
examples_client_client_LDADD = src/libwolfssh.la
examples_client_client_DEPENDENCIES = src/libwolfssh.la

if BUILD_TPM
examples_client_client_SOURCES += ../wolfTPM/examples/tpm_io.c
endif
endif
5 changes: 3 additions & 2 deletions examples/echoserver/echoserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -2619,8 +2619,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)

#endif /* NO_WOLFSSH_SERVER */


void wolfSSL_Debugging_ON(void);
#ifdef DEBUG_WOLFSSH
extern void wolfSSL_Debugging_ON(void);
#endif

int wolfSSH_Echoserver(int argc, char** argv)
{
Expand Down
15 changes: 14 additions & 1 deletion src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
#include "src/misc.c"
#endif

#ifdef WOLFSSH_TPM
#include <wolftpm/tpm2_wrap.h>
#endif

/*
Flags:
Expand Down Expand Up @@ -10087,11 +10090,21 @@ static int BuildUserAuthRequestRsa(WOLFSSH* ssh,
ret = WS_CRYPTO_FAILED;
}
else {
int sigSz;
int sigSz = 0;
WLOG(WS_LOG_INFO, "Signing hash with RSA.");
#ifdef WOLFSSH_TPM
if (ssh->ctx->tpmDev && ssh->ctx->tpmKey) {
wolfTPM2_SignHashScheme(ssh->ctx->tpmDev, ssh->ctx->tpmKey,
encDigest, encDigestSz,
output+begin, (int*)&sigSz,
TPM_ALG_OAEP, TPM_ALG_SHA1);
}
else
#else
sigSz = wc_RsaSSL_Sign(encDigest, encDigestSz,
output + begin, keySig->sigSz,
&keySig->ks.rsa.key, ssh->rng);
#endif
if (sigSz <= 0 || (word32)sigSz != keySig->sigSz) {
WLOG(WS_LOG_DEBUG, "SUAR: Bad RSA Sign");
ret = WS_RSA_E;
Expand Down
Loading