diff --git a/Makefile.am b/Makefile.am
index 497357b3..cd0a6127 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,6 +39,7 @@ include IDE/include.am
include certs/include.am
include tests/include.am
include docs/include.am
+include wrapper/include.am
EXTRA_DIST+= README.md
EXTRA_DIST+= ChangeLog.md
diff --git a/src/tpm2_param_enc.c b/src/tpm2_param_enc.c
index 6c60a7a4..eb1b3735 100644
--- a/src/tpm2_param_enc.c
+++ b/src/tpm2_param_enc.c
@@ -173,7 +173,7 @@ int TPM2_KDFa(
copyLen = keySz - pos;
}
- memcpy(keyStream, hash, copyLen);
+ XMEMCPY(keyStream, hash, copyLen);
keyStream += copyLen;
}
ret = keySz;
diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c
index 12cf6bef..9c2ee651 100644
--- a/src/tpm2_wrap.c
+++ b/src/tpm2_wrap.c
@@ -172,6 +172,272 @@ int wolfTPM2_Init(WOLFTPM2_DEV* dev, TPM2HalIoCb ioCb, void* userCtx)
return rc;
}
+#ifndef WOLFTPM2_NO_HEAP
+WOLFTPM2_DEV *wolfTPM2_New(void)
+{
+ WOLFTPM2_DEV *dev = NULL;
+
+ dev = (WOLFTPM2_DEV *) XMALLOC(sizeof(WOLFTPM2_DEV), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (dev == NULL) {
+ return NULL;
+ }
+
+ if (wolfTPM2_Init(dev, NULL, NULL) != TPM_RC_SUCCESS) {
+ return NULL;
+ }
+
+ return dev;
+}
+
+int wolfTPM2_Free(WOLFTPM2_DEV *dev)
+{
+ if (dev != NULL) {
+ wolfTPM2_Cleanup(dev);
+ XFREE(dev, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ return TPM_RC_SUCCESS;
+}
+
+WOLFTPM2_KEYBLOB* wolfTPM2_GetNewKeyBlob(void)
+{
+ WOLFTPM2_KEYBLOB* blob = NULL;
+
+ blob = (WOLFTPM2_KEYBLOB *) XMALLOC(sizeof(WOLFTPM2_KEYBLOB), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (blob == NULL) {
+ return NULL;
+ }
+
+ XMEMSET(blob, 0, sizeof(WOLFTPM2_KEYBLOB));
+ return blob;
+}
+
+int wolfTPM2_CleanupKeyBlob(WOLFTPM2_KEYBLOB* blob)
+{
+ if (blob != NULL) {
+ XFREE(blob, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ return TPM_RC_SUCCESS;
+}
+
+WOLFTPM_API TPMT_PUBLIC* wolfTPM2_GetNewPublicTemplate(void)
+{
+ TPMT_PUBLIC* template = NULL;
+
+ template = (TPMT_PUBLIC *) XMALLOC(sizeof(TPMT_PUBLIC), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (template == NULL) {
+ return NULL;
+ }
+
+ XMEMSET(template, 0, sizeof(TPMT_PUBLIC));
+ return template;
+}
+
+WOLFTPM_API int wolfTPM2_CleanupPublicTemplate(TPMT_PUBLIC* template)
+{
+ if (template != NULL) {
+ XFREE(template, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ return TPM_RC_SUCCESS;
+}
+
+WOLFTPM_API WOLFTPM2_KEY* wolfTPM2_GetNewKey(void)
+{
+ WOLFTPM2_KEY* key = NULL;
+
+ key = (WOLFTPM2_KEY *) XMALLOC(sizeof(WOLFTPM2_KEY), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (key == NULL) {
+ return NULL;
+ }
+
+ XMEMSET(key, 0, sizeof(WOLFTPM2_KEY));
+ return key;
+}
+
+WOLFTPM_API int wolfTPM2_CleanupKey(WOLFTPM2_KEY* key)
+{
+ if (key != NULL) {
+ XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ return TPM_RC_SUCCESS;
+}
+
+WOLFTPM2_SESSION* wolfTPM2_GetNewSession(void)
+{
+ WOLFTPM2_SESSION* session = NULL;
+
+ session = (WOLFTPM2_SESSION *) XMALLOC(sizeof(WOLFTPM2_SESSION), NULL,
+ DYNAMIC_TYPE_TMP_BUFFER);
+ if (session == NULL) {
+ return NULL;
+ }
+
+ XMEMSET(session, 0, sizeof(WOLFTPM2_SESSION));
+ return session;
+}
+
+int wolfTPM2_CleanupSession(WOLFTPM2_SESSION* session)
+{
+ if (session != NULL) {
+ XFREE(session, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+ }
+ return TPM_RC_SUCCESS;
+}
+#endif /* WOLFTPM2_NO_HEAP */
+
+WOLFTPM2_HANDLE* wolfTPM2_GetHandleRefFromKey(WOLFTPM2_KEY* key)
+{
+ if (key == NULL) {
+ return NULL;
+ }
+ return &(key->handle);
+}
+
+int wolfTPM2_GetKeyBlobAsBuffer(byte *buffer, word32 bufferSz,
+ WOLFTPM2_KEYBLOB* key)
+{
+ int rc = 0;
+ int sz = 0;
+ byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)];
+ int pubAreaSize;
+
+ if ((buffer == NULL) || (bufferSz <= 0) || (key == NULL)) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* publicArea is encoded format. Eliminates empty fields, saves space. */
+ rc = TPM2_AppendPublic(pubAreaBuffer, (word32)sizeof(pubAreaBuffer),
+ &pubAreaSize, &key->pub);
+ if (rc != TPM_RC_SUCCESS) {
+ return rc;
+ }
+
+ if (pubAreaSize != (key->pub.size + (int)sizeof(key->pub.size))) {
+#ifdef WOLFTPM_DEBUG_VERBOSE
+ printf("Sanity check for publicArea size failed\n");
+#endif
+ return BUFFER_E;
+ }
+
+ if (bufferSz < sizeof(key->pub.size) + sizeof(UINT16) + key->pub.size +
+ sizeof(UINT16) + key->priv.size) {
+ return BUFFER_E;
+ }
+
+ /* Write size marker for the public part */
+ XMEMCPY(buffer + sz, &key->pub.size, sizeof(key->pub.size));
+ sz += sizeof(key->pub.size);
+
+ /* Write the public part with bytes aligned */
+ XMEMCPY(buffer + sz, pubAreaBuffer, sizeof(UINT16) + key->pub.size);
+ sz += sizeof(UINT16) + key->pub.size;
+
+ /* Write the private part, size marker is included */
+ XMEMCPY(buffer + sz, &key->priv, sizeof(UINT16) + key->priv.size);
+ sz += sizeof(UINT16) + key->priv.size;
+
+#ifdef WOLFTPM_DEBUG_VERBOSE
+ TPM2_PrintBin(buffer, sz);
+ printf("Getting %d bytes\n", (int)sz);
+#endif
+
+ return sz;
+}
+
+int wolfTPM2_SetKeyBlobFromBuffer(WOLFTPM2_KEYBLOB* key, byte *buffer,
+ word32 bufferSz)
+{
+ int rc = 0;
+ byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)];
+ int pubAreaSize;
+ byte *runner = buffer;
+ size_t done_reading = 0;
+
+ if ((key == NULL) || (buffer == NULL) || (bufferSz <= 0)) {
+ return BAD_FUNC_ARG;
+ }
+
+ XMEMSET(key, 0, sizeof(WOLFTPM2_KEYBLOB));
+
+#ifdef WOLFTPM_DEBUG_VERBOSE
+ TPM2_PrintBin(buffer, bufferSz);
+ printf("Setting %d bytes\n", (int)bufferSz);
+#endif
+
+ if (bufferSz < done_reading + sizeof(key->pub.size)) {
+#ifdef WOLFTPM_DEBUG_VERBOSE
+ printf("Buffer size check failed (%d)\n", bufferSz);
+#endif
+ return BUFFER_E;
+ }
+
+ XMEMCPY(&key->pub.size, runner, sizeof(key->pub.size));
+ runner += sizeof(key->pub.size);
+ done_reading += sizeof(key->pub.size);
+
+ if (bufferSz < done_reading + sizeof(UINT16) + key->pub.size) {
+#ifdef WOLFTPM_DEBUG_VERBOSE
+ printf("Buffer size check failed (%d)\n", bufferSz);
+#endif
+ return BUFFER_E;
+ }
+
+ XMEMCPY(pubAreaBuffer, runner, sizeof(UINT16) + key->pub.size);
+ runner += sizeof(UINT16) + key->pub.size;
+ done_reading += sizeof(UINT16) + key->pub.size;
+
+ /* 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 (bufferSz < done_reading + sizeof(key->priv.size)) {
+#ifdef WOLFTPM_DEBUG_VERBOSE
+ printf("Buffer size check failed (%d)\n", bufferSz);
+#endif
+ return BUFFER_E;
+ }
+
+ XMEMCPY(&key->priv.size, runner, sizeof(key->priv.size));
+ runner += sizeof(key->priv.size);
+ done_reading += sizeof(key->priv.size);
+
+ if (bufferSz < done_reading + key->priv.size) {
+#ifdef WOLFTPM_DEBUG_VERBOSE
+ printf("Buffer size check failed (%d)\n", bufferSz);
+#endif
+ return BUFFER_E;
+ }
+
+ XMEMCPY(key->priv.buffer, runner, key->priv.size);
+ runner += key->priv.size;
+ done_reading += key->priv.size;
+
+ return TPM_RC_SUCCESS;
+}
+
+int wolfTPM2_SetKeyAuthPassword(WOLFTPM2_KEY *key, const byte* auth,
+ int authSz)
+{
+ if ((key == NULL) || (authSz < 0)) {
+ return BAD_FUNC_ARG;
+ }
+
+ if ((auth != NULL) && (authSz == 0)) {
+ return BAD_FUNC_ARG;
+ }
+
+ /* specify auth password for storage key */
+ key->handle.auth.size = authSz;
+ XMEMCPY(key->handle.auth.buffer, auth, authSz);
+ return TPM_RC_SUCCESS;
+}
+
/* Access already started TPM module */
int wolfTPM2_OpenExisting(WOLFTPM2_DEV* dev, TPM2HalIoCb ioCb, void* userCtx)
{
diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h
index 261dd5e1..6d857c33 100644
--- a/wolftpm/tpm2_wrap.h
+++ b/wolftpm/tpm2_wrap.h
@@ -569,8 +569,8 @@ WOLFTPM_API int wolfTPM2_ChangeAuthKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
\sa wolfTPM2_CreatePrimaryKey
*/
WOLFTPM_API int wolfTPM2_CreateKey(WOLFTPM2_DEV* dev,
- WOLFTPM2_KEYBLOB* keyBlob, WOLFTPM2_HANDLE* parent, TPMT_PUBLIC* publicTemplate,
- const byte* auth, int authSz);
+ WOLFTPM2_KEYBLOB* keyBlob, WOLFTPM2_HANDLE* parent,
+ TPMT_PUBLIC* publicTemplate, const byte* auth, int authSz);
/*!
\ingroup wolfTPM2_Wrappers
@@ -2348,6 +2348,28 @@ WOLFTPM_API int wolfTPM2_ClearCryptoDevCb(WOLFTPM2_DEV* dev, int devId);
#endif /* WOLF_CRYPTO_CB */
+#ifndef WOLFTPM2_NO_HEAP
+WOLFTPM_API WOLFTPM2_DEV *wolfTPM2_New(void);
+WOLFTPM_API int wolfTPM2_Free(WOLFTPM2_DEV *dev);
+WOLFTPM_API WOLFTPM2_KEYBLOB* wolfTPM2_GetNewKeyBlob(void);
+WOLFTPM_API int wolfTPM2_CleanupKeyBlob(WOLFTPM2_KEYBLOB* blob);
+WOLFTPM_API TPMT_PUBLIC* wolfTPM2_GetNewPublicTemplate(void);
+WOLFTPM_API int wolfTPM2_CleanupPublicTemplate(TPMT_PUBLIC* template);
+WOLFTPM_API WOLFTPM2_KEY* wolfTPM2_GetNewKey(void);
+WOLFTPM_API int wolfTPM2_CleanupKey(WOLFTPM2_KEY* key);
+WOLFTPM_API WOLFTPM2_SESSION* wolfTPM2_GetNewSession(void);
+WOLFTPM_API int wolfTPM2_CleanupSession(WOLFTPM2_SESSION* session);
+#endif
+
+WOLFTPM_API int wolfTPM2_OpenExistingDev(WOLFTPM2_DEV* dev);
+WOLFTPM_API WOLFTPM2_HANDLE* wolfTPM2_GetHandleRefFromKey(WOLFTPM2_KEY* key);
+WOLFTPM_API int wolfTPM2_SetKeyAuthPassword(WOLFTPM2_KEY *key, const byte* auth,
+ int authSz);
+WOLFTPM_API int wolfTPM2_GetKeyBlobAsBuffer(byte *buffer, word32 bufferSz,
+ WOLFTPM2_KEYBLOB* key);
+WOLFTPM_API int wolfTPM2_SetKeyBlobFromBuffer(WOLFTPM2_KEYBLOB* key,
+ byte *buffer, word32 bufferSz);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/wrapper/CSharp/.runsettings b/wrapper/CSharp/.runsettings
new file mode 100644
index 00000000..fd2dd642
--- /dev/null
+++ b/wrapper/CSharp/.runsettings
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+ %PATH%;..\..\..\..\..\out\build\x64-Debug\bin
+
+
+
\ No newline at end of file
diff --git a/wrapper/CSharp/README.md b/wrapper/CSharp/README.md
new file mode 100644
index 00000000..cbecd80c
--- /dev/null
+++ b/wrapper/CSharp/README.md
@@ -0,0 +1,75 @@
+# wolfTPM (TPM 2.0) CSharp Wrappers
+
+This directory contains the CSharp wrapper for the TPM 2.0 API wrapper API.
+
+
+Once you have created the simulator, you can should build wolfssl as described
+in the README.md in the root of this repo. Then you can build wolfTPM:
+
+## Windows
+
+A Visual Studio solution is provided. This will allow you to build the
+wrappers. In order to run the tests you will need to update the
+`.runsettings` to add the location of the `wolftpm.dll`. There is a
+placeholder to leverage a vcpkg build, but cmake can also be used to
+build wolfTPM with Visual Studios.
+
+## Linux
+
+The wrapper has been tested with the swtpm TCP protocol for use with
+the simulator. Please follow instructions in the `docs/SWTPM.md` file
+for building and running the simulator.
+
+
+```
+./autogen.sh
+./configure --enable-swtpm
+make all
+make check
+```
+
+Prerequisites for linux
+
+```
+apt install mono-tools-devel nunit
+```
+
+You can then build and run the test wolfTPM:
+
+```
+cd wrapper/CSharp
+mcs wolfTPM.cs wolfTPM-tests.cs -r:/usr/lib/cli/nunit.framework-2.6.3/nunit.framework.dll -t:library
+# run selftest case
+LD_LIBRARY_PATH=../../src/.libs/ nunit-console wolfTPM.dll -run=tpm_csharp_test.WolfTPMTest.TrySelfTest
+#run all tests
+LD_LIBRARY_PATH=../../src/.libs/ nunit-console wolfTPM.dll
+```
+
+
+You should see something similar to the following output:
+
+```
+NUnit-Console version 2.6.4.0
+Copyright (C) 2002-2012 Charlie Poole.
+Copyright (C) 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov.
+Copyright (C) 2000-2002 Philip Craig.
+All Rights Reserved.
+
+Runtime Environment -
+ OS Version: Unix 5.13.0.40
+ CLR Version: 4.0.30319.42000 ( Mono 4.0 ( 6.8.0.105 (Debian 6.8.0.105+dfsg-2 Wed Feb 26 23:23:50 UTC 2020) ) )
+
+ProcessModel: Default DomainUsage: Single
+Execution Runtime: mono-4.0
+Selected test(s): tpm_csharp_test.WolfTPMTest.TryFillBufferWithRandom
+.wolfSSL Entering wolfCrypt_Init
+wolfSSL Entering wolfCrypt_Cleanup
+buf: { 44, 95, 206, 69, 252, 157, 173, 149, 26, 160, 21, 5, 35, 19, 255, 29, 251, 228, 206, 36, 77, 79, 160, 42, 25, 172, 82, 172, 152, 143, 179, 147, 52, 211, 238, 63, 34, 227, 243, 155, 17, 77, 135, 233, 103, 39, 211, 180, 55, 54, 36, 180, 87, 168, 28, 143, 104, 175, 176, 156, 154, 8, 114, 143, 123, 99, 110, 247, 46, 193, 93, 54, 208, 128, 162, 190, 225, 255, 109, 44, 8, 153, 21, 162, 139, 70, 7, 73, 13, 145, 157, 111, 20, 151, 101, 44, 45, 154, 159, 139, 153, 48, 117, 69, 179, 186, 48, 225, 20, 145, 120, 78, 58, 228, 4, 146, 241, 195, 121, 94, 44, 92, 246, 198, 71, 122, 176, 133, 21, 27, 41, 17, 7, 96, 122, 155, 105, 57, 150, 45, 63, 165, 136, 195, 173, 160, 137, 136, 207, 19, 60, 140, 2, 203, 246, 248, 179, 170, 203, 153, 154, 229, 104, 200, 141, 94, 139, 25, 103, 235, 116, 97, 186, 29, 32, 133, 205, 122, 230, 51, 88, 195, 69, 158, 199, 255, 212, 117, 3, 110, 201, 179, 138, 242, 172, 160, 121, 46, 117, 41, 185, 11, 22, 99, 4, 214, 37, 179, 246, 71, 146, 168, 116, 28, 146, 221, 53, 21, 5, 18, 84, 57, 137, 171, 237, 233, 215, 91, 88, 4, 205, 207, 218, 74, 46, 105, 106, 55, 254, 211, 186, 151, 136, 81, 128, 33, 77, 218, 203, 19, 164, 76, 177, 2, 185, 212, } (256 bytes)
+
+Tests run: 1, Errors: 0, Failures: 0, Inconclusive: 0, Time: 0.0747956 seconds
+ Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0
+```
+
+If you run this multiple time, you will see the content of the buffer changing
+for each execution.
+
diff --git a/wrapper/CSharp/include.am b/wrapper/CSharp/include.am
new file mode 100644
index 00000000..3a9c6022
--- /dev/null
+++ b/wrapper/CSharp/include.am
@@ -0,0 +1,11 @@
+# vim:ft=automake
+# All paths should be given relative to the root
+
+wrapper_CSharpdir = $(wrapperdir)/CSharp
+
+dist_wrapper_CSharp_DATA= \
+ wrapper/CSharp/README.md \
+ wrapper/CSharp/wolfTPM.cs \
+ wrapper/CSharp/wolfTPM-tests.cs \
+ wrapper/CSharp/.runsettings \
+ wrapper/CSharp/wolfTPM-csharp.csproj
diff --git a/wrapper/CSharp/wolfTPM-csharp.csproj b/wrapper/CSharp/wolfTPM-csharp.csproj
new file mode 100644
index 00000000..df87d8d1
--- /dev/null
+++ b/wrapper/CSharp/wolfTPM-csharp.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Library
+ netcoreapp3.1
+ wolfTPM_csharp
+
+
+
+
+
+
+
+
+
diff --git a/wrapper/CSharp/wolfTPM-tests.cs b/wrapper/CSharp/wolfTPM-tests.cs
new file mode 100644
index 00000000..7f6748e5
--- /dev/null
+++ b/wrapper/CSharp/wolfTPM-tests.cs
@@ -0,0 +1,326 @@
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Text;
+using wolfTPM;
+
+namespace tpm_csharp_test
+{
+ [TestFixture]
+ public class WolfTPMTest
+ {
+ /* Globals used for setup and teardown */
+ private Device device = new Device();
+ private Key parent_key;
+ private static byte[] priv_buffer = {
+ 0xd5, 0x38, 0x1b, 0xc3, 0x8f, 0xc5, 0x93, 0x0c,
+ 0x47, 0x0b, 0x6f, 0x35, 0x92, 0xc5, 0xb0, 0x8d,
+ 0x46, 0xc8, 0x92, 0x18, 0x8f, 0xf5, 0x80, 0x0a,
+ 0xf7, 0xef, 0xa1, 0xfe, 0x80, 0xb9, 0xb5, 0x2a,
+ 0xba, 0xca, 0x18, 0xb0, 0x5d, 0xa5, 0x07, 0xd0,
+ 0x93, 0x8d, 0xd8, 0x9c, 0x04, 0x1c, 0xd4, 0x62,
+ 0x8e, 0xa6, 0x26, 0x81, 0x01, 0xff, 0xce, 0x8a,
+ 0x2a, 0x63, 0x34, 0x35, 0x40, 0xaa, 0x6d, 0x80,
+ 0xde, 0x89, 0x23, 0x6a, 0x57, 0x4d, 0x9e, 0x6e,
+ 0xad, 0x93, 0x4e, 0x56, 0x90, 0x0b, 0x6d, 0x9d,
+ 0x73, 0x8b, 0x0c, 0xae, 0x27, 0x3d, 0xde, 0x4e,
+ 0xf0, 0xaa, 0xc5, 0x6c, 0x78, 0x67, 0x6c, 0x94,
+ 0x52, 0x9c, 0x37, 0x67, 0x6c, 0x2d, 0xef, 0xbb,
+ 0xaf, 0xdf, 0xa6, 0x90, 0x3c, 0xc4, 0x47, 0xcf,
+ 0x8d, 0x96, 0x9e, 0x98, 0xa9, 0xb4, 0x9f, 0xc5,
+ 0xa6, 0x50, 0xdc, 0xb3, 0xf0, 0xfb, 0x74, 0x17
+ };
+
+ private static byte[] pub_buffer = {
+ 0xc3, 0x03, 0xd1, 0x2b, 0xfe, 0x39, 0xa4, 0x32,
+ 0x45, 0x3b, 0x53, 0xc8, 0x84, 0x2b, 0x2a, 0x7c,
+ 0x74, 0x9a, 0xbd, 0xaa, 0x2a, 0x52, 0x07, 0x47,
+ 0xd6, 0xa6, 0x36, 0xb2, 0x07, 0x32, 0x8e, 0xd0,
+ 0xba, 0x69, 0x7b, 0xc6, 0xc3, 0x44, 0x9e, 0xd4,
+ 0x81, 0x48, 0xfd, 0x2d, 0x68, 0xa2, 0x8b, 0x67,
+ 0xbb, 0xa1, 0x75, 0xc8, 0x36, 0x2c, 0x4a, 0xd2,
+ 0x1b, 0xf7, 0x8b, 0xba, 0xcf, 0x0d, 0xf9, 0xef,
+ 0xec, 0xf1, 0x81, 0x1e, 0x7b, 0x9b, 0x03, 0x47,
+ 0x9a, 0xbf, 0x65, 0xcc, 0x7f, 0x65, 0x24, 0x69,
+ 0xa6, 0xe8, 0x14, 0x89, 0x5b, 0xe4, 0x34, 0xf7,
+ 0xc5, 0xb0, 0x14, 0x93, 0xf5, 0x67, 0x7b, 0x3a,
+ 0x7a, 0x78, 0xe1, 0x01, 0x56, 0x56, 0x91, 0xa6,
+ 0x13, 0x42, 0x8d, 0xd2, 0x3c, 0x40, 0x9c, 0x4c,
+ 0xef, 0xd1, 0x86, 0xdf, 0x37, 0x51, 0x1b, 0x0c,
+ 0xa1, 0x3b, 0xf5, 0xf1, 0xa3, 0x4a, 0x35, 0xe4,
+ 0xe1, 0xce, 0x96, 0xdf, 0x1b, 0x7e, 0xbf, 0x4e,
+ 0x97, 0xd0, 0x10, 0xe8, 0xa8, 0x08, 0x30, 0x81,
+ 0xaf, 0x20, 0x0b, 0x43, 0x14, 0xc5, 0x74, 0x67,
+ 0xb4, 0x32, 0x82, 0x6f, 0x8d, 0x86, 0xc2, 0x88,
+ 0x40, 0x99, 0x36, 0x83, 0xba, 0x1e, 0x40, 0x72,
+ 0x22, 0x17, 0xd7, 0x52, 0x65, 0x24, 0x73, 0xb0,
+ 0xce, 0xef, 0x19, 0xcd, 0xae, 0xff, 0x78, 0x6c,
+ 0x7b, 0xc0, 0x12, 0x03, 0xd4, 0x4e, 0x72, 0x0d,
+ 0x50, 0x6d, 0x3b, 0xa3, 0x3b, 0xa3, 0x99, 0x5e,
+ 0x9d, 0xc8, 0xd9, 0x0c, 0x85, 0xb3, 0xd9, 0x8a,
+ 0xd9, 0x54, 0x26, 0xdb, 0x6d, 0xfa, 0xac, 0xbb,
+ 0xff, 0x25, 0x4c, 0xc4, 0xd1, 0x79, 0xf4, 0x71,
+ 0xd3, 0x86, 0x40, 0x18, 0x13, 0xb0, 0x63, 0xb5,
+ 0x72, 0x4e, 0x30, 0xc4, 0x97, 0x84, 0x86, 0x2d,
+ 0x56, 0x2f, 0xd7, 0x15, 0xf7, 0x7f, 0xc0, 0xae,
+ 0xf5, 0xfc, 0x5b, 0xe5, 0xfb, 0xa1, 0xba, 0xd3
+ };
+
+ private byte[] generatedAES;
+ private byte[] generatedRSA;
+
+ private static void PrintByteArray(byte[] bytes)
+ {
+ var sb = new StringBuilder("buf: { ");
+ foreach (var b in bytes)
+ {
+ sb.Append(b + ", ");
+ }
+ sb.Append("} (");
+ sb.Append(bytes.Length);
+ sb.Append(" bytes)");
+ Console.WriteLine(sb.ToString());
+ }
+
+ void getSRK(Key srkKey, string auth)
+ {
+ int ret = device.CreateSRK(srkKey,
+ (int)TPM2_Alg.RSA,
+ auth);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+ }
+
+ [SetUp]
+ public void TestInit()
+ {
+ parent_key = new Key();
+ getSRK(parent_key, "ThisIsMyStorageKeyAuth");
+ }
+
+ [TearDown]
+ public void TestCleanup()
+ {
+ int ret = (int)Status.TPM_RC_SUCCESS;
+
+ ret = device.UnloadHandle(parent_key);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+ }
+
+ [Test]
+ public void TrySelfTest()
+ {
+ uint ret = (uint)device.SelfTest();
+ Assert.That(ret, Is.EqualTo((uint)Status.TPM_RC_SUCCESS) | Is.EqualTo(0x80280400));
+ }
+
+ [Test]
+ public void TryFillBufferWithRandom()
+ {
+ const int bufSz = 256;
+ byte[] buf = new byte[bufSz];
+ int ret = device.GetRandom(buf);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+ PrintByteArray(buf);
+
+ Assert.That(buf, Has.Some.GreaterThan(0));
+ }
+
+ [Test]
+ public void TryGenerateAndLoadRSA()
+ {
+ GenerateRSA();
+ LoadGeneratedRSA();
+ }
+
+ [Test]
+ public void TryGenerateAndLoadAES()
+ {
+ GenerateAES();
+ LoadGeneratedAES();
+ }
+
+ void GenerateRSA()
+ {
+ GenerateKey("RSA");
+ }
+
+ void GenerateAES()
+ {
+ GenerateKey("AES");
+ }
+
+ void GenerateKey(string algorithm)
+ {
+ int ret = (int)Status.TPM_RC_SUCCESS;
+ KeyBlob blob = new KeyBlob();
+ Template template = new Template();
+ byte[] blob_buffer = new byte[Device.MAX_KEYBLOB_BYTES];
+
+ if (algorithm == "RSA")
+ {
+ ret = template.GetKeyTemplate_RSA((ulong)(
+ TPM2_Object.sensitiveDataOrigin |
+ TPM2_Object.userWithAuth |
+ TPM2_Object.decrypt |
+ TPM2_Object.sign |
+ TPM2_Object.noDA));
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+ }
+ else if (algorithm == "AES")
+ {
+ ret = template.GetKeyTemplate_Symmetric(256, TPM2_Alg.CTR, true, true);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+ }
+ else
+ {
+ Console.WriteLine("Unexpected algorithm name!!!");
+ Assert.Fail();
+ }
+
+ ret = device.CreateKey(blob, parent_key, template,
+ "ThisIsMyStorageKeyAuth");
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+
+ ret = device.LoadKey(blob, parent_key);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+
+ ret = blob.GetKeyBlobAsBuffer(blob_buffer);
+
+ if (ret > 0)
+ {
+ Array.Resize(ref blob_buffer, ret);
+ if (algorithm == "RSA")
+ {
+ generatedRSA = blob_buffer;
+ }
+ else if (algorithm == "AES")
+ {
+ generatedAES = blob_buffer;
+ }
+ else
+ {
+ Console.WriteLine("Unexpected algorithm name!!!");
+ return;
+ }
+ ret = (int)Status.TPM_RC_SUCCESS;
+ }
+ else
+ {
+ Console.WriteLine("wolfTPM2_GetKeyBlobAsBuffer() failed.");
+ ret = -1;
+ }
+
+
+ ret = device.UnloadHandle(blob);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+
+ }
+
+
+ void LoadGeneratedRSA()
+ {
+ LoadGeneratedKey("RSA");
+ }
+
+ void LoadGeneratedAES()
+ {
+ LoadGeneratedKey("AES");
+ }
+
+ void LoadGeneratedKey(string algorithm)
+ {
+ int ret = (int)Status.TPM_RC_SUCCESS;
+ KeyBlob blob = new KeyBlob();
+ byte[] blob_buffer;
+
+ if (algorithm == "RSA")
+ {
+ blob_buffer = generatedRSA;
+ }
+ else if (algorithm == "AES")
+ {
+ blob_buffer = generatedAES;
+ }
+ else
+ {
+ Console.WriteLine("Unexpected algorithm name!!!");
+ return;
+ }
+
+ ret = blob.SetKeyBlobFromBuffer(blob_buffer);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+
+ ret = device.LoadKey(blob, parent_key);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+
+ ret = device.UnloadHandle(blob);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+
+ }
+
+ [Test]
+ public void TryLoadRSAPublicKey()
+ {
+ int ret = (int)Status.TPM_RC_SUCCESS;
+ Key pub_key;
+ int exp = 0x10001;
+
+ PrintByteArray(pub_buffer);
+
+ pub_key = new Key();
+
+ ret = device.LoadRsaPublicKey(pub_key, pub_buffer, exp);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+
+ ret = device.UnloadHandle(pub_key);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+ }
+
+ [Test]
+ public void TryLoadRSAPrivateKey()
+ {
+ int ret = (int)Status.TPM_RC_SUCCESS;
+
+ Key priv_key;
+ int exp = 0x10001;
+
+ PrintByteArray(pub_buffer);
+ PrintByteArray(priv_buffer);
+
+ priv_key = new Key();
+
+ ret = device.LoadRsaPrivateKey(parent_key, priv_key,
+ pub_buffer, exp,
+ priv_buffer);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+
+ ret = device.UnloadHandle(priv_key);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+ }
+
+ [Test]
+ public void TryImportRSAPrivateKey()
+ {
+ int ret = (int)Status.TPM_RC_SUCCESS;
+
+ KeyBlob blob;
+ int exp = 0x10001;
+
+ PrintByteArray(pub_buffer);
+ PrintByteArray(priv_buffer);
+
+ blob = new KeyBlob();
+
+ ret = device.ImportRsaPrivateKey(parent_key, blob,
+ pub_buffer,
+ exp, priv_buffer,
+ (uint)TPM2_Alg.NULL, (uint)TPM2_Alg.NULL);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+
+ ret = device.UnloadHandle(blob);
+ Assert.AreEqual((int)Status.TPM_RC_SUCCESS, ret);
+
+ }
+
+ }
+}
diff --git a/wrapper/CSharp/wolfTPM.cs b/wrapper/CSharp/wolfTPM.cs
new file mode 100644
index 00000000..24b9ea7e
--- /dev/null
+++ b/wrapper/CSharp/wolfTPM.cs
@@ -0,0 +1,479 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace wolfTPM
+{
+
+ public enum Status : int
+ {
+ TPM_RC_SUCCESS = 0,
+ }
+
+ public enum TPM2_Object : ulong
+ {
+ fixedTPM = 0x00000002,
+ stClear = 0x00000004,
+ fixedParent = 0x00000010,
+ sensitiveDataOrigin = 0x00000020,
+ userWithAuth = 0x00000040,
+ adminWithPolicy = 0x00000080,
+ derivedDataOrigin = 0x00000200,
+ noDA = 0x00000400,
+ encryptedDuplication = 0x00000800,
+ restricted = 0x00010000,
+ decrypt = 0x00020000,
+ sign = 0x00040000,
+ }
+
+ public enum TPM2_Alg : uint
+ {
+ ERROR = 0x0000,
+ RSA = 0x0001,
+ SHA = 0x0004,
+ SHA1 = SHA,
+ HMAC = 0x0005,
+ AES = 0x0006,
+ MGF1 = 0x0007,
+ KEYEDHASH = 0x0008,
+ XOR = 0x000A,
+ SHA256 = 0x000B,
+ SHA384 = 0x000C,
+ SHA512 = 0x000D,
+ NULL = 0x0010,
+ SM3_256 = 0x0012,
+ SM4 = 0x0013,
+ RSASSA = 0x0014,
+ RSAES = 0x0015,
+ RSAPSS = 0x0016,
+ OAEP = 0x0017,
+ ECDSA = 0x0018,
+ ECDH = 0x0019,
+ ECDAA = 0x001A,
+ SM2 = 0x001B,
+ ECSCHNORR = 0x001C,
+ ECMQV = 0x001D,
+ KDF1_SP800_56A = 0x0020,
+ KDF2 = 0x0021,
+ KDF1_SP800_108 = 0x0022,
+ ECC = 0x0023,
+ SYMCIPHER = 0x0025,
+ CAMELLIA = 0x0026,
+ CTR = 0x0040,
+ OFB = 0x0041,
+ CBC = 0x0042,
+ CFB = 0x0043,
+ ECB = 0x0044,
+ }
+
+ public enum SE : byte
+ {
+ HMAC = 0x00,
+ POLICY = 0x01,
+ TRIAL = 0x03,
+ }
+
+ public class KeyBlob
+ {
+ const string DLLNAME = "wolftpm";
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_GetNewKeyBlob")]
+ private static extern IntPtr wolfTPM2_GetNewKeyBlob();
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_CleanupKeyBlob")]
+ private static extern int wolfTPM2_CleanupKeyBlob(IntPtr blob);
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_GetKeyBlobAsBuffer")]
+ private static extern int wolfTPM2_GetKeyBlobAsBuffer(byte[] buffer,
+ int bufferSz, IntPtr key);
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_SetKeyBlobFromBuffer")]
+ private static extern int wolfTPM2_SetKeyBlobFromBuffer(IntPtr key,
+ byte[] buffer, int bufferSz);
+ internal IntPtr keyblob;
+
+ public KeyBlob()
+ {
+ keyblob = wolfTPM2_GetNewKeyBlob();
+ }
+
+ ~KeyBlob()
+ {
+ if (keyblob != IntPtr.Zero)
+ {
+ // TODO: check return value?
+ wolfTPM2_CleanupKeyBlob(keyblob);
+ }
+ }
+
+ public int GetKeyBlobAsBuffer(byte[] buffer)
+ {
+ return wolfTPM2_GetKeyBlobAsBuffer(buffer, buffer.Length, keyblob);
+ }
+
+ public int SetKeyBlobFromBuffer(byte[] buffer)
+ {
+ return wolfTPM2_SetKeyBlobFromBuffer(keyblob, buffer, buffer.Length);
+ }
+ }
+
+ public class Key
+ {
+ const string DLLNAME = "wolftpm";
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_GetNewKey")]
+ private static extern IntPtr wolfTPM2_GetNewKey();
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_CleanupKey")]
+ private static extern int wolfTPM2_CleanupKey(IntPtr key);
+
+ /* ================================================================== */
+ /* Native Getters and Setters */
+ /* ================================================================== */
+
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_SetKeyAuthPassword")]
+ private static extern int wolfTPM2_SetKeyAuthPassword(
+ IntPtr key,
+ string auth,
+ int authSz);
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_GetHandleRefFromKey")]
+ private static extern IntPtr wolfTPM2_GetHandleRefFromKey(IntPtr key);
+
+ internal IntPtr key;
+
+ public Key()
+ {
+ key = wolfTPM2_GetNewKey();
+ }
+
+ ~Key()
+ {
+ if (key != IntPtr.Zero)
+ {
+ // TODO: check return value
+ wolfTPM2_CleanupKey(key);
+ }
+ }
+
+ public IntPtr GetHandleRefFromKey()
+ {
+ return wolfTPM2_GetHandleRefFromKey(key);
+ }
+
+ public int SetKeyAuthPassword(string auth)
+ {
+ return wolfTPM2_SetKeyAuthPassword(key,
+ auth,
+ auth.Length);
+ }
+
+ }
+
+ public class Template
+ {
+ const string DLLNAME = "wolftpm";
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_GetNewPublicTemplate")]
+ private static extern IntPtr wolfTPM2_GetNewPublicTemplate();
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_CleanupPublicTemplate")]
+ private static extern int wolfTPM2_CleanupPublicTemplate(IntPtr template);
+
+ internal IntPtr template;
+ public Template()
+ {
+ template = wolfTPM2_GetNewPublicTemplate();
+ }
+
+ ~Template()
+ {
+ wolfTPM2_CleanupPublicTemplate(template);
+ }
+
+ /* non-device functions: template and auth */
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_GetKeyTemplate_RSA")]
+ private static extern int wolfTPM2_GetKeyTemplate_RSA(IntPtr publicTemplate,
+ ulong objectAttributes);
+ public int GetKeyTemplate_RSA(ulong objectAttributes)
+ {
+ return wolfTPM2_GetKeyTemplate_RSA(template,
+ objectAttributes);
+ }
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_GetKeyTemplate_Symmetric")]
+ private static extern int wolfTPM2_GetKeyTemplate_Symmetric(
+ IntPtr publicTemplate, int keyBits, uint algMode, int isSign,
+ int isDecrypt);
+
+ public int GetKeyTemplate_Symmetric(int keyBits,
+ TPM2_Alg algMode,
+ bool isSign,
+ bool isDecrypt)
+ {
+ return wolfTPM2_GetKeyTemplate_Symmetric(template,
+ keyBits,
+ (uint)algMode,
+ isSign ? 1 : 0,
+ isDecrypt ? 1 : 0);
+ }
+
+
+ }
+
+ public class Session
+ {
+ const string DLLNAME = "wolftpm";
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_GetNewSession")]
+ private static extern IntPtr wolfTPM2_GetNewSession();
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_CleanupSession")]
+ private static extern int wolfTPM2_CleanupSession(IntPtr session);
+
+
+ internal IntPtr session;
+
+ public Session()
+ {
+ session = wolfTPM2_GetNewSession();
+ }
+
+ ~Session()
+ {
+ if (session != IntPtr.Zero)
+ {
+ // TODO: check return value
+ wolfTPM2_CleanupSession(session);
+ }
+ }
+
+ }
+
+ public class Device
+ {
+ /* ================================================================== */
+ /* Constants */
+ /* ================================================================== */
+
+ const string DLLNAME = "wolftpm";
+
+ public const int MAX_KEYBLOB_BYTES = 1024;
+ private IntPtr device = IntPtr.Zero;
+
+ public Device()
+ {
+ device = wolfTPM2_New();
+ }
+
+ ~Device()
+ {
+ if (device != IntPtr.Zero)
+ {
+ wolfTPM2_Free(device);
+ }
+ }
+ /* Note that this one is not an empty; it actually calls wolfTPM2_Init()
+ * as a convenience for the user. */
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_New")]
+ private static extern IntPtr wolfTPM2_New();
+
+ /* WOLFTPM_API int wolfTPM2_SimpleCleanup(WOLFTPM2_DEV *dev); */
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_Free")]
+ private static extern int wolfTPM2_Free(IntPtr dev);
+
+ /* ================================================================== */
+ /* Native Wrappers */
+ /* ================================================================== */
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_SelfTest")]
+ private static extern int wolfTPM2_SelfTest(IntPtr dev);
+ public int SelfTest()
+ {
+ return wolfTPM2_SelfTest(device);
+ }
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_GetRandom")]
+ private static extern int wolfTPM2_GetRandom(IntPtr dev,
+ byte[] buf,
+ int len);
+ public int GetRandom(byte[] buf)
+ {
+ return wolfTPM2_GetRandom(device, buf, buf.Length);
+ }
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_CreateSRK")]
+ private static extern int wolfTPM2_CreateSRK(IntPtr dev,
+ IntPtr srkKey,
+ int alg,
+ string auth,
+ int authSz);
+ public int CreateSRK(Key srkKey,
+ int alg,
+ string auth)
+ {
+ return wolfTPM2_CreateSRK(device,
+ srkKey.key,
+ alg,
+ auth,
+ auth.Length);
+ }
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_StartSession")]
+ private static extern int wolfTPM2_StartSession(IntPtr dev, IntPtr session,
+ IntPtr tmpKey, IntPtr bind, byte sesType, int encDecAlg);
+ public int StartSession(IntPtr session,
+ Key tmpKey,
+ IntPtr bind,
+ byte sesType,
+ int encDecAlg)
+ {
+ return wolfTPM2_StartSession(device,
+ session,
+ tmpKey.key,
+ bind,
+ sesType,
+ encDecAlg);
+ }
+
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_ReadPublicKey")]
+ private static extern int wolfTPM2_ReadPublicKey(IntPtr dev,
+ IntPtr key,
+ ulong handle);
+ public int ReadPublicKey(Key key,
+ ulong handle)
+ {
+ return wolfTPM2_ReadPublicKey(device,
+ key.key,
+ handle);
+ }
+
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_CreateKey")]
+ private static extern int wolfTPM2_CreateKey(
+ IntPtr dev,
+ IntPtr keyBlob,
+ IntPtr parent,
+ IntPtr publicTemplate,
+ string auth,
+ int authSz);
+ public int CreateKey(KeyBlob keyBlob,
+ Key parent,
+ Template publicTemplate,
+ string auth)
+ {
+ return wolfTPM2_CreateKey(device,
+ keyBlob.keyblob,
+ parent.GetHandleRefFromKey(),
+ publicTemplate.template,
+ auth,
+ auth.Length);
+ }
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_LoadKey")]
+ private static extern int wolfTPM2_LoadKey(
+ IntPtr dev,
+ IntPtr keyBlob,
+ IntPtr parent);
+ public int LoadKey(KeyBlob keyBlob,
+ Key parent)
+ {
+ return wolfTPM2_LoadKey(device, keyBlob.keyblob, parent.GetHandleRefFromKey());
+ }
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_ImportRsaPrivateKey")]
+ private static extern int wolfTPM2_ImportRsaPrivateKey(
+ IntPtr dev,
+ IntPtr parentKey,
+ IntPtr keyBlob,
+ byte[] rsaPub,
+ int rsaPubSz,
+ int exponent,
+ byte[] rsaPriv,
+ int rsaPrivSz,
+ uint scheme,
+ uint hashAlg);
+
+ public int ImportRsaPrivateKey(
+ Key parentKey,
+ KeyBlob keyBlob,
+ byte[] rsaPub,
+ int exponent,
+ byte[] rsaPriv,
+ uint scheme,
+ uint hashAlg)
+ {
+ return wolfTPM2_ImportRsaPrivateKey(device,
+ parentKey.key,
+ keyBlob.keyblob,
+ rsaPub,
+ rsaPub.Length,
+ exponent,
+ rsaPriv,
+ rsaPriv.Length,
+ scheme,
+ hashAlg);
+ }
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_LoadRsaPublicKey")]
+ private static extern int wolfTPM2_LoadRsaPublicKey(
+ IntPtr dev,
+ IntPtr key,
+ byte[] rsaPub,
+ int rsaPubSz,
+ int exponent);
+ public int LoadRsaPublicKey(Key key,
+ byte[] rsaPub,
+ int exponent)
+ {
+ return wolfTPM2_LoadRsaPublicKey(device,
+ key.key,
+ rsaPub,
+ rsaPub.Length,
+ exponent);
+ }
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_LoadRsaPrivateKey")]
+ private static extern int wolfTPM2_LoadRsaPrivateKey(
+ IntPtr dev,
+ IntPtr parentKey,
+ IntPtr key,
+ byte[] rsaPub,
+ int rsaPubSz,
+ int exponent,
+ byte[] rsaPriv,
+ int rsaPrivSz);
+ public int LoadRsaPrivateKey(
+ Key parentKey,
+ Key key,
+ byte[] rsaPub,
+ int exponent,
+ byte[] rsaPriv)
+ {
+ return wolfTPM2_LoadRsaPrivateKey(
+ device,
+ parentKey.key,
+ key.key,
+ rsaPub,
+ rsaPub.Length,
+ exponent,
+ rsaPriv,
+ rsaPriv.Length);
+ }
+
+ [DllImport(DLLNAME, EntryPoint = "wolfTPM2_UnloadHandle")]
+ private static extern int wolfTPM2_UnloadHandle(IntPtr dev, IntPtr handle);
+ public int UnloadHandle(Key key)
+ {
+ return wolfTPM2_UnloadHandle(device, key.key);
+ }
+
+ public int UnloadHandle(KeyBlob keyblob)
+ {
+ return wolfTPM2_UnloadHandle(device, keyblob.keyblob);
+ }
+
+
+ }
+}
diff --git a/wrapper/include.am b/wrapper/include.am
new file mode 100644
index 00000000..991a32ac
--- /dev/null
+++ b/wrapper/include.am
@@ -0,0 +1,7 @@
+# vim:ft=automake
+# All paths should be given relative to the root
+
+include wrapper/CSharp/include.am
+
+wrapperdir = $(docdir)/wrapper
+dist_wrapper_DATA= wrapper/wolfTPM-csharp.sln
diff --git a/wrapper/wolfTPM-csharp.sln b/wrapper/wolfTPM-csharp.sln
new file mode 100644
index 00000000..9ee0779d
--- /dev/null
+++ b/wrapper/wolfTPM-csharp.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31205.134
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "wolfTPM-csharp", "CSharp\wolfTPM-csharp.csproj", "{B94757A8-B2A3-4289-887D-A0B23C34F418}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B94757A8-B2A3-4289-887D-A0B23C34F418}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B94757A8-B2A3-4289-887D-A0B23C34F418}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B94757A8-B2A3-4289-887D-A0B23C34F418}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B94757A8-B2A3-4289-887D-A0B23C34F418}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C5F3DA80-4658-45F2-9224-EF22CAD6108B}
+ EndGlobalSection
+EndGlobal