Also use the new privatExponent for dP, dQ and qInv.
There are two functions that need to be adapted:
- ComputePrivateExponent: producer of these parameters
- RsaPrivateKeyOp : consumer of these parameters
ComputePrivateExponent is converted to store the results into Z->dP,
Z->dQ, and Z->qInv. Therefore, remove the old privateExponent parameter
*pExp, that was previously used to store them, from the signature of this
function and pull out the initialization of pExp and preservation of Q
to be done before calling this function. This is done in the 2 calling
functions. After returning from the function copy the values of Z->dP,
Z->dQ, and Z->qInv to the old privateExponent where the results had
been stored previously and where we need to have them.
This change results in a sequence like this for the 2 callers:
RsaInitializeExponentOld(&rsaKey->privateExponent);
BnCopy((bigNum)&rsaKey->privateExponent.Q, Z->Q); // preserve Q
VERIFY(ComputePrivateExponent(bnE, Z));
RsaSetExponentOld(&rsaKey->privateExponent, Z); // duplicate dP, dQ, qInv
The values for dP, dQ, ad qInv are consumed by RsaPrivateKeyOp. Therefore,
adjust this functions signature by removing the old privateExponent
parameter *pExp from it and make sure that callers initialize Z->dP,
Z->dQ, and Z->qInv before calling this functions. There are two call-sites
where the one in RSADP looks like this:
RsaSetExponentFromOld(Z, &key->privateExponent); // copy Q, dP, dQ, qInv to Z
VERIFY(RsaPrivateKeyOp(bnM, Z));
The call site in CryptRsaGenerateKey has called ComputePrivateExponent
before, therefore it already holds the values in Z.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Pass the new privateExponent to RsaPrivateKeyOp replacing the P parameter.
To be able to use MakePgreaterThanQ(Z), make sure that both callers of
this function have Z->P and Z->Q values properly set.
This function has the following two callers:
- CryptRsaPrivateKey: Z->P and Z->Q are already holding valid values
- RSADP: Copy the value of privateExponent.Q to Z->Q.
An inconsequential side effect of the changes to RsaPrivateKeyOp()
is that Z->P is greater than Z->Q upon return from this function.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Replace the local variable bnP with Z->P. Initialize Z->P with the
value that bnP had been initialized with.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Replace the P and Q parameters of ComputePrivateExponent with the new
privateExponent struct (sync with upstream).
ComputePrivateExponent has two callers:
- CryptRsaGenerateKey: Z already holds P and Q from previous change
- CryptRsaLoadPrivateExponent: Sync the code with upstream so that we can also
use the privateExponent Z as parameter to ComputePrivateExponent holding
valid values in Z->P and Z->Q.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
- Import RsaInitializeExponent from upstream
- CryptRsaGenerateKey: Replace local bnP and bnQ variables by using Z->P
and Z->Q respectively
The only side-effect this change has is that it costs more initialization
time when NEW_PRIVATE_EXPONENT initializes the currently unused variables
dP_unused, dQ_unused, and qInv_unused.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
The upstream function switches entirely to publicArea and sensitive
parameters for CrytpRsaGenerateKey getting rid of the OBJECT. We still
need the OBJECT at this point, so keep it for now but annotate the
code and add a consitency check that ensures that the publicArea and
sensitive parameters are from the OBJECT. This holds for the single
caller.
Adjust the single caller to the change in parameters.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Previously the key check was done when object == NULL. Now this
particular case is handle by a check being done when parent == NULL
since the only caller of ObjectLoad() with object == NULL also has
parent == NULL, so there's no behavior change. All other cases
are handled as before.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
- Use UnsignedCompareB() rather than BnUnsignedCmp()
- Use VERIFY to check results and add failure exit.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
- Remove code related to CRT_FORMAT_RSA == NO.
- Remove N parameter from function and adjust callers
- Use VERIFY after each statement
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
- Remove support for CRT_FORMAT_RSA == NO
- Remove now unused parameter N from function signature; adjust callers
- Rename E to pubExp
- Rename temp to pT
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
- Continue the prime number generation while retVal == TPM_RC_NO_RESULT
- Terminate the loop when BnGeneratePrimeForRSA() returns a failure
The changes should not lead to any different primary keys than before.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
RSA_PRIVATE_SIZE is the correct size to use since this is the size that
TPM2B_PRIVATE_KEY_RSA has been defined with.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
When an object is later marshalled in TPM2_ContextSave, the publicOnly
attribute isn't taken into account and therefore potentially stale
sensitive information can be marshalled, which is a problem if the
buffer sizes it contains have values that are too large - this
triggers assertion failures.
Avoid this by clearing out the sensitive area upon ObjectLoad if not
provided, making the behaviour consistent with when a fresh, unused,
object entry is used.
Signed-off-by: Rob Shearman <rob@graphiant.com>
Fix two locations where s_ccAttr[0].commandIndex is used to access the
commandIndex, which does not work when bitfields are not used. Use
GET_ATTRIBUTE() to access the field so that it works when bitfields are
used and when they are not used. There are several locations in this
file where GET_ATTRIBUTE() is already used to access commandIndex.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Address a false positive issue detect by Coverity (CID 1517797)
about *buflen.
Per this assignment of buflen
cached_blobs[st].buflen = buffer ? buflen : BUFLEN_EMPTY_BUFFER;
the following is true:
If cached_blobs[].buffer is NULL then *buflen = BUFLEN_EMPTY_BUFFER
If cached_blobs[].buffer is not NULL then *buflen != BUFLEN_EMPTY_BUFFER
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Add the implementation for TPM2_ECC_Encrypt/Decrypt. It cannot be
easily enabled due to possible downgrading requirements and also
issues with size-expansion of the PERSISTENT_DATA.auditCommands from
14 to 15 bytes.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Sync with upstream to fix issue in CryptParameterEncryption() from TPM 2
errate v1.4 2.6.1:
"The functions CryptParameterEncryption() and CryptParameterDecryption() in
the reference code in Part 4, 10.2.6.6.5 and 10.2.6.6.6 do not correctly
check the size of the parameter buffer to be encrypted or decrypted. To fix
the issue, the functions should be corrected to check that the parameter
buffer (a TPM2B type field) is at least 2 bytes in length and should use
the function UINT16_Unmarshal() to read the size of the buffer instead of"
BYTE_ARRAY_TO_UINT16().
[...]
The fixed CryptParameterEncryption() function will enter failure mode and
return TPM_RC_FAILURE if the internal response buffer does not contain
enough data for the UINT16 size field."
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Fix the following issue from TPM 2 errata v1.4 2.6.3:
"The function CryptGenerateKeyDes() in the reference code in Part 4,
0.2.9.2.3 does not correctly check the symmetric key size provided in the
sensitive parameter. To fix the issue, the function will check that the
size of the requested TDES key is a multiple of 8 bytes or otherwise the
TPM will return TPM_RC_SYMMETRIC."
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Fix the missing buffer size check that the TPM 2 errata v1.4 mentions in
2.6.2 by adding a buffer size check before reading 2 bytes from a
TPM2B_NAME buffer. There's no known CVE for this.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Check that there are sufficient bytes in the buffer before reading the
cipherSize from it. Also, reduce the bufferSize variable by the number
of bytes that make up the cipherSize to avoid reading and writing bytes
beyond the buffer in subsequent steps that do in-place decryption.
This fixes CVE-2023-1017 & CVE-2023-1018.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Add a caching layer to GetEVPCipher() to avoid having to call evpfn()
mulitple times. Instead, return the 'const EVP_CIPHER *' that a single
call to evpfn() (for a particular algorithm + mode + key size) returned
and cache it for subsequent calls.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Replace usage of deprecated DES_random_key() with EVP_CIPHER API calls.
These newer calls are much more time consuming than the deprecated call.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This reverts commit 9afebc712a.
The issue is that opensslv.h is not included and thus the
OPENSSL_VERSION_NUMBER is not getting set.
Signed-off-by: William Roberts <william.c.roberts@intel.com>
Delay the creation of the EVP_PKEY in InitOpenSSLRSAPrivateKey
so that we can create the key with all the parameters at once.
We have to do this since with the OpenSSL 3.0 API we cannot set
parameters after the initial creation of the key anymore.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Get the BIGNUMs N and E from an RSA key OBJECT. The purpose of
this refactoring is be able to reuse the new function.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Implement BuildRSAKey for building an RSA EVP_PKEY from copies
of the BIGNUMs it gets passed. This way it is clear that the
caller has to free the BIGNUMs it passed itself also in case of
error returned by BuildRSAKey.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Exit the loop when the variable could not be filled with data from the
byte stream. This avoids accessing the variable 'element' in case it
wasn't initialized. The old could would have accessed the possibly
uninitialized variable but exited the loop immediately after.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Only access the entrysize variable if it was read from the buffer. In case
of an error just head towards the exit. Previously, an error would also
have lead the function to do no more useful processing and exited it with
an error code bug Coverity complains that the entrysize variable would be
access while it wasn't initialized.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Check the secret size against the size of the buffer, not the size
member that has not been set yet.
Reported by Coverity.
Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
In TPM_NVRAM_LoadData(), there is an unlikely path where the function
will return an error code but still expect the caller to free the
allocated data. At least some of the callers don't handle this correctly
so ensure that the caller only needs to free data if the function
returns success.
Reported by Coverity.
Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
The build environment used by OSS-Fuzz reports this error.
In file included from /src/libtpms/src/tpm_debug.c:42:
/src/libtpms/src/tpm_debug.h:69:9: error: 'printf' macro redefined [-Werror,-Wmacro-redefined]
#define printf(...) TPMLIB_LogPrintf(__VA_ARGS__);
: ^
/usr/include/x86_64-linux-gnu/bits/stdio2.h:110:11: note: previous definition is here
# define printf(...) \
^
1 error generated.
The simple fix is to #undef printf in case it is #define'd.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Address an issue reported by cppcheck that raises the issue that
tpm_state_path could be NULL when the #define TPM_NV_DISK is not set.
Require that the #define TPM_NV_DISK always be set.
Resolves: https://github.com/stefanberger/libtpms/issues/313
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Initialize a variable in ExecuteCommand following Coverity report
CID 1461252.
Down the callpath as reported in CID 1461252 in
TPMI_ST_COMMAND_TAG_Unmarshal() the passed-in value of
TPMI_ST_COMMAND_TAG *target is stored and possibly restored later on in
case of failure. Coverity complains that the variable is uninitialized.
While this is correct, there's no harm reading the uninitialized value
from the structure and possibly restoring it later on while not doing
anything else with it otherwise. Therefore, it's a false positive.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Initialize a variable in TPM2_PolicyAuthorizeNV() following Coverity
report CID 1470811.
Down the callpath as reported in CID 1470811 in TPMI_ALG_HASH_Unmarshal()
the passed-in value of TPMI_ALG_HASH *target is stored and possibly
restored later on in case of failure. Coverity complains that the variable
is uninitialized. While this is correct, there's no harm reading the
uninitialized value from the structure and possibly restoring it later
on while not doing anything else with it otherwise. Therefore, it's a
false positive.
Resolves: https://github.com/stefanberger/libtpms/issues/311
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Initialize a variable in USER_NVRAM_Unmarshal() follow Coverity
report CID 1470812.
Down the callpath as reported in CID 1470812 in TPMA_NV_Unmarshal() the
passed-in value of TPMA_NV *target is stored and possibly restored later
on in case of failure. Coverity complains that the variable is
uninitialized. While this is correct, there's no harm reading the
uninitialized value from the structure and possibly restoring it later
on while not doing anything else with it otherwise. Therefore, it's a
false positive.
Resolves: https://github.com/stefanberger/libtpms/issues/310
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Openssl 3.0 did return an error if EVP_PKEY_CTX_set0_rsa_oaep_label was called
with label size 0. The function should only be called if the size of the label
is greater 0.
With this fix TPM2_RSA_Encrypt/Decrypt did work with OpenSSL 1.1 and 3.0
for encryption without label.
Signed-off-by: Juergen Repp <juergen.repp@sit.fraunhofer.de>
Only access the variable 'nvi' when the previous unmarshalling worked.
Before this change the undefined value of nvi would have been written
to memory but the error code from the failed marshalling propagated to
the caller so that it was working correctly before as well.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Cast the '1' to UINT64 before shifting it.
Since the shift value is always below 32 it would have never exceeded
the 32bit value it was using before the cast.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Fix typo in the __GNUC_MINOR__ preprocessor symbol.
This change is unlikely to have any impact since it was used for
comparions for gcc version 4.2, which is not in use anymore by now.
Resolves: https://github.com/stefanberger/libtpms/issues/289
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
If s_ContextSlotMask was not set since the TPM 2 was not initialized
by a call to TPM_Manufacture() or the state was not resumed, then
initialize the s_ContextSlotMask to 0xffff.
This situation can occur if a VM with an attached swtpm was started
and the VM's firmware either doesn't support TPM or didn't get to
initialize the vTPM.
The following commands recreated the issue with a SeaBIOS-only VM that
had no attached hard disk but an attached TPM 2:
virsh start BIOS-only-VM ; virsh save BIOS-only-VM save.bin ; \
virsh restore save.bin
Error: Failed to restore domain from save.bin
error: internal error: qemu unexpectedly closed the monitor: \
2022-01-04T19:26:18.835851Z qemu-system-x86_64: tpm-emulator: Setting the stateblob (type 2) failed with a TPM error 0x3 a parameter is bad
2022-01-04T19:26:18.835899Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'tpm-emulator'
2022-01-04T19:26:18.835929Z qemu-system-x86_64: load of migration failed: Input/output error
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2035731
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
exp_array_size is always initialized if `rc == TPM_RC_SUCCESS` and never used
if `rc != TPM_RC_SUCCESS` but some compilers have trouble noticing this.
Signed-off-by: kpcyrd <git@rxv.cc>
To avoid timeouts on short-running commands, such as TPM2_PCR_Extend,
avoid triggering the writing of the permanent state of the TPM 2
if only the clock was updated. So the clock by itself will not cause
the permanent state to be written out anymore but there have to be
other reasons as well.
The state will still be written out upon a TPM2_Shutdown, which is
supposed to be the last command to be sent to the TPM when shutting
down the VM/vTPM. Also, the permanent state will still carry the
latest clock value if it is retrieved via control channel for
VM/VTPM suspend.
The case that may be affected, but is of lesser importance, is the one
where swtpm's volatile state is written to storage using 'swtpm_ioctl -v'
and then swtpm is terminated and restarted (similar to suspend/resume)
and the permanent state file is read from storage but does not contain
the latest clock value. In this case the go.clock will be updated when
the first command after resume is executed.
This fixes the swtpm issue https://github.com/stefanberger/swtpm/issues/597.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Instead of using -Wno-deprecated-declarations use
-DOPENSSL_SUPPRESS_DEPRECATED to only suppress OpenSSL deprecated
declarations warnings.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
OpenSSL 3.0 has changed the signature of EVP_PKEY_get0_RSA() from
struct rsa_st *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
to
const struct rsa_st *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey);
We now have to use EVP_PKEY_get1_RSA with this signature so that we can
access the RSA key. The signature of that function hasn't changed between
OpenSSL 1.1.0 and 3.0.0.
struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
Free the additional reference held on the RSA key.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Event sequence objects were never properly marshalled and when their state
was saved and later restored their state may have been corrupted. Fix this
now by also marshalling the state of event sequence objects.
Bump up the version of the HASH_OBJECT's header to '3' so that previously
written state can be resumed if an event sequence object is encountered
and we only unmarshal an event sequence object when the version is at least
'3'.
Fixes issue #259.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Make the expected array size of compile-time constants dependent on
the version of the header. This way we can add elements to the array
while bumping up the version of the header.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Extend the test case data generation script with sm4. Since several
distros' openssl do not support sm4, we need to test for whether sm4
is supported by the installed openssl.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Use the EC_POINT_set/get_affine_coordinates function on OpenSSL >= 1.1.
These function are a 1:1 replacement for the
EC_POINT_set/get_affine_coordinates_GFp functions and are available
since OpenSSL 1.1 and are deprecated in OpenSSL 3.0.
This patch addresses one aspect of the OpenSSL 3.0 issues raised in
issue #215.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
The NVRAM entries in s_indexOrderlyRam array do not need to contain a
0-sized terminating node. Instead, the entries may fill up this 512
byte array so that no NV_RAM_HEADER structure fits anymore. The fact
that no more NV_RAM_HEADER structure fits is also an indicator for the
last entry. We need to account for this in the code marshalling and
unmarshalling the entries so that we stop marshalling the entries
then and similarly stop unmarshalling.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Initialize a while OBJECT before using it. This is necessary since
an OBJECT may also be used as a HASH_OBJECT via the ANY_OBJECT
union and that HASH_OBJECT can leave bad size inidicators in TPM2B
buffer in the OBJECT. To get rid of this problem we reset the whole
OBJECT to 0 before using it. This is as if the memory for the
OBJECT was just initialized.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Fix the following compiler warning from gcc 10.3.0 by using memcpy
instead of MemoryCopy (fixes issue #229).
tpm2/NVDynamic.c: In function 'NvRamGetEnd':
tpm2/NVDynamic.c:378:12: warning: function may return address of local variable [-Wreturn-local-addr]
378 | return iter;
| ^
tpm2/NVDynamic.c:339:26: note: declared here
339 | NV_RAM_HEADER header;
| ^
tpm2/NVDynamic.c: In function 'NvRamGetIndex':
tpm2/NVDynamic.c:411:12: warning: function may return address of local variable [-Wreturn-local-addr]
411 | return currentAddr;
| ^
tpm2/NVDynamic.c:339:26: note: declared here
339 | NV_RAM_HEADER header;
| ^
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Restore the original value of the memory location where data from
a stream was unmarshalled and the unmarshalled value was found to
be illegal. The goal is to not keep illegal values in memory.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Add maxSize parameter to TPM2B_Marshal and assert on it checking
the size of the data intended to be marshaled versus the maximum
buffer size.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reset the buffer size indicator in a TPM2B type of buffer after it failed
the test for the maximum buffer size it allows. This prevents having bad
buffer sizes in memory that can come to haunt us when writing the volatile
state for example.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Windows 2019 Server padds the TPM_ContextLoad() command with additional
bytes up to TPM_PT_MAX_OBJECT_CONTEXT for the TPMS_CONTEXT part. Since
libtpms does not use an OBJECT to serialize the keys (anymore) it now
uses less bytes than the MAXimum of TPM_PT_MAX_OBJECT_CONTEXT bytes and
the padding leaves some unconsumed bytes that end up failing the command
since no left-over bytes are allowed in any command.
When unconsumed bytes are left in TPMS_CONTEXT_Unmarshal() we check that
the original passed in size was that of TPM_PT_MAX_OBJECT_CONTEXT and
only then consume the additional padding bytes. Luckily only one command
calls TPMS_CONTEXT_Unmarshal() so that no unwanted side effects should
occur anywhere else, such as no bytes left for unmarshalling the next
structure.
The wisdom behind the padding is not quite clear but it feels like
ill-fixing the code to work around a Windows 2019 server bug...
This patch fixes issed #217
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This patch addresses issue #209.
The context gap for libtpms is currently only 0xff due to the CONTEXT_SLOT
being a UINT8. To extend this to 0xffff, we need to define the CONTEXT_SLOT
as UINT16 and introduce a global variable s_ContextArrayMask that takes on
two valid values, 0xff for simulating the CONTEXT_SLOT when it was UINT8
and 0xffff for usage with the new CONTEXT_SLOT of type UINT16. All
occurrences of casts to CONTEXT_SLOT are replaced with a macro
CONTEXT_SLOT_MASKED that applies this mask to a value instead of using the
cast. We also use it for some calculations to avoid spilling over from
1 byte into 2 bytes for example. The cast with the new code is the same as
applying the mask 0xffff, and using the 0xff mask we can simulate the old
CONTEXT_SLOT (1 byte), which we need for seamlessly resuming old state. We
switch from the 0xff mask to the 0xffff mask when the TPM is reset.
There's one place where the s_ContextArrayMask is initialized to 0xff, and
this is when we resume 'old' STATE_RESET_DATA. The places where it is
intialized to 0xffff are in TPM_Manufacture() and
TPM_SessionStartup(SU_CLEAR), both of which are not called after resuming
state.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Do not call BLOCK_SKIP_READ once rc has been set to any error value.
Therefore, surround all occurrences of BLOCK_SKIP_READ() with tests
of 'rc'.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Implement a cache for the private exponent 'D' and prime 'Q' so that we
do not have to recalculate 'Q' and 'D' every time an RSA key is used. For
a cache hit we now use ~34000 cycles and on a cache miss it needs around
130000 cycles. Previously it needed around 100000 cycles to calcuate 'Q'
and 'D'. Assuming that keys will be reused and the cache is big enough
for the number of keys being use (64 entries), it seems well worth it.
This solution is better than extending the OBJECT with 'D' since OBJECT is
kept in the TPM's NVRAM and we would then need more memory to store OBJECTs
there.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
When testing downgrading from libtpms 0.8 to 0.7 (which is not
possible), the error message which is reported is:
libtpms/tpm2: Unexpect value for MAX_RSA_KEY_BITS; its value 3072 is
not = 2048; (version: 2).
codespell (https://github.com/codespell-project/codespell) reports a
misspelling for "Unexpect", which should be "Unexpected". As the project
contains many more misspellings in comments, error messages and
documentation, fix all misspellings reported by codespell.
Signed-off-by: Nicolas Iooss <nicolas.iooss@ledger.fr>
The TPM is supposed to provide the output IV in the ivInOut parameter in
CryptSymmetricEncrypt. In the case of using the openssl routines, the
output IV is missed, and the resulting output from the TPM is in the
input IV.
OpenSSL unfortunately does not export EVP_CIPHER_CTX_iv() until
tags/OpenSSL_1_1_0, so we have to fall back to the reference code for
previous OpenSSL versions.
Signed-off-by: William Roberts <william.c.roberts@intel.com>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This patch addresses the bug reported in issue #195 where the saving of
an externally loaded public key's context doesn't work due to the usage of
ANY_CONTEXT_SAVE for saving key contexts. This patch fixes the issue by
creating local versions of TPM_SENSITIVE_Marshal/_Unmarshal that deals
with the case where sensitiveType is not a type of private key but a
public key instead that basically doesn't have much information in
TPM_SENSITIVE but is all zeros instead.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
For some peace-of-mind add a function that allows us to check the RSA keys
that are generated, especially the primary keys that are not generated by
OpenSSL.
Use the following configure line to compile libtpms:
CFLAGS="-DDO_RSA_CHECK_KEY=1" ./autogen.sh --prefix=/usr \
--with-tpm2 --with-openssl
Start swtpm after installing libtpms:
swtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --ctrl type=tcp,port=2322 \
--server type=tcp,port=2321 --flags not-need-init --log level=0
We can now run this test program to check keys by using an RSA primary key
for signing.
export TPM_COMMAND_PORT=2321 TPM_PLATFORM_PORT=2322 \
TPM_SERVER_NAME=localhost TPM_INTERFACE_TYPE=socsim \
TPM_SERVER_TYPE=raw
echo "test" > input
swtpm_ioctl --tcp :${TPM_PLATFORM_PORT} -i
tssstartup
while :; do
for keysize in 2048 3072; do
tsscreateprimary -rsa $keysize -si -hi n
tsssign -hk 80000000 -if input
tssflushcontext -ha 80000000
done
done
Libtpms has passed multiple hours of testing.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Some older systems do not define static_assert, so we have to provide
our own static_assert that does 'nothing'.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Sanitize some of the values read from the TPM state stream.
All Coverity discoveries seem to be false positives.
Coverity doesn't like to see array_size being used in the loop even
though it was compared against ARRAY_SIZE() before. We solve this by
using ARRAY_SIZE() as the loop limit now rather than array size.
Compare seed.b.size against PRIMARY_SEED_SIZE even though this is
already being done in TPM2B_Unmarshal().
The num_bytes parameter is sanitized via a comparison involving a
sum over a sum of values, but Coverity doesn't seem to detect this.
Then we have to use it as a loop limit. I don't see another way.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Prevent a potential buffer overrun by checking that EVP_DecryptUpdate()
has not overrun the buffer it was passed in, so this overrun should
never occurr unless EVP_DecryptUpdate() was wrong. Also the pAssert above
it should have taken care of it already.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Coverity complains that the *output* variable passed to
AES_set_encrypt_key contains uninitialized bytes, so we initialize
the variables now.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Coverity complains that nrh may not be initialize when copying nrh.size
from it into the buffer pointer to by nrhp. So resolve this by clearing
nrh at the beginning of the loop and checking 'rc' after the Unmarshal.
Previously we could have copied an uninitialized nrh.size but would have
propagated the rc error code from UINT32_Unmarshal(), so this fix doesn't
really change anything.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Save key and hash contexts using the ANY_OBJECT_Marshal function and try
to load it using ANY_OBJECT_Unmarshal(). Unfortunately older contexts were
written out as plain OBJECTs, so we have to accomodate this case as well
so that we can restore key contexts from libtpms-0.7.x. We do not support
resuming HASH contexts from libtpms-0.7.x.
Before this modification context files written out by the IBM TSS stack
were 2692 bytes independent of content. Now an RSA 2048 key is 1222 bytes
and a NIST p384 key is 982 bytes.
Several of the original TPM 2 function exporting Sequence state and
importing it can now be disabled.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Make the functions ANY_OBJECT_Marshal/Unmarshal non-static so that we can
call it from other places. Also allow passing a parameter 'verbose' to the
ANY_OBJECT_Unmarshal function that allows us to call this function without
it logging errors. We need this when trying to load a context from an older
libtpms versions that did not use ANY_OBJECT_Marshal to write out the
OBJECT (but copied it right from memory).
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This patch ensures that the leading zeros in the b parameter for NIST P521
are being kept so that HLK accepts the returned parameters from
TPM2_ECC_Parameters. Now 66 bytes are reported for 'b' rather than only 65.
Do the same for the 'a' parameter, though that one was properly reported
already because it didn't have any leading zeros.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This patch addresses issue #177 by fixing some typos and error
reporting inconsistencies (how structures are spelled) in NVMarhsal.c.
Reported-by: Nicolas Iooss <nicolas.iooss@ledger.fr>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
cppcheck has detected the following issues in 2 functions. However,
neither one of the out-of-bounds array access can happen with the
existing code (see comments in patch).
src/tpm2/Session.c:399:5: note: After for loop, slotIndex has value 3
for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++)
^
src/tpm2/Session.c:414:15: note: Assuming condition is false
if(result != TPM_RC_SUCCESS)
^
src/tpm2/Session.c:419:15: note: Array index out of bounds
s_sessions[slotIndex].occupied = TRUE;
^
src/tpm2/Session.c:591:27: error: Array 's_sessions[3]' accessed at index 3, which is out of bounds. [arrayIndexOutOfBounds]
MemoryCopy(&s_sessions[slotIndex].session, session, sizeof(SESSION));
^
src/tpm2/Session.c:571:5: note: After for loop, slotIndex has value 3
for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++)
^
src/tpm2/Session.c:581:8: note: Assuming condition is false
&& contextIndex != s_oldestSavedSession)
^
src/tpm2/Session.c:591:27: note: Array index out of bounds
MemoryCopy(&s_sessions[slotIndex].session, session, sizeof(SESSION));
^
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
UBSAN detects possibly misaligned address when reading out of the
TPM 2's NVRAM and when writing back into it. The NV_RAM_HEADER may
be unaligned like this:
tests/test_tpm2_save_load_state_3.log:tpm2/Marshal.c:117:29: \
runtime error: load of misaligned address 0x7ffcb53b3bca for type 'UINT32', which requires 4 byte alignment
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Make sure that the value of bnK is not short so that the subsequent
BnEccModMult() runs in constant time. We take the same approach as with
the modifications to BnEccGenerateKeyPair() where we request bnK to have
all bytes set (no leading zeros that will be cut away) in case the order
of the curve is as byte boundary. In the other cases we add the order
to bnK, which creates bnK1, which we then use for BnEccModMult's scalar
parameter.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Suggested-by: Charanjit Jutla <csjutla@us.ibm.com>
Reviewed-by: Charanjit Jutla <csjutla@us.ibm.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
To avoid a potential side channel in the EcSchnorr signing algorithm,
enforce that the OpenSSL-generated bnD does not have leading zeros
that may then cause a timing side channel in the BnEccModMult() operation.
We modified BnEccGenerateKeyPair() so it calls BnEccModMult with a scalar
of constant number of bytes (for a particular curve):
In this version of BnEccGenerateKeyPair we take a dual approach to constant
time requirements: For curves whose order is at the byte boundary, e.g.
NIST P224/P256/P384, we make sure that bnD has all bytes set (no leading zeros)
so that OpenSSL BIGNUM code will not reduce the number of bytes and the
subsequent BnEccModMult() would run faster for a shoter value. For all other
curves whose order is not at the byte boundary, e.g. NIST P521, we simply
always add the order to bnD and call BnEccModMult() with the result bnD1,
which leads to the same result.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Suggested-by: Charanjit Jutla <csjutla@us.ibm.com>
Reviewed-by: Charanjit Jutla <csjutla@us.ibm.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
A tpm12 function that is only needed with freebl library can
be conditionally enabled with '#if USE_FREEBL_CRYPTO_LIBRARY'.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
The JSON returned by TPM2_GetInfo contains a leading zero in the level.
$> swtpm_ioctl --tcp :10000 --info 1
{"TPMSpecification":{"family":"2.0","level":00,"revision":162+0}}
This patch fixes this to:
$> swtpm_ioctl --tcp :10000 --info 1
{"TPMSpecification":{"family":"2.0","level":0,"revision":162+0}}
This patch fixes the following compilation error on Fedora 32 / s390x:
tpm2/Marshal.c: In function 'TPM2B_CREATION_DATA_Marshal':
tpm2/Marshal.c:95:19: error: 'sizePtr' may be used uninitialized in this function [-Werror=maybe-uninitialized]
95 | (*buffer)[0] = (BYTE)((*source >> 8) & 0xff);
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tpm2/Marshal.c:2201:11: note: 'sizePtr' was declared here
2201 | BYTE *sizePtr;
| ^~~~~~~
The error is a false positive since sizePtr will have been initialized if
UINT16_Marshal() is called.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
tpm12/tpm_nvram.c: In function 'TPM_Process_NVWriteValue':
tpm12/tpm_nvram.c:2313:45: error: 'd1NvdataSensitive' may be used uninitialized in this function [-Werror=maybe-uninitialized]
2313 | if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITEALL) &&
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
This compiler error is a false positive since the above statement is inside
this if clause:
if ((returnCode == TPM_SUCCESS) && !done && !dir) {
However, if d1NvdataSensitive was not set then returnCode is
either != TPM_SUCCESS OR
- case index0 = FALSE : dir = TRUE per line 2106 OR
- case index0 = TRUE (nvIndex = 0): done = TRUE per line 2215.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Fix PCRBelongsTCBGroup by adjusting the set of PCRs that belong to the TCB
Group. The effect of this is that PCR changes to PCR 16 (for example) do
not change the pcrUpdateCounter anymore. The effect *should not* have any
negative side effects when using the TPM.
We also need to update the test cases that now show a different
pcrUpdateCounter in the responses. Also 'swtpm' test cases need
to be fixed to expect the changed result.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This does not affect the proper functioning of the code since all
of the commands at the end of the array are currently disabled.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
In corner cases where the size of the salt and the size of the hash
to sign + 2 exceed the signature size we cannot use the salt length =
hash length but have to resort to using the maximum possible salt
length.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Sync up on the #define's for HASH_ALIGNMENT, which does not have much
relevance for the OpenSSL implementation.
The affected 32 or 64 bit align field in the ANY_HASH_STATE doesn't carry
any significance. It can be commented without side effects.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Remove CURVE_NAME_DEF field from ECC_CURVE structure and add
#define CURVE_NAME(N)
so that nothing misses the removed field, which wasn't used
before, either.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Add the #define SYMMETRIC_ALIGNMENT that aligns the tpmCryptKeySchedule_t
size. Since this tpmCryptKeySchedule_t only seems to be used as a stack
variable and the alignment field is never accessed nor the size of the
structre taken, it shouldn't affect anything.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Call EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) when creating an RSA
signature to set the PSS salt length to the digest length. Without
this call we previously set the salt length to the maximum
permissible value, but this is not how TPM 2 implements it.
Per interoperability testing between signatures created previously
with the max. permissible value and the new code, which does not
modify the signature verification code, old signatures still verify.
New signatures also verify.
This patch may solve interoperability with hardware TPMs that signatures
created following this patch now verify on hardware TPMs as well.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Always use a temporary buffer large enough to meet the requirements of the
EVP_DecryptUpdate() call.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Add missing call of EVP_CIPHER_CTX_set_padding(ctx, 0) in the symmetric
decryption case. This was missing and failed some decryption cases.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Add a missing input size check for CryptSymmetricDecrypt so that we return
the proper error code TPM_RC_SIZE in case the input size is not a multiple
of the block size. Before TPM_RC_FAILURE was returned.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
For the RSA decryption we have to use an output buffer of the size of the
(largest possible) RSA key for the decryption to always work.
This fixes a stack corruption bug that caused a SIGBUS and termination of
'swtpm'.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Add missing EC Curve cases in Unmarshal function.
Also, don't accept curves that are not usable during runtime because OpenSSL
may not support them.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
PrimeSieve was accessing the sieveMarks array at out-of-bounds index 5
due to a bug in other parts of the code. This patch fixes the issue
and prevents this access by limiting the values that 'next' can take on.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Return the RSAKeySizes in the JSON produced by TPM2_GetInfo() under
a new flag with value '4'. This helps higher level tools and users
to easily determine what key sizes are supported for RSA.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Start supporting RSA 3072 keys.
NVMarshal.c: We now accept state that was written by libtpms when RSA keys
sizes were 2048 or are 3072, basically less-or-equal than 3072.
Also increase the NVRAM memory size by ~45 kb to accommodate the worst
case where the USER NVRAM is full of 65 2048 bit persisted keys whose 65
OBJECTs are now expanding and need to again fit into the NVRAM. We have
to add exactly 45760 bytes to accomodate this case. See swtpm test
case test_tpm2_save_load_state_2. 65 * 704 = 45760.
NOTE: BETTER TO NOT BACKPORT!!! MAY NEGATIVELY AFFECT UPGRADE PATH!
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Increase the MAX_CONTEXT_SIZE to 2680 to support the increased context
size when using 3072 bit keys.
NVMarhsal.c: Accept MAX_CONTEXT_SIZE values of less-or-equal the 2680,
which also accepts context sizes of the old value 2474.
NOTE: BETTER TO NOT BACKPORT!
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This is the Coverity complaint about the line
infoDataSize = TimeGetMarshaled(&infoData);
CID 1402057: Out-of-bounds access (OVERRUN)
1. overrun-buffer-val: Overrunning array infoData of 32 bytes by passing
it to a function which accesses it at byte offset 255.
TimeGetMarshaled() correctly serializes into &infoData, which is casted to
a buffer and then the data are written into the buffer. Also only 25 bytes,
as indicated by infoDataSize, are used, which is less than sizeof(infoData),
which is 32.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>