google / go-attestation

Apache License 2.0
340 stars 86 forks source link

Infinity Loop in EKs() method #260

Open l0nax opened 2 years ago

l0nax commented 2 years ago

I'm using the latest published version (v0.3.2) of this library with a TPM 2.0.

With the following code (copied from the examples):

func main() {
    tpm, err := attest.OpenTPM(nil)
    if err != nil {
        log.Fatalf("Failed to open TPM: %v", err)
    }
    defer tpm.Close()

    log.Printf("+ Opened TPM!\n")

    // Create a new AK.
    ak, err := tpm.NewAK(nil)
    if err != nil {
        log.Fatalf("Failed to create AK: %v", err)
    }
    defer ak.Close(tpm)

    log.Printf("+ Created new AK\n")

    // Read the EK.
    ek, err := tpm.EKs()
    if err != nil {
        log.Fatalf("Failed to enumerate EKs: %v", err)
    }

    log.Printf("+ Got EKs len=%d ==> %+v\n", len(ek), ek)

    // Read parameters necessary to generate a challenge.
    ap := ak.AttestationParameters()

    // Generate a credential activation challenge (usually done on the server).
    activation := attest.ActivationParameters{
        TPMVersion: tpm.Version(),
        EK:         ek[0].Public,
        AK:         ap,
    }
    secret, challenge, err := activation.Generate()
    if err != nil {
        log.Fatalf("Failed to generate activation challenge: %v", err)
    }

    // Challenge the AK & EK properties to recieve the decrypted secret.
    decrypted, err := ak.ActivateCredential(tpm, *challenge)
    if err != nil {
        log.Fatalf("Failed to activate credential: %v", err)
    }

    // Check that the AK completed the challenge (usually done on the server).
    if subtle.ConstantTimeCompare(secret, decrypted) == 0 {
        log.Fatal("Activation response did not match secret")
    }
}

It seems that, if I execute the program, it never finishes after calling tpm.EKs(). After a little debugging it came clear that the tpm2.NVReadEx(…) tries to determine the block size if the blockSize parameter is zero by reading the capability NVMaxBufferSize.

But it seems that my TPM does not have this capability:

Command Output ```bash ~$ tpm2_getcap properties-variable TPM2_PT_PERSISTENT: ownerAuthSet: 0 endorsementAuthSet: 0 lockoutAuthSet: 0 reserved1: 0 disableClear: 0 inLockout: 0 tpmGeneratedEPS: 0 reserved2: 0 TPM2_PT_STARTUP_CLEAR: phEnable: 1 shEnable: 1 ehEnable: 1 phEnableNV: 1 reserved1: 0 orderly: 0 TPM2_PT_HR_NV_INDEX: 0x4 TPM2_PT_HR_LOADED: 0x0 TPM2_PT_HR_LOADED_AVAIL: 0x3 TPM2_PT_HR_ACTIVE: 0x0 TPM2_PT_HR_ACTIVE_AVAIL: 0x40 TPM2_PT_HR_TRANSIENT_AVAIL: 0x3 TPM2_PT_HR_PERSISTENT: 0x2 TPM2_PT_HR_PERSISTENT_AVAIL: 0x8 TPM2_PT_NV_COUNTERS: 0x0 TPM2_PT_NV_COUNTERS_AVAIL: 0xC TPM2_PT_ALGORITHM_SET: 0x0 TPM2_PT_LOADED_CURVES: 0x0 TPM2_PT_LOCKOUT_COUNTER: 0x0 TPM2_PT_MAX_AUTH_FAIL: 0x20 TPM2_PT_LOCKOUT_INTERVAL: 0x1C20 TPM2_PT_LOCKOUT_RECOVERY: 0x15180 TPM2_PT_AUDIT_COUNTER_0: 0x0 TPM2_PT_AUDIT_COUNTER_1: 0x0 ~$ tpm2_getcap properties-fixed TPM2_PT_FAMILY_INDICATOR: raw: 0x322E3000 value: "2.0" TPM2_PT_LEVEL: raw: 0 TPM2_PT_REVISION: raw: 0x63 value: 0.99 TPM2_PT_DAY_OF_YEAR: raw: 0xCE TPM2_PT_YEAR: raw: 0x7DD TPM2_PT_MANUFACTURER: raw: 0x49465800 value: "IFX" TPM2_PT_VENDOR_STRING_1: raw: 0x534C4239 value: "SLB9" TPM2_PT_VENDOR_STRING_2: raw: 0x36363500 value: "665" TPM2_PT_VENDOR_STRING_3: raw: 0x0 value: "" TPM2_PT_VENDOR_STRING_4: raw: 0x0 value: "" TPM2_PT_VENDOR_TPM_TYPE: raw: 0x1 TPM2_PT_FIRMWARE_VERSION_1: raw: 0x50000 TPM2_PT_FIRMWARE_VERSION_2: raw: 0x44102 TPM2_PT_INPUT_BUFFER: raw: 0x400 TPM2_PT_HR_TRANSIENT_MIN: raw: 0x3 TPM2_PT_HR_PERSISTENT_MIN: raw: 0x7 TPM2_PT_HR_LOADED_MIN: raw: 0x3 TPM2_PT_ACTIVE_SESSIONS_MAX: raw: 0x40 TPM2_PT_PCR_COUNT: raw: 0x18 TPM2_PT_PCR_SELECT_MIN: raw: 0x3 TPM2_PT_CONTEXT_GAP_MAX: raw: 0xFFFFFFFF TPM2_PT_NV_COUNTERS_MAX: raw: 0x0 TPM2_PT_NV_INDEX_MAX: raw: 0x680 TPM2_PT_MEMORY: raw: 0x6 TPM2_PT_CLOCK_UPDATE: raw: 0x1000 TPM2_PT_CONTEXT_HASH: raw: 0xB TPM2_PT_CONTEXT_SYM: raw: 0x6 TPM2_PT_CONTEXT_SYM_SIZE: raw: 0x80 TPM2_PT_ORDERLY_COUNT: raw: 0xFF TPM2_PT_MAX_COMMAND_SIZE: raw: 0x500 TPM2_PT_MAX_RESPONSE_SIZE: raw: 0x500 TPM2_PT_MAX_DIGEST: raw: 0x20 TPM2_PT_MAX_OBJECT_CONTEXT: raw: 0x26A TPM2_PT_MAX_SESSION_CONTEXT: raw: 0xE9 TPM2_PT_PS_FAMILY_INDICATOR: raw: 0x1 TPM2_PT_PS_LEVEL: raw: 0x2 TPM2_PT_PS_REVISION: raw: 0x100 TPM2_PT_PS_DAY_OF_YEAR: raw: 0x0 TPM2_PT_PS_YEAR: raw: 0x0 TPM2_PT_SPLIT_MAX: raw: 0x0 TPM2_PT_TOTAL_COMMANDS: raw: 0x55 TPM2_PT_LIBRARY_COMMANDS: raw: 0x54 TPM2_PT_VENDOR_COMMANDS: raw: 0x1 ```
l0nax commented 2 years ago

The TPM I'm using is the Infineon SLB 9665TT2.0.