|
| 1 | +From 83474625ad1816e55afa224dabfb4a6f29bd6123 Mon Sep 17 00:00:00 2001 |
| 2 | +From: archana25-ms < [email protected]> |
| 3 | +Date: Mon, 16 Jun 2025 16:40:42 +0000 |
| 4 | +Subject: [PATCH] Address CVE-2025-49133 |
| 5 | +Upstream Patch Reference: https://github.com/stefanberger/libtpms/commit/9f9baccdba9cd3fc32f1355613abd094b21f7ba0 |
| 6 | +--- |
| 7 | + src/tpm2/CryptUtil.c | 119 +++++++++++++++++++++++----- |
| 8 | + src/tpm2/SigningCommands.c | 11 ++- |
| 9 | + src/tpm2/crypto/CryptHash_fp.h | 2 +- |
| 10 | + src/tpm2/crypto/openssl/CryptHash.c | 4 +- |
| 11 | + 4 files changed, 109 insertions(+), 27 deletions(-) |
| 12 | + |
| 13 | +diff --git a/src/tpm2/CryptUtil.c b/src/tpm2/CryptUtil.c |
| 14 | +index 8fae5b6..f0d8a28 100644 |
| 15 | +--- a/src/tpm2/CryptUtil.c |
| 16 | ++++ b/src/tpm2/CryptUtil.c |
| 17 | +@@ -67,7 +67,7 @@ |
| 18 | + #include "Tpm.h" |
| 19 | + /* 10.2.6.3 Hash/HMAC Functions */ |
| 20 | + /* 10.2.6.3.1 CryptHmacSign() */ |
| 21 | +-/* Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a message. */ |
| 22 | ++/* Sign a digest using an HMAC key. This is an HMAC of a digest, not an HMAC of a message. */ |
| 23 | + /* Error Returns Meaning */ |
| 24 | + /* TPM_RC_HASH not a valid hash */ |
| 25 | + static TPM_RC |
| 26 | +@@ -79,12 +79,18 @@ CryptHmacSign( |
| 27 | + { |
| 28 | + HMAC_STATE hmacState; |
| 29 | + UINT32 digestSize; |
| 30 | +- digestSize = CryptHmacStart2B(&hmacState, signature->signature.any.hashAlg, |
| 31 | +- &signKey->sensitive.sensitive.bits.b); |
| 32 | +- CryptDigestUpdate2B(&hmacState.hashState, &hashData->b); |
| 33 | +- CryptHmacEnd(&hmacState, digestSize, |
| 34 | +- (BYTE *)&signature->signature.hmac.digest); |
| 35 | +- return TPM_RC_SUCCESS; |
| 36 | ++ |
| 37 | ++ if(signature->sigAlg == TPM_ALG_HMAC) |
| 38 | ++ { |
| 39 | ++ digestSize = CryptHmacStart2B(&hmacState, |
| 40 | ++ signature->signature.any.hashAlg, |
| 41 | ++ &signKey->sensitive.sensitive.bits.b); |
| 42 | ++ CryptDigestUpdate2B(&hmacState.hashState, &hashData->b); |
| 43 | ++ CryptHmacEnd(&hmacState, digestSize, |
| 44 | ++ (BYTE *)&signature->signature.hmac.digest); |
| 45 | ++ return TPM_RC_SUCCESS; |
| 46 | ++ } |
| 47 | ++ return TPM_RC_SCHEME; |
| 48 | + } |
| 49 | + /* 10.2.6.3.2 CryptHMACVerifySignature() */ |
| 50 | + /* This function will verify a signature signed by a HMAC key. Note that a caller needs to prepare |
| 51 | +@@ -1096,7 +1102,7 @@ CryptIsSplitSign( |
| 52 | + } |
| 53 | + } |
| 54 | + /* 10.2.6.6.11 CryptIsAsymSignScheme() */ |
| 55 | +-/* This function indicates if a scheme algorithm is a sign algorithm. */ |
| 56 | ++/* This function indicates if a scheme algorithm is a sign algorithm valid for the public key type. */ |
| 57 | + BOOL |
| 58 | + CryptIsAsymSignScheme( |
| 59 | + TPMI_ALG_PUBLIC publicType, // IN: Type of the object |
| 60 | +@@ -1125,9 +1131,11 @@ CryptIsAsymSignScheme( |
| 61 | + #if ALG_ECC |
| 62 | + // If ECC is implemented ECDSA is required |
| 63 | + case TPM_ALG_ECC: |
| 64 | ++# if !ALG_ECDSA |
| 65 | ++# error "ECDSA required if ECC enabled." |
| 66 | ++# endif |
| 67 | + switch(scheme) |
| 68 | + { |
| 69 | +- // Support for ECDSA is required for ECC |
| 70 | + case TPM_ALG_ECDSA: |
| 71 | + #if ALG_ECDAA // ECDAA is optional |
| 72 | + case TPM_ALG_ECDAA: |
| 73 | +@@ -1151,6 +1159,58 @@ CryptIsAsymSignScheme( |
| 74 | + } |
| 75 | + return isSignScheme; |
| 76 | + } |
| 77 | ++//*** CryptIsValidSignScheme() |
| 78 | ++// This function checks that a signing scheme is valid. This includes verifying |
| 79 | ++// that the scheme signing algorithm is compatible with the signing object type |
| 80 | ++// and that the scheme specifies a valid hash algorithm. |
| 81 | ++static BOOL CryptIsValidSignScheme(TPMI_ALG_PUBLIC publicType, // IN: Type of the object |
| 82 | ++ TPMT_SIG_SCHEME* scheme // IN: the signing scheme |
| 83 | ++) |
| 84 | ++{ |
| 85 | ++ BOOL isValidSignScheme = TRUE; |
| 86 | ++ |
| 87 | ++ switch(publicType) |
| 88 | ++ { |
| 89 | ++#if ALG_RSA |
| 90 | ++ case TPM_ALG_RSA: |
| 91 | ++ isValidSignScheme = CryptIsAsymSignScheme(publicType, scheme->scheme); |
| 92 | ++ break; |
| 93 | ++#endif // ALG_RSA |
| 94 | ++ |
| 95 | ++#if ALG_ECC |
| 96 | ++ case TPM_ALG_ECC: |
| 97 | ++ isValidSignScheme = CryptIsAsymSignScheme(publicType, scheme->scheme); |
| 98 | ++ break; |
| 99 | ++#endif // ALG_ECC |
| 100 | ++ |
| 101 | ++ case TPM_ALG_KEYEDHASH: |
| 102 | ++ if(scheme->scheme != TPM_ALG_HMAC) |
| 103 | ++ { |
| 104 | ++ isValidSignScheme = FALSE; |
| 105 | ++ } |
| 106 | ++ break; |
| 107 | ++ |
| 108 | ++ default: |
| 109 | ++ isValidSignScheme = FALSE; |
| 110 | ++ break; |
| 111 | ++ } |
| 112 | ++ |
| 113 | ++ // Ensure that a valid hash algorithm is specified. Pass 'flag' = FALSE to |
| 114 | ++ // indicate that TPM_ALG_NULL should not be treated as valid. |
| 115 | ++ // |
| 116 | ++ // NOTE: 'details' is of type TPMU_SIG_SCHEME which is a union of many |
| 117 | ++ // different signature scheme types. In all these types (including the type |
| 118 | ++ // of 'any'), the very first member is of type TPMI_ALG_HASH. Therefore, |
| 119 | ++ // when 'any.hashAlg' is set to a valid hash algorithm ID, the hash for any |
| 120 | ++ // signature scheme type will also be a valid hash algorithm ID. (All valid |
| 121 | ++ // hash algorithm IDs are the same for all signature scheme types.) |
| 122 | ++ if(!CryptHashIsValidAlg(scheme->details.any.hashAlg, /* flag = */ FALSE)) |
| 123 | ++ { |
| 124 | ++ isValidSignScheme = FALSE; |
| 125 | ++ } |
| 126 | ++ |
| 127 | ++ return isValidSignScheme; |
| 128 | ++} |
| 129 | + /* 10.2.6.6.12 CryptIsAsymDecryptScheme() */ |
| 130 | + /* This function indicate if a scheme algorithm is a decrypt algorithm. */ |
| 131 | + BOOL |
| 132 | +@@ -1205,8 +1265,9 @@ CryptIsAsymDecryptScheme( |
| 133 | + } |
| 134 | + /* 10.2.6.6.13 CryptSelectSignScheme() */ |
| 135 | + /* This function is used by the attestation and signing commands. It implements the rules for |
| 136 | +- selecting the signature scheme to use in signing. This function requires that the signing key |
| 137 | +- either be TPM_RH_NULL or be loaded. */ |
| 138 | ++ selecting the signature scheme to use in signing and validates that the selected scheme is |
| 139 | ++ compatible with the key type. It also ensures the selected scheme specifies a valid hash |
| 140 | ++ algorithm. This function requires that the signing key either be TPM_RH_NULL or be loaded. */ |
| 141 | + /* If a default scheme is defined in object, the default scheme should be chosen, otherwise, the |
| 142 | + input scheme should be chosen. In the case that both object and input scheme has a non-NULL |
| 143 | + scheme algorithm, if the schemes are compatible, the input scheme will be chosen. */ |
| 144 | +@@ -1237,25 +1298,32 @@ CryptSelectSignScheme( |
| 145 | + { |
| 146 | + // assignment to save typing. |
| 147 | + publicArea = &signObject->publicArea; |
| 148 | +- // A symmetric cipher can be used to encrypt and decrypt but it can't |
| 149 | +- // be used for signing |
| 150 | +- if(publicArea->type == TPM_ALG_SYMCIPHER) |
| 151 | +- return FALSE; |
| 152 | +- // Point to the scheme object |
| 153 | ++ |
| 154 | ++ // Get a point to the scheme object |
| 155 | + if(CryptIsAsymAlgorithm(publicArea->type)) |
| 156 | +- objectScheme = |
| 157 | +- (TPMT_SIG_SCHEME *)&publicArea->parameters.asymDetail.scheme; |
| 158 | ++ { |
| 159 | ++ objectScheme = |
| 160 | ++ (TPMT_SIG_SCHEME *)&publicArea->parameters.asymDetail.scheme; |
| 161 | ++ } |
| 162 | ++ else if(publicArea->type == TPM_ALG_KEYEDHASH) |
| 163 | ++ { |
| 164 | ++ objectScheme = |
| 165 | ++ (TPMT_SIG_SCHEME *)&publicArea->parameters.keyedHashDetail.scheme; |
| 166 | ++ } |
| 167 | + else |
| 168 | +- objectScheme = |
| 169 | +- (TPMT_SIG_SCHEME *)&publicArea->parameters.keyedHashDetail.scheme; |
| 170 | ++ { |
| 171 | ++ // Only asymmetric key types (RSA, ECC) and keyed hashes can be |
| 172 | ++ // used for signing. A symmetric cipher can be used to encrypt and |
| 173 | ++ // decrypt but can't be used for signing. |
| 174 | ++ return FALSE; |
| 175 | ++ } |
| 176 | ++ |
| 177 | + // If the object doesn't have a default scheme, then use the |
| 178 | + // input scheme. |
| 179 | + if(objectScheme->scheme == TPM_ALG_NULL) |
| 180 | + { |
| 181 | + // Input and default can't both be NULL |
| 182 | + OK = (scheme->scheme != TPM_ALG_NULL); |
| 183 | +- // Assume that the scheme is compatible with the key. If not, |
| 184 | +- // an error will be generated in the signing operation. |
| 185 | + } |
| 186 | + else if(scheme->scheme == TPM_ALG_NULL) |
| 187 | + { |
| 188 | +@@ -1282,6 +1350,13 @@ CryptSelectSignScheme( |
| 189 | + && (objectScheme->details.any.hashAlg |
| 190 | + == scheme->details.any.hashAlg); |
| 191 | + } |
| 192 | ++ |
| 193 | ++ if(OK) |
| 194 | ++ { |
| 195 | ++ // Check that the scheme is compatible with the key type and has a |
| 196 | ++ // valid hash algorithm specified. |
| 197 | ++ OK = CryptIsValidSignScheme(publicArea->type, scheme); |
| 198 | ++ } |
| 199 | + } |
| 200 | + return OK; |
| 201 | + } |
| 202 | +diff --git a/src/tpm2/SigningCommands.c b/src/tpm2/SigningCommands.c |
| 203 | +index 529c40c..ec93c84 100644 |
| 204 | +--- a/src/tpm2/SigningCommands.c |
| 205 | ++++ b/src/tpm2/SigningCommands.c |
| 206 | +@@ -116,16 +116,23 @@ TPM2_Sign( |
| 207 | + // |
| 208 | + // Input Validation |
| 209 | + if(!IsSigningObject(signObject)) |
| 210 | ++ { |
| 211 | + return TPM_RCS_KEY + RC_Sign_keyHandle; |
| 212 | ++ } |
| 213 | + |
| 214 | + // A key that will be used for x.509 signatures can't be used in TPM2_Sign(). |
| 215 | + if(IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, x509sign)) |
| 216 | ++ { |
| 217 | + return TPM_RCS_ATTRIBUTES + RC_Sign_keyHandle; |
| 218 | ++ } |
| 219 | + |
| 220 | +- // pick a scheme for sign. If the input sign scheme is not compatible with |
| 221 | +- // the default scheme, return an error. |
| 222 | ++ // Pick a scheme for signing. If the input signing scheme is not compatible |
| 223 | ++ // with the default scheme or the signing key type, return an error. If a |
| 224 | ++ // valid hash algorithm is not specified, return an error. |
| 225 | + if(!CryptSelectSignScheme(signObject, &in->inScheme)) |
| 226 | ++ { |
| 227 | + return TPM_RCS_SCHEME + RC_Sign_inScheme; |
| 228 | ++ } |
| 229 | + // If validation is provided, or the key is restricted, check the ticket |
| 230 | + if(in->validation.digest.t.size != 0 |
| 231 | + || IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, restricted)) |
| 232 | +diff --git a/src/tpm2/crypto/CryptHash_fp.h b/src/tpm2/crypto/CryptHash_fp.h |
| 233 | +index adf1ba9..721d335 100644 |
| 234 | +--- a/src/tpm2/crypto/CryptHash_fp.h |
| 235 | ++++ b/src/tpm2/crypto/CryptHash_fp.h |
| 236 | +@@ -77,7 +77,7 @@ CryptGetHashDef( |
| 237 | + BOOL |
| 238 | + CryptHashIsValidAlg( |
| 239 | + TPM_ALG_ID hashAlg, |
| 240 | +- BOOL flag |
| 241 | ++ BOOL isAlgNullValid |
| 242 | + ); |
| 243 | + LIB_EXPORT TPM_ALG_ID |
| 244 | + CryptHashGetAlgByIndex( |
| 245 | +diff --git a/src/tpm2/crypto/openssl/CryptHash.c b/src/tpm2/crypto/openssl/CryptHash.c |
| 246 | +index cb5bd0f..eb484b8 100644 |
| 247 | +--- a/src/tpm2/crypto/openssl/CryptHash.c |
| 248 | ++++ b/src/tpm2/crypto/openssl/CryptHash.c |
| 249 | +@@ -139,12 +139,12 @@ CryptGetHashDef( |
| 250 | + BOOL |
| 251 | + CryptHashIsValidAlg( |
| 252 | + TPM_ALG_ID hashAlg, // IN: the algorithm to check |
| 253 | +- BOOL flag // IN: TRUE if TPM_ALG_NULL is to be treated |
| 254 | ++ BOOL isAlgNullValid // IN: TRUE if TPM_ALG_NULL is to be treated |
| 255 | + // as a valid hash |
| 256 | + ) |
| 257 | + { |
| 258 | + if(hashAlg == TPM_ALG_NULL) |
| 259 | +- return flag; |
| 260 | ++ return isAlgNullValid; |
| 261 | + return CryptGetHashDef(hashAlg) != &NULL_Def; |
| 262 | + } |
| 263 | + /* 10.2.13.4.4 CryptHashGetAlgByIndex() */ |
| 264 | +-- |
| 265 | +2.45.3 |
| 266 | + |
0 commit comments