From e601803f1bb473def2236214aa9b87d1d70495b1 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 30 Nov 2023 11:00:20 -0800 Subject: [PATCH 1/5] Added support for PK callbacks with RSA Sign using PKCSv1.5 and PSS. Fixes for building wolfTPM without crypto callbacks. Fixes for building/running with FIPS. --- docs/WindowTBS.md | 2 + examples/csr/csr.c | 8 +- examples/run_examples.sh | 7 +- examples/tls/tls_client.c | 58 +++-- examples/tls/tls_server.c | 46 +++- examples/wrap/wrap_test.c | 2 + src/tpm2.c | 17 +- src/tpm2_cryptocb.c | 441 +++++++++++++++++++++++++++++++++++++- src/tpm2_wrap.c | 6 +- tests/unit_tests.c | 3 +- wolftpm/tpm2_types.h | 3 + wolftpm/tpm2_wrap.h | 51 ++++- 12 files changed, 610 insertions(+), 34 deletions(-) diff --git a/docs/WindowTBS.md b/docs/WindowTBS.md index 0a6b353f..7bab18dd 100644 --- a/docs/WindowTBS.md +++ b/docs/WindowTBS.md @@ -46,6 +46,8 @@ make ./examples ``` +Note: To install the development base tools on MSYS2 use: `pacman -s base-devel` and `pacman -S mingw-w64-x86_64-toolchain`. + ## Building on linux Tested using mingw-w32-bin_x86_64-linux_20131221.tar.bz2 diff --git a/examples/csr/csr.c b/examples/csr/csr.c index b0a12d3a..38ea0dc2 100644 --- a/examples/csr/csr.c +++ b/examples/csr/csr.c @@ -25,7 +25,8 @@ #include -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM2_CERT_GEN) +#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM2_CERT_GEN) && \ + defined(WOLFTPM_CRYPTOCB) #include #include @@ -252,14 +253,15 @@ int TPM2_CSR_ExampleArgs(void* userCtx, int argc, char *argv[]) /* --- END TPM2 CSR Example -- */ /******************************************************************************/ -#endif /* !WOLFTPM2_NO_WRAPPER && WOLFTPM2_CERT_GEN */ +#endif /* !WOLFTPM2_NO_WRAPPER && WOLFTPM2_CERT_GEN && WOLFTPM_CRYPTOCB */ #ifndef NO_MAIN_DRIVER int main(int argc, char *argv[]) { int rc = -1; -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM2_CERT_GEN) +#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM2_CERT_GEN) && \ + defined(WOLFTPM_CRYPTOCB) rc = TPM2_CSR_ExampleArgs(NULL, argc, argv); #else (void)argc; diff --git a/examples/run_examples.sh b/examples/run_examples.sh index 2ed37338..129544c7 100755 --- a/examples/run_examples.sh +++ b/examples/run_examples.sh @@ -176,9 +176,11 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ]; then [ $RESULT -ne 0 ] && echo -e "pkcs7 failed! $RESULT" && exit 1 fi -# TLS Tests RSA +# TLS Tests echo -e "TLS tests" -generate_port() { # function to produce a random port number +generate_port() { + # for now it is okay to use the same port + # Note: The SW TPM uses many local ports, which can cause bind() issue port=11111 echo -e "Using port $port" echo -e "Using port $port" >> run.out @@ -193,6 +195,7 @@ run_tpm_tls_client() { # Usage: run_tpm_tls_client [ecc/rsa] [tpmargs]] [ $RESULT -ne 0 ] && echo -e "tls server $1 $2 failed! $RESULT" && exit 1 popd >> run.out sleep 0.1 + ./examples/tls/tls_client -p=$port -$1 $2 2>&1 >> run.out RESULT=$? [ $RESULT -ne 0 ] && echo -e "tpm tls client $1 $2 failed! $RESULT" && exit 1 diff --git a/examples/tls/tls_client.c b/examples/tls/tls_client.c index 017c02bf..aa63ee5b 100644 --- a/examples/tls/tls_client.c +++ b/examples/tls/tls_client.c @@ -25,7 +25,7 @@ #include -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_CRYPTOCB) && \ +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFCRYPT_ONLY) #include @@ -83,6 +83,9 @@ static void usage(void) printf("* -ecc: Use RSA or ECC key\n"); printf("* -aes/xor: Use Parameter Encryption\n"); printf("* -p=port: Supply a custom port number (default %d)\n", TLS_PORT); +#if defined(WOLFTPM_CRYPTOCB) && defined(HAVE_PK_CALLBACKS) + printf("* -pk: Use PK callbacks, not crypto callbacks\n"); +#endif } int TPM2_TLS_Client(void* userCtx) @@ -108,7 +111,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) #endif TpmCryptoDevCtx tpmCtx; SockIoCbCtx sockIoCtx; - int tpmDevId; + int tpmDevId = INVALID_DEVID; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; #ifndef TLS_BENCH_MODE @@ -121,6 +124,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) int i; #endif int useECC = 0; + int usePK = 0; TPM_ALG_ID paramEncAlg = TPM_ALG_NULL; WOLFTPM2_SESSION tpmSession; TPMT_PUBLIC publicTemplate; @@ -139,6 +143,10 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) #ifdef HAVE_ECC XMEMSET(&eccKey, 0, sizeof(eccKey)); XMEMSET(&wolfEccKey, 0, sizeof(wolfEccKey)); + #ifndef WOLFTPM2_USE_SW_ECDHE + /* Ephemeral Key */ + XMEMSET(&ecdhKey, 0, sizeof(ecdhKey)); + #endif #endif XMEMSET(&tpmSession, 0, sizeof(tpmSession)); @@ -163,6 +171,11 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) else if (XSTRCMP(argv[argc-1], "-xor") == 0) { paramEncAlg = TPM_ALG_XOR; } + #if defined(WOLFTPM_CRYPTOCB) && defined(HAVE_PK_CALLBACKS) + else if (XSTRCMP(argv[argc-1], "-pk") == 0) { + usePK = 1; + } + #endif else if (XSTRNCMP(argv[argc-1], "-p=", XSTRLEN("-p=")) == 0) { const char* portStr = argv[argc-1] + XSTRLEN("-p="); port = (word32)XATOI(portStr); @@ -183,6 +196,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) } /* Setup the wolf crypto device callback */ + tpmCtx.dev = &dev; #ifndef NO_RSA tpmCtx.rsaKey = &rsaKey; #endif @@ -193,9 +207,14 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) #ifdef WOLFTPM_USE_SYMMETRIC tpmCtx.useSymmetricOnTPM = 1; #endif - rc = wolfTPM2_SetCryptoDevCb(&dev, wolfTPM2_CryptoDevCb, &tpmCtx, &tpmDevId); - if (rc != 0) goto exit; +#ifdef WOLFTPM_CRYPTOCB + if (!usePK) { + rc = wolfTPM2_SetCryptoDevCb(&dev, wolfTPM2_CryptoDevCb, &tpmCtx, &tpmDevId); + if (rc != 0) goto exit; + } +#endif + /* See if primary storage key already exists */ rc = getPrimaryStoragekey(&dev, &storageKey, TPM_ALG_RSA); if (rc != 0) goto exit; @@ -209,7 +228,8 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) /* set session for authorization of the storage key */ rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession, - (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | TPMA_SESSION_continueSession)); + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); if (rc != 0) goto exit; } @@ -251,7 +271,6 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) #ifndef WOLFTPM2_USE_SW_ECDHE /* Ephemeral Key */ - XMEMSET(&ecdhKey, 0, sizeof(ecdhKey)); tpmCtx.ecdhKey = &ecdhKey; #endif #endif /* HAVE_ECC */ @@ -269,6 +288,13 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) wolfSSL_CTX_SetIORecv(ctx, SockIORecv); wolfSSL_CTX_SetIOSend(ctx, SockIOSend); + /* Setup PK callbacks */ +#ifdef HAVE_PK_CALLBACKS + if (usePK) { + wolfTPM_PK_SetCb(ctx); + } +#endif + /* Server certificate validation */ /* Note: Can use "WOLFSSL_VERIFY_NONE" to skip server cert validation */ wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify); @@ -456,6 +482,13 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) goto exit; } + /* Setup PK Callback context */ +#ifdef HAVE_PK_CALLBACKS + if (usePK) { + wolfTPM_PK_SetCbCtx(ssl, &tpmCtx); + } +#endif + /* Setup socket and connection */ rc = SetupSocketAndConnect(&sockIoCtx, TLS_HOST, port); if (rc != 0) goto exit; @@ -564,10 +597,11 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) printf("Shutdown not complete\n"); } - CloseAndCleanupSocket(&sockIoCtx); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); + CloseAndCleanupSocket(&sockIoCtx); + wolfTPM2_UnloadHandle(&dev, &storageKey.handle); #ifndef NO_RSA wc_FreeRsaKey(&wolfRsaKey); @@ -591,23 +625,23 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) /* --- END TPM TLS Client Example -- */ /******************************************************************************/ -#endif /* !WOLFTPM2_NO_WRAPPER && WOLFTPM_CRYPTOCB && !NO_WOLFSSL_CLIENT && \ - * !WOLFCRYPT_ONLY */ +#endif /* !WOLFTPM2_NO_WRAPPER && !WOLFTPM2_NO_WOLFCRYPT && !NO_WOLFSSL_CLIENT \ + * && !WOLFCRYPT_ONLY */ #ifndef NO_MAIN_DRIVER int main(int argc, char* argv[]) { int rc = -1; -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_CRYPTOCB) && \ +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFCRYPT_ONLY) rc = TPM2_TLS_ClientArgs(NULL, argc, argv); #else (void)argc; (void)argv; - printf("Wrapper/Crypto callback code or TLS support not compiled in\n"); - printf("Build wolfssl with ./configure --enable-cryptocb\n"); + printf("TPM Wrapper or PK//Crypto callback or TLS support not compiled in\n"); + printf("Build wolfssl with ./configure --enable-wolftpm\n"); #endif return rc; diff --git a/examples/tls/tls_server.c b/examples/tls/tls_server.c index 16684b98..ca96847c 100644 --- a/examples/tls/tls_server.c +++ b/examples/tls/tls_server.c @@ -25,7 +25,7 @@ #include -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_CRYPTOCB) && \ +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ !defined(NO_WOLFSSL_SERVER) && !defined(WOLFCRYPT_ONLY) #include @@ -80,6 +80,9 @@ static void usage(void) printf("* -ecc: Use RSA or ECC key\n"); printf("* -aes/xor: Use Parameter Encryption\n"); printf("* -p=port: Supply a custom port number (default %d)\n", TLS_PORT); +#if defined(WOLFTPM_CRYPTOCB) && defined(HAVE_PK_CALLBACKS) + printf("* -pk: Use PK callbacks, not crypto callbacks\n"); +#endif } int TPM2_TLS_Server(void* userCtx) @@ -104,7 +107,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) #endif TpmCryptoDevCtx tpmCtx; SockIoCbCtx sockIoCtx; - int tpmDevId; + int tpmDevId = INVALID_DEVID; WOLFSSL_CTX* ctx = NULL; WOLFSSL* ssl = NULL; #ifndef TLS_BENCH_MODE @@ -128,6 +131,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) int total_size; #endif int useECC = 0; + int usePK = 0; TPM_ALG_ID paramEncAlg = TPM_ALG_NULL; WOLFTPM2_SESSION tpmSession; TPMT_PUBLIC publicTemplate; @@ -174,6 +178,11 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) else if (XSTRCMP(argv[argc-1], "-xor") == 0) { paramEncAlg = TPM_ALG_XOR; } + #if defined(WOLFTPM_CRYPTOCB) && defined(HAVE_PK_CALLBACKS) + else if (XSTRCMP(argv[argc-1], "-pk") == 0) { + usePK = 1; + } + #endif else if (XSTRNCMP(argv[argc-1], "-p=", XSTRLEN("-p=")) == 0) { const char* portStr = argv[argc-1] + XSTRLEN("-p="); port = (word32)XATOI(portStr); @@ -197,6 +206,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) } /* Setup the wolf crypto device callback */ + tpmCtx.dev = &dev; #ifndef NO_RSA tpmCtx.rsaKey = &rsaKey; #endif @@ -207,9 +217,13 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) #ifdef WOLFTPM_USE_SYMMETRIC tpmCtx.useSymmetricOnTPM = 1; #endif - rc = wolfTPM2_SetCryptoDevCb(&dev, wolfTPM2_CryptoDevCb, &tpmCtx, &tpmDevId); - if (rc != 0) goto exit; +#ifdef WOLFTPM_CRYPTOCB + if (!usePK) { + rc = wolfTPM2_SetCryptoDevCb(&dev, wolfTPM2_CryptoDevCb, &tpmCtx, &tpmDevId); + if (rc != 0) goto exit; + } +#endif /* See if primary storage key already exists */ rc = getPrimaryStoragekey(&dev, &storageKey, TPM_ALG_RSA); if (rc != 0) goto exit; @@ -285,6 +299,13 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) wolfSSL_CTX_SetIORecv(ctx, SockIORecv); wolfSSL_CTX_SetIOSend(ctx, SockIOSend); + /* Setup PK callbacks */ +#ifdef HAVE_PK_CALLBACKS + if (usePK) { + wolfTPM_PK_SetCb(ctx); + } +#endif + /* Server certificate validation */ #if 0 /* skip server cert validation for this test */ @@ -439,6 +460,13 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) goto exit; } + /* Setup PK Callback context */ +#ifdef HAVE_PK_CALLBACKS + if (usePK) { + wolfTPM_PK_SetCbCtx(ssl, &tpmCtx); + } +#endif + /* Setup socket and connection */ rc = SetupSocketAndListen(&sockIoCtx, port); if (rc != 0) goto exit; @@ -568,23 +596,23 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) /* --- END TLS Server Example -- */ /******************************************************************************/ -#endif /* !WOLFTPM2_NO_WRAPPER && WOLFTPM_CRYPTOCB && !NO_WOLFSSL_SERVER && \ - * !WOLFCRYPT_ONLY */ +#endif /* !WOLFTPM2_NO_WRAPPER && !WOLFTPM2_NO_WOLFCRYPT && !NO_WOLFSSL_SERVER \ + * && !WOLFCRYPT_ONLY */ #ifndef NO_MAIN_DRIVER int main(int argc, char* argv[]) { int rc = -1; -#if !defined(WOLFTPM2_NO_WRAPPER) && defined(WOLFTPM_CRYPTOCB) && \ +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ !defined(NO_WOLFSSL_SERVER) && !defined(WOLFCRYPT_ONLY) rc = TPM2_TLS_ServerArgs(NULL, argc, argv); #else (void)argc; (void)argv; - printf("Wrapper/Crypto callback code or TLS support not compiled in\n"); - printf("Build wolfssl with ./configure --enable-cryptocb\n"); + printf("TPM Wrapper or PK//Crypto callback or TLS support not compiled in\n"); + printf("Build wolfssl with ./configure --enable-wolftpm\n"); #endif return rc; diff --git a/examples/wrap/wrap_test.c b/examples/wrap/wrap_test.c index ea2b0b78..cc347c75 100644 --- a/examples/wrap/wrap_test.c +++ b/examples/wrap/wrap_test.c @@ -437,8 +437,10 @@ int TPM2_Wrapper_TestArgs(void* userCtx, int argc, char *argv[]) rc = wc_InitRsaKey(&wolfRsaPrivKey, NULL); if (rc != 0) goto exit; idx = 0; + PRIVATE_KEY_UNLOCK(); rc = wc_RsaPrivateKeyDecode(kRsaKeyPrivDer, &idx, &wolfRsaPrivKey, (word32)sizeof(kRsaKeyPrivDer)); + PRIVATE_KEY_LOCK(); if (rc != 0) goto exit; rc = wolfTPM2_RsaKey_WolfToTpm_ex(&dev, &storageKey, &wolfRsaPrivKey, &rsaKey); diff --git a/src/tpm2.c b/src/tpm2.c index 7450fe8d..d714144f 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -442,6 +442,19 @@ static TPM_RC TPM2_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet) } #ifndef WOLFTPM2_NO_WOLFCRYPT +#ifdef HAVE_FIPS +static void WolfFipsCb(int ok, int err, const char* hash) +{ + printf("in my Fips callback, ok = %d, err = %d\n", ok, err); + printf("message = %s\n", wc_GetErrorString(err)); + printf("hash = %s\n", hash); + + if (err == IN_CORE_FIPS_E) { + printf("In core integrity hash check failure, copy above hash\n"); + printf("into verifyCore[] in fips_test.c and rebuild\n"); + } +} +#endif static inline int TPM2_WolfCrypt_Init(void) { int rc = 0; @@ -451,7 +464,9 @@ static inline int TPM2_WolfCrypt_Init(void) #ifdef DEBUG_WOLFSSL wolfSSL_Debugging_ON(); #endif - + #ifdef HAVE_FIPS + wolfCrypt_SetCb_fips(WolfFipsCb); + #endif rc = wolfCrypt_Init(); #ifdef WC_RNG_SEED_CB if (rc == 0) diff --git a/src/tpm2_cryptocb.c b/src/tpm2_cryptocb.c index d738e2ce..844576ee 100644 --- a/src/tpm2_cryptocb.c +++ b/src/tpm2_cryptocb.c @@ -21,7 +21,9 @@ #include -#if defined(WOLFTPM_CRYPTOCB) && !defined(WOLFTPM2_NO_WRAPPER) +#if !defined(WOLFTPM2_NO_WRAPPER) + +#ifdef WOLFTPM_CRYPTOCB /* Internal structure for tracking hash state */ typedef struct WOLFTPM2_HASHCTX { @@ -687,5 +689,440 @@ static int wolfTPM2_HashUpdateCache(WOLFTPM2_HASHCTX* hashCtx, return ret; } #endif /* WOLFTPM_USE_SYMMETRIC */ +#endif /* WOLFTPM_CRYPTOCB */ + + +#if defined(HAVE_PK_CALLBACKS) && !defined(WOLFCRYPT_ONLY) + +#ifndef NO_RSA + +#ifndef RSA_MAX_SIZE +#define RSA_MAX_SIZE 4096 +#endif + +/* Padding Function, PKCSv15 (not exposed in wolfCrypt FIPS 3389) */ +static int RsaPadPkcsv15Type1(const byte* input, word32 inputLen, + byte* pkcsBlock, word32 pkcsBlockLen) +{ + if (input == NULL || inputLen == 0 || pkcsBlock == NULL || + pkcsBlockLen == 0) { + return BAD_FUNC_ARG; + } + if (pkcsBlockLen > RSA_MAX_SIZE/8) { + return RSA_BUFFER_E; + } + if (pkcsBlockLen - RSA_MIN_PAD_SZ < inputLen) { + #ifdef DEBUG_WOLFTPM + printf("RsaPad error, invalid length\n"); + #endif + return RSA_PAD_E; + } + + pkcsBlock[0] = 0x0; /* set first byte to zero and advance */ + pkcsBlock++; pkcsBlockLen--; + pkcsBlock[0] = RSA_BLOCK_TYPE_1; /* insert padValue */ + + /* pad with 0xff bytes */ + XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2); + + pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */ + XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); + + return 0; +} + +int wolfTPM2_PK_RsaSign(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, word32* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx) +{ + int ret; + RsaKey rsapub; + TpmCryptoDevCtx* tlsCtx = (TpmCryptoDevCtx*)ctx; + + (void)ssl; + +#ifdef DEBUG_WOLFTPM + printf("PK RSA Sign: inSz %u, keySz %u\n", inSz, keySz); +#endif + + /* load RSA public key */ + ret = wc_InitRsaKey(&rsapub, NULL); + if (ret == 0) { + word32 keyIdx = 0; + ret = wc_RsaPublicKeyDecode(keyDer, &keyIdx, &rsapub, (word32)keySz); + if (ret == 0) { + byte inPad[RSA_MAX_SIZE/8]; + word32 inPadSz = wc_RsaEncryptSize(&rsapub); + /* Pad with PKCSv1.5 type 1 */ + ret = RsaPadPkcsv15Type1(in, inSz, inPad, inPadSz); + if (ret == 0) { + /* private operations */ + ret = wolfTPM2_RsaDecrypt(tlsCtx->dev, tlsCtx->rsaKey, + TPM_ALG_NULL, /* no padding */ + inPad, inPadSz, + out, (int*)outSz); + } + } + wc_FreeRsaKey(&rsapub); + } + + if (ret > 0) { + ret = WC_HW_E; + } + +#ifdef DEBUG_WOLFTPM + printf("PK RSA Sign: ret %d, outSz %u\n", ret, *outSz); +#endif + return ret; +} + +int wolfTPM2_PK_RsaSignCheck(WOLFSSL* ssl, + unsigned char* sig, unsigned int sigSz, + unsigned char** out, + const unsigned char* keyDer, unsigned int keySz, + void* ctx) +{ + TpmCryptoDevCtx* tlsCtx = (TpmCryptoDevCtx*)ctx; + + (void)ssl; + (void)sig; + (void)sigSz; + (void)out; + (void)keyDer; + (void)keySz; + (void)tlsCtx; + /* We used sign hardware, so assume sign is good */ + return 0; +} + +#ifdef WC_RSA_PSS + +/* Uses MGF1 standard as a mask generation function + hType: hash type used + seed: seed to use for generating mask + seedSz: size of seed buffer + out: mask output after generation + outSz: size of output buffer + */ +static int RsaMGF1(wc_HashAlg* hash, enum wc_HashType hType, + byte* seed, word32 seedSz, byte* out, word32 outSz) +{ + int ret; + byte tmp[RSA_MAX_SIZE/8]; + word32 tmpSz = 0, counter = 0, idx = 0; + int hLen, i = 0; + + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) { + return hLen; + } + + /* find largest amount of memory needed, which will be the max of + * hLen and (seedSz + 4) since tmp is used to store the hash digest */ + tmpSz = ((seedSz + 4) > (word32)hLen) ? seedSz + 4: (word32)hLen; + if (tmpSz > sizeof(tmp)) { + return BAD_FUNC_ARG; + } + + do { + XMEMCPY(tmp, seed, seedSz); + + /* counter to byte array appended to tmp */ + tmp[seedSz] = (byte)((counter >> 24) & 0xFF); + tmp[seedSz + 1] = (byte)((counter >> 16) & 0xFF); + tmp[seedSz + 2] = (byte)((counter >> 8) & 0xFF); + tmp[seedSz + 3] = (byte)((counter) & 0xFF); + + /* hash and append to existing output */ + ret = wc_HashUpdate(hash, hType, tmp, (seedSz + 4)); + if (ret == 0) { + ret = wc_HashFinal(hash, hType, tmp); + } + if (ret == 0) { + for (i = 0; i < hLen && idx < outSz; i++) { + out[idx++] = tmp[i]; + } + } + counter++; + } while (ret == 0 && idx < outSz); + + return ret; +} + +/* This routine performs a bitwise XOR operation of <*buf> and <*mask> of n + * counts, placing the result in <*buf>. */ +static void xorbuf(void* buf, const void* mask, word32 count) +{ + word32 i; + byte* b = (byte*)buf; + const byte* m = (const byte*)mask; + for (i = 0; i < count; i++) { + b[i] ^= m[i]; + } +} + +/* 0x00 .. 0x00 0x01 | Salt | Gen Hash | 0xbc + * XOR MGF over all bytes down to end of Salt + * Gen Hash = HASH(8 * 0x00 | Message Hash | Salt) + * + * input Digest of the message. + * inputLen Length of digest. + * pkcsBlock Buffer to write to. + * pkcsBlockLen Length of buffer to write to. + * rng Random number generator (for salt). + * htype Hash function to use. + * mgf Mask generation function. + * saltLen Length of salt to put in padding. + * bits Length of key in bits. + * returns 0 on success, PSS_SALTLEN_E when the salt length is invalid + * and other negative values on error. + */ +static int RsaPadPss(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, WC_RNG* rng, int hash, int mgf, + int saltLen, int bits) +{ + int ret = 0, hLen, o, maskLen, hiBits; + byte *m, *s, *salt; + byte msg[RSA_MAX_SIZE/8 + RSA_PSS_PAD_SZ]; + enum wc_HashType hType; + wc_HashAlg hashCtx; /* big stack consumer */ + + switch (hash) { + #ifndef NO_SHA256 + case SHA256h: + hType = WC_HASH_TYPE_SHA256; + break; + #endif + #ifdef WOLFSSL_SHA384 + case SHA384h: + hType = WC_HASH_TYPE_SHA384; + break; + #endif + #ifdef WOLFSSL_SHA512 + case SHA512h: + hType = WC_HASH_TYPE_SHA512; + break; + #endif + default: + return NOT_COMPILED_IN; + } + + ret = wc_HashGetDigestSize(hType); + if (ret < 0) { + return ret; + } + hLen = ret; + + if ((int)inputLen != hLen) { + return BAD_FUNC_ARG; + } + + hiBits = (bits - 1) & 0x7; + if (hiBits == 0) { + /* Per RFC8017, set the leftmost 8emLen - emBits bits of the + * leftmost octet in DB to zero. */ + *(pkcsBlock++) = 0; + pkcsBlockLen--; + } + + if (saltLen == RSA_PSS_SALT_LEN_DEFAULT) { + saltLen = hLen; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE) { + saltLen = RSA_PSS_SALT_MAX_SZ; + } + #endif + } + if ((int)pkcsBlockLen - hLen < saltLen + 2) { + return PSS_SALTLEN_E; + } + + ret = wc_HashInit_ex(&hashCtx, hType, NULL, INVALID_DEVID); + if (ret != 0) { + return ret; + } + + maskLen = (int)pkcsBlockLen - 1 - hLen; + salt = s = m = msg; + XMEMSET(m, 0, RSA_PSS_PAD_SZ); + m += RSA_PSS_PAD_SZ; + XMEMCPY(m, input, inputLen); + m += inputLen; + o = (int)(m - s); + if (saltLen > 0) { + ret = wc_RNG_GenerateBlock(rng, m, (word32)saltLen); + if (ret == 0) { + m += saltLen; + } + } + if (ret == 0) { + /* Put Hash at end of pkcsBlock - 1 */ + ret = wc_HashUpdate(&hashCtx, hType, s, (word32)(m - s)); + if (ret == 0) { + ret = wc_HashFinal(&hashCtx, hType, pkcsBlock + maskLen); + } + } + if (ret == 0) { + /* Set the last eight bits or trailer field to the octet 0xbc */ + pkcsBlock[pkcsBlockLen - 1] = RSA_PSS_PAD_TERM; + + ret = RsaMGF1(&hashCtx, hType, pkcsBlock + maskLen, (word32)hLen, + pkcsBlock, (word32)maskLen); + (void)mgf; /* not needed, using hType */ + } + if (ret == 0) { + /* Clear the first high bit when "8emLen - emBits" is non-zero, + * where emBits = n modBits - 1 */ + if (hiBits) { + pkcsBlock[0] &= (byte)((1 << hiBits) - 1); + } + m = pkcsBlock + maskLen - saltLen - 1; + *(m++) ^= 0x01; + xorbuf(m, salt + o, (word32)saltLen); + } + wc_HashFree(&hashCtx, hType); + return ret; +} + +int wolfTPM2_PK_RsaPssSign(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx) +{ + int ret; + TpmCryptoDevCtx* tlsCtx = (TpmCryptoDevCtx*)ctx; + RsaKey rsapub; + + (void)ssl; + +#ifdef DEBUG_WOLFTPM + printf("PK RSA PSS Sign: inSz %u, keySz %u, hash %d\n", inSz, keySz, hash); +#endif + + /* load RSA public key */ + ret = wc_InitRsaKey(&rsapub, NULL); + if (ret == 0) { + word32 keyIdx = 0; + ret = wc_RsaPublicKeyDecode(keyDer, &keyIdx, &rsapub, (word32)keySz); + if (ret == 0) { + byte inPad[RSA_MAX_SIZE/8]; + word32 inPadSz = (word32)wc_RsaEncryptSize(&rsapub); + #if 1 + /* Use local PSS padding function */ + ret = RsaPadPss( + in, inSz, + inPad, inPadSz, + wolfTPM2_GetRng(tlsCtx->dev), hash, mgf, + RSA_PSS_SALT_LEN_DEFAULT, inPadSz*8); + #else + /* Pad with PSS using internal wolfSSL API, if available */ + ret = wc_RsaPad_ex(in, inSz, inPad, inPadSz, RSA_BLOCK_TYPE_1, + wolfTPM2_GetRng(tlsCtx->dev), WC_RSA_PSS_PAD, hash, mgf, + NULL, 0, RSA_PSS_SALT_LEN_DEFAULT, inPadSz*8, NULL); + #endif + if (ret == 0) { + /* private operations */ + ret = wolfTPM2_RsaDecrypt(tlsCtx->dev, tlsCtx->rsaKey, + TPM_ALG_NULL, /* no padding */ + inPad, inPadSz, + out, (int*)outSz); + } + } + wc_FreeRsaKey(&rsapub); + } + + if (ret > 0) { + #ifdef DEBUG_WOLFTPM + printf("PK RSA PSS Sign Hash Failure 0x%x: %s\n", + ret, wolfTPM2_GetRCString(ret)); + #endif + ret = WC_HW_E; + } + +#ifdef DEBUG_WOLFTPM + printf("PK RSA PSS Sign: ret %d, outSz %u\n", ret, *outSz); +#endif + return ret; +} + +int wolfTPM2_PK_RsaPssSignCheck(WOLFSSL* ssl, + unsigned char* sig, unsigned int sigSz, unsigned char** out, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx) +{ + TpmCryptoDevCtx* tlsCtx = (TpmCryptoDevCtx*)ctx; + + (void)ssl; + (void)sig; + (void)sigSz; + (void)out; + (void)hash; + (void)mgf; + (void)keyDer; + (void)keySz; + (void)tlsCtx; + /* We used sign hardware, so assume sign is good */ + return 0; +} + +#endif /* WC_RSA_PSS */ +#endif /* !NO_RSA */ + +#if 0 /* TODO: def HAVE_ECC */ +int wolfTPM2_PK_EccSign(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, word32* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx) +{ + +} +#endif + +/* Setup PK callbacks */ +int wolfTPM_PK_SetCb(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + +#ifndef NO_RSA + wolfSSL_CTX_SetRsaSignCb(ctx, wolfTPM2_PK_RsaSign); + wolfSSL_CTX_SetRsaSignCheckCb(ctx, wolfTPM2_PK_RsaSignCheck); + #ifdef WC_RSA_PSS + wolfSSL_CTX_SetRsaPssSignCb(ctx, wolfTPM2_PK_RsaPssSign); + wolfSSL_CTX_SetRsaPssSignCheckCb(ctx, wolfTPM2_PK_RsaPssSignCheck); + #endif +#endif +#if 0 /* TODO: def HAVE_ECC */ + wolfSSL_CTX_SetEccSignCb(ctx, wolfTPM2_PK_EccSign); +#endif + return 0; +} + +/* Setup PK Callback context */ +int wolfTPM_PK_SetCbCtx(WOLFSSL* ssl, void* userCtx) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + +#ifndef NO_RSA + wolfSSL_SetRsaSignCtx(ssl, userCtx); + #ifdef WC_RSA_PSS + wolfSSL_SetRsaPssSignCtx(ssl, userCtx); + #endif +#endif +#if 0 /* TODO: def HAVE_ECC */ + wolfSSL_SetEccSignCtx(ssl, userCtx); +#endif + return 0; +} + +#endif /* HAVE_PK_CALLBACKS && !WOLFCRYPT_ONLY */ -#endif /* WOLFTPM_CRYPTOCB && !WOLFTPM2_NO_WRAPPER */ +#endif /* !WOLFTPM2_NO_WRAPPER */ diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 95f00cef..95864750 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -3066,8 +3066,10 @@ int wolfTPM2_RsaKey_WolfToTpm_ex(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* parentKe XMEMSET(q, 0, sizeof(q)); /* export the raw private and public RSA as unsigned binary */ + PRIVATE_KEY_UNLOCK(); rc = wc_RsaExportKey(wolfKey, e, &eSz, n, &nSz, d, &dSz, p, &pSz, q, &qSz); + PRIVATE_KEY_LOCK(); if (rc == 0) { exponent = wolfTPM2_RsaKey_Exponent(e, eSz); rc = wolfTPM2_LoadRsaPrivateKey(dev, parentKey, tpmKey, n, nSz, @@ -6099,7 +6101,7 @@ static void wolfTPM2_CopyNvPublic(TPMS_NV_PUBLIC* out, const TPMS_NV_PUBLIC* in) /* --- BEGIN Certificate Signing Request (CSR) Functions -- */ /******************************************************************************/ -#ifdef WOLFTPM2_CERT_GEN +#if defined(WOLFTPM2_CERT_GEN) && defined(WOLFTPM_CRYPTOCB) /* Distinguished Name Strings */ typedef struct DNTags { @@ -6476,7 +6478,7 @@ int wolfTPM2_CSR_Generate(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, out, outSz, 0, 0, INVALID_DEVID); } -#endif /* WOLFTPM2_CERT_GEN */ +#endif /* WOLFTPM2_CERT_GEN && WOLFTPM_CRYPTOCB */ /******************************************************************************/ /* --- END Certificate Signing Request (CSR) Functions -- */ diff --git a/tests/unit_tests.c b/tests/unit_tests.c index 1859ae16..2fb3716d 100644 --- a/tests/unit_tests.c +++ b/tests/unit_tests.c @@ -298,7 +298,8 @@ static void test_TPM2_KDFa(void) static void test_wolfTPM2_CSR(void) { -#if defined(WOLFTPM2_CERT_GEN) && !defined(WOLFTPM2_NO_HEAP) +#if defined(WOLFTPM2_CERT_GEN) && !defined(WOLFTPM2_NO_HEAP) && \ + defined(WOLFTPM_CRYPTOCB) int rc; WOLFTPM2_CSR* csr = wolfTPM2_NewCSR(); AssertNotNull(csr); diff --git a/wolftpm/tpm2_types.h b/wolftpm/tpm2_types.h index 0a15e26b..d3bee529 100644 --- a/wolftpm/tpm2_types.h +++ b/wolftpm/tpm2_types.h @@ -99,6 +99,9 @@ typedef int64_t INT64; #include #include #include + #if defined(HAVE_PK_CALLBACKS) && !defined(NO_RSA) && defined(WC_RSA_PSS) + #include /* for enum Hash_Sum */ + #endif #include #include #include diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index 01577416..801ef8ac 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -2862,9 +2862,8 @@ WOLFTPM_LOCAL int wolfTPM2_EncryptSecret(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* TPM2B_DATA *secret, TPM2B_ENCRYPTED_SECRET *encSecret, const char* label); -#ifdef WOLFTPM_CRYPTOCB +#if defined(WOLFTPM_CRYPTOCB) || defined(HAVE_PK_CALLBACKS) struct TpmCryptoDevCtx; -typedef int (*CheckWolfKeyCallbackFunc)(wc_CryptoInfo* info, struct TpmCryptoDevCtx* ctx); typedef struct TpmCryptoDevCtx { WOLFTPM2_DEV* dev; @@ -2887,6 +2886,10 @@ typedef struct TpmCryptoDevCtx { unsigned short useFIPSMode:1; /* if set requires FIPS mode on TPM and no fallback to software algos */ } TpmCryptoDevCtx; +#endif /* WOLFTPM_CRYPTOCB || HAVE_PK_CALLBACKS */ + +#ifdef WOLFTPM_CRYPTOCB + /*! \ingroup wolfTPM2_Wrappers \brief A reference crypto callback API for using the TPM for crypto offload. @@ -2942,6 +2945,50 @@ WOLFTPM_API int wolfTPM2_ClearCryptoDevCb(WOLFTPM2_DEV* dev, int devId); #endif /* WOLFTPM_CRYPTOCB */ +#if defined(HAVE_PK_CALLBACKS) && !defined(WOLFTPM2_NO_WRAPPER) && \ + !defined(WOLFCRYPT_ONLY) +#ifndef NO_RSA +WOLFTPM_API int wolfTPM2_PK_RsaSign(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, word32* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); + +WOLFTPM_API int wolfTPM2_PK_RsaSignCheck(WOLFSSL* ssl, + unsigned char* sig, unsigned int sigSz, + unsigned char** out, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); + +#ifdef WC_RSA_PSS +WOLFTPM_API int wolfTPM2_PK_RsaPssSign(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); + +WOLFTPM_API int wolfTPM2_PK_RsaPssSignCheck(WOLFSSL* ssl, + unsigned char* sig, unsigned int sigSz, unsigned char** out, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +#endif /* WC_RSA_PSS */ +#endif /* !NO_RSA */ +#ifdef HAVE_ECC +WOLFTPM_API int wolfTPM2_PK_EccSign(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, word32* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +#endif + +/* Helpers for setting generic PK callbacks */ +WOLFTPM_API int wolfTPM_PK_SetCb(WOLFSSL_CTX* ctx); +WOLFTPM_API int wolfTPM_PK_SetCbCtx(WOLFSSL* ssl, void* userCtx); + +#endif /* HAVE_PK_CALLBACKS */ + #ifndef WOLFTPM2_NO_HEAP /*! From 137a348c140599e0b298568b08295fe55fafa587 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 1 Dec 2023 14:12:57 -0800 Subject: [PATCH 2/5] TLS PK callback RSA PSS Padding cleanups. TLS server/client cleanups. Added server `-i` option to keep running unless failure. --- examples/tls/tls_client.c | 20 ++-- examples/tls/tls_server.c | 199 +++++++++++++++++++++----------------- src/tpm2_cryptocb.c | 20 ++-- 3 files changed, 138 insertions(+), 101 deletions(-) diff --git a/examples/tls/tls_client.c b/examples/tls/tls_client.c index aa63ee5b..7992dd86 100644 --- a/examples/tls/tls_client.c +++ b/examples/tls/tls_client.c @@ -36,11 +36,14 @@ #include -#undef USE_CERT_BUFFERS_2048 -#define USE_CERT_BUFFERS_2048 -#undef USE_CERT_BUFFERS_256 -#define USE_CERT_BUFFERS_256 -#include +#ifdef NO_FILESYSTEM + /* Load test certificates / keys from wolfSSL */ + #undef USE_CERT_BUFFERS_2048 + #define USE_CERT_BUFFERS_2048 + #undef USE_CERT_BUFFERS_256 + #define USE_CERT_BUFFERS_256 + #include +#endif #ifdef TLS_BENCH_MODE double benchStart; @@ -180,6 +183,9 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) const char* portStr = argv[argc-1] + XSTRLEN("-p="); port = (word32)XATOI(portStr); } + else { + printf("Warning: Unrecognized option: %s\n", argv[argc-1]); + } argc--; } @@ -391,7 +397,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) goto exit; } #else - printf("RSA not supported in this build\n"); + printf("Error: RSA not compiled in\n"); rc = -1; goto exit; #endif /* !NO_RSA */ @@ -440,7 +446,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) goto exit; } #else - printf("RSA not supported in this build\n"); + printf("Error: ECC not compiled in\n"); rc = -1; goto exit; #endif /* !NO_RSA */ diff --git a/examples/tls/tls_server.c b/examples/tls/tls_server.c index ca96847c..7247b533 100644 --- a/examples/tls/tls_server.c +++ b/examples/tls/tls_server.c @@ -36,6 +36,8 @@ #include +static int mStop = 0; + #ifdef TLS_BENCH_MODE double benchStart; #endif @@ -73,6 +75,7 @@ /******************************************************************************/ /* --- BEGIN TLS SERVER Example -- */ /******************************************************************************/ + static void usage(void) { printf("Expected usage:\n"); @@ -83,6 +86,7 @@ static void usage(void) #if defined(WOLFTPM_CRYPTOCB) && defined(HAVE_PK_CALLBACKS) printf("* -pk: Use PK callbacks, not crypto callbacks\n"); #endif + printf("* -i: Run in loop, keep serving connections until failure\n"); } int TPM2_TLS_Server(void* userCtx) @@ -132,6 +136,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) #endif int useECC = 0; int usePK = 0; + int runLoop = 0; TPM_ALG_ID paramEncAlg = TPM_ALG_NULL; WOLFTPM2_SESSION tpmSession; TPMT_PUBLIC publicTemplate; @@ -183,6 +188,9 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) usePK = 1; } #endif + else if (XSTRCMP(argv[argc-1], "-i") == 0) { + runLoop = 1; + } else if (XSTRNCMP(argv[argc-1], "-p=", XSTRLEN("-p=")) == 0) { const char* portStr = argv[argc-1] + XSTRLEN("-p="); port = (word32)XATOI(portStr); @@ -435,7 +443,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) * This API accepts public keys when crypto callbacks are enabled */ if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { - printf("Failed to set ECC key!\r\n"); + printf("Failed to set ECC key!\n"); goto exit; } #else @@ -446,7 +454,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) } #endif /* !NO_FILESYSTEM */ -#if 0 +#ifdef TLS_CIPHER_SUITE /* Optionally choose the cipher suite */ rc = wolfSSL_CTX_set_cipher_list(ctx, TLS_CIPHER_SUITE); if (rc != WOLFSSL_SUCCESS) { @@ -454,107 +462,122 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) } #endif - /* Create wolfSSL object/session */ - if ((ssl = wolfSSL_new(ctx)) == NULL) { - rc = wolfSSL_get_error(ssl, 0); - goto exit; - } - - /* Setup PK Callback context */ -#ifdef HAVE_PK_CALLBACKS - if (usePK) { - wolfTPM_PK_SetCbCtx(ssl, &tpmCtx); - } -#endif - /* Setup socket and connection */ rc = SetupSocketAndListen(&sockIoCtx, port); if (rc != 0) goto exit; - /* Setup read/write callback contexts */ - wolfSSL_SetIOReadCtx(ssl, &sockIoCtx); - wolfSSL_SetIOWriteCtx(ssl, &sockIoCtx); - - /* Accept client connections */ - rc = SocketWaitClient(&sockIoCtx); - if (rc != 0) goto exit; - - /* perform accept */ -#ifdef TLS_BENCH_MODE - benchStart = gettime_secs(1); -#endif - do { - rc = wolfSSL_accept(ssl); - if (rc != WOLFSSL_SUCCESS) { + while (rc == 0 && !mStop) { + /* Create wolfSSL object/session */ + if ((ssl = wolfSSL_new(ctx)) == NULL) { rc = wolfSSL_get_error(ssl, 0); + goto exit; } - } while (rc == WOLFSSL_ERROR_WANT_READ || rc == WOLFSSL_ERROR_WANT_WRITE); - if (rc != WOLFSSL_SUCCESS) { - goto exit; - } -#ifdef TLS_BENCH_MODE - benchStart = gettime_secs(0) - benchStart; - printf("Accept: %9.3f sec (%9.3f CPS)\n", benchStart, 1/benchStart); -#endif -#ifdef TLS_BENCH_MODE - rc = 0; - total_size = 0; - while (rc == 0 && total_size < TOTAL_MSG_SZ) -#endif - { - /* perform read */ + /* Setup PK Callback context */ + #ifdef HAVE_PK_CALLBACKS + if (usePK) { + wolfTPM_PK_SetCbCtx(ssl, &tpmCtx); + } + #endif + + /* Setup read/write callback contexts */ + wolfSSL_SetIOReadCtx(ssl, &sockIoCtx); + wolfSSL_SetIOWriteCtx(ssl, &sockIoCtx); + + /* Accept client connections */ + rc = SocketWaitClient(&sockIoCtx); + if (rc != 0) goto exit; + + /* perform accept */ #ifdef TLS_BENCH_MODE - benchStart = 0; /* use the read callback to trigger timing */ + benchStart = gettime_secs(1); #endif do { - rc = wolfSSL_read(ssl, msg, sizeof(msg)); - if (rc < 0) { + rc = wolfSSL_accept(ssl); + if (rc != WOLFSSL_SUCCESS) { rc = wolfSSL_get_error(ssl, 0); } - } while (rc == WOLFSSL_ERROR_WANT_READ); - if (rc >= 0) { - msgSz = rc; - #ifdef TLS_BENCH_MODE - benchStart = gettime_secs(0) - benchStart; - printf("Read: %d bytes in %9.3f sec (%9.3f KB/sec)\n", - msgSz, benchStart, msgSz / benchStart / 1024); - total_size += msgSz; - #else - /* null terminate */ - if (msgSz >= (int)sizeof(msg)) - msgSz = (int)sizeof(msg) - 1; - msg[msgSz] = '\0'; - printf("Read (%d): %s\n", msgSz, msg); - #endif - rc = 0; /* success */ + } while (rc == WOLFSSL_ERROR_WANT_READ || rc == WOLFSSL_ERROR_WANT_WRITE); + if (rc != WOLFSSL_SUCCESS) { + goto exit; } - if (rc != 0) goto exit; + #ifdef TLS_BENCH_MODE + benchStart = gettime_secs(0) - benchStart; + printf("Accept: %9.3f sec (%9.3f CPS)\n", benchStart, 1/benchStart); + #endif + + printf("Cipher Suite: %s\n", wolfSSL_get_cipher(ssl)); - /* perform write */ #ifdef TLS_BENCH_MODE - benchStart = gettime_secs(1); - #else - msgSz = sizeof(webServerMsg); - XMEMCPY(msg, webServerMsg, msgSz); + rc = 0; + total_size = 0; + while (rc == 0 && total_size < TOTAL_MSG_SZ) #endif - do { - rc = wolfSSL_write(ssl, msg, msgSz); - if (rc != msgSz) { - rc = wolfSSL_get_error(ssl, 0); + { + /* perform read */ + #ifdef TLS_BENCH_MODE + benchStart = 0; /* use the read callback to trigger timing */ + #endif + do { + rc = wolfSSL_read(ssl, msg, sizeof(msg)); + if (rc < 0) { + rc = wolfSSL_get_error(ssl, 0); + } + } while (rc == WOLFSSL_ERROR_WANT_READ); + if (rc >= 0) { + msgSz = rc; + #ifdef TLS_BENCH_MODE + benchStart = gettime_secs(0) - benchStart; + printf("Read: %d bytes in %9.3f sec (%9.3f KB/sec)\n", + msgSz, benchStart, msgSz / benchStart / 1024); + total_size += msgSz; + #else + /* null terminate */ + if (msgSz >= (int)sizeof(msg)) + msgSz = (int)sizeof(msg) - 1; + msg[msgSz] = '\0'; + printf("Read (%d): %s\n", msgSz, msg); + #endif + rc = 0; /* success */ } - } while (rc == WOLFSSL_ERROR_WANT_WRITE); - if (rc >= 0) { - msgSz = rc; + if (rc != 0) goto exit; + + /* perform write */ #ifdef TLS_BENCH_MODE - benchStart = gettime_secs(0) - benchStart; - printf("Write: %d bytes in %9.3f sec (%9.3f KB/sec)\n", - msgSz, benchStart, msgSz / benchStart / 1024); + benchStart = gettime_secs(1); #else - printf("Write (%d): %s\n", msgSz, msg); + msgSz = sizeof(webServerMsg); + XMEMCPY(msg, webServerMsg, msgSz); #endif - rc = 0; /* success */ + do { + rc = wolfSSL_write(ssl, msg, msgSz); + if (rc != msgSz) { + rc = wolfSSL_get_error(ssl, 0); + } + } while (rc == WOLFSSL_ERROR_WANT_WRITE); + if (rc >= 0) { + msgSz = rc; + #ifdef TLS_BENCH_MODE + benchStart = gettime_secs(0) - benchStart; + printf("Write: %d bytes in %9.3f sec (%9.3f KB/sec)\n", + msgSz, benchStart, msgSz / benchStart / 1024); + #else + printf("Write (%d): %s\n", msgSz, msg); + #endif + rc = 0; /* success */ + } } + + /* Bidirectional shutdown */ + while (wolfSSL_shutdown(ssl) == SSL_SHUTDOWN_NOT_DONE) { + printf("Shutdown not complete\n"); + } + + wolfSSL_free(ssl); + ssl = NULL; + + if (!runLoop) + mStop = 1; } exit: @@ -563,12 +586,14 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) printf("Failure %d (0x%x): %s\n", rc, rc, wolfTPM2_GetRCString(rc)); } - /* Bidirectional shutdown */ - while (wolfSSL_shutdown(ssl) == SSL_SHUTDOWN_NOT_DONE) { - printf("Shutdown not complete\n"); - } + if (ssl != NULL) { + /* Bidirectional shutdown */ + while (wolfSSL_shutdown(ssl) == SSL_SHUTDOWN_NOT_DONE) { + printf("Shutdown not complete\n"); + } - wolfSSL_free(ssl); + wolfSSL_free(ssl); + } wolfSSL_CTX_free(ctx); CloseAndCleanupSocket(&sockIoCtx); diff --git a/src/tpm2_cryptocb.c b/src/tpm2_cryptocb.c index 844576ee..68f9c71e 100644 --- a/src/tpm2_cryptocb.c +++ b/src/tpm2_cryptocb.c @@ -810,7 +810,8 @@ static int RsaMGF1(wc_HashAlg* hash, enum wc_HashType hType, byte* seed, word32 seedSz, byte* out, word32 outSz) { int ret; - byte tmp[RSA_MAX_SIZE/8]; + /* needs to be large enough for seed size plus counter(4) */ + byte tmp[WC_MAX_DIGEST_SIZE + 4]; word32 tmpSz = 0, counter = 0, idx = 0; int hLen, i = 0; @@ -820,12 +821,14 @@ static int RsaMGF1(wc_HashAlg* hash, enum wc_HashType hType, } /* find largest amount of memory needed, which will be the max of - * hLen and (seedSz + 4) since tmp is used to store the hash digest */ + * hLen and (seedSz + 4) */ tmpSz = ((seedSz + 4) > (word32)hLen) ? seedSz + 4: (word32)hLen; if (tmpSz > sizeof(tmp)) { return BAD_FUNC_ARG; } + XMEMSET(tmp, 0, sizeof(tmp)); + do { XMEMCPY(tmp, seed, seedSz); @@ -884,8 +887,8 @@ static int RsaPadPss(const byte* input, word32 inputLen, byte* pkcsBlock, int saltLen, int bits) { int ret = 0, hLen, o, maskLen, hiBits; - byte *m, *s, *salt; - byte msg[RSA_MAX_SIZE/8 + RSA_PSS_PAD_SZ]; + byte *m, *s; + byte salt[WC_MAX_DIGEST_SIZE]; enum wc_HashType hType; wc_HashAlg hashCtx; /* big stack consumer */ @@ -946,15 +949,17 @@ static int RsaPadPss(const byte* input, word32 inputLen, byte* pkcsBlock, } maskLen = (int)pkcsBlockLen - 1 - hLen; - salt = s = m = msg; + + s = m = pkcsBlock; XMEMSET(m, 0, RSA_PSS_PAD_SZ); m += RSA_PSS_PAD_SZ; XMEMCPY(m, input, inputLen); m += inputLen; - o = (int)(m - s); + o = 0; if (saltLen > 0) { - ret = wc_RNG_GenerateBlock(rng, m, (word32)saltLen); + ret = wc_RNG_GenerateBlock(rng, salt, (word32)saltLen); if (ret == 0) { + XMEMCPY(m, salt, (size_t)saltLen); m += saltLen; } } @@ -1012,6 +1017,7 @@ int wolfTPM2_PK_RsaPssSign(WOLFSSL* ssl, if (ret == 0) { byte inPad[RSA_MAX_SIZE/8]; word32 inPadSz = (word32)wc_RsaEncryptSize(&rsapub); + XMEMSET(inPad, 0, sizeof(inPad)); #if 1 /* Use local PSS padding function */ ret = RsaPadPss( From 53acf0bcbfc8f41c0fef460a8e226736d5ffba3a Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 1 Dec 2023 14:37:34 -0800 Subject: [PATCH 3/5] Use localhost 127.0.0.1 for CSR. Add TLS server option `-self` to use the self signed certs. --- examples/csr/csr.c | 4 ++-- examples/tls/tls_server.c | 26 ++++++++++++++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/examples/csr/csr.c b/examples/csr/csr.c index 38ea0dc2..6bd3bd09 100644 --- a/examples/csr/csr.c +++ b/examples/csr/csr.c @@ -73,11 +73,11 @@ static int TPM2_CSR_Generate(WOLFTPM2_DEV* dev, int keyType, WOLFTPM2_KEY* key, /* make sure each subject is unique */ if (keyType == RSA_TYPE) { subject = "/C=US/ST=Oregon/L=Portland/SN=Test/O=wolfSSL" - "/OU=RSA/CN=www.wolfssl.com/emailAddress=info@wolfssl.com"; + "/OU=RSA/CN=127.0.0.1/emailAddress=info@wolfssl.com"; } else if (keyType == ECC_TYPE) { subject = "/C=US/ST=Oregon/L=Portland/SN=Test/O=wolfSSL" - "/OU=ECC/CN=www.wolfssl.com/emailAddress=info@wolfssl.com"; + "/OU=ECC/CN=127.0.0.1/emailAddress=info@wolfssl.com"; } outputSz = (int)sizeof(output); diff --git a/examples/tls/tls_server.c b/examples/tls/tls_server.c index 7247b533..fc19f220 100644 --- a/examples/tls/tls_server.c +++ b/examples/tls/tls_server.c @@ -87,6 +87,7 @@ static void usage(void) printf("* -pk: Use PK callbacks, not crypto callbacks\n"); #endif printf("* -i: Run in loop, keep serving connections until failure\n"); + printf("* -self: Use self-signed certs (csr -cert)\n"); } int TPM2_TLS_Server(void* userCtx) @@ -137,6 +138,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) int useECC = 0; int usePK = 0; int runLoop = 0; + int useSelfSign = 0; TPM_ALG_ID paramEncAlg = TPM_ALG_NULL; WOLFTPM2_SESSION tpmSession; TPMT_PUBLIC publicTemplate; @@ -191,6 +193,9 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) else if (XSTRCMP(argv[argc-1], "-i") == 0) { runLoop = 1; } + else if (XSTRCMP(argv[argc-1], "-self") == 0) { + useSelfSign = 1; + } else if (XSTRNCMP(argv[argc-1], "-p=", XSTRLEN("-p=")) == 0) { const char* portStr = argv[argc-1] + XSTRLEN("-p="); port = (word32)XATOI(portStr); @@ -383,13 +388,15 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) #ifndef NO_RSA byte der[1024]; word32 derSz = sizeof(der); + const char* useCert = "./certs/server-rsa-cert.pem"; + if (useSelfSign) { + useCert = "./certs/tpm-rsa-cert.pem"; + } - printf("Loading RSA certificate and public key\n"); + printf("Loading RSA certificate (%s) and public key\n", useCert); - if ((rc = wolfSSL_CTX_use_certificate_file(ctx, - "./certs/server-rsa-cert.pem", - WOLFSSL_FILETYPE_PEM)) - != WOLFSSL_SUCCESS) { + if ((rc = wolfSSL_CTX_use_certificate_file(ctx, useCert, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { printf("Error loading RSA client cert\n"); goto exit; } @@ -420,11 +427,14 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) #ifdef HAVE_ECC byte der[256]; word32 derSz = sizeof(der); + const char* useCert = "./certs/server-ecc-cert.pem"; + if (useSelfSign) { + useCert = "./certs/tpm-ecc-cert.pem"; + } - printf("Loading ECC certificate and public key\n"); + printf("Loading ECC certificate (%s) and public key\n", useCert); - if ((rc = wolfSSL_CTX_use_certificate_file(ctx, - "./certs/server-ecc-cert.pem", + if ((rc = wolfSSL_CTX_use_certificate_file(ctx, useCert, WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { printf("Error loading ECC client cert\n"); goto exit; From c0cd64d705d8eaf5e58c7a539c0721dcb94d8af7 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 6 Dec 2023 17:23:53 -0800 Subject: [PATCH 4/5] Add ECC sign PK callback support. --- src/tpm2_cryptocb.c | 91 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 16 deletions(-) diff --git a/src/tpm2_cryptocb.c b/src/tpm2_cryptocb.c index 68f9c71e..dd30009a 100644 --- a/src/tpm2_cryptocb.c +++ b/src/tpm2_cryptocb.c @@ -23,6 +23,22 @@ #if !defined(WOLFTPM2_NO_WRAPPER) +#if defined(WOLFTPM_CRYPTOCB) || \ + (defined(HAVE_PK_CALLBACKS) && !defined(WOLFCRYPT_ONLY)) + +/* Helper to trim leading zeros when not required */ +static byte* wolfTPM2_ASNTrimZeros(byte* in, word32* len) +{ + word32 idx = 0; + while (idx+1 < *len && in[idx] == 0 && (in[idx+1] & 0x80) == 0) { + idx++; + in++; + } + *len -= idx; + return in; +} +#endif /* WOLFTPM_CRYPTOCB || HAVE_PK_CALLBACKS */ + #ifdef WOLFTPM_CRYPTOCB /* Internal structure for tracking hash state */ @@ -45,18 +61,6 @@ static int wolfTPM2_HashUpdateCache(WOLFTPM2_HASHCTX* hashCtx, const byte* in, word32 inSz); #endif /* WOLFTPM_USE_SYMMETRIC */ -/* Helper to trim leading zeros when not required */ -static byte* wolfTPM2_ASNTrimZeros(byte* in, word32* len) -{ - word32 idx = 0; - while (idx+1 < *len && in[idx] == 0 && (in[idx+1] & 0x80) == 0) { - idx++; - in++; - } - *len -= idx; - return in; -} - int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) { int rc = CRYPTOCB_UNAVAILABLE; @@ -1080,14 +1084,69 @@ int wolfTPM2_PK_RsaPssSignCheck(WOLFSSL* ssl, #endif /* WC_RSA_PSS */ #endif /* !NO_RSA */ -#if 0 /* TODO: def HAVE_ECC */ +#ifdef HAVE_ECC int wolfTPM2_PK_EccSign(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, unsigned char* out, word32* outSz, - const unsigned char* keyDer, unsigned int keySz, + const unsigned char* keyDer, unsigned int keyDerSz, void* ctx) { + int ret; + TpmCryptoDevCtx* tlsCtx = (TpmCryptoDevCtx*)ctx; + ecc_key eccpub; + + (void)ssl; +#ifdef DEBUG_WOLFTPM + printf("PK ECC Sign: inSz %u, keyDerSz %u\n", inSz, keyDerSz); +#endif + + /* load ECC public key */ + ret = wc_ecc_init_ex(&eccpub, NULL, INVALID_DEVID); + if (ret == 0) { + word32 keyIdx = 0; + ret = wc_EccPublicKeyDecode(keyDer, &keyIdx, &eccpub, (word32)keyDerSz); + if (ret == 0) { + byte sigRS[MAX_ECC_BYTES*2]; + word32 rsLen = sizeof(sigRS), keySz; + + /* truncate input to match key size */ + keySz = wc_ecc_size(&eccpub); + if (inSz > keySz) + inSz = keySz; + + ret = wolfTPM2_SignHash(tlsCtx->dev, tlsCtx->eccKey, + in, inSz, sigRS, (int*)&rsLen); + if (ret == 0) { + byte *r, *s; + word32 rLen, sLen; + + /* Make sure leading zero's not required are trimmed */ + rLen = sLen = rsLen / 2; + r = &sigRS[0]; + s = &sigRS[rLen]; + r = wolfTPM2_ASNTrimZeros(r, &rLen); + s = wolfTPM2_ASNTrimZeros(s, &sLen); + + /* Encode ECDSA Header */ + ret = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen, out, outSz); + } + } + wc_ecc_free(&eccpub); + } + + if (ret > 0) { + #ifdef DEBUG_WOLFTPM + printf("PK ECC Sign Hash Failure 0x%x: %s\n", + ret, wolfTPM2_GetRCString(ret)); + #endif + ret = WC_HW_E; + } + +#ifdef DEBUG_WOLFTPM + printf("PK ECC Sign: ret %d, outSz %u\n", ret, *outSz); +#endif + return ret; } #endif @@ -1105,7 +1164,7 @@ int wolfTPM_PK_SetCb(WOLFSSL_CTX* ctx) wolfSSL_CTX_SetRsaPssSignCheckCb(ctx, wolfTPM2_PK_RsaPssSignCheck); #endif #endif -#if 0 /* TODO: def HAVE_ECC */ +#ifdef HAVE_ECC wolfSSL_CTX_SetEccSignCb(ctx, wolfTPM2_PK_EccSign); #endif return 0; @@ -1123,7 +1182,7 @@ int wolfTPM_PK_SetCbCtx(WOLFSSL* ssl, void* userCtx) wolfSSL_SetRsaPssSignCtx(ssl, userCtx); #endif #endif -#if 0 /* TODO: def HAVE_ECC */ +#ifdef HAVE_ECC wolfSSL_SetEccSignCtx(ssl, userCtx); #endif return 0; From a50e4fee6ca2b7c82b514a2a4fec240176baeeb2 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 8 Dec 2023 11:44:00 -0800 Subject: [PATCH 5/5] Add tests for the TLS PK with TPM. --- .github/workflows/make-test-swtpm.yml | 2 +- examples/run_examples.sh | 12 ++++++++++++ examples/tls/tls_client.c | 1 + examples/tls/tls_server.c | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/make-test-swtpm.yml b/.github/workflows/make-test-swtpm.yml index eb1148be..77a1bfa8 100644 --- a/.github/workflows/make-test-swtpm.yml +++ b/.github/workflows/make-test-swtpm.yml @@ -25,7 +25,7 @@ jobs: run: ./autogen.sh - name: wolfssl configure working-directory: ./wolfssl - run: ./configure --enable-wolftpm + run: ./configure --enable-wolftpm --enable-pkcallbacks - name: wolfssl make install working-directory: ./wolfssl run: sudo make install diff --git a/examples/run_examples.sh b/examples/run_examples.sh index 129544c7..693c40bd 100755 --- a/examples/run_examples.sh +++ b/examples/run_examples.sh @@ -218,6 +218,7 @@ run_tpm_tls_server() { # Usage: run_tpm_tls_server [ecc/rsa] [tpmargs]] } if [ $WOLFCRYPT_ENABLE -eq 1 ]; then + # Run with Crypto CB run_tpm_tls_client "rsa" "" run_tpm_tls_client "rsa" "-aes" run_tpm_tls_client "ecc" "" @@ -227,6 +228,17 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ]; then run_tpm_tls_server "rsa" "-aes" run_tpm_tls_server "ecc" "" run_tpm_tls_server "ecc" "-aes" + + # Run with PK + run_tpm_tls_client "rsa" "-pk" + run_tpm_tls_client "rsa" "-pk -aes" + run_tpm_tls_client "ecc" "-pk" + run_tpm_tls_client "ecc" "-pk -aes" + + run_tpm_tls_server "rsa" "-pk " + run_tpm_tls_server "rsa" "-pk -aes" + run_tpm_tls_server "ecc" "-pk" + run_tpm_tls_server "ecc" "-pk -aes" fi diff --git a/examples/tls/tls_client.c b/examples/tls/tls_client.c index 7992dd86..bd9fffb4 100644 --- a/examples/tls/tls_client.c +++ b/examples/tls/tls_client.c @@ -193,6 +193,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) printf("\tUse %s keys\n", useECC ? "ECC" : "RSA"); printf("\tUse Parameter Encryption: %s\n", TPM2_GetAlgName(paramEncAlg)); printf("\tUsing Port: %d\n", port); + printf("\tUsing %s callbacks\n", usePK ? "PK" : "Crypto"); /* Init the TPM2 device */ rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); diff --git a/examples/tls/tls_server.c b/examples/tls/tls_server.c index fc19f220..5fe5bd92 100644 --- a/examples/tls/tls_server.c +++ b/examples/tls/tls_server.c @@ -210,6 +210,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) printf("\tUse %s keys\n", useECC ? "ECC" : "RSA"); printf("\tUse Parameter Encryption: %s\n", TPM2_GetAlgName(paramEncAlg)); printf("\tUsing Port: %d\n", port); + printf("\tUsing %s callbacks\n", usePK ? "PK" : "Crypto"); /* Init the TPM2 device */ rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx);