[prev in list] [next in list] [prev in thread] [next in thread] 

List:       trousers-users
Subject:    Re: [TrouSerS-users] Output of TSS_TPM_Quote() function
From:       Hal Finney <hal.finney () gmail ! com>
Date:       2009-12-08 18:54:45
Message-ID: da7b3ce30912081054w78e84dd1nad48d4d04fad2daf () mail ! gmail ! com
[Download RAW message or body]

Hi Hardeep - Actually you mean that you will use the public identity
key to *verify the signature* of data in ValidationData. Let me
explain this in more detail. I wrote a long message about this a few
days ago but I will focus on this one issue.

Tspi_TPM_Quote() takes a TSS_VALIDATION structure which has one input
buffer and two output buffers.  The input buffer is rgbExternalData
and is "external data" that you supply to be signed, which should be 20 bytes
long.  The output buffers are rgbData and rgbValidationData.  rgbData
is a TPM_QUOTE_INFO struct which gets signed.  rgbValidationData is
the RSA signature over the rgbData buffer.  In addition, the TSS_HPCRS
object gets updated on return to hold the PCR
values that were signed.

So to verify the signature, the first thing you do is to hash the
rgbData value, and then use an RSA library to check that
rgbValidationData is a valid signature on the rgbData hash, using the
public identity key. You can perform this step without hashing any
PCRs; it is self-contained based on the return values from the Quote
call. But you need to do more, and that is what you are asking about.

The next step is that you need to verify that the hash of the PCRs
matches the field compositeHash in TPM_QUOTE_INFO. You are asking how
to hash the PCRs.

What you do is to create a TPM_PCR_COMPOSITE structure holding the PCR
values, and hash that. However it has to be formatted in a special
way. If you look at tpm.h in the include/tss subdirectory (which also
defines TPM_QUOTE_INFO), you will see the following structure
definitions:

typedef struct tdTPM_PCR_SELECTION                          /* 1.1b */
{
    UINT16    sizeOfSelect;
    SIZEIS(sizeOfSelect)
        BYTE *pcrSelect;
} TPM_PCR_SELECTION;

typedef struct tdTPM_PCR_COMPOSITE                          /* 1.1b */
{
    TPM_PCR_SELECTION select;
    UINT32            valueSize;
    SIZEIS(valueSize)
        TPM_PCRVALUE *pcrValue;
} TPM_PCR_COMPOSITE;

The second one, TPM_PCR_COMPOSITE, is what you want to hash, but note
that it includes TPM_PCR_SELECTION, the first one. Now you have to
format these in a special way. Note the fields pcrSelect and pcrValue
- they are pointers. Instead, you need to format them as in-line byte
arrays. They are preceded by fields which hold the length in bytes of
these arrays.

pcrSelect is supposed to be a bit map of which PCRs are being used in
the Quote. The LSB of the 1st byte is PCR 0; the MSB of the 1st byte
is PCR 7; the LSB of the 2nd byte is PCR 8, and so on. The length
should be enough to hold all the PCRs supported by the TPM. Normally
that will be 3 bytes with a modern TPM (corresponding to 24 PCRs).
Therefore sizeOfSelect should be 3.

pcrValue holds the actual PCR values being signed, 20 bytes each, one
after another, concatenated. So its length will be 20 times the number
of PCRs that are being signed, and that is what should be stored in
valueSize.

Putting this together, set up a data structure in memory that starts
with 2 bytes of sizeOfSelect. This should hold the value 3. NOTE THAT
IT IS IN BIG_ENDIAN FORM. The 1st byte is 0 and the 2nd byte is 3.
Then comes 3 bytes of the bit map for which PCRs are signed, as I
explained earlier. Then comes 4 bytes of valueSize, which again should
be 20 times the number of PCRs being signed, AGAIN IN BIG-ENDIAN FORM.
Finally come the actual PCR values, 20 bytes each. The total length of
this will be 2 + 3 + 4 + 20*nPCRs. Hash this buffer and compare with
the compositeHash field of TPM_QUOTE_INFO (ie. rgbData). If they
match, you know that these are the set of PCRs which are signed.

Now here is a special note, which is how to read the PCR values.
Rather than reading them from the TPM, it is better to read them from
the HPCRS object that you passed to Tspi_TPM_Quote(). When the PCRs
are signed, their values are stored in this object. You can read the
signed values using Tspi_PcrComposite_GetPcrValue() on the HPCRS
object, for each PCR that was signed. Then these get stored in the
data structure I described above. This is a more reliable way to read
the correct PCR values.

Well, this is probably more complicated than you expected, but that is
the general rule when dealing with the TPM. Get used to it! I will be
glad to answer more questions if you have them.

Hal Finney



On Mon, Dec 7, 2009 at 11:10 PM, Hardeep Uppal
<hardeepu@cs.washington.edu> wrote:
> Ok. So I can use the public identy key to decrypt data in
> ValidationData.rgbValidationData but it will not match the current set of
> pcr values that are in the tpm since the signed pcr values were hashed
> before getting signed. This means that I need to look up the current pcr
> values in the tpm, do SHA-1 hash of each value and then compare that with
> the decrypted data in ValidationData.rgbValidationData to check if the pcr
> values getting signed are same as the pcr values in the tpm. Does that sound
> correct?
>
> --Hardeep
>
> On Mon, Dec 7, 2009 at 10:47 PM, adrian golding <adriangolding@gmail.com>
> wrote:
>>
>> hi,
>> yeah, the ValidationData.rgbValidationData holds the hashed then signed
>> pcr values.
>> ValidationData.rgbExternalData holds the nonce i think.
>> ValidationData.rgbData is another struct that holds things such as
>> version, fixed bytes of "QUOT", the nonce (rgbExternalData) and the hash of
>> your PCR(s).  note that the PCRs contained in the hash is never in plain.
>> i think you can just put in some known value as the nonce and create a
>> quote to check if the above is correct. hope that helps! =]
>> regards - adrian
>>
>>
>>
>> On Tue, Dec 8, 2009 at 2:15 PM, Hardeep Uppal <hardeepu@cs.washington.edu>
>> wrote:
>>>
>>> Hi Adrian,
>>>
>>> Thanks for the reply. One thing I read on a forum was that the tpm will
>>> hash the current pcr values and then sign the hashed pcr value with a key.
>>> Is that true? Also which byte array holds the sign pcr values? Can you give
>>> me a description of what each byte array means.
>>>
>>> --Hardeep
>>>
>>> On Mon, Dec 7, 2009 at 10:02 PM, adrian golding <adriangolding@gmail.com>
>>> wrote:
>>>>
>>>> hi,
>>>>
>>>> typedef struct tdTSS_VALIDATION
>>>> {
>>>>     TSS_VERSION  versionInfo;
>>>>     UINT32       ulExternalDataLength;
>>>> #ifdef __midl
>>>>     [size_is(ulExternalDataLength)]
>>>> #endif
>>>>     BYTE*        rgbExternalData;
>>>>     UINT32       ulDataLength;
>>>> #ifdef __midl
>>>>     [size_is(ulDataLength)]
>>>> #endif
>>>>     BYTE*     rgbData;
>>>>     UINT32    ulValidationDataLength;
>>>> #ifdef __midl
>>>>     [size_is(ulValidationDataLength)]
>>>> #endif
>>>>     BYTE*     rgbValidationData;
>>>> } TSS_VALIDATION;
>>>>
>>>> its in ~/src/includes/tss/tss_structs.h
>>>>
>>>> regards - adrian
>>>
>>
>
>
> ------------------------------------------------------------------------------
> Return on Information:
> Google Enterprise Search pays you back
> Get the facts.
> http://p.sf.net/sfu/google-dev2dev
>
> _______________________________________________
> TrouSerS-users mailing list
> TrouSerS-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/trousers-users
>
>

------------------------------------------------------------------------------
Return on Information:
Google Enterprise Search pays you back
Get the facts.
http://p.sf.net/sfu/google-dev2dev
_______________________________________________
TrouSerS-users mailing list
TrouSerS-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/trousers-users

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic