diff --git a/README.md b/README.md index dc9e93d7..34902e55 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ Mfg NTC (0), Vendor NPCT75x"!!4rls, Fw 7.2 (131072), FIPS 140-2 1, CC-EAL4 0 git clone https://github.com/wolfSSL/wolfssl.git cd wolfssl ./autogen.sh -./configure --enable-certgen --enable-certreq --enable-certext --enable-pkcs7 --enable-cryptocb --enable-aescfb +./configure --enable-wolftpm make sudo make install sudo ldconfig diff --git a/examples/pcr/policy_sign.c b/examples/pcr/policy_sign.c index 41a1515f..72a3673c 100644 --- a/examples/pcr/policy_sign.c +++ b/examples/pcr/policy_sign.c @@ -109,7 +109,7 @@ static int PolicySign(TPM_ALG_ID alg, const char* keyFile, const char* password, if (rc == 0) { /* handle PEM conversion to DER */ if (encType == ENCODING_TYPE_PEM) { - #if !defined(WOLFTPM2_NO_HEAP) && defined(WOLFSSL_PEM_TO_DER) + #ifdef WOLFTPM2_PEM_DECODE /* der size is base 64 decode length */ word32 derSz = (word32)bufSz * 3 / 4 + 1; byte* derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -185,12 +185,16 @@ static int PolicySign(TPM_ALG_ID alg, const char* keyFile, const char* password, rc = wc_ecc_sign_hash_ex(hash, hashSz, &rng, &key.ecc, &r, &s); } if (rc == 0) { - word32 keySz = key.ecc.dp->size; - mp_to_unsigned_bin(&r, sig); - mp_to_unsigned_bin(&s, sig + keySz); + word32 keySz = key.ecc.dp->size, rSz, sSz; + *sigSz = keySz * 2; + XMEMSET(sig, 0, *sigSz); + /* export sign r/s - zero pad to key size */ + rSz = mp_unsigned_bin_size(&r); + mp_to_unsigned_bin(&r, &sig[keySz - rSz]); + sSz = mp_unsigned_bin_size(&s); + mp_to_unsigned_bin(&s, &sig[keySz + (keySz - sSz)]); mp_clear(&r); mp_clear(&s); - *sigSz = keySz * 2; } } wc_ecc_free(&key.ecc); diff --git a/examples/run_examples.sh b/examples/run_examples.sh index 4713b955..2ed37338 100755 --- a/examples/run_examples.sh +++ b/examples/run_examples.sh @@ -179,14 +179,8 @@ fi # TLS Tests RSA echo -e "TLS tests" generate_port() { # function to produce a random port number - if [[ "$OSTYPE" == "linux"* ]]; then - port=$(($(od -An -N2 /dev/urandom) % (65535-49512) + 49512)) - elif [[ "$OSTYPE" == "darwin"* ]]; then - port=$(($(od -An -N2 /dev/random) % (65535-49512) + 49512)) - else - echo "Unknown OS TYPE" - exit 1 - fi + port=11111 + echo -e "Using port $port" echo -e "Using port $port" >> run.out } @@ -194,11 +188,11 @@ run_tpm_tls_client() { # Usage: run_tpm_tls_client [ecc/rsa] [tpmargs]] echo -e "TLS test (TPM as client) $1 $2" generate_port pushd $WOLFSSL_PATH >> run.out - ./examples/server/server -p $port -g -A ./certs/tpm-ca-$1-cert.pem 2>&1 >> $PWD/run.out & + ./examples/server/server -p $port -w -g -A ./certs/tpm-ca-$1-cert.pem 2>&1 >> $PWD/run.out & RESULT=$? [ $RESULT -ne 0 ] && echo -e "tls server $1 $2 failed! $RESULT" && exit 1 popd >> run.out - sleep 0.4 + 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 @@ -207,12 +201,14 @@ run_tpm_tls_client() { # Usage: run_tpm_tls_client [ecc/rsa] [tpmargs]] run_tpm_tls_server() { # Usage: run_tpm_tls_server [ecc/rsa] [tpmargs]] echo -e "TLS test (TPM as server) $1 $2" generate_port + ./examples/tls/tls_server -p=$port -$1 $2 2>&1 >> run.out & RESULT=$? [ $RESULT -ne 0 ] && echo -e "tpm tls server $1 $2 failed! $RESULT" && exit 1 pushd $WOLFSSL_PATH >> run.out - sleep 0.4 - ./examples/client/client -p $port -g -A ./certs/tpm-ca-$1-cert.pem 2>&1 >> $PWD/run.out + sleep 0.1 + + ./examples/client/client -p $port -w -g -A ./certs/tpm-ca-$1-cert.pem 2>&1 >> $PWD/run.out RESULT=$? [ $RESULT -ne 0 ] && echo -e "tls client $1 $2 failed! $RESULT" && exit 1 popd >> run.out diff --git a/examples/tls/tls_client.c b/examples/tls/tls_client.c index b9107a5d..017c02bf 100644 --- a/examples/tls/tls_client.c +++ b/examples/tls/tls_client.c @@ -130,6 +130,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) XMEMSET(&storageKey, 0, sizeof(storageKey)); XMEMSET(&sockIoCtx, 0, sizeof(sockIoCtx)); sockIoCtx.fd = -1; + sockIoCtx.listenFd = -1; XMEMSET(&tpmCtx, 0, sizeof(tpmCtx)); #ifndef NO_RSA XMEMSET(&rsaKey, 0, sizeof(rsaKey)); @@ -558,6 +559,15 @@ int TPM2_TLS_ClientArgs(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"); + } + + CloseAndCleanupSocket(&sockIoCtx); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + wolfTPM2_UnloadHandle(&dev, &storageKey.handle); #ifndef NO_RSA wc_FreeRsaKey(&wolfRsaKey); @@ -572,12 +582,6 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[]) #endif wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); - wolfSSL_shutdown(ssl); - - CloseAndCleanupSocket(&sockIoCtx); - wolfSSL_free(ssl); - wolfSSL_CTX_free(ctx); - wolfTPM2_Cleanup(&dev); return rc; diff --git a/examples/tls/tls_common.h b/examples/tls/tls_common.h index 9b313902..faa98fdb 100644 --- a/examples/tls/tls_common.h +++ b/examples/tls/tls_common.h @@ -209,7 +209,7 @@ static inline int SockIOSend(WOLFSSL* ssl, char* buff, int sz, void* ctx) static inline int SetupSocketAndListen(SockIoCbCtx* sockIoCtx, word32 port) { struct sockaddr_in servAddr; - int optval = 1; + int optval; #ifdef _WIN32 WSADATA wsd; @@ -230,17 +230,26 @@ static inline int SetupSocketAndListen(SockIoCbCtx* sockIoCtx, word32 port) return -1; } - /* allow reuse */ + /* allow reuse of port and address */ + optval = 1; if (setsockopt(sockIoCtx->listenFd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(optval)) == -1) { printf("setsockopt SO_REUSEADDR failed\n"); return -1; } +#ifdef SO_REUSEPORT + optval = 1; + if (setsockopt(sockIoCtx->listenFd, SOL_SOCKET, SO_REUSEPORT, + (void*)&optval, sizeof(optval)) == -1) { + printf("setsockopt SO_REUSEPORT failed\n"); + return -1; + } +#endif /* Connect to the server */ if (bind(sockIoCtx->listenFd, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) { - printf("ERROR: failed to bind\n"); + printf("ERROR: failed to bind! errno %d\n", errno); return -1; } diff --git a/examples/tls/tls_server.c b/examples/tls/tls_server.c index 2ca18de8..16684b98 100644 --- a/examples/tls/tls_server.c +++ b/examples/tls/tls_server.c @@ -137,6 +137,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) XMEMSET(&storageKey, 0, sizeof(storageKey)); XMEMSET(&sockIoCtx, 0, sizeof(sockIoCtx)); sockIoCtx.fd = -1; + sockIoCtx.listenFd = -1; XMEMSET(&tpmCtx, 0, sizeof(tpmCtx)); #ifndef NO_RSA XMEMSET(&rsaKey, 0, sizeof(rsaKey)); @@ -534,12 +535,16 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[]) printf("Failure %d (0x%x): %s\n", rc, rc, wolfTPM2_GetRCString(rc)); } - wolfSSL_shutdown(ssl); + /* Bidirectional shutdown */ + while (wolfSSL_shutdown(ssl) == SSL_SHUTDOWN_NOT_DONE) { + 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); diff --git a/src/tpm2.c b/src/tpm2.c index fa8a5f23..7450fe8d 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -2952,7 +2952,9 @@ TPM_RC TPM2_Sign(Sign_In* in, Sign_Out* out) TPM2_Packet_AppendBytes(&packet, in->digest.buffer, in->digest.size); TPM2_Packet_AppendU16(&packet, in->inScheme.scheme); - TPM2_Packet_AppendU16(&packet, in->inScheme.details.any.hashAlg); + if (in->inScheme.scheme != TPM_ALG_NULL) { + TPM2_Packet_AppendU16(&packet, in->inScheme.details.any.hashAlg); + } TPM2_Packet_AppendU16(&packet, in->validation.tag); TPM2_Packet_AppendU32(&packet, in->validation.hierarchy); diff --git a/src/tpm2_cryptocb.c b/src/tpm2_cryptocb.c index 8daad7fe..d738e2ce 100644 --- a/src/tpm2_cryptocb.c +++ b/src/tpm2_cryptocb.c @@ -43,6 +43,17 @@ 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) { @@ -78,14 +89,41 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) #ifndef NO_RSA /* RSA */ if (info->pk.type == WC_PK_TYPE_RSA_KEYGEN) { - /* TODO: Add crypto callback RSA keygen support */ - #if 0 - RsaKey* key; - int size; - long e; - WC_RNG* rng; - #endif - rc = exit_rc; + #ifdef WOLFSSL_KEY_GEN + if (tlsCtx->rsaKeyGen != NULL && tlsCtx->storageKey != NULL) { + /* create a new RSA key */ + TPMT_PUBLIC publicTemplate; + XMEMSET(&publicTemplate, 0, sizeof(publicTemplate)); + rc = GetKeyTemplateRSA(&publicTemplate, + WOLFTPM2_WRAP_DIGEST, /* name algorithm */ + ( /* objectAttributes */ + TPMA_OBJECT_sensitiveDataOrigin | + TPMA_OBJECT_userWithAuth | + TPMA_OBJECT_decrypt | + TPMA_OBJECT_noDA + ), + info->pk.rsakg.size, /* keyBits */ + info->pk.rsakg.e, /* exponent */ + TPM_ALG_NULL, /* sigScheme */ + WOLFTPM2_WRAP_DIGEST /* sigHash */ + ); + if (rc == 0) { + rc = wolfTPM2_CreateKey(tlsCtx->dev, tlsCtx->rsaKeyGen, + &tlsCtx->storageKey->handle, &publicTemplate, NULL, 0); + } + if (rc == 0) { + rc = wolfTPM2_LoadKey(tlsCtx->dev, tlsCtx->rsaKeyGen, + &tlsCtx->storageKey->handle); + } + if (rc == 0) { + /* export public portion of new key to wolf RsaKey struct */ + rc = wolfTPM2_RsaKey_TpmToWolf(tlsCtx->dev, + (WOLFTPM2_KEY*)tlsCtx->rsaKeyGen, info->pk.rsakg.key); + } + } + else + #endif + rc = exit_rc; } else if (info->pk.type == WC_PK_TYPE_RSA) { switch (info->pk.rsa.type) { @@ -135,25 +173,56 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) rc = exit_rc; #else int curve_id; + WOLFTPM2_KEY* key; /* Make sure an ECDH key has been set and curve is supported */ - rc = TPM2_GetTpmCurve(info->pk.eckg.curveId); - if (rc < 0 || tlsCtx->ecdhKey == NULL || tlsCtx->eccKey == NULL) { + curve_id = info->pk.eckg.curveId; + if (curve_id == 0 && info->pk.eckg.key->dp != NULL) { + curve_id = info->pk.eckg.key->dp->id; /* use dp */ + } + rc = TPM2_GetTpmCurve(curve_id); + if (rc < 0 || (tlsCtx->ecdhKey == NULL && tlsCtx->eccKey == NULL)) { return exit_rc; } curve_id = rc; rc = 0; - /* Generate ephemeral key - if one isn't already created */ - if (tlsCtx->ecdhKey->handle.hndl == 0 || - tlsCtx->ecdhKey->handle.hndl == TPM_RH_NULL) { - rc = wolfTPM2_ECDHGenKey(tlsCtx->dev, tlsCtx->ecdhKey, curve_id, - (byte*)tlsCtx->eccKey->handle.auth.buffer, - tlsCtx->eccKey->handle.auth.size); + /* If ecdhKey is NULL then it is a signing key */ + if (tlsCtx->ecdhKey == NULL) { + /* Create an ECC key for ECDSA - if one isn't already created */ + key = tlsCtx->eccKey; + if (key->handle.hndl == 0 || + key->handle.hndl == TPM_RH_NULL + ) { + TPMT_PUBLIC publicTemplate; + XMEMSET(&publicTemplate, 0, sizeof(publicTemplate)); + + rc = wolfTPM2_GetKeyTemplate_ECC(&publicTemplate, + TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth | + TPMA_OBJECT_sign | TPMA_OBJECT_noDA, + curve_id, TPM_ALG_ECDSA); + if (rc == 0) { + publicTemplate.nameAlg = TPM_ALG_SHA256; /* make sure its SHA256 */ + rc = wolfTPM2_CreateAndLoadKey(tlsCtx->dev, key, + &tlsCtx->storageKey->handle, &publicTemplate, + (byte*)key->handle.auth.buffer, + key->handle.auth.size); + } + } + } + else { + /* Generate ephemeral key - if one isn't already created */ + key = tlsCtx->ecdhKey; + if (key->handle.hndl == 0 || + key->handle.hndl == TPM_RH_NULL) { + rc = wolfTPM2_ECDHGenKey(tlsCtx->dev, key, curve_id, + NULL, 0 /* no auth for ephemeral key */ + ); + } } if (rc == 0) { /* Export public key info to wolf ecc_key */ - rc = wolfTPM2_EccKey_TpmToWolf(tlsCtx->dev, tlsCtx->ecdhKey, + rc = wolfTPM2_EccKey_TpmToWolf(tlsCtx->dev, key, info->pk.eckg.key); if (rc != 0) { /* if failure, release key */ @@ -164,27 +233,34 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) /* if the curve is not supported on TPM, then fall-back to software */ rc = exit_rc; /* Make sure ECDHE key indicates nothing loaded */ - tlsCtx->ecdhKey->handle.hndl = TPM_RH_NULL; + key->handle.hndl = TPM_RH_NULL; } #endif /* WOLFTPM2_USE_SW_ECDHE */ } else if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) { byte sigRS[MAX_ECC_BYTES*2]; - byte *r = sigRS, *s; - word32 rsLen = sizeof(sigRS), rLen, sLen; + word32 rsLen = sizeof(sigRS), keySz; word32 inlen = info->pk.eccsign.inlen; /* truncate input to match key size */ - rLen = wc_ecc_size(info->pk.eccsign.key); - if (inlen > rLen) - inlen = rLen; + keySz = wc_ecc_size(info->pk.eccsign.key); + if (inlen > keySz) + inlen = keySz; rc = wolfTPM2_SignHash(tlsCtx->dev, tlsCtx->eccKey, info->pk.eccsign.in, inlen, sigRS, (int*)&rsLen); if (rc == 0) { - /* Encode ECDSA Header */ + 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 */ rc = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen, info->pk.eccsign.out, info->pk.eccsign.outlen); } @@ -194,7 +270,9 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) byte sigRS[MAX_ECC_BYTES*2]; byte *r = sigRS, *s = &sigRS[MAX_ECC_BYTES]; word32 rLen = MAX_ECC_BYTES, sLen = MAX_ECC_BYTES; + XMEMSET(&eccPub, 0, sizeof(eccPub)); + XMEMSET(sigRS, 0, sizeof(sigRS)); /* Decode ECDSA Header */ rc = wc_ecc_sig_to_rs(info->pk.eccverify.sig, @@ -204,16 +282,25 @@ int wolfTPM2_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) rc = wolfTPM2_EccKey_WolfToTpm(tlsCtx->dev, info->pk.eccverify.key, &eccPub); if (rc == 0) { - /* combine R and S */ - XMEMCPY(sigRS + rLen, s, sLen); + /* combine R and S at key size (zero pad leading) */ + word32 keySz = wc_ecc_size(info->pk.eccverify.key); + XMEMCPY(&sigRS[keySz-rLen], r, rLen); + XMEMSET(&sigRS[0], 0, keySz-rLen); + XMEMCPY(&sigRS[keySz + (keySz-sLen)], s, sLen); + XMEMSET(&sigRS[keySz], 0, keySz-sLen); rc = wolfTPM2_VerifyHash(tlsCtx->dev, &eccPub, - sigRS, rLen + sLen, + sigRS, keySz*2, info->pk.eccverify.hash, info->pk.eccverify.hashlen); - - if (rc == 0 && info->pk.eccverify.res) { - *info->pk.eccverify.res = 1; + if (info->pk.eccverify.res) { + if ((rc & TPM_RC_SIGNATURE) == TPM_RC_SIGNATURE) { + /* mark invalid signature */ + *info->pk.eccverify.res = 0; + rc = 0; + } + else if (rc == 0) { + *info->pk.eccverify.res = 1; + } } - wolfTPM2_UnloadHandle(tlsCtx->dev, &eccPub.handle); } else if (rc & TPM_RC_CURVE) { diff --git a/src/tpm2_param_enc.c b/src/tpm2_param_enc.c index 8d315b9e..f72a2e78 100644 --- a/src/tpm2_param_enc.c +++ b/src/tpm2_param_enc.c @@ -103,7 +103,7 @@ int TPM2_KDFa( return NOT_COMPILED_IN; hLen = TPM2_GetHashDigestSize(hashAlg); - if ( (hLen <= 0) || (hLen > WC_MAX_DIGEST_SIZE)) + if ((hLen <= 0) || (hLen > WC_MAX_DIGEST_SIZE)) return NOT_COMPILED_IN; /* get label length if provided, including null termination */ @@ -128,46 +128,39 @@ int TPM2_KDFa( else { ret = wc_HmacSetKey(&hmac_ctx, hashType, NULL, 0); } - if (ret != 0) - goto exit; - /* add counter - KDFa i2 */ - TPM2_Packet_U32ToByteArray(counter, uint32Buf); - ret = wc_HmacUpdate(&hmac_ctx, uint32Buf, (word32)sizeof(uint32Buf)); - if (ret != 0) - goto exit; - + if (ret == 0) { + TPM2_Packet_U32ToByteArray(counter, uint32Buf); + ret = wc_HmacUpdate(&hmac_ctx, uint32Buf, (word32)sizeof(uint32Buf)); + } /* add label - KDFa label */ - if (label != NULL) { + if (ret == 0 && label != NULL) { ret = wc_HmacUpdate(&hmac_ctx, (byte*)label, lLen); - if (ret != 0) - goto exit; } /* add contextU */ - if (contextU != NULL && contextU->size > 0) { + if (ret == 0 && contextU != NULL && contextU->size > 0) { ret = wc_HmacUpdate(&hmac_ctx, contextU->buffer, contextU->size); - if (ret != 0) - goto exit; } /* add contextV */ - if (contextV != NULL && contextV->size > 0) { + if (ret == 0 && contextV != NULL && contextV->size > 0) { ret = wc_HmacUpdate(&hmac_ctx, contextV->buffer, contextV->size); - if (ret != 0) - goto exit; } /* add size in bits */ - TPM2_Packet_U32ToByteArray(sizeInBits, uint32Buf); - ret = wc_HmacUpdate(&hmac_ctx, uint32Buf, (word32)sizeof(uint32Buf)); - if (ret != 0) - goto exit; + if (ret == 0) { + TPM2_Packet_U32ToByteArray(sizeInBits, uint32Buf); + ret = wc_HmacUpdate(&hmac_ctx, uint32Buf, (word32)sizeof(uint32Buf)); + } /* get result */ - ret = wc_HmacFinal(&hmac_ctx, hash); - if (ret != 0) + if (ret == 0) { + ret = wc_HmacFinal(&hmac_ctx, hash); + } + if (ret != 0) { goto exit; + } if ((UINT32)hLen > keySz - pos) { copyLen = keySz - pos; diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 2f4f464b..05abe126 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -999,7 +999,7 @@ static int TPM2_KDFe( hashType = (enum wc_HashType)ret; hLen = TPM2_GetHashDigestSize(hashAlg); - if ( (hLen <= 0) || (hLen > WC_MAX_DIGEST_SIZE)) + if ((hLen <= 0) || (hLen > WC_MAX_DIGEST_SIZE)) return NOT_COMPILED_IN; /* get label length if provided, including null termination */ @@ -1021,39 +1021,35 @@ static int TPM2_KDFe( TPM2_Packet_U32ToByteArray(counter, uint32Buf); ret = wc_HashUpdate(&hash_ctx, hashType, uint32Buf, (word32)sizeof(uint32Buf)); - if (ret != 0) - goto exit; - /* add Z */ - ret = wc_HashUpdate(&hash_ctx, hashType, Z->buffer, Z->size); - + if (ret == 0) { + ret = wc_HashUpdate(&hash_ctx, hashType, Z->buffer, Z->size); + } /* add label */ - if (label != NULL) { + if (ret == 0 && label != NULL) { ret = wc_HashUpdate(&hash_ctx, hashType, (byte*)label, lLen); - if (ret != 0) - goto exit; } /* add partyUInfo */ - if (partyUInfo != NULL && partyUInfo->size > 0) { + if (ret == 0 && partyUInfo != NULL && partyUInfo->size > 0) { ret = wc_HashUpdate(&hash_ctx, hashType, partyUInfo->buffer, partyUInfo->size); - if (ret != 0) - goto exit; } /* add partyVInfo */ - if (partyVInfo != NULL && partyVInfo->size > 0) { + if (ret == 0 && partyVInfo != NULL && partyVInfo->size > 0) { ret = wc_HashUpdate(&hash_ctx, hashType, partyVInfo->buffer, partyVInfo->size); - if (ret != 0) - goto exit; } /* get result */ - ret = wc_HashFinal(&hash_ctx, hashType, hash); - if (ret != 0) + if (ret == 0) { + ret = wc_HashFinal(&hash_ctx, hashType, hash); + } + + if (ret != 0) { goto exit; + } if ((UINT32)hLen > keySz - pos) { copyLen = keySz - pos; @@ -1088,6 +1084,7 @@ static int wolfTPM2_EncryptSecret_ECC(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* tpm TPM2B_ECC_POINT pubPoint, secretPoint; ecc_point r[1]; mp_int prime, a; + word32 keySz; publicArea = &tpmKey->pub.publicArea; XMEMSET(&rng, 0, sizeof(rng)); @@ -1122,6 +1119,8 @@ static int wolfTPM2_EncryptSecret_ECC(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* tpm TPM2_GetWolfCurve(publicArea->parameters.eccDetail.curveID)); } if (rc == 0) { + keySz = wc_ecc_size(&eccKeyPriv); + /* export private's public point as data */ rc = wolfTPM2_EccKey_WolfToPubPoint(dev, &eccKeyPriv, &pubPoint); } @@ -1149,9 +1148,11 @@ static int wolfTPM2_EncryptSecret_ECC(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* tpm r, &a, &prime, 1); } if (rc == 0) { - /* export shared secret x */ + /* export shared secret x - zero pad to key size */ secretPoint.point.x.size = mp_unsigned_bin_size(r->x); - rc = mp_to_unsigned_bin(r->x, secretPoint.point.x.buffer); + rc = mp_to_unsigned_bin(r->x, + &secretPoint.point.x.buffer[keySz-secretPoint.point.x.size]); + secretPoint.point.x.size = keySz; } if (rc == 0) { /* set size encryption key */ @@ -2380,7 +2381,11 @@ int wolfTPM2_ImportEccPrivateKeySeed(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* pare pub.publicArea.nameAlg = WOLFTPM2_WRAP_DIGEST; pub.publicArea.objectAttributes = attributes; pub.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_NULL; - pub.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL; + /* if both sign and decrypt are set then must use NULL algorithm */ + pub.publicArea.parameters.eccDetail.scheme.scheme = + ((attributes & TPMA_OBJECT_sign) && + (attributes & TPMA_OBJECT_decrypt)) ? + TPM_ALG_NULL : TPM_ALG_ECDSA; pub.publicArea.parameters.eccDetail.scheme.details.ecdsa.hashAlg = WOLFTPM2_WRAP_DIGEST; pub.publicArea.parameters.eccDetail.curveID = curveId; @@ -2717,9 +2722,7 @@ int wolfTPM2_ImportPublicKeyBuffer(WOLFTPM2_DEV* dev, int keyType, } if (encodingType == ENCODING_TYPE_PEM) { - #if !defined(WOLFTPM2_NO_HEAP) && defined(WOLFSSL_PEM_TO_DER) && \ - (defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)) && \ - !defined(NO_ASN) + #ifdef WOLFTPM2_PEM_DECODE /* der size is base 64 decode length */ derSz = inSz * 3 / 4 + 1; derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -2755,7 +2758,7 @@ int wolfTPM2_ImportPublicKeyBuffer(WOLFTPM2_DEV* dev, int keyType, #endif } -#if !defined(WOLFTPM2_NO_HEAP) && defined(WOLFSSL_PEM_TO_DER) +#ifdef WOLFTPM2_PEM_DECODE if (derBuf != (byte*)input) { XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } @@ -2785,7 +2788,7 @@ int wolfTPM2_ImportPrivateKeyBuffer(WOLFTPM2_DEV* dev, XMEMSET(&sens, 0, sizeof(sens)); if (encodingType == ENCODING_TYPE_PEM) { - #if !defined(WOLFTPM2_NO_HEAP) && defined(WOLFSSL_PEM_TO_DER) + #ifdef WOLFTPM2_PEM_DECODE /* der size is base 64 decode length */ derSz = inSz * 3 / 4 + 1; derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -2856,7 +2859,7 @@ int wolfTPM2_ImportPrivateKeyBuffer(WOLFTPM2_DEV* dev, rc = wolfTPM2_ImportPrivateKey(dev, parentKey, keyBlob, pub, &sens); } -#if !defined(WOLFTPM2_NO_HEAP) && defined(WOLFSSL_PEM_TO_DER) +#ifdef WOLFTPM2_PEM_DECODE if (derBuf != (byte*)input) { XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); } @@ -2915,8 +2918,7 @@ int wolfTPM2_RsaPrivateKeyImportDer(WOLFTPM2_DEV* dev, } #endif /* !NO_ASN */ -#if !defined(WOLFTPM2_NO_HEAP) && defined(WOLFSSL_PEM_TO_DER) - +#ifdef WOLFTPM2_PEM_DECODE int wolfTPM2_RsaPrivateKeyImportPem(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* parentKey, WOLFTPM2_KEYBLOB* keyBlob, const char* input, word32 inSz, char* pass, @@ -2927,8 +2929,7 @@ int wolfTPM2_RsaPrivateKeyImportPem(WOLFTPM2_DEV* dev, return wolfTPM2_ImportPrivateKeyBuffer(dev, parentKey, TPM_ALG_RSA, keyBlob, ENCODING_TYPE_PEM, input, inSz, pass, 0, NULL, 0); } - -#endif /* !WOLFTPM2_NO_HEAP && WOLFSSL_PEM_TO_DER */ +#endif /* WOLFTPM2_PEM_DECODE */ int wolfTPM2_RsaKey_TpmToWolf(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey, @@ -3097,17 +3098,14 @@ int wolfTPM2_RsaKey_PubPemToTpm(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey, const byte* pem, word32 pemSz) { int rc = TPM_RC_FAILURE; -#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFSSL_PEM_TO_DER) && \ - (defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)) +#ifdef WOLFTPM2_PEM_DECODE RsaKey rsaKey; #endif if (dev == NULL || tpmKey == NULL || pem == NULL) return BAD_FUNC_ARG; -#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFSSL_PEM_TO_DER) && \ - (defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)) && \ - !defined(NO_ASN) +#ifdef WOLFTPM2_PEM_DECODE /* Prepare wolfCrypt key structure */ rc = wc_InitRsaKey(&rsaKey, NULL); if (rc == 0) { @@ -3202,15 +3200,46 @@ int wolfTPM2_EccKey_WolfToTpm_ex(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* parentKey, if (rc < 0) return rc; curve_id = rc; + rc = 0; - if (parentKey && wolfKey->type == ECC_PRIVATEKEY) { + if (parentKey && wolfKey->type != ECC_PUBLICKEY) { byte d[WOLFTPM2_WRAP_ECC_KEY_BITS / 8]; word32 dSz = sizeof(d); XMEMSET(d, 0, sizeof(d)); - /* export the raw private/public ECC portions */ - rc = wc_ecc_export_private_raw(wolfKey, qx, &qxSz, qy, &qySz, d, &dSz); + if (wolfKey->type == ECC_PRIVATEKEY_ONLY) { + /* compute public point without modifying incoming wolf key */ + int keySz = wc_ecc_size(wolfKey); + ecc_point* point = wc_ecc_new_point(); + if (point == NULL) { + rc = MEMORY_E; + } + if (rc == 0) { + #ifdef ECC_TIMING_RESISTANT + rc = wc_ecc_make_pub_ex(wolfKey, point, wolfKey->rng); + #else + rc = wc_ecc_make_pub(wolfKey, point); + #endif + if (rc == 0) + rc = wc_export_int(point->x, qx, &qxSz, keySz, + WC_TYPE_UNSIGNED_BIN); + if (rc == 0) + rc = wc_export_int(point->y, qy, &qySz, keySz, + WC_TYPE_UNSIGNED_BIN); + if (rc == 0) + rc = wc_ecc_export_private_only(wolfKey, d, &dSz); + wc_ecc_del_point(point); + } + } + else { + /* export the raw private/public ECC portions */ + rc = wc_ecc_export_private_raw(wolfKey, + qx, &qxSz, + qy, &qySz, + d, &dSz); + } + if (rc == 0) { rc = wolfTPM2_LoadEccPrivateKey(dev, parentKey, tpmKey, curve_id, qx, qxSz, qy, qySz, d, dSz); @@ -3470,7 +3499,9 @@ int wolfTPM2_SignHash(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, if (key->pub.publicArea.type == TPM_ALG_ECC) { sigAlg = key->pub.publicArea.parameters.eccDetail.scheme.scheme; hashAlg = key->pub.publicArea.parameters.eccDetail.scheme.details.any.hashAlg; - + if (sigAlg == TPM_ALG_NULL) { + sigAlg = TPM_ALG_ECDSA; + } } else if (key->pub.publicArea.type == TPM_ALG_RSA) { sigAlg = key->pub.publicArea.parameters.rsaDetail.scheme.scheme; @@ -4488,12 +4519,13 @@ int wolfTPM2_NVDelete(WOLFTPM2_DEV* dev, TPM_HANDLE authHandle, #ifndef WOLFTPM2_NO_WOLFCRYPT struct WC_RNG* wolfTPM2_GetRng(WOLFTPM2_DEV* dev) { + WC_RNG* rng = NULL; if (dev) { #ifdef WOLFTPM2_USE_WOLF_RNG - return &dev->ctx.rng; + (void)TPM2_GetWolfRng(&rng); #endif } - return NULL; + return rng; } #endif @@ -5280,8 +5312,8 @@ int wolfTPM2_ChangePlatformAuth(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* session) /* --- BEGIN Utility Functions -- */ /******************************************************************************/ -static int GetKeyTemplateRSA(TPMT_PUBLIC* publicTemplate, - TPM_ALG_ID nameAlg, TPMA_OBJECT objectAttributes, int keyBits, int exponent, +int GetKeyTemplateRSA(TPMT_PUBLIC* publicTemplate, + TPM_ALG_ID nameAlg, TPMA_OBJECT objectAttributes, int keyBits, long exponent, TPM_ALG_ID sigScheme, TPM_ALG_ID sigHash) { if (publicTemplate == NULL) @@ -5293,7 +5325,7 @@ static int GetKeyTemplateRSA(TPMT_PUBLIC* publicTemplate, publicTemplate->nameAlg = nameAlg; publicTemplate->objectAttributes = objectAttributes; publicTemplate->parameters.rsaDetail.keyBits = keyBits; - publicTemplate->parameters.rsaDetail.exponent = exponent; + publicTemplate->parameters.rsaDetail.exponent = (UINT32)exponent; publicTemplate->parameters.rsaDetail.scheme.scheme = sigScheme; publicTemplate->parameters.rsaDetail.scheme.details.anySig.hashAlg = sigHash; /* For fixedParent or (decrypt and restricted) enable symmetric */ @@ -5311,7 +5343,7 @@ static int GetKeyTemplateRSA(TPMT_PUBLIC* publicTemplate, return TPM_RC_SUCCESS; } -static int GetKeyTemplateECC(TPMT_PUBLIC* publicTemplate, +int GetKeyTemplateECC(TPMT_PUBLIC* publicTemplate, TPM_ALG_ID nameAlg, TPMA_OBJECT objectAttributes, TPM_ECC_CURVE curve, TPM_ALG_ID sigScheme, TPM_ALG_ID sigHash) { @@ -5977,18 +6009,14 @@ static void wolfTPM2_CopyPubT(TPMT_PUBLIC* out, const TPMT_PUBLIC* in) &in->parameters.eccDetail.symmetric); out->parameters.eccDetail.scheme.scheme = in->parameters.eccDetail.scheme.scheme; - if (out->parameters.eccDetail.scheme.scheme != TPM_ALG_NULL) { - out->parameters.eccDetail.scheme.details.any.hashAlg = - in->parameters.eccDetail.scheme.details.any.hashAlg; - } + out->parameters.eccDetail.scheme.details.any.hashAlg = + in->parameters.eccDetail.scheme.details.any.hashAlg; out->parameters.eccDetail.curveID = in->parameters.eccDetail.curveID; out->parameters.eccDetail.kdf.scheme = in->parameters.eccDetail.kdf.scheme; - if (out->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL) { - out->parameters.eccDetail.kdf.details.any.hashAlg = - in->parameters.eccDetail.kdf.details.any.hashAlg; - } + out->parameters.eccDetail.kdf.details.any.hashAlg = + in->parameters.eccDetail.kdf.details.any.hashAlg; wolfTPM2_CopyEccParam(&out->unique.ecc.x, &in->unique.ecc.x); wolfTPM2_CopyEccParam(&out->unique.ecc.y, @@ -5999,9 +6027,8 @@ static void wolfTPM2_CopyPubT(TPMT_PUBLIC* out, const TPMT_PUBLIC* in) &in->parameters.asymDetail.symmetric); out->parameters.asymDetail.scheme.scheme = in->parameters.asymDetail.scheme.scheme; - if (out->parameters.asymDetail.scheme.scheme != TPM_ALG_NULL) - out->parameters.asymDetail.scheme.details.anySig.hashAlg = - in->parameters.asymDetail.scheme.details.anySig.hashAlg; + out->parameters.asymDetail.scheme.details.anySig.hashAlg = + in->parameters.asymDetail.scheme.details.anySig.hashAlg; break; } } diff --git a/tests/unit_tests.c b/tests/unit_tests.c index aa42b05e..1859ae16 100644 --- a/tests/unit_tests.c +++ b/tests/unit_tests.c @@ -328,7 +328,7 @@ static void test_wolfTPM2_CSR(void) #endif } -#ifndef WOLFTPM2_NO_WOLFCRYPT +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFTPM2_PEM_DECODE) static WOLFTPM2_KEY authKey; /* also used for test_wolfTPM2_PCRPolicy */ static void test_wolfTPM_ImportPublicKey(void) @@ -433,7 +433,7 @@ static void test_wolfTPM2_PCRPolicy(void) wolfTPM2_Cleanup(&dev); } -#endif /* !WOLFTPM2_NO_WOLFCRYPT */ +#endif /* !WOLFTPM2_NO_WOLFCRYPT && WOLFTPM2_PEM_DECODE */ #if defined(HAVE_THREAD_LS) && defined(HAVE_PTHREAD) #include @@ -505,7 +505,7 @@ int unit_tests(int argc, char *argv[]) test_TPM2_KDFa(); test_wolfTPM2_ReadPublicKey(); test_wolfTPM2_CSR(); - #ifndef WOLFTPM2_NO_WOLFCRYPT + #if !defined(WOLFTPM2_NO_WOLFCRYPT) && defined(WOLFTPM2_PEM_DECODE) test_wolfTPM_ImportPublicKey(); test_wolfTPM2_PCRPolicy(); #endif diff --git a/wolftpm/tpm2_types.h b/wolftpm/tpm2_types.h index 4cc0e1fb..0a15e26b 100644 --- a/wolftpm/tpm2_types.h +++ b/wolftpm/tpm2_types.h @@ -650,6 +650,11 @@ typedef int64_t INT64; #define WOLFTPM2_CERT_GEN #endif +#if !defined(WOLFTPM2_NO_HEAP) && defined(WOLFSSL_PEM_TO_DER) && \ + (defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER)) && \ + !defined(NO_ASN) + #define WOLFTPM2_PEM_DECODE +#endif /* ---------------------------------------------------------------------------*/ /* ENDIANESS HELPERS */ diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index a43274f6..01577416 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -2870,6 +2870,9 @@ typedef struct TpmCryptoDevCtx { WOLFTPM2_DEV* dev; #ifndef NO_RSA WOLFTPM2_KEY* rsaKey; /* RSA */ + #ifdef WOLFSSL_KEY_GEN + WOLFTPM2_KEYBLOB* rsaKeyGen; /* RSA KeyGen */ + #endif #endif #ifdef HAVE_ECC WOLFTPM2_KEY* eccKey; /* ECDSA */ @@ -3387,6 +3390,15 @@ WOLFTPM_API int wolfTPM2_PolicyAuthorizeMake(TPM_ALG_ID pcrAlg, const TPM2B_PUBLIC* pub, byte* digest, word32* digestSz, const byte* policyRef, word32 policyRefSz); + +/* Internal API's */ +WOLFTPM_LOCAL int GetKeyTemplateRSA(TPMT_PUBLIC* publicTemplate, + TPM_ALG_ID nameAlg, TPMA_OBJECT objectAttributes, int keyBits, long exponent, + TPM_ALG_ID sigScheme, TPM_ALG_ID sigHash); +WOLFTPM_LOCAL int GetKeyTemplateECC(TPMT_PUBLIC* publicTemplate, + TPM_ALG_ID nameAlg, TPMA_OBJECT objectAttributes, TPM_ECC_CURVE curve, + TPM_ALG_ID sigScheme, TPM_ALG_ID sigHash); + #ifdef __cplusplus } /* extern "C" */ #endif