parallaxsecond / rust-tss-esapi

TSS 2.0 Enhanced System API (ESAPI) Rust wrapper
https://docs.rs/tss-esapi/
Apache License 2.0
85 stars 51 forks source link

how to use nv_read_public()? #479

Closed bingzhux closed 8 months ago

bingzhux commented 8 months ago

I have a TPM NV handle value, e.g. 0x01500047, and I'm pretty sure that it is already created inside TPM.

However, I don't know how to call this _nv_read_public()_ below by passing this handle value (0x01500047) as parameter, to get this nv's public information.

https://github.com/parallaxsecond/rust-tss-esapi/blob/2dfc3158ced10b3394aded4c053dc059ccf35ac1/tss-esapi/src/context/tpm_commands/non_volatile_storage.rs#L458

because this function requires a handle NvIndexHandle value, which is not the u32 value of 0x01500047.

I understand that, please correct me if I am wrong, we can use this code below to convert this u32 value to NvIndexTpmHandle value: let nvtpmhandle = NvIndexTpmHandle::new(0x01500047).unwrap();

But now, the question is how to convert the value (nvtpmhandle) type of NvIndexTpmHandle to the type of NvIndexHandle, which is required to be passed into function nv_read_public()?

Actually, there are too many handles, which is quite confusing to me. For example, NvIndexTpmHandle, NvIndexHandle, TpmHandle, ObjectHandle...

Superhepper commented 8 months ago

So if you want to skip to do the steps that are required when dealing with NV memory in the TPM, I suggest you look at abstractions feature where you have several functions which can help you dealing with NV memory.

About the handles yes. There are a lot of handles. Because the specification specifies a lot of handles and they can be a bit confusing. They are there in order to some extent mimic the specification.

ESAPI: ObjectHandle - General handle type that can point to anything. NvIndexHandle - A handle associated with a NV space. It is returned when the NV memory is defined and is used in all interactions with nv context methods.

TPM: TpmHandle - A TPM handle as it is defined in the standard. NvIndexTpmHandle - A Tpm,Handle in NV range of TPM Handles.

So how would one go about looking up a TPM handle then and start interacting with the NV memory?

Something like this.

  1. Create NvTpmIndexHandle.

    let nv_tpm_index_handle = NvIndexTpmHandle::new(0x01500047).expect("Failed to create nv index tom handle.");
  2. Look up the object handle associated with this tpm handle and convert into an nv index handle.

    let new_nv_index_handle = context
    .tr_from_tpm_public(nv_tpm_index_handle .into())
    .map(NvIndexHandle::from)
    .expect("Failed to retrieve nv index handle");

Now you have the handle needed in order to call the nv context methods.

I hope this helps.

bingzhux commented 8 months ago

Thank you so much. But with this code, i got an issue:

WARNING:esys:src/tss2-esys/api/Esys_NV_ReadPublic.c:309:Esys_NV_ReadPublic_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/esys_tr.c:209:Esys_TR_FromTPMPublic_Finish() Error NV_ReadPublic ErrorCode (0x00000982)
ERROR:esys:src/tss2-esys/esys_tr.c:320:Esys_TR_FromTPMPublic() Error TR FromTPMPublic ErrorCode (0x00000982)
thread 'main' panicked at src/main.rs:62:10:
Failed to retrieve nv index handle: TssError(Tpm(FormatOne(TpmFormatOneResponseCode { error_number: Attributes, argument_number: Session(1) })))
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

the error code is 0x00000982, which is decoded as below. I've no idea what is "inconsistent attributes" here.

Format Error:
Session: 0x1
Error: TPM_RC_ATTRIBUTES
Description: inconsistent attributes

Here is my code snippet.

fn nv_test(){
    let mut context =
        Context::new(TctiNameConf::Mssim(Default::default())).expect("Failed to create Context");
    context
        .startup(StartupType::Clear)
        .expect("Failed to startup TPM2!");

    let session = context
        .start_auth_session(
            None,
            None,
            None,
            SessionType::Hmac,
            SymmetricDefinition::AES_256_CFB,
            HashingAlgorithm::Sha256,
        )
        .expect("Failed to create session")
        .expect("Received invalid handle");

    context.set_sessions((Some(session), None, None));

    let nv_tpm_handle =
        NvIndexTpmHandle::new(NV_HANDLE_VALUE).expect("Failed to create nv index tom handle.");

    let _new_nv_index_handle = context
        .tr_from_tpm_public(nv_tpm_handle.into())
        .map(NvIndexHandle::from)
        .expect("Failed to retrieve nv index handle");
}

I'm pretty sure my index 0x01500047 was created, because when I recreate it with nv_define_space(), I got an error code 0x0000014c (NV index or persisted object already defined).