Git Product home page Git Product logo

go-attestation's Introduction

Go-Attestation

GoDoc

Go-Attestation abstracts remote attestation operations across a variety of platforms and TPMs, enabling remote validation of machine identity and state. This project attempts to provide high level primitives for both client and server logic.

Talks on this project:

  • "Making Device Identity Trustworthy" - Open Source Summit Europe - October 2019 - (Slides)
  • "Using TPMs to Cryptographically Verify Devices at Scale" - Open Source Summit North America - September 2019 - (Video 39min)
  • "Making Remote Attestation Useful on Linux" - Linux Security Summit - September 2019 - (Video 26min)

Status

Go-Attestation is under active development. Expect API changes at any time.

Please note that this is not an official Google product.

TPM 1.2 support is best effort, meaning we will accept fixes for TPM 1.2, but testing is not covered by CI.

Installation

The go-attestation package is installable using go get: go get github.com/google/go-attestation/attest

TPM1.2

By default, go-attestation does not build in TPM1.2 support on Linux. Linux users must install libtspi and its headers if they need TPM 1.2 support. This can be installed on debian-based systems using: sudo apt-get install libtspi-dev. Then, build go-attestation with the tspi build tag go build --tags=tspi.

Windows users can use go-attestation with TPM1.2 by default.

Example: device identity

TPMs can be used to identify a device remotely and provision unique per-device hardware-bound keys.

TPMs are provisioned with a set of Endorsement Keys (EKs) by the manufacturer. These optionally include a certificate signed by the manufacturer and act as a TPM's identity. For privacy reasons the EK can't be used to sign or encrypt data directly, and is instead used to attest to the presence of a signing key, an Attestation Key (AK), on the same TPM. (Newer versions of the spec may allow the EK to sign directly.)

During attestation, a TPM generates an AK and proves to a certificate authority that the AK is on the same TPM as a EK. If the certificate authority trusts the EK, it can transitively trust the AK, for example by issuing a certificate for the AK.

To perform attestation, the client generates an AK and sends the EK and AK parameters to the server:

// Client generates an AK and sends it to the server

config := &attest.OpenConfig{}
tpm, err := attest.OpenTPM(config)
if err != nil {
    // handle error
}

eks, err := tpm.EKs()
if err != nil {
    // handle error
}
ek := eks[0]

akConfig := &attest.AKConfig{}
ak, err := tpm.NewAK(akConfig)
if err != nil {
    // handle error
}
attestParams := ak.AttestationParameters()

akBytes, err := ak.Marshal()
if err != nil {
    // handle error
}

if err := os.WriteFile("encrypted_aik.json", akBytes, 0600); err != nil {
    // handle error
}

// send TPM version, EK, and attestParams to the server

The server uses the EK and AK parameters to generate a challenge encrypted to the EK, returning the challenge to the client. During this phase, the server determines if it trusts the EK, either by chaining its certificate to a known manufacturer and/or querying an inventory system.

// Server validates EK and/or EK certificate

params := attest.ActivationParameters{
    TPMVersion: tpmVersion,
    EK:         ek.Public,
    AK:         attestParams,
}
secret, encryptedCredentials, err := params.Generate()
if err != nil {
    // handle error
}

// return encrypted credentials to client

The client proves possession of the AK by decrypting the challenge and returning the same secret to the server.

// Client decrypts the credential

akBytes, err := os.ReadFile("encrypted_aik.json")
if err != nil {
    // handle error
}
ak, err := tpm.LoadAK(akBytes)
if err != nil {
    // handle error
}
secret, err := ak.ActivateCredential(tpm, encryptedCredentials)
if err != nil {
    // handle error
}

// return secret to server

At this point, the server records the AK and EK association and allows the client to use its AK as a credential (e.g. by issuing it a client certificate).

go-attestation's People

Contributors

alexmwu avatar brandonweeks avatar chrisfenner avatar copybara-service[bot] avatar deepikarajani24 avatar deniskarch avatar dependabot[bot] avatar djm-google avatar ericchiang avatar gerow avatar hansinator avatar hslatman avatar jkl73 avatar josephlr avatar juanvallejo avatar ldez avatar liamjm avatar lindi2 avatar malt3 avatar mjg59 avatar mwielgoszewski avatar pawalt avatar pszal avatar smo4201 avatar strideynet avatar tracefinder avatar twitchy-jsonp avatar xaionaro avatar xose avatar zhsh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-attestation's Issues

Infinity Loop in EKs() method

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
~$ 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

ActivateCredential error on Nuvoton TPM 2.0

Hello,
While running the code from the project's README (also attached with the post: tpm_attest .go.txt), I am getting the following error:

ActivateCredential: parameter 2, error code 0x4 : value is out of range or is not correct for the context

The TPM equipped on the device is a Nuvoton TPM 2.0. Following is the output from running Intel's TPM TSS tpm2_tools' (version: 2.1.0) tpm2_dump_capability:

TPM_PT_FAMILY_INDICATOR:
as UINT32: 0x08322e3000
as string: "2.0"
TPM_PT_LEVEL: 0
TPM_PT_REVISION: 1.00
TPM_PT_DAY_OF_YEAR: 0x0000002f
TPM_PT_YEAR: 0x000007df
TPM_PT_MANUFACTURER: 0x4e544300
TPM_PT_VENDOR_STRING_1:
as UINT32: 0x726c7300
as string: "rls"
TPM_PT_VENDOR_STRING_2:
as UINT32: 0x4e504354
as string: "NPCT"
TPM_PT_VENDOR_STRING_3:
as UINT32: 0x20000000
as string: " "
TPM_PT_VENDOR_STRING_4:
as UINT32: 0x20000000
as string: " "
TPM_PT_VENDOR_TPM_TYPE: 0x00000001
TPM_PT_FIRMWARE_VERSION_1: 0x00010003
TPM_PT_FIRMWARE_VERSION_2: 0x00000001

My guess is that the problem lies in ActivateCredential is called for this particular device. Using a test from Intel's tpm2-tools (Attached: tpm2_clear_and_test_activation-221.sh.txt) I get the following error on the same host:
ERROR: ActivateCredential failed. TPM Error:0x80012

On performing a tpm2_rc_decode on the error code, I get:

tpm2_rc_decode 0x80012
error layer
hex: 0x80000
identifier: TSS2_SYS_ERROR_LEVEL
description: Error from the SAPI
base error code
identifier: TSS2_BASE_RC_INSUFFICIENT_CONTEXT
description: Context not large enough

When I execute the same two attached files on another host with a different TPM, they run as expected.

Any help in this regard is greatly appreciated.

Thanks!

Best regards,

Write error on /dev/tpmrm0

I'm working on implementing TPM credential activation using this library. I've got EC and AIK creation working, but I'm getting a strange error when I try to actually activate the credential:

failed to activate credential: write /dev/tpmrm0: invalid argument"

Here's the relevant code:

func CalculateResponse(ec *attest.EncryptedCredential, aik *attest.AIK, path string) (*ChallengeResponse, error) {
        tpm, err := attest.OpenTPM(&attest.OpenConfig{
                TPMVersion: attest.TPMVersion20,
        })
        if err != nil {
                return nil, fmt.Errorf("failed to connect to tpm: %v", err)
        }
        defer tpm.Close()

        log.Println(*ec)

        secret, err := aik.ActivateCredential(tpm, *ec)
        if err != nil {
                return nil, fmt.Errorf("failed to activate credential: %v", err)
        }
        return &ChallengeResponse{
                Secret: secret,
        }, nil
}

Any idea what might be wrong here? I am running as root FWIW. Thanks!

PCRs from Quote

Hello, I do like to know how/if can I retrieve the values of the PCRs from the Quote, because I didn't see any method related to that.

Segfault in ParseAKPublic

[signal SIGSEGV: segmentation violation code=0x1 addr=0x2 pc=0x56251519dc69]

<redacted>/attest.ParseAKPublic(0x2, 0xc0029c44e0, 0x1a, 0x20, 0xc002a13980, 0x1, 0x1)
        <redacted>/attest/attest.go:244 +0x449 fp=0xc002a63090 sp=0xc002a62fa8 pc=0x56251519dc69

Appears to be a deref somewhere in .RSAParameters.Sign.Hash.

This input can cause it: [0 1 0 4 0 1 0 0 0 0 0 6 0 128 0 67 0 16 8 0 0 1 0 1 0 0]

attest: surprising that EKs() makes HTTP GET request to Intel

This should be its own call or take a context. When packages make requests, users MUST be able to provide a custom http.Client for scenarios like transport proxies.

Can we expand the PlatformEK so uses can handle these cases?

type EK struct {
    // Public key of the EK.
    Public crypto.PublicKey

    // Certificate is the EK certificate. This may be nil, depending on the provider.
    Certificate *x509.Certificate

    // For Intel TPMs, Intel hosts certificates at a public URL derived from the
    // Public key. Clients or servers can perform an HTTP GET to this URL, and
    // use ParseEKCertificate on the response body.
    CertificateURL string
}

func ParseEKCertificate(b []byte) (*x509.Certificate, error)

parseSpecIDEvent can allocate an unbounded amount of memory

algs := make([]specAlgSize, header.NumAlgs)
if err := binary.Read(r, binary.LittleEndian, &algs); err != nil {
    return nil, fmt.Errorf("reading algorithms: %v", err)
}

Reproduction:

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
RyXs7SdTSQ==

Produces:

header{
    Signature: [16]uint8{0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44, 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x0}, 
    PlatformClass: 0x0, 
    VersionMinor: 0x0, 
    VersionMajor: 0x2,
    Errata: 0x0, 
    UintnSize: 0x2, 
    NumAlgs: 0xffff0001,
}

0xffff0001 = 4.295 GB

Tests don't build on MacOS or Windows

Found this when migrating to GitHub actions

#239

E.g. setupSimulatedTPM is only defined on Linux but is referenced in other files

attest/certification_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/certification_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/attest_simulated_tpm20_test.go:func setupSimulatedTPM(t *testing.T) (*simulator.Simulator, *TPM) {
attest/attest_simulated_tpm20_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/attest_simulated_tpm20_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/attest_simulated_tpm20_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/attest_simulated_tpm20_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/attest_simulated_tpm20_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/attest_simulated_tpm20_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/attest_simulated_tpm20_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/attest_simulated_tpm20_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/attest_simulated_tpm20_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/application_key_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/application_key_test.go:	sim, tpm := setupSimulatedTPM(t)
attest/application_key_test.go:	sim, tpm := setupSimulatedTPM(t)

Running go test ./... on MacOS or Windows should both build and pass, skipping anything that requires Linux dependencies.

Secure-boot: parsing authority events starting with `[]byte{185 65 36 160}` fails

Analysis ongoing, but I have a failing unit test:

--- FAIL: TestSecureBootBugThing (0.00s)
    secureboot_test.go:58: failed parsing secureboot state: failed parsing EFI variable authority at event 12: asn1: structure error: tags don't match (16 vs {class:2 tag:25 length:65 isCompound:true}) {optional:false explicit:false application:false private:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false lax:true name:} certificate @2
    secureboot_test.go:60: <nil>

Bounds check failure in ParseEKCertificate

Found by oss-fuzz + ASAN.

  | Bot: oss-fuzz-linux-zone3-host-7gp2-4
  | Time ran: 0.310926914215
  |  
  | INFO: Seed: 1399422185
  | INFO: 65536 Extra Counters
  | /mnt/scratch0/clusterfuzz/bot/builds/clusterfuzz-builds_go-attestation_6af98b8fbc8e1eba35c78858068206247723399f/revisions/parse_ek_certificate_fuzzer: Running 1 inputs 100 time(s) each.
  | Running: /crash-dbfcf248daa33db6546c2cd1ab0de0a4fcfcf534
  | panic: runtime error: slice bounds out of range [5:4]
  |  
  | goroutine 17 [running, locked to thread]:
  | github.com/google/go-attestation/attest.ParseEKCertificate(0x6020000000b0, 0x6, 0x6, 0x559843, 0x10c00006a058, 0x10c00006a058)
  | /root/go/src/github.com/google/go-attestation/attest/tpm.go:165 +0x753
  | github.com/google/go-attestation/attest.FuzzParseEKCertificate(0x6020000000b0, 0x6, 0x6, 0x7ffe955cfe28)
  | /root/go/src/github.com/google/go-attestation/attest/attest_fuzz.go:44 +0x5d
  | main.LLVMFuzzerTestOneInput(0x6020000000b0, 0x6, 0x9c3f58)
  | github.com/google/go-attestation/attest/go.fuzz.main/main.go:35 +0x66
  | main._cgoexpwrap_120fe4414799_LLVMFuzzerTestOneInput(0x6020000000b0, 0x6, 0xacf800)
  | _cgo_gotypes.go:64 +0x37
  | AddressSanitizer:DEADLYSIGNAL
  | =================================================================
  | ==1==ERROR: AddressSanitizer: ABRT on unknown address 0x000000000001 (pc 0x0000005aad51 bp 0x10c000046b60 sp 0x10c000046b48 T0)
  | SCARINESS: 10 (signal)
  | #0 0x5aad51 in runtime.raise runtime/sys_linux_amd64.s:150
  |  
  | AddressSanitizer can not provide additional info.
  | SUMMARY: AddressSanitizer: ABRT (/mnt/scratch0/clusterfuzz/bot/builds/clusterfuzz-builds_go-attestation_6af98b8fbc8e1eba35c78858068206247723399f/revisions/parse_ek_certificate_fuzzer+0x5aad51)
  | ==1==ABORTING
  |  
  |  
  | +----------------------------------------Release Build Unsymbolized Stacktrace (diff)----------------------------------------+
  |  
  | ==1==ERROR: AddressSanitizer: ABRT on unknown address 0x000000000001 (pc 0x0000005aad51 bp 0x10c000046b60 sp 0x10c000046b48 T0)
  | SCARINESS: 10 (signal)
  | #0 0x5aad51  (/mnt/scratch0/clusterfuzz/bot/builds/clusterfuzz-builds_go-attestation_6af98b8fbc8e1eba35c78858068206247723399f/revisions/parse_ek_certificate_fuzzer+0x5aad51)
  |  
  | AddressSanitizer can not provide additional info.

Replicating input: 1001 00ff ff20

Open /dev/tpm0: device or resource busy

Hello guys

When trying to OpenTPM() to perform attestation, I always get the following error: "Open /dev/tpm0: device or resource busy".
When I run the same piece of code in a real HW TPM, everything works fine, but when running in a virtualized environment (VMs instantiated through qemu and vTPM by means of SWTPM, TSS, ABRMD) I get this error.

Has anyone been through this before?

Any help is appreciated.

TPM-Keys in virtual SmartCards

Hello,
great library you have created so far! I would like to use the created Keys to provision certificates that are bound to a TPM. Eventually, I would like to have a virtual SmartCard interface that I can use in a browser, as it is possible, e.g. with the TPM2-TSS tools (https://github.com/tpm2-software/tpm2-pkcs11). Are you aware of an implementation in GO where this SmartCard object is created? Do you plan on extending the code for using it in combination with certificates?

Trouble with credential activation

Hello. I am trying to understand the TPM credential activation flow. I have been trying to run a simple test that does:

---client produces EK, AK data, sends to server---
ak := tpm.NewAK()
ap := ak.AttestationParameters()
---server generates encrypted challenge for EK,AK---
activation := attest.ActivationParameters{ //deserialized data from client }
secret1, challenge := activation.Generate()
---client receives challenge blob---
ak := tpm.LoadAK()
secret2 := attest.ActivateCredential(challenge)
---server receives decrypted challenge---
validate(secret1, secret2)

In my testing, client and server are running on the same machine. My test fails at activation.Generate() complaining that the AK in ActivationParameters is not an RSA key. Is it wrong to use AttestationParameters.Public from Tpm.NewAK().AttestationParameters() here? It looks like the template used by Tpm.NewAK() is an RSA key as prescribed. I looked at a hex dump of the data and if I'm parsing the fields correctly, the AK produced is RSA/SHA1. Any hints?

Derek

attest: tests and package should build on non windows/linux+cgo platforms

There's no reason you shouldn't be able to run the platform independent code on Mac, or on a Linux server without cgo.

$ GOOS=darwin go test -v -c github.com/google/go-attestation/attest
# github.com/google/go-attestation/attest [github.com/google/go-attestation/attest.test]
./attest.go:88:9: undefined: platformTPM
./attest.go:90:26: undefined: platformTPM
./attest.go:91:11: undefined: platformTPM
./tpm.go:274:7: undefined: platformTPM
$ GOOS=linux CGO_ENABLED=0 go test -c github.com/google/go-attestation/attest
build github.com/google/go-tspi/tspi: cannot load github.com/google/go-tspi/tspi: no Go source files

AK Activation Windows Platform Crypto Provider Steps

In issue #98 it was mentioned that some of the AK activation was done to match how the windows Platform Crypto Provider performs things.

Would it be possible to document this as an example (even if in a rough way) somewhere?

I've made a client that successfully performs the AIK activation using raw TPM commands, but I've been trying to convert that to use the PCP and have found progress hard (not due to this project, but lack of windows documentation) and any information would be useful.

parseRawEvent can allocate an unbounded amount of memory

var h rawEventHeader
if err = binary.Read(r, binary.LittleEndian, &h); err != nil {
    return event, err
}
data := make([]byte, int(h.EventSize))

In this code path an attacker can control the number of allocated bytes. This can lead to a DoS attack by OOMing the process.

Example:

Mzk0MDIwMDYxOTYzOTQ0NzkyMTIyNzkwNDAxbUfvv70AMDAxNDM2MTM4MDUwNzk3MzkyNzA0NjU0
NDY2Njc5NDgyOTM0MDQyNDU3MjE3NzE0OTY4NzAzMjkwNDcyNjYwODgyNTg5MzgwMDE4NjE2MDY5
NzMxMTIzMTk=

Produces:

rawEventHeader{
    PCRIndex:0x30343933, 
    Type:0x36303032, 
    Digest:[20]uint8{0x31, 0x39, 0x36, 0x33, 0x39, 0x34, 0x34, 0x37, 0x39, 0x32, 0x31, 0x32, 0x32, 0x37, 0x39, 0x30, 0x34, 0x30, 0x31, 0x6d},
    EventSize:0xbdbfef47,
}

0xbdbfef47 being 3.183 GB.

It doesn't appear that the TCG EFI Protocol Specification defines a maximum size for an event. So it seems our options are either choosing an arbitrary maximum or reporting this to the TCG as undefined behavior.

attest: Allow verification of quote without a corresponding event log

Users may choose to use Quote() to challenge the presence of an AIK, by quoting over PCRs and providing a nonce. In this case, there is no event log (and there may be none present), but we still want to be able to verify the quote.

Currently, the API for verifying a quote is coupled into event log verification (users must call EventLog{}.Validate(), which will fail if they do not provide an event log).

Proposal 1: Add a Verify(aik, nonce, pcrs) method directly on Quote
Proposal 2: Make it legal to call Validate on EventLog where no event log is present.

WDYT @ericchiang ?

attest: Implement EK cert verification, remove verifier/ subpackage

Use-case: Verifying an EK certificate chains up to a set of known root CA's and intermediates.

We could leave this to implementers to hack something up using x509.CertPool, but there are a few complexities that make that suboptimal:

  • Numerous roots for a few vendors are malformed in ways that Go's x509/asn1 library refuses to parse (but cert-transparency can).
  • Key usages for EK certificate do not map onto the PKI model used for the web, meaning verification using defaults will fail.
  • Unrecognised extensions in the certs cause problems.

Proposal:

  • Make an EKCertVerifier structure, that consumes a slice of intermediate & root x509 certificates.

  • Users call .Verify(der) and recieve the validated certificate chain, or an error.

WDYT?

Flag to use to avoid installing libtspi-dev.

Hey Guys
I am running a test and I am seeing

# github.com/google/go-tspi/tspi
/go/pkg/mod/github.com/google/[email protected]/tspi/context.go:17:27: fatal error: trousers/tss.h: No such file or directory
 // #include <trousers/tss.h>
                           ^
compilation terminated.

I am assuming this is the related issue of not installing the libtspi-dev since I am running it on centos. May I know if I dont want TPM12 support what I should run to build?

I check the relate issues here #163 but not pretty clear how I should use any flag to make it build.

Thanks!

Verifying the Quote

Hello, a couple days ago I came here to talk about a question of retrieving the PCRs values from the Quote and I got Verify method as answer, I've studied about this method and as I see, it compares all 24 PCRs values, I would like to know if I could select which PCRs I want to be compared. For example, In my problem I only need PCRs 2, 4, 5, 6 and 9.

Instructions on how to generate CSR

Hi! Really appreciate your hard work on this project guys. I have a question regarding post-activation steps

the server records the AK and EK association and allows the client to use its AK as a credential (e.g. by issuing it a client certificate).

My understanding is that client should also send a CSR for server to issue certificate. I've spent some time trying to find information on how to create CSR using generated AK, but did not succeed. Can you please give me any links/instructions to point me in the right direction?

TPM2 AK activation/validation seems unnecessarily complicated

Currently TPM2 clients generate an AK and then self-certify using TPM2_Certify.

But I don't think the self-certification is currently serving any purpose:

  • TPM2_MakeCredential already guarantees that the reported TPM2_PUBLIC must correctly describes the AK, otherwise TPM2_ActivateCredential won't allow the EK to decrypt the sealed credential.
  • For the AK's self-certification to be meaningful, we have to trust that the AK is good, which is kinda begging the question.
  • TPM2_Certify could be useful if go-attestation checked any of the TPMS_ATTEST fields (e.g., clockInfo or firmwareVersion) or TPMS_CREATION_DATA fields (e.g., it could check that the AK was recently generated), but go-attestation doesn't seem to pay attention to these.

As far as I can tell, if att.AttestedCreationInfo.Name.Digest in generateChallengeTPM20 was replaced with tpm2.DecodePublic(p.AIK.Public).Name().Digest, then p.AIK.CreateData and p.AIK.CreateAttestation can be removed entirely without losing any security properties.

But maybe I'm missing something, or there are plans to eventually utilize more of the attestation data. E.g., maybe firmwareVersion is useful to log in case it's discovered that some TPM firmware versions had key generation vulnerabilities (e.g., ROCA for RSA keys, or Yubikey's FIPS RNG goofup affecting both RSA and ECC keys); though in that case, you probably need to re-generate (and re-certify) the EK too, so I'm not sure the AK is your biggest concern.

TPM2 Windows: ActivateCredential needs an admin cmd in order to succeed

Running this sample , which is based on the official example, ActivateCredential, and especially the call to nCryptGetProperty fails on 2 of my Windows 10 machines with the following error code : 0X80090030 (NTE_DEVICE_NOT_READY).
Running the same sample but using an admin cmd, everything works as expected.

I'm sorry I'm not quite yet familiar with how PCP handles all this TPM 2.0 stuff, but is this a normal behaviour ? or is there something I should be doing beforehand ?

Thanks.

Document how to generate data for unit tests

Document how to use the attest-tool for generating unit test data. Needed for #64 and #62. In the short term. This needs to be documented publicly so users can give us meaningful reports and ensure fixes have appropriate coverage.

Attest-tool throws error in linux system

Tried running attest-tool "self-test" in RHEL 8.4 systems.

Getting the following error :

Error: NewAK() failed: failed to get SRK handle: CreatePrimary failed: session 1, error code 0x22 : authorization failure without DA implications

Does any permissions need to be enabled ? Please share the commands for that.

attest: figure out hashing algorithm strategy

This is a super-set of #72

It's currently unclear when a user needs to provide SHA1 or SHA256, or when we can infer it from other data. There are several places where we need a hash:

  • To determine the signature algorithm on the quote. Is this always inferred from the TPM public blob?
  • To determine which quote we should send to the server. TPM 2.0 doesn't guarantee that the eventlog will correctly contain SHA256, even if the PCRs store SHA256 values. Should this be determined by inspecting the measurement log?
  • It's unclear why AIK.Quote() requires a HashAlg, or how this should be filled.

For now, I propose we modify the MeasurementLog signature to return the hash:

func (t *TPM) MeasurementLog() ([]byte, HashAlg, error)

And the PCRs call to take a hash:

func (t *TPM) PCRs(alg HashAlg) ([]PCR, error)

Users would then do something like

rawLog, alg, err := tpm.MeasurementLog()
if err != nil {
    // ...
}
pcrs, err := tpm.PCRs(alg)

Quote of set of PCRs

Hello, I'm working with your lib and I wonder if you plan to make a function to make the quote using a set of pcrs. Because I've studied your lib and I saw you only give me a way to make a quote using all pcrs.

Revert of tspi build tag

Yo,

It seems the changes made to the buildflag to disable tspi was reverted without any explicit comment why?

Introduction: #237

Revert: be496f1

Would i be possible to partially revert this revert or is there any reason for this change?

Unable to execute attest-tool in some windows systems

Tried to run 'self-test' , 'tpm-info' , getting the following error :
FAIL
Error: credential activation failed: failed to generate activate credential: NCryptGetProperty returned 80090030 (The operation completed successfully.) for key activation

I am able to run the same binary and get expected output output in some systems while in some other systems, I am getting the error mentioned.

It will be very useful if someone can point out a way to solve this error. Many Thanks.

Pi Build

I'm trying a simple test program on my Pi and i run into this issue during building:

# github.com/google/go-tspi/tspi
../go/pkg/mod/github.com/google/[email protected]/tspi/tpm.go:92:13: type [1073741824]_Ctype_struct_tdTSS_PCR_EVENT larger than address space
../go/pkg/mod/github.com/google/[email protected]/tspi/tpm.go:92:13: type [1073741824]_Ctype_struct_tdTSS_PCR_EVENT too large

if i understood this error correctly this is linked to
image
in attest/tpm.go. Is there a common or known workaround for this issue?

Specs:
Pi4 (raspdebian 10.9)
go1.16.5 linux/arm

Use build tags to allow building without tspi

Right now, a user of go-attestation must download and install libtspi-dev even if they only wish to use TPM2 (such as with GCE). This can be problematic as this library is not distributed with all Linux distros.

Go supports build constraints to allow for conditional compilation. Similar to how we don't require tspi on Windows builds, we could use a notspi build constraint to allow:

go build -notspi windows ./attest/attest-tool

to build without tspi.

We could also invert the semantics, having the tspi build flag enable support for TPM 1.2 on Linux, depending on what we want to be the default.

Make platformTPM public for downstream testing

I am contributing to a downstream project, spire-tpm-plugin, and would like to be able to test using the TPM simulator like this project does:

func setupSimulatedTPM(t *testing.T) (*simulator.Simulator, *TPM) {
t.Helper()
tpm, err := simulator.Get()
if err != nil {
t.Fatal(err)
}
return tpm, &TPM{tpm: &platformTPM{
version: TPMVersion20,
interf: TPMInterfaceKernelManaged,
sysPath: "/dev/tpmrm0",
rwc: tpm,
}}
}

The issue I'm running into is that platformTPM is a private struct, so I am unable to "fake" the TPM in downstream testing

attest: Add signal that Data section in an event corresponds to the event digest

Use case:

  • Sometimes interesting information is put in the Data section of an event
  • In these cases the event is such that the digest extended matches the digest of the Data section
  • In this case, the consumer of the Event would like to use the contents of the data section if and only if the data section matches the digest of the event

Proposal:

  • Add a method/field that would indicate whether the data field of an Event is verified by the digest or not.

Credential activation fails due to activating against EK with inconsistent template

The error: parameter 2, error code 0x4 : value is out of range or is not correct for the context

(one of the) causes: 2.2.1.2.3 specifies that the EK template can have a nonce. We never accounted for that logic when creating the EK primary key. This feature is a footgun and was only used on old TPMs, hence why I never encountered it before.

The fix is to correctly interrogate the NV indices for the nonce and template when creating the EK if its not already persisted.

Thanks for @chrisfenner for debugging this with me.

AttestPlatform() returns an empty event log on some systems

This can lead to errors when trying to parse it: invalid log: event data size is 0.

Given an empty event log defeats the point of platform attestation, a call to AttestPlatform() should return an error if the platform does not have a valid event log.

API cleanups

Looking at the exported API the package is a little cluttered. https://godoc.org/github.com/google/go-attestation/attest

Some thoughts for cleaning up the API, these are mostly just nits:

  • Replace HashAlg with crypto.Hash
  • PlatformEK -> EK
  • Remove KeyPurpose (#60)
  • MintOptions -> AIKConfig / TPM.MintAIK -> TPM.NewAIK (so all the AIK options are ordered together)

support for machines without an EK certificate?

I have some TPM1.2 machines that do not seem to come with an EK certificate. They have an Intel discrete TPM but Intel's HTTP interface returns just 404 and attempts to write a dummy EK certificate to the NVRAM also fail. Would you be interested in a pull request that makes the self-test work on such machines? I understood that TPM1.2 support was in maintenance-only mode now so I thought I'd ask before spending too much time polishing a PR.

I got this to work by modifying eks() in tpm12_linux.go to read the EK directly from the TPM if reading the EK certificate from NVRAM fails. This required also adding two functions to go-tspi to read the EK from the TPM.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.