Repository navigation
fwTPM: ECDSA signatureR/signatureS are not padded to the curve size #649
Description
FwSignDigestAndAppend returns the ECDSA signatureR and signatureS at the minimal length wc_ecc_sig_to_rs gives them. TPM 2.0 Part 1, Annex C.8, says ECC parameters a TPM returns "must be padded with zeros to the length of the respective curve". Whenever r or s has leading zero bytes, the signature comes back shorter:
- P-521: about half the time, since its top byte is often zero.
- P-256: about 1 time in 128.
Clients that build an IEEE P1363 r || s signature from the two values, or that check both are the curve size, reject or mis-encode these signatures. tpm2-pkcs11 answers CKR_DEVICE_ERROR ("TPM returned ECC signature with inconsistent padding").
Reproduction (ESYS). Create an ECDSA signing key (Esys_Create + Esys_Load under a storage primary, or a primary), call Esys_Sign with 200 different SHA-256 digests, and count the signatures whose signatureR.size or signatureS.size is below the curve size:
fwTPM master swtpm 0.10.2
P-256 (32 bytes) r short in 2, s in 1 0, 0
P-521 (66 bytes) r short in 88, s in 109 0, 0
Suggested fix. Left-pad r and s to FwGetEccKeySize(curveID). With this change no signature is short in the run above.
diff --git a/src/fwtpm/fwtpm_crypto.c b/src/fwtpm/fwtpm_crypto.c
index c0de62e..6708078 100644
--- a/src/fwtpm/fwtpm_crypto.c
+++ b/src/fwtpm/fwtpm_crypto.c
@@ -3977,6 +3977,25 @@ TPM_RC FwSignDigestAndAppend(FWTPM_CTX* ctx, FWTPM_Object* obj,
rc = TPM_RC_FAILURE;
}
+ /* r and s are padded with zeros to the curve size (TPM 2.0 Part 1
+ * Annex C.8), not returned at their minimal length */
+ if (rc == 0) {
+ int keySz = FwGetEccKeySize(
+ obj->pub.parameters.eccDetail.curveID);
+ if (keySz <= 0 || keySz > (int)sizeof(rBuf) ||
+ (int)rSz > keySz || (int)sSz > keySz) {
+ rc = TPM_RC_FAILURE;
+ }
+ else {
+ XMEMMOVE(rBuf + (keySz - rSz), rBuf, rSz);
+ XMEMSET(rBuf, 0, keySz - rSz);
+ rSz = (word32)keySz;
+ XMEMMOVE(sBuf + (keySz - sSz), sBuf, sSz);
+ XMEMSET(sBuf, 0, keySz - sSz);
+ sSz = (word32)keySz;
+ }
+ }
+
if (rc == 0) {
TPM2_Packet_AppendU16(rsp, sigScheme);
TPM2_Packet_AppendU16(rsp, sigHashAlg);Separately, minor: TPM2_Sign with an all-zero digest answers TPM_RC_FAILURE, where swtpm signs it. wolfCrypt presumably refuses a zero hash. ECDSA defines e = 0, but nobody should sign that in practice, so this is only a note.
Environment
- wolfTPM
masterat d7f73b5 (also seen in v4.2.0), fwTPM built with./configure --enable-fwtpm-only --enable-swtpmon wolfSSL v5.9.4-stable (--enable-wolftpm --enable-pkcallbacks --enable-keygen). fwtpm_server --port 2341 --platform-port 2342, reached through the tpm2-tss 4.2.0swtpmTCTI (swtpm:host=127.0.0.1,port=2341).- For comparison, the same program against swtpm 0.10.2 (libtpms).
- Found while running tpm2-pkcs11 on fwTPM.
Activity
dgarske commentedon Oct 28, 2026
Hi @AlexLaroche thank you for all the reports. Can you review and try out the fixes in #656 ?
Thanks, David Garske, wolfSSL